From 90658f362de0fd534e37d9c9da11660c0ba9e0bb Mon Sep 17 00:00:00 2001 From: collin Date: Thu, 30 Apr 2020 10:27:13 -0700 Subject: [PATCH] impl operator assign statements --- benchmark/simple.leo | 12 +++---- compiler/src/ast.rs | 49 ++++++++++++++++++++------ compiler/src/leo.pest | 29 ++++++++------- compiler/src/types.rs | 2 +- compiler/src/types_from.rs | 72 +++++++++++++++++++++++++++++++++++--- 5 files changed, 128 insertions(+), 36 deletions(-) diff --git a/benchmark/simple.leo b/benchmark/simple.leo index 29af0ca2aa..54945d6b66 100644 --- a/benchmark/simple.leo +++ b/benchmark/simple.leo @@ -1,9 +1,5 @@ -function test() -> (u32, u32[2]) { - return 1, [2, 3] -} - -function main() -> (u32[3]) { - a, b = test(); - // a, u32[2] b = test() <- explicit type also works - return [a, ...b] +function main() -> (u32) { + a = 2; + a /= 3; + return a } \ No newline at end of file diff --git a/compiler/src/ast.rs b/compiler/src/ast.rs index f59e50675b..6406f27d66 100644 --- a/compiler/src/ast.rs +++ b/compiler/src/ast.rs @@ -512,7 +512,6 @@ pub struct NotExpression<'ast> { // #[pest_ast(rule(Rule::expression_increment))] // pub struct IncrementExpression<'ast> { // pub expression: Box>, -// pub operation: Increment<'ast>, // #[pest_ast(outer())] // pub span: Span<'ast>, // } @@ -521,7 +520,6 @@ pub struct NotExpression<'ast> { // #[pest_ast(rule(Rule::expression_decrement))] // pub struct DecrementExpression<'ast> { // pub expression: Box>, -// pub operation: Decrement<'ast>, // #[pest_ast(outer())] // pub span: Span<'ast>, // } @@ -700,25 +698,25 @@ fn parse_term(pair: Pair) -> Box { }, // Rule::expression_increment => { // println!("expression increment"); - // // let span = next.as_span(); - // // let mut inner = next.into_inner(); - // // let expression = parse_term(inner.next().unwrap()); + // let span = next.as_span(); + // let mut inner = next.into_inner(); + // let expression = parse_term(inner.next().unwrap()); // // let operation = match inner.next().unwrap().as_rule() { // // Rule::operation_post_increment => Increment::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(), // // rule => unreachable!("`expression_increment` should yield `operation_post_increment`, found {:#?}", rule) // // }; - // // Expression::Increment(IncrementExpression { operation, expression, span }) + // Expression::Increment(IncrementExpression { expression, span }) // }, // Rule::expression_decrement => { // println!("expression decrement"); - // // let span = next.as_span(); - // // let mut inner = next.into_inner(); - // // let expression = parse_term(inner.next().unwrap()); + // let span = next.as_span(); + // let mut inner = next.into_inner(); + // let expression = parse_term(inner.next().unwrap()); // // let operation = match inner.next().unwrap().as_rule() { // // Rule::operation_post_decrement => Decrement::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(), // // rule => unreachable!("`expression_decrement` should yield `operation_post_decrement`, found {:#?}", rule) // // }; - // // Expression::Decrement(DecrementExpression { operation, expression, span }) + // Expression::Decrement(DecrementExpression { expression, span }) // }, Rule::expression_postfix => { Expression::Postfix( @@ -853,10 +851,41 @@ pub struct DefinitionStatement<'ast> { pub span: Span<'ast>, } +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::assign))] +pub struct Assign {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::operation_add_assign))] +pub struct AddAssign {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::operation_sub_assign))] +pub struct SubAssign {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::operation_mul_assign))] +pub struct MulAssign {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::operation_div_assign))] +pub struct DivAssign {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::operation_assign))] +pub enum OperationAssign { + Assign(Assign), + AddAssign(AddAssign), + SubAssign(SubAssign), + MulAssign(MulAssign), + DivAssign(DivAssign), +} + #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::statement_assign))] pub struct AssignStatement<'ast> { pub assignee: Assignee<'ast>, + pub assign: OperationAssign, pub expression: Expression<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, diff --git a/compiler/src/leo.pest b/compiler/src/leo.pest index 752e244fec..4409bca335 100644 --- a/compiler/src/leo.pest +++ b/compiler/src/leo.pest @@ -9,11 +9,9 @@ visibility = { visibility_public | visibility_private } operation_pre_not = { "!" } expression_not = { operation_pre_not ~ expression_term } -// operation_post_increment = { "++" } -// expression_increment = { operation_post_increment ~ expression_term } +// expression_increment = { expression+ ~ "++" } // -// operation_post_decrement = { "--" } -// expression_decrement = { operation_post_decrement ~ expression_term } +// expression_decrement = { expression ~ "--" } /// Binary Operations @@ -34,17 +32,24 @@ operation_mul = { "*" } operation_div = { "/" } operation_pow = { "**" } -operation_binary = _ { +operation_binary = _{ operation_and | operation_or | operation_eq | operation_neq | operation_geq | operation_gt | operation_leq | operation_lt | operation_add | operation_sub | operation_pow | operation_mul | operation_div } -// operation_add_assign = { "+=" } -// operation_sub_assign = { "-=" } -// operation_mul_assign = { "*=" } -// operation_div_assign = { "/=" } +assign = { "=" } +operation_add_assign = { "+=" } +operation_sub_assign = { "-=" } +operation_mul_assign = { "*=" } +operation_div_assign = { "/=" } + +operation_assign = { + assign + | operation_add_assign | operation_sub_assign + | operation_mul_assign | operation_div_assign +} /// Types @@ -60,7 +65,7 @@ type_list = _{(ty ~ ("," ~ ty)*)?} /// Values -value_number = @{ "-"? ~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*)} +value_number = @{ "0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT* } value_u32 = { value_number ~ ty_u32? } value_field = { value_number ~ ty_field } value_boolean = { "true" | "false" } @@ -145,7 +150,7 @@ expression_tuple = _{ (expression ~ ("," ~ expression)*)? } // statement_one_or_more = { (statement ~ NEWLINE*)* } statement_return = { "return" ~ expression_tuple } statement_definition = { ty ~ variable ~ "=" ~ expression } -statement_assign = { assignee ~ "=" ~ expression } +statement_assign = { assignee ~ operation_assign ~ expression } statement_multiple_assignment = { optionally_typed_variable_tuple ~ "=" ~ variable ~ "(" ~ expression_tuple ~ ")" } statement_conditional = {"if" ~ "(" ~ expression ~ ")" ~ "{" ~ NEWLINE* ~ statement+ ~ "}" ~ ("else" ~ conditional_nested_or_end)?} conditional_nested_or_end = { statement_conditional | "{" ~ NEWLINE* ~ statement+ ~ "}"} @@ -183,8 +188,6 @@ import_symbol = { variable ~ ("as" ~ variable)? } import_symbol_tuple = _{ import_symbol ~ ("," ~ NEWLINE* ~ import_symbol)* } import = { "from" ~ "\"" ~ import_source ~ "\"" ~ "import" ~ ("*" | ("{" ~ NEWLINE* ~ import_symbol_tuple ~ NEWLINE* ~ "}")) ~ LINE_END} -// import = { main_import | from_import } -// main_import = {"import" ~ "\"" ~ import_source ~ "\"" ~ ("as" ~ variable)? ~ NEWLINE+} /// Program File diff --git a/compiler/src/types.rs b/compiler/src/types.rs index 53095f72bc..c65c36fd38 100644 --- a/compiler/src/types.rs +++ b/compiler/src/types.rs @@ -79,7 +79,7 @@ pub enum Expression { // Arrays Array(Vec>>), - ArrayAccess(Box>, Box>), + ArrayAccess(Box>, Box>), // (array name, range) // Structs Struct(Variable, Vec>), diff --git a/compiler/src/types_from.rs b/compiler/src/types_from.rs index 7813960a66..2ed957757f 100644 --- a/compiler/src/types_from.rs +++ b/compiler/src/types_from.rs @@ -303,6 +303,30 @@ impl<'ast, F: Field + PrimeField> types::Expression { } } +// ast::Assignee -> types::Expression for operator assign statements +impl<'ast, F: Field + PrimeField> From> for types::Expression { + fn from(assignee: ast::Assignee<'ast>) -> Self { + let variable = types::Expression::Variable(types::Variable::from(assignee.variable)); + + // we start with the id, and we fold the array of accesses by wrapping the current value + assignee + .accesses + .into_iter() + .fold(variable, |acc, access| match access { + ast::AssigneeAccess::Member(struct_member) => { + types::Expression::StructMemberAccess( + Box::new(acc), + types::Variable::from(struct_member.variable), + ) + } + ast::AssigneeAccess::Array(array) => types::Expression::ArrayAccess( + Box::new(acc), + Box::new(types::RangeOrExpression::from(array.expression)), + ), + }) + } +} + /// pest ast -> types::Assignee impl<'ast, F: Field + PrimeField> From> for types::Assignee { @@ -358,10 +382,50 @@ impl<'ast, F: Field + PrimeField> From> for types impl<'ast, F: Field + PrimeField> From> for types::Statement { fn from(statement: ast::AssignStatement<'ast>) -> Self { - types::Statement::Assign( - types::Assignee::from(statement.assignee), - types::Expression::from(statement.expression), - ) + match statement.assign { + ast::OperationAssign::Assign(ref _assign) => types::Statement::Assign( + types::Assignee::from(statement.assignee), + types::Expression::from(statement.expression), + ), + operation_assign => { + // convert assignee into postfix expression + let converted = types::Expression::from(statement.assignee.clone()); + + match operation_assign { + ast::OperationAssign::AddAssign(ref _assign) => types::Statement::Assign( + types::Assignee::from(statement.assignee), + types::Expression::Add( + Box::new(converted), + Box::new(types::Expression::from(statement.expression)), + ), + ), + ast::OperationAssign::SubAssign(ref _assign) => types::Statement::Assign( + types::Assignee::from(statement.assignee), + types::Expression::Sub( + Box::new(converted), + Box::new(types::Expression::from(statement.expression)), + ), + ), + ast::OperationAssign::MulAssign(ref _assign) => types::Statement::Assign( + types::Assignee::from(statement.assignee), + types::Expression::Mul( + Box::new(converted), + Box::new(types::Expression::from(statement.expression)), + ), + ), + ast::OperationAssign::DivAssign(ref _assign) => types::Statement::Assign( + types::Assignee::from(statement.assignee), + types::Expression::Div( + Box::new(converted), + Box::new(types::Expression::from(statement.expression)), + ), + ), + ast::OperationAssign::Assign(ref _assign) => { + unimplemented!("cannot assign twice to assign statement") + } + } + } + } } }