mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
impl function scope
This commit is contained in:
parent
455c0b631a
commit
6b6bce38cb
@ -1,6 +1,6 @@
|
|||||||
def main() -> (field):
|
struct Foo {
|
||||||
a = 1
|
bool x
|
||||||
for i in 0..4 do
|
}
|
||||||
a = a + 1
|
def main() -> (bool):
|
||||||
endfor
|
Foo f = Foo {x: true}
|
||||||
return a
|
return f.x
|
||||||
|
@ -70,34 +70,76 @@ impl fmt::Display for ResolvedValue {
|
|||||||
}
|
}
|
||||||
write!(f, "]")
|
write!(f, "]")
|
||||||
}
|
}
|
||||||
_ => unimplemented!("display not impl for value"),
|
ResolvedValue::StructDefinition(ref _definition) => {
|
||||||
|
unimplemented!("cannot return struct definition in program")
|
||||||
|
}
|
||||||
|
ResolvedValue::Function(ref _function) => {
|
||||||
|
unimplemented!("cannot return function definition in program")
|
||||||
|
}
|
||||||
|
// _ => unimplemented!("display not impl for value"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ResolvedProgram {
|
pub struct ResolvedProgram {
|
||||||
pub resolved_variables: HashMap<Variable, ResolvedValue>,
|
pub resolved_names: HashMap<String, ResolvedValue>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_scope(outer: String, inner: String) -> String {
|
||||||
|
format!("{}_{}", outer, inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_scope_from_variable(outer: String, inner: &Variable) -> String {
|
||||||
|
new_scope(outer, inner.0.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResolvedProgram {
|
impl ResolvedProgram {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
resolved_variables: HashMap::new(),
|
resolved_names: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert(&mut self, variable: Variable, value: ResolvedValue) {
|
fn store(&mut self, name: String, value: ResolvedValue) {
|
||||||
self.resolved_variables.insert(variable, value);
|
self.resolved_names.insert(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn store_variable(&mut self, variable: Variable, value: ResolvedValue) {
|
||||||
|
self.store(variable.0, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contains_name(&self, name: &String) -> bool {
|
||||||
|
self.resolved_names.contains_key(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contains_variable(&self, variable: &Variable) -> bool {
|
||||||
|
self.contains_name(&variable.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&self, name: &String) -> Option<&ResolvedValue> {
|
||||||
|
self.resolved_names.get(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mut(&mut self, name: &String) -> Option<&mut ResolvedValue> {
|
||||||
|
self.resolved_names.get_mut(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mut_variable(&mut self, variable: &Variable) -> Option<&mut ResolvedValue> {
|
||||||
|
self.get_mut(&variable.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bool_from_variable<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn bool_from_variable<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
variable: Variable,
|
variable: Variable,
|
||||||
) -> Boolean {
|
) -> Boolean {
|
||||||
if self.resolved_variables.contains_key(&variable) {
|
// Evaluate variable name in current function scope
|
||||||
|
let variable_name = new_scope_from_variable(scope, &variable);
|
||||||
|
|
||||||
|
if self.contains_name(&variable_name) {
|
||||||
// TODO: return synthesis error: "assignment missing" here
|
// TODO: return synthesis error: "assignment missing" here
|
||||||
match self.resolved_variables.get(&variable).unwrap() {
|
match self.get(&variable_name).unwrap() {
|
||||||
ResolvedValue::Boolean(boolean) => boolean.clone(),
|
ResolvedValue::Boolean(boolean) => boolean.clone(),
|
||||||
_ => panic!("expected a boolean, got field"),
|
_ => panic!("expected a boolean, got field"),
|
||||||
}
|
}
|
||||||
@ -116,11 +158,15 @@ impl ResolvedProgram {
|
|||||||
fn u32_from_variable<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn u32_from_variable<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
variable: Variable,
|
variable: Variable,
|
||||||
) -> UInt32 {
|
) -> UInt32 {
|
||||||
if self.resolved_variables.contains_key(&variable) {
|
// Evaluate variable name in current function scope
|
||||||
|
let variable_name = new_scope_from_variable(scope, &variable);
|
||||||
|
|
||||||
|
if self.contains_name(&variable_name) {
|
||||||
// TODO: return synthesis error: "assignment missing" here
|
// TODO: return synthesis error: "assignment missing" here
|
||||||
match self.resolved_variables.get(&variable).unwrap() {
|
match self.get(&variable_name).unwrap() {
|
||||||
ResolvedValue::FieldElement(field) => field.clone(),
|
ResolvedValue::FieldElement(field) => field.clone(),
|
||||||
_ => panic!("expected a field, got boolean"),
|
_ => panic!("expected a field, got boolean"),
|
||||||
}
|
}
|
||||||
@ -141,12 +187,13 @@ impl ResolvedProgram {
|
|||||||
fn get_bool_value<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn get_bool_value<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
expression: BooleanExpression,
|
expression: BooleanExpression,
|
||||||
) -> Boolean {
|
) -> Boolean {
|
||||||
match expression {
|
match expression {
|
||||||
BooleanExpression::Variable(variable) => self.bool_from_variable(cs, variable),
|
BooleanExpression::Variable(variable) => self.bool_from_variable(cs, scope, variable),
|
||||||
BooleanExpression::Value(value) => Boolean::Constant(value),
|
BooleanExpression::Value(value) => Boolean::Constant(value),
|
||||||
expression => match self.enforce_boolean_expression(cs, expression) {
|
expression => match self.enforce_boolean_expression(cs, scope, expression) {
|
||||||
ResolvedValue::Boolean(value) => value,
|
ResolvedValue::Boolean(value) => value,
|
||||||
_ => unimplemented!("boolean expression did not resolve to boolean"),
|
_ => unimplemented!("boolean expression did not resolve to boolean"),
|
||||||
},
|
},
|
||||||
@ -156,12 +203,13 @@ impl ResolvedProgram {
|
|||||||
fn get_u32_value<F: Field + PrimeField + PrimeField, CS: ConstraintSystem<F>>(
|
fn get_u32_value<F: Field + PrimeField + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
expression: FieldExpression,
|
expression: FieldExpression,
|
||||||
) -> UInt32 {
|
) -> UInt32 {
|
||||||
match expression {
|
match expression {
|
||||||
FieldExpression::Variable(variable) => self.u32_from_variable(cs, variable),
|
FieldExpression::Variable(variable) => self.u32_from_variable(cs, scope, variable),
|
||||||
FieldExpression::Number(number) => UInt32::constant(number),
|
FieldExpression::Number(number) => UInt32::constant(number),
|
||||||
field => match self.enforce_field_expression(cs, field) {
|
field => match self.enforce_field_expression(cs, scope, field) {
|
||||||
ResolvedValue::FieldElement(value) => value,
|
ResolvedValue::FieldElement(value) => value,
|
||||||
_ => unimplemented!("field expression did not resolve to field"),
|
_ => unimplemented!("field expression did not resolve to field"),
|
||||||
},
|
},
|
||||||
@ -171,9 +219,10 @@ impl ResolvedProgram {
|
|||||||
fn enforce_not<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_not<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
expression: BooleanExpression,
|
expression: BooleanExpression,
|
||||||
) -> Boolean {
|
) -> Boolean {
|
||||||
let expression = self.get_bool_value(cs, expression);
|
let expression = self.get_bool_value(cs, scope, expression);
|
||||||
|
|
||||||
expression.not()
|
expression.not()
|
||||||
}
|
}
|
||||||
@ -181,11 +230,12 @@ impl ResolvedProgram {
|
|||||||
fn enforce_or<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_or<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
left: BooleanExpression,
|
left: BooleanExpression,
|
||||||
right: BooleanExpression,
|
right: BooleanExpression,
|
||||||
) -> Boolean {
|
) -> Boolean {
|
||||||
let left = self.get_bool_value(cs, left);
|
let left = self.get_bool_value(cs, scope.clone(), left);
|
||||||
let right = self.get_bool_value(cs, right);
|
let right = self.get_bool_value(cs, scope.clone(), right);
|
||||||
|
|
||||||
Boolean::or(cs, &left, &right).unwrap()
|
Boolean::or(cs, &left, &right).unwrap()
|
||||||
}
|
}
|
||||||
@ -193,11 +243,12 @@ impl ResolvedProgram {
|
|||||||
fn enforce_and<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_and<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
left: BooleanExpression,
|
left: BooleanExpression,
|
||||||
right: BooleanExpression,
|
right: BooleanExpression,
|
||||||
) -> Boolean {
|
) -> Boolean {
|
||||||
let left = self.get_bool_value(cs, left);
|
let left = self.get_bool_value(cs, scope.clone(), left);
|
||||||
let right = self.get_bool_value(cs, right);
|
let right = self.get_bool_value(cs, scope.clone(), right);
|
||||||
|
|
||||||
Boolean::and(cs, &left, &right).unwrap()
|
Boolean::and(cs, &left, &right).unwrap()
|
||||||
}
|
}
|
||||||
@ -205,11 +256,12 @@ impl ResolvedProgram {
|
|||||||
fn enforce_bool_equality<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_bool_equality<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
left: BooleanExpression,
|
left: BooleanExpression,
|
||||||
right: BooleanExpression,
|
right: BooleanExpression,
|
||||||
) -> Boolean {
|
) -> Boolean {
|
||||||
let left = self.get_bool_value(cs, left);
|
let left = self.get_bool_value(cs, scope.clone(), left);
|
||||||
let right = self.get_bool_value(cs, right);
|
let right = self.get_bool_value(cs, scope.clone(), right);
|
||||||
|
|
||||||
left.enforce_equal(cs.ns(|| format!("enforce bool equal")), &right)
|
left.enforce_equal(cs.ns(|| format!("enforce bool equal")), &right)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -220,11 +272,12 @@ impl ResolvedProgram {
|
|||||||
fn enforce_field_equality<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_field_equality<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
left: FieldExpression,
|
left: FieldExpression,
|
||||||
right: FieldExpression,
|
right: FieldExpression,
|
||||||
) -> Boolean {
|
) -> Boolean {
|
||||||
let left = self.get_u32_value(cs, left);
|
let left = self.get_u32_value(cs, scope.clone(), left);
|
||||||
let right = self.get_u32_value(cs, right);
|
let right = self.get_u32_value(cs, scope.clone(), right);
|
||||||
|
|
||||||
left.conditional_enforce_equal(
|
left.conditional_enforce_equal(
|
||||||
cs.ns(|| format!("enforce field equal")),
|
cs.ns(|| format!("enforce field equal")),
|
||||||
@ -239,37 +292,39 @@ impl ResolvedProgram {
|
|||||||
fn enforce_boolean_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_boolean_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
expression: BooleanExpression,
|
expression: BooleanExpression,
|
||||||
) -> ResolvedValue {
|
) -> ResolvedValue {
|
||||||
match expression {
|
match expression {
|
||||||
BooleanExpression::Variable(variable) => {
|
BooleanExpression::Variable(variable) => {
|
||||||
ResolvedValue::Boolean(self.bool_from_variable(cs, variable))
|
ResolvedValue::Boolean(self.bool_from_variable(cs, scope, variable))
|
||||||
}
|
}
|
||||||
BooleanExpression::Value(value) => ResolvedValue::Boolean(Boolean::Constant(value)),
|
BooleanExpression::Value(value) => ResolvedValue::Boolean(Boolean::Constant(value)),
|
||||||
BooleanExpression::Not(expression) => {
|
BooleanExpression::Not(expression) => {
|
||||||
ResolvedValue::Boolean(self.enforce_not(cs, *expression))
|
ResolvedValue::Boolean(self.enforce_not(cs, scope, *expression))
|
||||||
}
|
}
|
||||||
BooleanExpression::Or(left, right) => {
|
BooleanExpression::Or(left, right) => {
|
||||||
ResolvedValue::Boolean(self.enforce_or(cs, *left, *right))
|
ResolvedValue::Boolean(self.enforce_or(cs, scope, *left, *right))
|
||||||
}
|
}
|
||||||
BooleanExpression::And(left, right) => {
|
BooleanExpression::And(left, right) => {
|
||||||
ResolvedValue::Boolean(self.enforce_and(cs, *left, *right))
|
ResolvedValue::Boolean(self.enforce_and(cs, scope, *left, *right))
|
||||||
}
|
}
|
||||||
BooleanExpression::BoolEq(left, right) => {
|
BooleanExpression::BoolEq(left, right) => {
|
||||||
ResolvedValue::Boolean(self.enforce_bool_equality(cs, *left, *right))
|
ResolvedValue::Boolean(self.enforce_bool_equality(cs, scope, *left, *right))
|
||||||
}
|
}
|
||||||
BooleanExpression::FieldEq(left, right) => {
|
BooleanExpression::FieldEq(left, right) => {
|
||||||
ResolvedValue::Boolean(self.enforce_field_equality(cs, *left, *right))
|
ResolvedValue::Boolean(self.enforce_field_equality(cs, scope, *left, *right))
|
||||||
}
|
}
|
||||||
BooleanExpression::IfElse(first, second, third) => {
|
BooleanExpression::IfElse(first, second, third) => {
|
||||||
let resolved_first = match self.enforce_boolean_expression(cs, *first) {
|
let resolved_first =
|
||||||
ResolvedValue::Boolean(resolved) => resolved,
|
match self.enforce_boolean_expression(cs, scope.clone(), *first) {
|
||||||
_ => unimplemented!("if else conditional must resolve to boolean"),
|
ResolvedValue::Boolean(resolved) => resolved,
|
||||||
};
|
_ => unimplemented!("if else conditional must resolve to boolean"),
|
||||||
|
};
|
||||||
if resolved_first.eq(&Boolean::Constant(true)) {
|
if resolved_first.eq(&Boolean::Constant(true)) {
|
||||||
self.enforce_boolean_expression(cs, *second)
|
self.enforce_boolean_expression(cs, scope, *second)
|
||||||
} else {
|
} else {
|
||||||
self.enforce_boolean_expression(cs, *third)
|
self.enforce_boolean_expression(cs, scope, *third)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BooleanExpression::Array(array) => ResolvedValue::BooleanArray(
|
BooleanExpression::Array(array) => ResolvedValue::BooleanArray(
|
||||||
@ -280,7 +335,7 @@ impl ResolvedProgram {
|
|||||||
unimplemented!("spreads not enforced yet")
|
unimplemented!("spreads not enforced yet")
|
||||||
}
|
}
|
||||||
BooleanSpreadOrExpression::BooleanExpression(expression) => {
|
BooleanSpreadOrExpression::BooleanExpression(expression) => {
|
||||||
match self.enforce_boolean_expression(cs, expression) {
|
match self.enforce_boolean_expression(cs, scope.clone(), expression) {
|
||||||
ResolvedValue::Boolean(value) => value,
|
ResolvedValue::Boolean(value) => value,
|
||||||
_ => unimplemented!("cannot resolve boolean"),
|
_ => unimplemented!("cannot resolve boolean"),
|
||||||
}
|
}
|
||||||
@ -295,11 +350,12 @@ impl ResolvedProgram {
|
|||||||
fn enforce_add<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_add<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
left: FieldExpression,
|
left: FieldExpression,
|
||||||
right: FieldExpression,
|
right: FieldExpression,
|
||||||
) -> UInt32 {
|
) -> UInt32 {
|
||||||
let left = self.get_u32_value(cs, left);
|
let left = self.get_u32_value(cs, scope.clone(), left);
|
||||||
let right = self.get_u32_value(cs, right);
|
let right = self.get_u32_value(cs, scope.clone(), right);
|
||||||
|
|
||||||
UInt32::addmany(
|
UInt32::addmany(
|
||||||
cs.ns(|| format!("enforce {} + {}", left.value.unwrap(), right.value.unwrap())),
|
cs.ns(|| format!("enforce {} + {}", left.value.unwrap(), right.value.unwrap())),
|
||||||
@ -311,11 +367,12 @@ impl ResolvedProgram {
|
|||||||
fn enforce_sub<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_sub<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
left: FieldExpression,
|
left: FieldExpression,
|
||||||
right: FieldExpression,
|
right: FieldExpression,
|
||||||
) -> UInt32 {
|
) -> UInt32 {
|
||||||
let left = self.get_u32_value(cs, left);
|
let left = self.get_u32_value(cs, scope.clone(), left);
|
||||||
let right = self.get_u32_value(cs, right);
|
let right = self.get_u32_value(cs, scope.clone(), right);
|
||||||
|
|
||||||
left.sub(
|
left.sub(
|
||||||
cs.ns(|| format!("enforce {} - {}", left.value.unwrap(), right.value.unwrap())),
|
cs.ns(|| format!("enforce {} - {}", left.value.unwrap(), right.value.unwrap())),
|
||||||
@ -327,11 +384,12 @@ impl ResolvedProgram {
|
|||||||
fn enforce_mul<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_mul<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
left: FieldExpression,
|
left: FieldExpression,
|
||||||
right: FieldExpression,
|
right: FieldExpression,
|
||||||
) -> UInt32 {
|
) -> UInt32 {
|
||||||
let left = self.get_u32_value(cs, left);
|
let left = self.get_u32_value(cs, scope.clone(), left);
|
||||||
let right = self.get_u32_value(cs, right);
|
let right = self.get_u32_value(cs, scope.clone(), right);
|
||||||
|
|
||||||
let res = left
|
let res = left
|
||||||
.mul(
|
.mul(
|
||||||
@ -346,11 +404,12 @@ impl ResolvedProgram {
|
|||||||
fn enforce_div<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_div<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
left: FieldExpression,
|
left: FieldExpression,
|
||||||
right: FieldExpression,
|
right: FieldExpression,
|
||||||
) -> UInt32 {
|
) -> UInt32 {
|
||||||
let left = self.get_u32_value(cs, left);
|
let left = self.get_u32_value(cs, scope.clone(), left);
|
||||||
let right = self.get_u32_value(cs, right);
|
let right = self.get_u32_value(cs, scope.clone(), right);
|
||||||
|
|
||||||
left.div(
|
left.div(
|
||||||
cs.ns(|| format!("enforce {} / {}", left.value.unwrap(), right.value.unwrap())),
|
cs.ns(|| format!("enforce {} / {}", left.value.unwrap(), right.value.unwrap())),
|
||||||
@ -362,11 +421,12 @@ impl ResolvedProgram {
|
|||||||
fn enforce_pow<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_pow<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
left: FieldExpression,
|
left: FieldExpression,
|
||||||
right: FieldExpression,
|
right: FieldExpression,
|
||||||
) -> UInt32 {
|
) -> UInt32 {
|
||||||
let left = self.get_u32_value(cs, left);
|
let left = self.get_u32_value(cs, scope.clone(), left);
|
||||||
let right = self.get_u32_value(cs, right);
|
let right = self.get_u32_value(cs, scope.clone(), right);
|
||||||
|
|
||||||
left.pow(
|
left.pow(
|
||||||
cs.ns(|| {
|
cs.ns(|| {
|
||||||
@ -384,40 +444,42 @@ impl ResolvedProgram {
|
|||||||
fn enforce_field_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_field_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
expression: FieldExpression,
|
expression: FieldExpression,
|
||||||
) -> ResolvedValue {
|
) -> ResolvedValue {
|
||||||
match expression {
|
match expression {
|
||||||
FieldExpression::Variable(variable) => {
|
FieldExpression::Variable(variable) => {
|
||||||
ResolvedValue::FieldElement(self.u32_from_variable(cs, variable))
|
ResolvedValue::FieldElement(self.u32_from_variable(cs, scope, variable))
|
||||||
}
|
}
|
||||||
FieldExpression::Number(number) => {
|
FieldExpression::Number(number) => {
|
||||||
ResolvedValue::FieldElement(UInt32::constant(number))
|
ResolvedValue::FieldElement(UInt32::constant(number))
|
||||||
}
|
}
|
||||||
FieldExpression::Add(left, right) => {
|
FieldExpression::Add(left, right) => {
|
||||||
ResolvedValue::FieldElement(self.enforce_add(cs, *left, *right))
|
ResolvedValue::FieldElement(self.enforce_add(cs, scope, *left, *right))
|
||||||
}
|
}
|
||||||
FieldExpression::Sub(left, right) => {
|
FieldExpression::Sub(left, right) => {
|
||||||
ResolvedValue::FieldElement(self.enforce_sub(cs, *left, *right))
|
ResolvedValue::FieldElement(self.enforce_sub(cs, scope, *left, *right))
|
||||||
}
|
}
|
||||||
FieldExpression::Mul(left, right) => {
|
FieldExpression::Mul(left, right) => {
|
||||||
ResolvedValue::FieldElement(self.enforce_mul(cs, *left, *right))
|
ResolvedValue::FieldElement(self.enforce_mul(cs, scope, *left, *right))
|
||||||
}
|
}
|
||||||
FieldExpression::Div(left, right) => {
|
FieldExpression::Div(left, right) => {
|
||||||
ResolvedValue::FieldElement(self.enforce_div(cs, *left, *right))
|
ResolvedValue::FieldElement(self.enforce_div(cs, scope, *left, *right))
|
||||||
}
|
}
|
||||||
FieldExpression::Pow(left, right) => {
|
FieldExpression::Pow(left, right) => {
|
||||||
ResolvedValue::FieldElement(self.enforce_pow(cs, *left, *right))
|
ResolvedValue::FieldElement(self.enforce_pow(cs, scope, *left, *right))
|
||||||
}
|
}
|
||||||
FieldExpression::IfElse(first, second, third) => {
|
FieldExpression::IfElse(first, second, third) => {
|
||||||
let resolved_first = match self.enforce_boolean_expression(cs, *first) {
|
let resolved_first =
|
||||||
ResolvedValue::Boolean(resolved) => resolved,
|
match self.enforce_boolean_expression(cs, scope.clone(), *first) {
|
||||||
_ => unimplemented!("if else conditional must resolve to boolean"),
|
ResolvedValue::Boolean(resolved) => resolved,
|
||||||
};
|
_ => unimplemented!("if else conditional must resolve to boolean"),
|
||||||
|
};
|
||||||
|
|
||||||
if resolved_first.eq(&Boolean::Constant(true)) {
|
if resolved_first.eq(&Boolean::Constant(true)) {
|
||||||
self.enforce_field_expression(cs, *second)
|
self.enforce_field_expression(cs, scope, *second)
|
||||||
} else {
|
} else {
|
||||||
self.enforce_field_expression(cs, *third)
|
self.enforce_field_expression(cs, scope, *third)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FieldExpression::Array(array) => ResolvedValue::FieldElementArray(
|
FieldExpression::Array(array) => ResolvedValue::FieldElementArray(
|
||||||
@ -428,7 +490,7 @@ impl ResolvedProgram {
|
|||||||
unimplemented!("spreads not enforced yet")
|
unimplemented!("spreads not enforced yet")
|
||||||
}
|
}
|
||||||
FieldSpreadOrExpression::FieldExpression(expression) => {
|
FieldSpreadOrExpression::FieldExpression(expression) => {
|
||||||
match self.enforce_field_expression(cs, expression) {
|
match self.enforce_field_expression(cs, scope.clone(), expression) {
|
||||||
ResolvedValue::FieldElement(value) => value,
|
ResolvedValue::FieldElement(value) => value,
|
||||||
_ => unimplemented!("cannot resolve field"),
|
_ => unimplemented!("cannot resolve field"),
|
||||||
}
|
}
|
||||||
@ -442,10 +504,11 @@ impl ResolvedProgram {
|
|||||||
fn enforce_struct_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_struct_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
variable: Variable,
|
variable: Variable,
|
||||||
members: Vec<StructMember>,
|
members: Vec<StructMember>,
|
||||||
) -> ResolvedValue {
|
) -> ResolvedValue {
|
||||||
if let Some(resolved_value) = self.resolved_variables.get_mut(&variable) {
|
if let Some(resolved_value) = self.get_mut_variable(&variable) {
|
||||||
match resolved_value {
|
match resolved_value {
|
||||||
ResolvedValue::StructDefinition(struct_definition) => {
|
ResolvedValue::StructDefinition(struct_definition) => {
|
||||||
struct_definition
|
struct_definition
|
||||||
@ -459,7 +522,8 @@ impl ResolvedProgram {
|
|||||||
}
|
}
|
||||||
// Resolve and possibly enforce struct fields
|
// Resolve and possibly enforce struct fields
|
||||||
// do we need to store the results here?
|
// do we need to store the results here?
|
||||||
let _result = self.enforce_expression(cs, member.expression);
|
let _result =
|
||||||
|
self.enforce_expression(cs, scope.clone(), member.expression);
|
||||||
});
|
});
|
||||||
|
|
||||||
ResolvedValue::StructExpression(variable, members)
|
ResolvedValue::StructExpression(variable, members)
|
||||||
@ -474,9 +538,10 @@ impl ResolvedProgram {
|
|||||||
fn enforce_index<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_index<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
index: FieldExpression,
|
index: FieldExpression,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
match self.enforce_field_expression(cs, index) {
|
match self.enforce_field_expression(cs, scope.clone(), index) {
|
||||||
ResolvedValue::FieldElement(number) => number.value.unwrap() as usize,
|
ResolvedValue::FieldElement(number) => number.value.unwrap() as usize,
|
||||||
value => unimplemented!("From index must resolve to a uint32, got {}", value),
|
value => unimplemented!("From index must resolve to a uint32, got {}", value),
|
||||||
}
|
}
|
||||||
@ -485,19 +550,20 @@ impl ResolvedProgram {
|
|||||||
fn enforce_array_access_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_array_access_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
array: Box<Expression>,
|
array: Box<Expression>,
|
||||||
index: FieldRangeOrExpression,
|
index: FieldRangeOrExpression,
|
||||||
) -> ResolvedValue {
|
) -> ResolvedValue {
|
||||||
match self.enforce_expression(cs, *array) {
|
match self.enforce_expression(cs, scope.clone(), *array) {
|
||||||
ResolvedValue::FieldElementArray(field_array) => {
|
ResolvedValue::FieldElementArray(field_array) => {
|
||||||
match index {
|
match index {
|
||||||
FieldRangeOrExpression::Range(from, to) => {
|
FieldRangeOrExpression::Range(from, to) => {
|
||||||
let from_resolved = match from {
|
let from_resolved = match from {
|
||||||
Some(from_index) => self.enforce_index(cs, from_index),
|
Some(from_index) => self.enforce_index(cs, scope.clone(), from_index),
|
||||||
None => 0usize, // Array slice starts at index 0
|
None => 0usize, // Array slice starts at index 0
|
||||||
};
|
};
|
||||||
let to_resolved = match to {
|
let to_resolved = match to {
|
||||||
Some(to_index) => self.enforce_index(cs, to_index),
|
Some(to_index) => self.enforce_index(cs, scope.clone(), to_index),
|
||||||
None => field_array.len(), // Array slice ends at array length
|
None => field_array.len(), // Array slice ends at array length
|
||||||
};
|
};
|
||||||
ResolvedValue::FieldElementArray(
|
ResolvedValue::FieldElementArray(
|
||||||
@ -505,7 +571,7 @@ impl ResolvedProgram {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
FieldRangeOrExpression::FieldExpression(index) => {
|
FieldRangeOrExpression::FieldExpression(index) => {
|
||||||
let index_resolved = self.enforce_index(cs, index);
|
let index_resolved = self.enforce_index(cs, scope.clone(), index);
|
||||||
ResolvedValue::FieldElement(field_array[index_resolved].to_owned())
|
ResolvedValue::FieldElement(field_array[index_resolved].to_owned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -514,11 +580,11 @@ impl ResolvedProgram {
|
|||||||
match index {
|
match index {
|
||||||
FieldRangeOrExpression::Range(from, to) => {
|
FieldRangeOrExpression::Range(from, to) => {
|
||||||
let from_resolved = match from {
|
let from_resolved = match from {
|
||||||
Some(from_index) => self.enforce_index(cs, from_index),
|
Some(from_index) => self.enforce_index(cs, scope.clone(), from_index),
|
||||||
None => 0usize, // Array slice starts at index 0
|
None => 0usize, // Array slice starts at index 0
|
||||||
};
|
};
|
||||||
let to_resolved = match to {
|
let to_resolved = match to {
|
||||||
Some(to_index) => self.enforce_index(cs, to_index),
|
Some(to_index) => self.enforce_index(cs, scope.clone(), to_index),
|
||||||
None => bool_array.len(), // Array slice ends at array length
|
None => bool_array.len(), // Array slice ends at array length
|
||||||
};
|
};
|
||||||
ResolvedValue::BooleanArray(
|
ResolvedValue::BooleanArray(
|
||||||
@ -526,7 +592,7 @@ impl ResolvedProgram {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
FieldRangeOrExpression::FieldExpression(index) => {
|
FieldRangeOrExpression::FieldExpression(index) => {
|
||||||
let index_resolved = self.enforce_index(cs, index);
|
let index_resolved = self.enforce_index(cs, scope.clone(), index);
|
||||||
ResolvedValue::Boolean(bool_array[index_resolved].to_owned())
|
ResolvedValue::Boolean(bool_array[index_resolved].to_owned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -538,16 +604,17 @@ impl ResolvedProgram {
|
|||||||
fn enforce_struct_access_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_struct_access_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
struct_variable: Box<Expression>,
|
struct_variable: Box<Expression>,
|
||||||
struct_member: Variable,
|
struct_member: Variable,
|
||||||
) -> ResolvedValue {
|
) -> ResolvedValue {
|
||||||
match self.enforce_expression(cs, *struct_variable) {
|
match self.enforce_expression(cs, scope.clone(), *struct_variable) {
|
||||||
ResolvedValue::StructExpression(_name, members) => {
|
ResolvedValue::StructExpression(_name, members) => {
|
||||||
let matched_member = members
|
let matched_member = members
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.find(|member| member.variable == struct_member);
|
.find(|member| member.variable == struct_member);
|
||||||
match matched_member {
|
match matched_member {
|
||||||
Some(member) => self.enforce_expression(cs, member.expression),
|
Some(member) => self.enforce_expression(cs, scope.clone(), member.expression),
|
||||||
None => unimplemented!("Cannot access struct member {}", struct_member.0),
|
None => unimplemented!("Cannot access struct member {}", struct_member.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -558,10 +625,11 @@ impl ResolvedProgram {
|
|||||||
fn enforce_function_access_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_function_access_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
function: Box<Expression>,
|
function: Box<Expression>,
|
||||||
arguments: Vec<Expression>,
|
arguments: Vec<Expression>,
|
||||||
) -> ResolvedValue {
|
) -> ResolvedValue {
|
||||||
match self.enforce_expression(cs, *function) {
|
match self.enforce_expression(cs, scope, *function) {
|
||||||
ResolvedValue::Function(function) => self.enforce_function(cs, function, arguments),
|
ResolvedValue::Function(function) => self.enforce_function(cs, function, arguments),
|
||||||
value => unimplemented!("Cannot call unknown function {}", value),
|
value => unimplemented!("Cannot call unknown function {}", value),
|
||||||
}
|
}
|
||||||
@ -570,22 +638,26 @@ impl ResolvedProgram {
|
|||||||
fn enforce_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_expression<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
) -> ResolvedValue {
|
) -> ResolvedValue {
|
||||||
match expression {
|
match expression {
|
||||||
Expression::Boolean(boolean_expression) => {
|
Expression::Boolean(boolean_expression) => {
|
||||||
self.enforce_boolean_expression(cs, boolean_expression)
|
self.enforce_boolean_expression(cs, scope, boolean_expression)
|
||||||
}
|
}
|
||||||
Expression::FieldElement(field_expression) => {
|
Expression::FieldElement(field_expression) => {
|
||||||
self.enforce_field_expression(cs, field_expression)
|
self.enforce_field_expression(cs, scope, field_expression)
|
||||||
}
|
}
|
||||||
Expression::Variable(unresolved_variable) => {
|
Expression::Variable(unresolved_variable) => {
|
||||||
if self.resolved_variables.contains_key(&unresolved_variable) {
|
let variable_name = new_scope_from_variable(scope, &unresolved_variable);
|
||||||
|
|
||||||
|
// Evaluate the variable name in the current function scope
|
||||||
|
if self.contains_name(&variable_name) {
|
||||||
// Reassigning variable to another variable
|
// Reassigning variable to another variable
|
||||||
self.resolved_variables
|
self.get_mut(&variable_name).unwrap().clone()
|
||||||
.get_mut(&unresolved_variable)
|
} else if self.contains_variable(&unresolved_variable) {
|
||||||
.unwrap()
|
// Check global scope (function and struct names)
|
||||||
.clone()
|
self.get_mut_variable(&unresolved_variable).unwrap().clone()
|
||||||
} else {
|
} else {
|
||||||
// The type of the unassigned variable depends on what is passed in
|
// The type of the unassigned variable depends on what is passed in
|
||||||
if std::env::args()
|
if std::env::args()
|
||||||
@ -594,23 +666,31 @@ impl ResolvedProgram {
|
|||||||
.parse::<bool>()
|
.parse::<bool>()
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
ResolvedValue::Boolean(self.bool_from_variable(cs, unresolved_variable))
|
ResolvedValue::Boolean(self.bool_from_variable(
|
||||||
|
cs,
|
||||||
|
variable_name,
|
||||||
|
unresolved_variable,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
ResolvedValue::FieldElement(self.u32_from_variable(cs, unresolved_variable))
|
ResolvedValue::FieldElement(self.u32_from_variable(
|
||||||
|
cs,
|
||||||
|
variable_name,
|
||||||
|
unresolved_variable,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::Struct(struct_name, members) => {
|
Expression::Struct(struct_name, members) => {
|
||||||
self.enforce_struct_expression(cs, struct_name, members)
|
self.enforce_struct_expression(cs, scope, struct_name, members)
|
||||||
}
|
}
|
||||||
Expression::ArrayAccess(array, index) => {
|
Expression::ArrayAccess(array, index) => {
|
||||||
self.enforce_array_access_expression(cs, array, index)
|
self.enforce_array_access_expression(cs, scope, array, index)
|
||||||
}
|
}
|
||||||
Expression::StructMemberAccess(struct_variable, struct_member) => {
|
Expression::StructMemberAccess(struct_variable, struct_member) => {
|
||||||
self.enforce_struct_access_expression(cs, struct_variable, struct_member)
|
self.enforce_struct_access_expression(cs, scope, struct_variable, struct_member)
|
||||||
}
|
}
|
||||||
Expression::FunctionCall(function, arguments) => {
|
Expression::FunctionCall(function, arguments) => {
|
||||||
self.enforce_function_access_expression(cs, function, arguments)
|
self.enforce_function_access_expression(cs, scope, function, arguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -618,23 +698,29 @@ impl ResolvedProgram {
|
|||||||
fn enforce_definition_statement<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_definition_statement<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
variable: Variable,
|
scope: String,
|
||||||
|
name: Variable,
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
) {
|
) {
|
||||||
let result = self.enforce_expression(cs, expression);
|
// Evaluate the expression in the current function scope
|
||||||
// println!(" statement result: {} = {}", variable.0, result);
|
let result = self.enforce_expression(cs, scope.clone(), expression);
|
||||||
self.insert(variable, result);
|
|
||||||
|
// Store the definition in the current scope
|
||||||
|
let definition_name = new_scope_from_variable(scope, &name);
|
||||||
|
|
||||||
|
self.store(definition_name, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enforce_return_statement<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_return_statement<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
statements: Vec<Expression>,
|
statements: Vec<Expression>,
|
||||||
) -> ResolvedValue {
|
) -> ResolvedValue {
|
||||||
ResolvedValue::Return(
|
ResolvedValue::Return(
|
||||||
statements
|
statements
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|expression| self.enforce_expression(cs, expression))
|
.map(|expression| self.enforce_expression(cs, scope.clone(), expression))
|
||||||
.collect::<Vec<ResolvedValue>>(),
|
.collect::<Vec<ResolvedValue>>(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -642,18 +728,19 @@ impl ResolvedProgram {
|
|||||||
fn enforce_statement<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_statement<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
statement: Statement,
|
statement: Statement,
|
||||||
) {
|
) {
|
||||||
match statement {
|
match statement {
|
||||||
Statement::Definition(variable, expression) => {
|
Statement::Definition(variable, expression) => {
|
||||||
self.enforce_definition_statement(cs, variable, expression);
|
self.enforce_definition_statement(cs, scope, variable, expression);
|
||||||
}
|
}
|
||||||
Statement::For(index, start, stop, statements) => {
|
Statement::For(index, start, stop, statements) => {
|
||||||
self.enforce_for_statement(cs, index, start, stop, statements);
|
self.enforce_for_statement(cs, scope, index, start, stop, statements);
|
||||||
}
|
}
|
||||||
Statement::Return(statements) => {
|
Statement::Return(statements) => {
|
||||||
// TODO: add support for early termination
|
// TODO: add support for early termination
|
||||||
let _res = self.enforce_return_statement(cs, statements);
|
let _res = self.enforce_return_statement(cs, scope, statements);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -661,18 +748,21 @@ impl ResolvedProgram {
|
|||||||
fn enforce_for_statement<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
fn enforce_for_statement<F: Field + PrimeField, CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
|
scope: String,
|
||||||
index: Variable,
|
index: Variable,
|
||||||
start: FieldExpression,
|
start: FieldExpression,
|
||||||
stop: FieldExpression,
|
stop: FieldExpression,
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
) {
|
) {
|
||||||
let start_index = self.enforce_index(cs, start);
|
let start_index = self.enforce_index(cs, scope.clone(), start);
|
||||||
let stop_index = self.enforce_index(cs, stop);
|
let stop_index = self.enforce_index(cs, scope.clone(), stop);
|
||||||
|
|
||||||
for i in start_index..stop_index {
|
for i in start_index..stop_index {
|
||||||
// Store index
|
// Store index in current function scope.
|
||||||
self.resolved_variables.insert(
|
// For loop scope is not implemented.
|
||||||
index.clone(),
|
let index_name = new_scope_from_variable(scope.clone(), &index);
|
||||||
|
self.store(
|
||||||
|
index_name,
|
||||||
ResolvedValue::FieldElement(UInt32::constant(i as u32)),
|
ResolvedValue::FieldElement(UInt32::constant(i as u32)),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -680,7 +770,7 @@ impl ResolvedProgram {
|
|||||||
statements
|
statements
|
||||||
.clone()
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|statement| self.enforce_statement(cs, statement));
|
.for_each(|statement| self.enforce_statement(cs, scope.clone(), statement));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -711,22 +801,22 @@ impl ResolvedProgram {
|
|||||||
// Check that argument is correct type
|
// Check that argument is correct type
|
||||||
match parameter.ty.clone() {
|
match parameter.ty.clone() {
|
||||||
Type::FieldElement => {
|
Type::FieldElement => {
|
||||||
match self.enforce_expression(cs, argument) {
|
match self.enforce_expression(cs, function.name(), argument) {
|
||||||
ResolvedValue::FieldElement(field) => {
|
ResolvedValue::FieldElement(field) => {
|
||||||
// Store argument as variable with parameter name
|
// Store argument as variable with {function_name}_{parameter name}
|
||||||
// TODO: this will not support multiple function calls or variables with same name as parameter
|
let variable_name =
|
||||||
self.resolved_variables.insert(
|
new_scope_from_variable(function.name(), ¶meter.variable);
|
||||||
parameter.variable.clone(),
|
self.store(variable_name, ResolvedValue::FieldElement(field));
|
||||||
ResolvedValue::FieldElement(field),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
argument => unimplemented!("expected field argument got {}", argument),
|
argument => unimplemented!("expected field argument got {}", argument),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Boolean => match self.enforce_expression(cs, argument) {
|
Type::Boolean => match self.enforce_expression(cs, function.name(), argument) {
|
||||||
ResolvedValue::Boolean(bool) => {
|
ResolvedValue::Boolean(bool) => {
|
||||||
self.resolved_variables
|
// Store argument as variable with {function_name}_{parameter name}
|
||||||
.insert(parameter.variable.clone(), ResolvedValue::Boolean(bool));
|
let variable_name =
|
||||||
|
new_scope_from_variable(function.name(), ¶meter.variable);
|
||||||
|
self.store(variable_name, ResolvedValue::Boolean(bool));
|
||||||
}
|
}
|
||||||
argument => unimplemented!("expected boolean argument got {}", argument),
|
argument => unimplemented!("expected boolean argument got {}", argument),
|
||||||
},
|
},
|
||||||
@ -744,13 +834,13 @@ impl ResolvedProgram {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|statement| match statement {
|
.for_each(|statement| match statement {
|
||||||
Statement::Definition(variable, expression) => {
|
Statement::Definition(variable, expression) => {
|
||||||
self.enforce_definition_statement(cs, variable, expression);
|
self.enforce_definition_statement(cs, function.name(), variable, expression);
|
||||||
}
|
}
|
||||||
Statement::For(index, start, stop, statements) => {
|
Statement::For(index, start, stop, statements) => {
|
||||||
self.enforce_for_statement(cs, index, start, stop, statements);
|
self.enforce_for_statement(cs, function.name(), index, start, stop, statements);
|
||||||
}
|
}
|
||||||
Statement::Return(expressions) => {
|
Statement::Return(expressions) => {
|
||||||
return_values = self.enforce_return_statement(cs, expressions)
|
return_values = self.enforce_return_statement(cs, function.name(), expressions)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -768,21 +858,17 @@ impl ResolvedProgram {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|(variable, struct_def)| {
|
.for_each(|(variable, struct_def)| {
|
||||||
resolved_program
|
resolved_program
|
||||||
.resolved_variables
|
.store_variable(variable, ResolvedValue::StructDefinition(struct_def));
|
||||||
.insert(variable, ResolvedValue::StructDefinition(struct_def));
|
|
||||||
});
|
});
|
||||||
program
|
program
|
||||||
.functions
|
.functions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|(function_name, function)| {
|
.for_each(|(function_name, function)| {
|
||||||
resolved_program
|
resolved_program.store(function_name.0, ResolvedValue::Function(function));
|
||||||
.resolved_variables
|
|
||||||
.insert(Variable(function_name.0), ResolvedValue::Function(function));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let main = resolved_program
|
let main = resolved_program
|
||||||
.resolved_variables
|
.get(&"main".into())
|
||||||
.get(&Variable("main".into()))
|
|
||||||
.expect("main function not defined");
|
.expect("main function not defined");
|
||||||
|
|
||||||
let result = match main.clone() {
|
let result = match main.clone() {
|
||||||
@ -792,20 +878,5 @@ impl ResolvedProgram {
|
|||||||
_ => unimplemented!("main must be a function"),
|
_ => unimplemented!("main must be a function"),
|
||||||
};
|
};
|
||||||
println!("\n {}", result);
|
println!("\n {}", result);
|
||||||
|
|
||||||
// program
|
|
||||||
// .statements
|
|
||||||
// .into_iter()
|
|
||||||
// .for_each(|statement| resolved_program.enforce_statement(cs, statement));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl Program {
|
|
||||||
// pub fn setup(&self) {
|
|
||||||
// self.statements
|
|
||||||
// .iter()
|
|
||||||
// .for_each(|statement| {
|
|
||||||
//
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
@ -158,15 +158,17 @@ pub struct Function {
|
|||||||
pub statements: Vec<Statement>,
|
pub statements: Vec<Statement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Function {
|
||||||
|
pub fn name(&self) -> String {
|
||||||
|
self.function_name.0.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A simple program with statement expressions, program arguments and program returns.
|
/// A simple program with statement expressions, program arguments and program returns.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Program {
|
pub struct Program {
|
||||||
pub id: String,
|
|
||||||
pub structs: HashMap<Variable, Struct>,
|
pub structs: HashMap<Variable, Struct>,
|
||||||
pub functions: HashMap<FunctionName, Function>,
|
pub functions: HashMap<FunctionName, Function>,
|
||||||
// pub statements: Vec<Statement>,
|
|
||||||
pub arguments: Vec<Variable>,
|
|
||||||
pub returns: Vec<Variable>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -730,12 +730,6 @@ impl<'ast> From<ast::File<'ast>> for types::Program {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
types::Program {
|
types::Program { structs, functions }
|
||||||
id: "main".into(),
|
|
||||||
structs,
|
|
||||||
functions,
|
|
||||||
arguments: vec![],
|
|
||||||
returns: vec![],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -812,7 +812,6 @@ pub struct Function<'ast> {
|
|||||||
pub struct File<'ast> {
|
pub struct File<'ast> {
|
||||||
pub structs: Vec<Struct<'ast>>,
|
pub structs: Vec<Struct<'ast>>,
|
||||||
pub functions: Vec<Function<'ast>>,
|
pub functions: Vec<Function<'ast>>,
|
||||||
pub statements: Vec<Statement<'ast>>,
|
|
||||||
pub eoi: EOI,
|
pub eoi: EOI,
|
||||||
#[pest_ast(outer())]
|
#[pest_ast(outer())]
|
||||||
pub span: Span<'ast>,
|
pub span: Span<'ast>,
|
||||||
|
@ -161,4 +161,4 @@ WHITESPACE = _{ " " | "\t" ~ (NEWLINE)* }
|
|||||||
|
|
||||||
/// Abstract Syntax Tree File
|
/// Abstract Syntax Tree File
|
||||||
|
|
||||||
file = { SOI ~ NEWLINE* ~ struct_definition* ~ NEWLINE* ~ function_definition* ~ NEWLINE* ~ statement* ~ NEWLINE* ~ EOI }
|
file = { SOI ~ NEWLINE* ~ struct_definition* ~ NEWLINE* ~ function_definition* ~ NEWLINE* ~ EOI }
|
||||||
|
Loading…
Reference in New Issue
Block a user