1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use crate::{
errors::StatementError,
program::ConstrainedProgram,
value::ConstrainedValue,
GroupType,
ResolvedAssigneeAccess,
};
use leo_asg::{
ArrayAccessExpression,
ArrayRangeAccessExpression,
CircuitAccessExpression,
Expression,
Node,
Span,
TupleAccessExpression,
Variable,
};
use std::sync::Arc;
use snarkvm_models::{
curves::{Field, PrimeField},
gadgets::r1cs::ConstraintSystem,
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
fn prepare_mut_access<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
expr: &Arc<Expression>,
span: &Span,
output: &mut Vec<ResolvedAssigneeAccess>,
) -> Result<Option<Variable>, StatementError> {
match &**expr {
Expression::ArrayRangeAccess(ArrayRangeAccessExpression { array, left, right, .. }) => {
let inner = self.prepare_mut_access(cs, array, span, output)?;
let start_index = left
.as_ref()
.map(|start| self.enforce_index(cs, start, &span))
.transpose()?;
let stop_index = right
.as_ref()
.map(|stop| self.enforce_index(cs, stop, &span))
.transpose()?;
output.push(ResolvedAssigneeAccess::ArrayRange(start_index, stop_index));
Ok(inner)
}
Expression::ArrayAccess(ArrayAccessExpression { array, index, .. }) => {
let inner = self.prepare_mut_access(cs, array, span, output)?;
let index = self.enforce_index(cs, index, &span)?;
output.push(ResolvedAssigneeAccess::ArrayIndex(index));
Ok(inner)
}
Expression::TupleAccess(TupleAccessExpression { tuple_ref, index, .. }) => {
let inner = self.prepare_mut_access(cs, tuple_ref, span, output)?;
output.push(ResolvedAssigneeAccess::Tuple(*index, span.clone()));
Ok(inner)
}
Expression::CircuitAccess(CircuitAccessExpression {
target: Some(target),
member,
..
}) => {
let inner = self.prepare_mut_access(cs, target, span, output)?;
output.push(ResolvedAssigneeAccess::Member(member.clone()));
Ok(inner)
}
Expression::VariableRef(variable_ref) => Ok(Some(variable_ref.variable.clone())),
_ => Ok(None),
}
}
pub fn resolve_mut_ref<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
assignee: &Arc<Expression>,
) -> Result<Option<Vec<&mut ConstrainedValue<F, G>>>, StatementError> {
let span = assignee.span().cloned().unwrap_or_default();
let mut accesses = vec![];
let target = self.prepare_mut_access(cs, assignee, &span, &mut accesses)?;
if target.is_none() {
return Ok(None);
}
let variable = target.unwrap();
let variable = variable.borrow();
let mut result = vec![match self.get_mut(&variable.id) {
Some(value) => value,
None => return Err(StatementError::undefined_variable(variable.name.to_string(), span)),
}];
for access in accesses {
result = Self::resolve_assignee_access(access, &span, result)?;
}
Ok(Some(result))
}
}