update parser and ast to be stricter, fix conversion to absy, wip
This commit is contained in:
parent
6e1ce97162
commit
e2878f19a3
6 changed files with 94 additions and 59 deletions
11
zokrates_cli/examples/assign_to_element.zok
Normal file
11
zokrates_cli/examples/assign_to_element.zok
Normal file
|
@ -0,0 +1,11 @@
|
|||
// def foo() -> u32:
|
||||
// return 0
|
||||
|
||||
def bar() -> (u32, u32):
|
||||
return 0, 0
|
||||
|
||||
|
||||
def main(u32[1] a, u32 b):
|
||||
//a[0] = foo()
|
||||
a[0], b = bar()
|
||||
return
|
|
@ -239,54 +239,69 @@ fn statements_from_definition(definition: pest::DefinitionStatement) -> Vec<absy
|
|||
|
||||
let e: absy::ExpressionNode = absy::ExpressionNode::from(definition.expression);
|
||||
|
||||
let s = match e.value {
|
||||
absy::Expression::FunctionCall(..) => absy::Statement::MultipleDefinition(
|
||||
vec![absy::AssigneeNode::from(a.a.clone())],
|
||||
e,
|
||||
),
|
||||
_ => absy::Statement::Definition(absy::AssigneeNode::from(a.a.clone()), e),
|
||||
};
|
||||
|
||||
match a.ty {
|
||||
Some(ty) => {
|
||||
assert_eq!(a.a.accesses.len(), 0);
|
||||
|
||||
match a {
|
||||
pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => {
|
||||
let declaration = absy::Statement::Declaration(
|
||||
absy::Variable::new(
|
||||
a.a.id.span.as_str(),
|
||||
absy::UnresolvedTypeNode::from(ty),
|
||||
i.identifier.span.as_str(),
|
||||
absy::UnresolvedTypeNode::from(i.ty),
|
||||
)
|
||||
.span(a.a.id.span.clone()),
|
||||
.span(i.identifier.span.clone()),
|
||||
)
|
||||
.span(definition.span.clone());
|
||||
|
||||
let s = match e.value {
|
||||
absy::Expression::FunctionCall(..) => absy::Statement::MultipleDefinition(
|
||||
vec![absy::AssigneeNode::from(i.identifier.clone())],
|
||||
e,
|
||||
),
|
||||
_ => absy::Statement::Definition(absy::AssigneeNode::from(i.identifier.clone()), e),
|
||||
};
|
||||
|
||||
vec![declaration, s.span(definition.span)]
|
||||
}
|
||||
None => {
|
||||
// Assignment
|
||||
},
|
||||
pest::TypedIdentifierOrAssignee::Assignee(a) => {
|
||||
let s = match e.value {
|
||||
absy::Expression::FunctionCall(..) => absy::Statement::MultipleDefinition(
|
||||
vec![absy::AssigneeNode::from(a)],
|
||||
e,
|
||||
),
|
||||
_ => absy::Statement::Definition(absy::AssigneeNode::from(a), e),
|
||||
};
|
||||
|
||||
vec![s.span(definition.span)]
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Multidefinition
|
||||
let declarations = lhs.clone().into_iter().filter(|i| i.ty.is_some()).map(|a| {
|
||||
let ty = a.ty;
|
||||
let a = a.a;
|
||||
|
||||
assert_eq!(a.accesses.len(), 0);
|
||||
absy::Statement::Declaration(
|
||||
absy::Variable::new(
|
||||
a.id.span.as_str(),
|
||||
absy::UnresolvedTypeNode::from(ty.unwrap()),
|
||||
let declarations = lhs.clone().into_iter().filter_map(|i| match i {
|
||||
pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => {
|
||||
let ty = i.ty;
|
||||
let id = i.identifier;
|
||||
|
||||
Some(absy::Statement::Declaration(
|
||||
absy::Variable::new(
|
||||
id.span.as_str(),
|
||||
absy::UnresolvedTypeNode::from(ty),
|
||||
)
|
||||
.span(id.span),
|
||||
)
|
||||
.span(a.id.span),
|
||||
)
|
||||
.span(a.span)
|
||||
.span(i.span))
|
||||
},
|
||||
_ => None
|
||||
});
|
||||
|
||||
let lhs = lhs
|
||||
.into_iter()
|
||||
.map(|i| absy::Assignee::Identifier(i.a.id.span.as_str()).span(i.a.id.span))
|
||||
.map(|i| match i {
|
||||
pest::TypedIdentifierOrAssignee::TypedIdentifier(i) => {
|
||||
absy::Assignee::Identifier(i.identifier.span.as_str()).span(i.identifier.span)
|
||||
},
|
||||
pest::TypedIdentifierOrAssignee::Assignee(a) => {
|
||||
absy::AssigneeNode::from(a)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let multi_def = absy::Statement::MultipleDefinition(
|
||||
|
|
|
@ -237,6 +237,8 @@ fn check_with_arena<'ast, T: Field, E: Into<imports::Error>>(
|
|||
let typed_ast = Checker::check(compiled)
|
||||
.map_err(|errors| CompileErrors(errors.into_iter().map(CompileError::from).collect()))?;
|
||||
|
||||
println!("{}", typed_ast);
|
||||
|
||||
let main_module = typed_ast.main.clone();
|
||||
|
||||
// analyse (unroll and constant propagation)
|
||||
|
|
|
@ -1484,6 +1484,9 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
|||
res
|
||||
}
|
||||
Statement::MultipleDefinition(assignees, rhs) => {
|
||||
|
||||
println!("ASSIGNEES: {:?}", assignees);
|
||||
|
||||
match rhs.value {
|
||||
// Right side has to be a function call
|
||||
Expression::FunctionCall(fun_id, generics, arguments) => {
|
||||
|
@ -1522,6 +1525,8 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
|||
|
||||
let assignee_types: Vec<_> = assignees.iter().map(|a| Some(a.get_type().clone())).collect();
|
||||
|
||||
println!("{:?}", assignee_types);
|
||||
|
||||
// find argument types
|
||||
let mut arguments_checked = vec![];
|
||||
for arg in arguments {
|
||||
|
@ -1534,6 +1539,8 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
|||
|
||||
let query = FunctionQuery::new(&fun_id, &generics_checked, &arguments_types, &assignee_types);
|
||||
|
||||
println!("QUERY {:?}", query);
|
||||
|
||||
let functions = self.find_functions(&query);
|
||||
|
||||
match functions.len() {
|
||||
|
|
|
@ -54,11 +54,11 @@ statement = { (return_statement // does not require subsequent newline
|
|||
|
||||
iteration_statement = { "for" ~ ty ~ identifier ~ "in" ~ expression ~ ".." ~ expression ~ "do" ~ NEWLINE* ~ statement* ~ "endfor"}
|
||||
return_statement = { "return" ~ expression_list}
|
||||
definition_statement = { optionally_typed_assignee_list ~ "=" ~ expression } // declare and assign, so only identifiers are allowed, unlike `assignment_statement`
|
||||
definition_statement = { typed_identifier_or_assignee_list ~ "=" ~ expression } // declare and assign, so only identifiers are allowed, unlike `assignment_statement`
|
||||
expression_statement = {"assert" ~ "(" ~ expression ~ ")"}
|
||||
|
||||
optionally_typed_assignee_list = _{ optionally_typed_assignee ~ ("," ~ optionally_typed_assignee)* }
|
||||
optionally_typed_assignee = { (ty ~ assignee) | (assignee) } // we don't use { ty? ~ identifier } as with a single token, it gets parsed as `ty` but we want `identifier`
|
||||
typed_identifier_or_assignee_list = _{ typed_identifier_or_assignee ~ ("," ~ typed_identifier_or_assignee)* }
|
||||
typed_identifier_or_assignee = { typed_identifier | assignee } // we don't use { ty? ~ identifier } as with a single token, it gets parsed as `ty` but we want `identifier`
|
||||
|
||||
// Expressions
|
||||
expression_list = _{(expression ~ ("," ~ expression)*)?}
|
||||
|
@ -103,6 +103,7 @@ array_initializer_expression = { "[" ~ expression ~ ";" ~ expression ~ "]" }
|
|||
|
||||
// End Expressions
|
||||
|
||||
typed_identifier = { ty ~ identifier }
|
||||
assignee = { identifier ~ assignee_access* }
|
||||
assignee_access = { array_access | member_access }
|
||||
identifier = @{ ((!keyword ~ ASCII_ALPHA) | (keyword ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* }
|
||||
|
|
|
@ -15,7 +15,7 @@ pub use ast::{
|
|||
FromExpression, FunctionDefinition, HexLiteralExpression, HexNumberExpression,
|
||||
IdentifierExpression, ImportDirective, ImportSource, ImportSymbol, InlineArrayExpression,
|
||||
InlineStructExpression, InlineStructMember, IterationStatement, LiteralExpression,
|
||||
OptionallyTypedAssignee, Parameter, PostfixExpression, Range, RangeOrExpression,
|
||||
TypedIdentifierOrAssignee, Parameter, PostfixExpression, Range, RangeOrExpression,
|
||||
ReturnStatement, Span, Spread, SpreadOrExpression, Statement, StructDefinition, StructField,
|
||||
SymbolDeclaration, TernaryExpression, ToExpression, Type, UnaryExpression, UnaryOperator,
|
||||
Underscore, Visibility,
|
||||
|
@ -349,7 +349,7 @@ mod ast {
|
|||
#[derive(Debug, FromPest, PartialEq, Clone)]
|
||||
#[pest_ast(rule(Rule::definition_statement))]
|
||||
pub struct DefinitionStatement<'ast> {
|
||||
pub lhs: Vec<OptionallyTypedAssignee<'ast>>,
|
||||
pub lhs: Vec<TypedIdentifierOrAssignee<'ast>>,
|
||||
pub expression: Expression<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
|
@ -635,10 +635,17 @@ mod ast {
|
|||
}
|
||||
|
||||
#[derive(Debug, FromPest, PartialEq, Clone)]
|
||||
#[pest_ast(rule(Rule::optionally_typed_assignee))]
|
||||
pub struct OptionallyTypedAssignee<'ast> {
|
||||
pub ty: Option<Type<'ast>>,
|
||||
pub a: Assignee<'ast>,
|
||||
#[pest_ast(rule(Rule::typed_identifier_or_assignee))]
|
||||
pub enum TypedIdentifierOrAssignee<'ast> {
|
||||
Assignee(Assignee<'ast>),
|
||||
TypedIdentifier(TypedIdentifier<'ast>)
|
||||
}
|
||||
|
||||
#[derive(Debug, FromPest, PartialEq, Clone)]
|
||||
#[pest_ast(rule(Rule::typed_identifier))]
|
||||
pub struct TypedIdentifier<'ast> {
|
||||
pub ty: Type<'ast>,
|
||||
pub identifier: IdentifierExpression<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
@ -1330,32 +1337,24 @@ mod tests {
|
|||
}))],
|
||||
statements: vec![Statement::Definition(DefinitionStatement {
|
||||
lhs: vec![
|
||||
OptionallyTypedAssignee {
|
||||
ty: Some(Type::Basic(BasicType::Field(FieldType {
|
||||
TypedIdentifierOrAssignee::TypedIdentifier(TypedIdentifier {
|
||||
ty: Type::Basic(BasicType::Field(FieldType {
|
||||
span: Span::new(&source, 23, 28).unwrap()
|
||||
}))),
|
||||
a: Assignee {
|
||||
id: IdentifierExpression {
|
||||
})),
|
||||
identifier: IdentifierExpression {
|
||||
value: String::from("a"),
|
||||
span: Span::new(&source, 29, 30).unwrap(),
|
||||
},
|
||||
accesses: vec![],
|
||||
span: Span::new(&source, 29, 30).unwrap()
|
||||
},
|
||||
span: Span::new(&source, 23, 30).unwrap()
|
||||
},
|
||||
OptionallyTypedAssignee {
|
||||
ty: None,
|
||||
a: Assignee {
|
||||
id: IdentifierExpression {
|
||||
value: String::from("b"),
|
||||
span: Span::new(&source, 32, 33).unwrap(),
|
||||
},
|
||||
accesses: vec![],
|
||||
span: Span::new(&source, 32, 34).unwrap()
|
||||
}),
|
||||
TypedIdentifierOrAssignee::Assignee(Assignee {
|
||||
id: IdentifierExpression {
|
||||
value: String::from("b"),
|
||||
span: Span::new(&source, 32, 33).unwrap(),
|
||||
},
|
||||
accesses: vec![],
|
||||
span: Span::new(&source, 32, 34).unwrap()
|
||||
},
|
||||
}),
|
||||
],
|
||||
expression: Expression::Postfix(PostfixExpression {
|
||||
id: IdentifierExpression {
|
||||
|
|
Loading…
Reference in a new issue