From 6b6bce38cb72eff604eac3a24d725c58d17f33ba Mon Sep 17 00:00:00 2001 From: collin Date: Thu, 16 Apr 2020 15:15:13 -0700 Subject: [PATCH] impl function scope --- simple.program | 12 +- src/aleo_program/constraints.rs | 337 +++++++++++++++++++------------- src/aleo_program/types.rs | 10 +- src/aleo_program/types_from.rs | 8 +- src/ast.rs | 1 - src/language.pest | 2 +- 6 files changed, 218 insertions(+), 152 deletions(-) diff --git a/simple.program b/simple.program index ab2b0dfdbd..dd5f5ba1e8 100644 --- a/simple.program +++ b/simple.program @@ -1,6 +1,6 @@ -def main() -> (field): - a = 1 - for i in 0..4 do - a = a + 1 - endfor - return a \ No newline at end of file +struct Foo { + bool x +} +def main() -> (bool): + Foo f = Foo {x: true} + return f.x diff --git a/src/aleo_program/constraints.rs b/src/aleo_program/constraints.rs index 932415cca4..6fdbb8ac66 100644 --- a/src/aleo_program/constraints.rs +++ b/src/aleo_program/constraints.rs @@ -70,34 +70,76 @@ impl fmt::Display for ResolvedValue { } 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 resolved_variables: HashMap, + pub resolved_names: HashMap, +} + +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 { fn new() -> Self { Self { - resolved_variables: HashMap::new(), + resolved_names: HashMap::new(), } } - fn insert(&mut self, variable: Variable, value: ResolvedValue) { - self.resolved_variables.insert(variable, value); + fn store(&mut self, name: String, value: ResolvedValue) { + 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>( &mut self, cs: &mut CS, + scope: String, variable: Variable, ) -> 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 - match self.resolved_variables.get(&variable).unwrap() { + match self.get(&variable_name).unwrap() { ResolvedValue::Boolean(boolean) => boolean.clone(), _ => panic!("expected a boolean, got field"), } @@ -116,11 +158,15 @@ impl ResolvedProgram { fn u32_from_variable>( &mut self, cs: &mut CS, + scope: String, variable: Variable, ) -> 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 - match self.resolved_variables.get(&variable).unwrap() { + match self.get(&variable_name).unwrap() { ResolvedValue::FieldElement(field) => field.clone(), _ => panic!("expected a field, got boolean"), } @@ -141,12 +187,13 @@ impl ResolvedProgram { fn get_bool_value>( &mut self, cs: &mut CS, + scope: String, expression: BooleanExpression, ) -> Boolean { 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), - expression => match self.enforce_boolean_expression(cs, expression) { + expression => match self.enforce_boolean_expression(cs, scope, expression) { ResolvedValue::Boolean(value) => value, _ => unimplemented!("boolean expression did not resolve to boolean"), }, @@ -156,12 +203,13 @@ impl ResolvedProgram { fn get_u32_value>( &mut self, cs: &mut CS, + scope: String, expression: FieldExpression, ) -> UInt32 { 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), - field => match self.enforce_field_expression(cs, field) { + field => match self.enforce_field_expression(cs, scope, field) { ResolvedValue::FieldElement(value) => value, _ => unimplemented!("field expression did not resolve to field"), }, @@ -171,9 +219,10 @@ impl ResolvedProgram { fn enforce_not>( &mut self, cs: &mut CS, + scope: String, expression: BooleanExpression, ) -> Boolean { - let expression = self.get_bool_value(cs, expression); + let expression = self.get_bool_value(cs, scope, expression); expression.not() } @@ -181,11 +230,12 @@ impl ResolvedProgram { fn enforce_or>( &mut self, cs: &mut CS, + scope: String, left: BooleanExpression, right: BooleanExpression, ) -> Boolean { - let left = self.get_bool_value(cs, left); - let right = self.get_bool_value(cs, right); + let left = self.get_bool_value(cs, scope.clone(), left); + let right = self.get_bool_value(cs, scope.clone(), right); Boolean::or(cs, &left, &right).unwrap() } @@ -193,11 +243,12 @@ impl ResolvedProgram { fn enforce_and>( &mut self, cs: &mut CS, + scope: String, left: BooleanExpression, right: BooleanExpression, ) -> Boolean { - let left = self.get_bool_value(cs, left); - let right = self.get_bool_value(cs, right); + let left = self.get_bool_value(cs, scope.clone(), left); + let right = self.get_bool_value(cs, scope.clone(), right); Boolean::and(cs, &left, &right).unwrap() } @@ -205,11 +256,12 @@ impl ResolvedProgram { fn enforce_bool_equality>( &mut self, cs: &mut CS, + scope: String, left: BooleanExpression, right: BooleanExpression, ) -> Boolean { - let left = self.get_bool_value(cs, left); - let right = self.get_bool_value(cs, right); + let left = self.get_bool_value(cs, scope.clone(), left); + let right = self.get_bool_value(cs, scope.clone(), right); left.enforce_equal(cs.ns(|| format!("enforce bool equal")), &right) .unwrap(); @@ -220,11 +272,12 @@ impl ResolvedProgram { fn enforce_field_equality>( &mut self, cs: &mut CS, + scope: String, left: FieldExpression, right: FieldExpression, ) -> Boolean { - let left = self.get_u32_value(cs, left); - let right = self.get_u32_value(cs, right); + let left = self.get_u32_value(cs, scope.clone(), left); + let right = self.get_u32_value(cs, scope.clone(), right); left.conditional_enforce_equal( cs.ns(|| format!("enforce field equal")), @@ -239,37 +292,39 @@ impl ResolvedProgram { fn enforce_boolean_expression>( &mut self, cs: &mut CS, + scope: String, expression: BooleanExpression, ) -> ResolvedValue { match expression { 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::Not(expression) => { - ResolvedValue::Boolean(self.enforce_not(cs, *expression)) + ResolvedValue::Boolean(self.enforce_not(cs, scope, *expression)) } 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) => { - ResolvedValue::Boolean(self.enforce_and(cs, *left, *right)) + ResolvedValue::Boolean(self.enforce_and(cs, scope, *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) => { - ResolvedValue::Boolean(self.enforce_field_equality(cs, *left, *right)) + ResolvedValue::Boolean(self.enforce_field_equality(cs, scope, *left, *right)) } BooleanExpression::IfElse(first, second, third) => { - let resolved_first = match self.enforce_boolean_expression(cs, *first) { - ResolvedValue::Boolean(resolved) => resolved, - _ => unimplemented!("if else conditional must resolve to boolean"), - }; + let resolved_first = + match self.enforce_boolean_expression(cs, scope.clone(), *first) { + ResolvedValue::Boolean(resolved) => resolved, + _ => unimplemented!("if else conditional must resolve to boolean"), + }; if resolved_first.eq(&Boolean::Constant(true)) { - self.enforce_boolean_expression(cs, *second) + self.enforce_boolean_expression(cs, scope, *second) } else { - self.enforce_boolean_expression(cs, *third) + self.enforce_boolean_expression(cs, scope, *third) } } BooleanExpression::Array(array) => ResolvedValue::BooleanArray( @@ -280,7 +335,7 @@ impl ResolvedProgram { unimplemented!("spreads not enforced yet") } BooleanSpreadOrExpression::BooleanExpression(expression) => { - match self.enforce_boolean_expression(cs, expression) { + match self.enforce_boolean_expression(cs, scope.clone(), expression) { ResolvedValue::Boolean(value) => value, _ => unimplemented!("cannot resolve boolean"), } @@ -295,11 +350,12 @@ impl ResolvedProgram { fn enforce_add>( &mut self, cs: &mut CS, + scope: String, left: FieldExpression, right: FieldExpression, ) -> UInt32 { - let left = self.get_u32_value(cs, left); - let right = self.get_u32_value(cs, right); + let left = self.get_u32_value(cs, scope.clone(), left); + let right = self.get_u32_value(cs, scope.clone(), right); UInt32::addmany( cs.ns(|| format!("enforce {} + {}", left.value.unwrap(), right.value.unwrap())), @@ -311,11 +367,12 @@ impl ResolvedProgram { fn enforce_sub>( &mut self, cs: &mut CS, + scope: String, left: FieldExpression, right: FieldExpression, ) -> UInt32 { - let left = self.get_u32_value(cs, left); - let right = self.get_u32_value(cs, right); + let left = self.get_u32_value(cs, scope.clone(), left); + let right = self.get_u32_value(cs, scope.clone(), right); left.sub( cs.ns(|| format!("enforce {} - {}", left.value.unwrap(), right.value.unwrap())), @@ -327,11 +384,12 @@ impl ResolvedProgram { fn enforce_mul>( &mut self, cs: &mut CS, + scope: String, left: FieldExpression, right: FieldExpression, ) -> UInt32 { - let left = self.get_u32_value(cs, left); - let right = self.get_u32_value(cs, right); + let left = self.get_u32_value(cs, scope.clone(), left); + let right = self.get_u32_value(cs, scope.clone(), right); let res = left .mul( @@ -346,11 +404,12 @@ impl ResolvedProgram { fn enforce_div>( &mut self, cs: &mut CS, + scope: String, left: FieldExpression, right: FieldExpression, ) -> UInt32 { - let left = self.get_u32_value(cs, left); - let right = self.get_u32_value(cs, right); + let left = self.get_u32_value(cs, scope.clone(), left); + let right = self.get_u32_value(cs, scope.clone(), right); left.div( cs.ns(|| format!("enforce {} / {}", left.value.unwrap(), right.value.unwrap())), @@ -362,11 +421,12 @@ impl ResolvedProgram { fn enforce_pow>( &mut self, cs: &mut CS, + scope: String, left: FieldExpression, right: FieldExpression, ) -> UInt32 { - let left = self.get_u32_value(cs, left); - let right = self.get_u32_value(cs, right); + let left = self.get_u32_value(cs, scope.clone(), left); + let right = self.get_u32_value(cs, scope.clone(), right); left.pow( cs.ns(|| { @@ -384,40 +444,42 @@ impl ResolvedProgram { fn enforce_field_expression>( &mut self, cs: &mut CS, + scope: String, expression: FieldExpression, ) -> ResolvedValue { match expression { FieldExpression::Variable(variable) => { - ResolvedValue::FieldElement(self.u32_from_variable(cs, variable)) + ResolvedValue::FieldElement(self.u32_from_variable(cs, scope, variable)) } FieldExpression::Number(number) => { ResolvedValue::FieldElement(UInt32::constant(number)) } 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) => { - ResolvedValue::FieldElement(self.enforce_sub(cs, *left, *right)) + ResolvedValue::FieldElement(self.enforce_sub(cs, scope, *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) => { - ResolvedValue::FieldElement(self.enforce_div(cs, *left, *right)) + ResolvedValue::FieldElement(self.enforce_div(cs, scope, *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) => { - let resolved_first = match self.enforce_boolean_expression(cs, *first) { - ResolvedValue::Boolean(resolved) => resolved, - _ => unimplemented!("if else conditional must resolve to boolean"), - }; + let resolved_first = + match self.enforce_boolean_expression(cs, scope.clone(), *first) { + ResolvedValue::Boolean(resolved) => resolved, + _ => unimplemented!("if else conditional must resolve to boolean"), + }; if resolved_first.eq(&Boolean::Constant(true)) { - self.enforce_field_expression(cs, *second) + self.enforce_field_expression(cs, scope, *second) } else { - self.enforce_field_expression(cs, *third) + self.enforce_field_expression(cs, scope, *third) } } FieldExpression::Array(array) => ResolvedValue::FieldElementArray( @@ -428,7 +490,7 @@ impl ResolvedProgram { unimplemented!("spreads not enforced yet") } FieldSpreadOrExpression::FieldExpression(expression) => { - match self.enforce_field_expression(cs, expression) { + match self.enforce_field_expression(cs, scope.clone(), expression) { ResolvedValue::FieldElement(value) => value, _ => unimplemented!("cannot resolve field"), } @@ -442,10 +504,11 @@ impl ResolvedProgram { fn enforce_struct_expression>( &mut self, cs: &mut CS, + scope: String, variable: Variable, members: Vec, ) -> 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 { ResolvedValue::StructDefinition(struct_definition) => { struct_definition @@ -459,7 +522,8 @@ impl ResolvedProgram { } // Resolve and possibly enforce struct fields // 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) @@ -474,9 +538,10 @@ impl ResolvedProgram { fn enforce_index>( &mut self, cs: &mut CS, + scope: String, index: FieldExpression, ) -> 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, value => unimplemented!("From index must resolve to a uint32, got {}", value), } @@ -485,19 +550,20 @@ impl ResolvedProgram { fn enforce_array_access_expression>( &mut self, cs: &mut CS, + scope: String, array: Box, index: FieldRangeOrExpression, ) -> ResolvedValue { - match self.enforce_expression(cs, *array) { + match self.enforce_expression(cs, scope.clone(), *array) { ResolvedValue::FieldElementArray(field_array) => { match index { FieldRangeOrExpression::Range(from, to) => { 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 }; 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 }; ResolvedValue::FieldElementArray( @@ -505,7 +571,7 @@ impl ResolvedProgram { ) } 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()) } } @@ -514,11 +580,11 @@ impl ResolvedProgram { match index { FieldRangeOrExpression::Range(from, to) => { 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 }; 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 }; ResolvedValue::BooleanArray( @@ -526,7 +592,7 @@ impl ResolvedProgram { ) } 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()) } } @@ -538,16 +604,17 @@ impl ResolvedProgram { fn enforce_struct_access_expression>( &mut self, cs: &mut CS, + scope: String, struct_variable: Box, struct_member: Variable, ) -> ResolvedValue { - match self.enforce_expression(cs, *struct_variable) { + match self.enforce_expression(cs, scope.clone(), *struct_variable) { ResolvedValue::StructExpression(_name, members) => { let matched_member = members .into_iter() .find(|member| member.variable == struct_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), } } @@ -558,10 +625,11 @@ impl ResolvedProgram { fn enforce_function_access_expression>( &mut self, cs: &mut CS, + scope: String, function: Box, arguments: Vec, ) -> ResolvedValue { - match self.enforce_expression(cs, *function) { + match self.enforce_expression(cs, scope, *function) { ResolvedValue::Function(function) => self.enforce_function(cs, function, arguments), value => unimplemented!("Cannot call unknown function {}", value), } @@ -570,22 +638,26 @@ impl ResolvedProgram { fn enforce_expression>( &mut self, cs: &mut CS, + scope: String, expression: Expression, ) -> ResolvedValue { match expression { Expression::Boolean(boolean_expression) => { - self.enforce_boolean_expression(cs, boolean_expression) + self.enforce_boolean_expression(cs, scope, boolean_expression) } Expression::FieldElement(field_expression) => { - self.enforce_field_expression(cs, field_expression) + self.enforce_field_expression(cs, scope, field_expression) } 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 - self.resolved_variables - .get_mut(&unresolved_variable) - .unwrap() - .clone() + self.get_mut(&variable_name).unwrap().clone() + } else if self.contains_variable(&unresolved_variable) { + // Check global scope (function and struct names) + self.get_mut_variable(&unresolved_variable).unwrap().clone() } else { // The type of the unassigned variable depends on what is passed in if std::env::args() @@ -594,23 +666,31 @@ impl ResolvedProgram { .parse::() .is_ok() { - ResolvedValue::Boolean(self.bool_from_variable(cs, unresolved_variable)) + ResolvedValue::Boolean(self.bool_from_variable( + cs, + variable_name, + unresolved_variable, + )) } 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) => { - self.enforce_struct_expression(cs, struct_name, members) + self.enforce_struct_expression(cs, scope, struct_name, members) } 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) => { - 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) => { - 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>( &mut self, cs: &mut CS, - variable: Variable, + scope: String, + name: Variable, expression: Expression, ) { - let result = self.enforce_expression(cs, expression); - // println!(" statement result: {} = {}", variable.0, result); - self.insert(variable, result); + // Evaluate the expression in the current function scope + let result = self.enforce_expression(cs, scope.clone(), expression); + + // 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>( &mut self, cs: &mut CS, + scope: String, statements: Vec, ) -> ResolvedValue { ResolvedValue::Return( statements .into_iter() - .map(|expression| self.enforce_expression(cs, expression)) + .map(|expression| self.enforce_expression(cs, scope.clone(), expression)) .collect::>(), ) } @@ -642,18 +728,19 @@ impl ResolvedProgram { fn enforce_statement>( &mut self, cs: &mut CS, + scope: String, statement: Statement, ) { match statement { 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) => { - self.enforce_for_statement(cs, index, start, stop, statements); + self.enforce_for_statement(cs, scope, index, start, stop, statements); } Statement::Return(statements) => { // 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>( &mut self, cs: &mut CS, + scope: String, index: Variable, start: FieldExpression, stop: FieldExpression, statements: Vec, ) { - let start_index = self.enforce_index(cs, start); - let stop_index = self.enforce_index(cs, stop); + let start_index = self.enforce_index(cs, scope.clone(), start); + let stop_index = self.enforce_index(cs, scope.clone(), stop); for i in start_index..stop_index { - // Store index - self.resolved_variables.insert( - index.clone(), + // Store index in current function scope. + // For loop scope is not implemented. + let index_name = new_scope_from_variable(scope.clone(), &index); + self.store( + index_name, ResolvedValue::FieldElement(UInt32::constant(i as u32)), ); @@ -680,7 +770,7 @@ impl ResolvedProgram { statements .clone() .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 match parameter.ty.clone() { Type::FieldElement => { - match self.enforce_expression(cs, argument) { + match self.enforce_expression(cs, function.name(), argument) { ResolvedValue::FieldElement(field) => { - // Store argument as variable with parameter name - // TODO: this will not support multiple function calls or variables with same name as parameter - self.resolved_variables.insert( - parameter.variable.clone(), - ResolvedValue::FieldElement(field), - ); + // Store argument as variable with {function_name}_{parameter name} + let variable_name = + new_scope_from_variable(function.name(), ¶meter.variable); + self.store(variable_name, ResolvedValue::FieldElement(field)); } 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) => { - self.resolved_variables - .insert(parameter.variable.clone(), ResolvedValue::Boolean(bool)); + // Store argument as variable with {function_name}_{parameter name} + 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), }, @@ -744,13 +834,13 @@ impl ResolvedProgram { .into_iter() .for_each(|statement| match statement { 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) => { - self.enforce_for_statement(cs, index, start, stop, statements); + self.enforce_for_statement(cs, function.name(), index, start, stop, statements); } 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() .for_each(|(variable, struct_def)| { resolved_program - .resolved_variables - .insert(variable, ResolvedValue::StructDefinition(struct_def)); + .store_variable(variable, ResolvedValue::StructDefinition(struct_def)); }); program .functions .into_iter() .for_each(|(function_name, function)| { - resolved_program - .resolved_variables - .insert(Variable(function_name.0), ResolvedValue::Function(function)); + resolved_program.store(function_name.0, ResolvedValue::Function(function)); }); let main = resolved_program - .resolved_variables - .get(&Variable("main".into())) + .get(&"main".into()) .expect("main function not defined"); let result = match main.clone() { @@ -792,20 +878,5 @@ impl ResolvedProgram { _ => unimplemented!("main must be a function"), }; 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| { -// -// }) -// } -// } diff --git a/src/aleo_program/types.rs b/src/aleo_program/types.rs index bf53e71904..cc2e779bf7 100644 --- a/src/aleo_program/types.rs +++ b/src/aleo_program/types.rs @@ -158,15 +158,17 @@ pub struct Function { pub statements: Vec, } +impl Function { + pub fn name(&self) -> String { + self.function_name.0.clone() + } +} + /// A simple program with statement expressions, program arguments and program returns. #[derive(Debug, Clone)] pub struct Program { - pub id: String, pub structs: HashMap, pub functions: HashMap, - // pub statements: Vec, - pub arguments: Vec, - pub returns: Vec, } #[cfg(test)] diff --git a/src/aleo_program/types_from.rs b/src/aleo_program/types_from.rs index 17a9d4f259..68c143d85b 100644 --- a/src/aleo_program/types_from.rs +++ b/src/aleo_program/types_from.rs @@ -730,12 +730,6 @@ impl<'ast> From> for types::Program { ); }); - types::Program { - id: "main".into(), - structs, - functions, - arguments: vec![], - returns: vec![], - } + types::Program { structs, functions } } } diff --git a/src/ast.rs b/src/ast.rs index 79b070fa6a..19d8bd13c3 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -812,7 +812,6 @@ pub struct Function<'ast> { pub struct File<'ast> { pub structs: Vec>, pub functions: Vec>, - pub statements: Vec>, pub eoi: EOI, #[pest_ast(outer())] pub span: Span<'ast>, diff --git a/src/language.pest b/src/language.pest index 83ec815dc8..0e74e7c159 100644 --- a/src/language.pest +++ b/src/language.pest @@ -161,4 +161,4 @@ WHITESPACE = _{ " " | "\t" ~ (NEWLINE)* } /// 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 }