impl operator assign statements

This commit is contained in:
collin 2020-04-30 10:27:13 -07:00
parent 48ab4747e0
commit 90658f362d
5 changed files with 128 additions and 36 deletions

View File

@ -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
}

View File

@ -512,7 +512,6 @@ pub struct NotExpression<'ast> {
// #[pest_ast(rule(Rule::expression_increment))]
// pub struct IncrementExpression<'ast> {
// pub expression: Box<Expression<'ast>>,
// 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<Expression<'ast>>,
// pub operation: Decrement<'ast>,
// #[pest_ast(outer())]
// pub span: Span<'ast>,
// }
@ -700,25 +698,25 @@ fn parse_term(pair: Pair<Rule>) -> Box<Expression> {
},
// 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>,

View File

@ -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

View File

@ -79,7 +79,7 @@ pub enum Expression<F: Field + PrimeField> {
// Arrays
Array(Vec<Box<SpreadOrExpression<F>>>),
ArrayAccess(Box<Expression<F>>, Box<RangeOrExpression<F>>),
ArrayAccess(Box<Expression<F>>, Box<RangeOrExpression<F>>), // (array name, range)
// Structs
Struct(Variable<F>, Vec<StructMember<F>>),

View File

@ -303,6 +303,30 @@ impl<'ast, F: Field + PrimeField> types::Expression<F> {
}
}
// ast::Assignee -> types::Expression for operator assign statements
impl<'ast, F: Field + PrimeField> From<ast::Assignee<'ast>> for types::Expression<F> {
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<ast::Variable<'ast>> for types::Assignee<F> {
@ -358,10 +382,50 @@ impl<'ast, F: Field + PrimeField> From<ast::DefinitionStatement<'ast>> for types
impl<'ast, F: Field + PrimeField> From<ast::AssignStatement<'ast>> for types::Statement<F> {
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")
}
}
}
}
}
}