pass positions to absy, allow one error per function
This commit is contained in:
parent
f39214df65
commit
d1295adc49
10 changed files with 531 additions and 221 deletions
|
@ -5,11 +5,13 @@
|
|||
//! @author Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>
|
||||
//! @date 2017
|
||||
|
||||
mod node;
|
||||
pub mod parameter;
|
||||
pub mod variable;
|
||||
|
||||
pub use absy::node::Node;
|
||||
pub use absy::parameter::Parameter;
|
||||
pub use absy::variable::Variable;
|
||||
pub use absy::variable::{Variable, VariableNode};
|
||||
use types::Signature;
|
||||
|
||||
use flat_absy::*;
|
||||
|
@ -125,9 +127,11 @@ impl<T: Field> fmt::Debug for Function<T> {
|
|||
#[derive(Clone, PartialEq)]
|
||||
pub enum Assignee<T: Field> {
|
||||
Identifier(String),
|
||||
ArrayElement(Box<Assignee<T>>, Box<Expression<T>>),
|
||||
ArrayElement(Box<AssigneeNode<T>>, Box<ExpressionNode<T>>),
|
||||
}
|
||||
|
||||
pub type AssigneeNode<T> = Node<Assignee<T>>;
|
||||
|
||||
impl<T: Field> fmt::Debug for Assignee<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
|
@ -143,12 +147,24 @@ impl<T: Field> fmt::Display for Assignee<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Field> From<Expression<T>> for Assignee<T> {
|
||||
fn from(e: Expression<T>) -> Self {
|
||||
match e {
|
||||
Expression::Select(box Expression::Identifier(id), box e2) => {
|
||||
Assignee::ArrayElement(box Assignee::Identifier(id), box e2)
|
||||
}
|
||||
impl<T: Field> From<ExpressionNode<T>> for AssigneeNode<T> {
|
||||
fn from(e: ExpressionNode<T>) -> Self {
|
||||
match e.value {
|
||||
Expression::Select(box e1, box e2) => match e1 {
|
||||
ExpressionNode {
|
||||
value: Expression::Identifier(id),
|
||||
start,
|
||||
end,
|
||||
} => Node::new(
|
||||
e.start,
|
||||
e.end,
|
||||
Assignee::ArrayElement(
|
||||
box Node::new(start, end, Assignee::Identifier(id)),
|
||||
box e2,
|
||||
),
|
||||
),
|
||||
_ => panic!("only use expression to assignee for elements like foo[bar]"),
|
||||
},
|
||||
_ => panic!("only use expression to assignee for elements like foo[bar]"),
|
||||
}
|
||||
}
|
||||
|
@ -156,12 +172,12 @@ impl<T: Field> From<Expression<T>> for Assignee<T> {
|
|||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum Statement<T: Field> {
|
||||
Return(ExpressionList<T>),
|
||||
Declaration(Variable),
|
||||
Definition(Assignee<T>, Expression<T>),
|
||||
Condition(Expression<T>, Expression<T>),
|
||||
For(Variable, T, T, Vec<Statement<T>>),
|
||||
MultipleDefinition(Vec<Assignee<T>>, Expression<T>),
|
||||
Return(ExpressionListNode<T>),
|
||||
Declaration(VariableNode),
|
||||
Definition(AssigneeNode<T>, ExpressionNode<T>),
|
||||
Condition(ExpressionNode<T>, ExpressionNode<T>),
|
||||
For(VariableNode, T, T, Vec<Statement<T>>),
|
||||
MultipleDefinition(Vec<AssigneeNode<T>>, ExpressionNode<T>),
|
||||
}
|
||||
|
||||
impl<T: Field> fmt::Display for Statement<T> {
|
||||
|
@ -218,25 +234,31 @@ impl<T: Field> fmt::Debug for Statement<T> {
|
|||
pub enum Expression<T: Field> {
|
||||
Number(T),
|
||||
Identifier(String),
|
||||
Add(Box<Expression<T>>, Box<Expression<T>>),
|
||||
Sub(Box<Expression<T>>, Box<Expression<T>>),
|
||||
Mult(Box<Expression<T>>, Box<Expression<T>>),
|
||||
Div(Box<Expression<T>>, Box<Expression<T>>),
|
||||
Pow(Box<Expression<T>>, Box<Expression<T>>),
|
||||
IfElse(Box<Expression<T>>, Box<Expression<T>>, Box<Expression<T>>),
|
||||
FunctionCall(String, Vec<Expression<T>>),
|
||||
Lt(Box<Expression<T>>, Box<Expression<T>>),
|
||||
Le(Box<Expression<T>>, Box<Expression<T>>),
|
||||
Eq(Box<Expression<T>>, Box<Expression<T>>),
|
||||
Ge(Box<Expression<T>>, Box<Expression<T>>),
|
||||
Gt(Box<Expression<T>>, Box<Expression<T>>),
|
||||
And(Box<Expression<T>>, Box<Expression<T>>),
|
||||
Not(Box<Expression<T>>),
|
||||
InlineArray(Vec<Expression<T>>),
|
||||
Select(Box<Expression<T>>, Box<Expression<T>>),
|
||||
Or(Box<Expression<T>>, Box<Expression<T>>),
|
||||
Add(Box<ExpressionNode<T>>, Box<ExpressionNode<T>>),
|
||||
Sub(Box<ExpressionNode<T>>, Box<ExpressionNode<T>>),
|
||||
Mult(Box<ExpressionNode<T>>, Box<ExpressionNode<T>>),
|
||||
Div(Box<ExpressionNode<T>>, Box<ExpressionNode<T>>),
|
||||
Pow(Box<ExpressionNode<T>>, Box<ExpressionNode<T>>),
|
||||
IfElse(
|
||||
Box<ExpressionNode<T>>,
|
||||
Box<ExpressionNode<T>>,
|
||||
Box<ExpressionNode<T>>,
|
||||
),
|
||||
FunctionCall(String, Vec<ExpressionNode<T>>),
|
||||
Lt(Box<ExpressionNode<T>>, Box<ExpressionNode<T>>),
|
||||
Le(Box<ExpressionNode<T>>, Box<ExpressionNode<T>>),
|
||||
Eq(Box<ExpressionNode<T>>, Box<ExpressionNode<T>>),
|
||||
Ge(Box<ExpressionNode<T>>, Box<ExpressionNode<T>>),
|
||||
Gt(Box<ExpressionNode<T>>, Box<ExpressionNode<T>>),
|
||||
And(Box<ExpressionNode<T>>, Box<ExpressionNode<T>>),
|
||||
Not(Box<ExpressionNode<T>>),
|
||||
InlineArray(Vec<ExpressionNode<T>>),
|
||||
Select(Box<ExpressionNode<T>>, Box<ExpressionNode<T>>),
|
||||
Or(Box<ExpressionNode<T>>, Box<ExpressionNode<T>>),
|
||||
}
|
||||
|
||||
pub type ExpressionNode<T> = Node<Expression<T>>;
|
||||
|
||||
impl<T: Field> fmt::Display for Expression<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
|
@ -325,9 +347,11 @@ impl<T: Field> fmt::Debug for Expression<T> {
|
|||
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ExpressionList<T: Field> {
|
||||
pub expressions: Vec<Expression<T>>,
|
||||
pub expressions: Vec<ExpressionNode<T>>,
|
||||
}
|
||||
|
||||
pub type ExpressionListNode<T> = Node<ExpressionList<T>>;
|
||||
|
||||
impl<T: Field> ExpressionList<T> {
|
||||
pub fn new() -> ExpressionList<T> {
|
||||
ExpressionList {
|
||||
|
|
27
zokrates_core/src/absy/node.rs
Normal file
27
zokrates_core/src/absy/node.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use parser::Position;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Node<T: fmt::Display> {
|
||||
pub start: Position,
|
||||
pub end: Position,
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
impl<T: fmt::Display> Node<T> {
|
||||
pub fn pos(&self) -> (Position, Position) {
|
||||
(self.start, self.end)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display> fmt::Display for Node<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{} ({}:{})", self.value, self.start, self.end)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display> Node<T> {
|
||||
pub fn new(start: Position, end: Position, value: T) -> Node<T> {
|
||||
Node { start, end, value }
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
use absy::Node;
|
||||
use std::fmt;
|
||||
use types::Type;
|
||||
|
||||
|
@ -7,6 +8,8 @@ pub struct Variable {
|
|||
pub _type: Type,
|
||||
}
|
||||
|
||||
pub type VariableNode = Node<Variable>;
|
||||
|
||||
impl Variable {
|
||||
pub fn new<S: Into<String>>(id: S, t: Type) -> Variable {
|
||||
Variable {
|
||||
|
|
|
@ -53,7 +53,7 @@ impl<T: Field> fmt::Display for CompileError<T> {
|
|||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let res = match *self {
|
||||
CompileError::ParserError(ref e) => format!("Syntax error: {}", e),
|
||||
CompileError::SemanticError(ref e) => format!("Semantic error: {}", e),
|
||||
CompileError::SemanticError(ref e) => format!("Semantic error: \n{}\n", e),
|
||||
CompileError::ReadError(ref e) => format!("Read error: {}", e),
|
||||
CompileError::ImportError(ref e) => format!("Import error: {}", e),
|
||||
};
|
||||
|
|
|
@ -4,3 +4,4 @@ mod tokenize;
|
|||
|
||||
pub use parser::error::Error;
|
||||
pub use parser::parse::parse_program;
|
||||
pub use parser::tokenize::Position;
|
||||
|
|
|
@ -3,21 +3,23 @@ use zokrates_field::field::Field;
|
|||
use parser::tokenize::{next_token, Position, Token};
|
||||
use parser::Error;
|
||||
|
||||
use absy::Expression;
|
||||
use absy::{Expression, ExpressionNode, Node};
|
||||
|
||||
fn parse_then_else<T: Field>(
|
||||
cond: Expression<T>,
|
||||
cond: ExpressionNode<T>,
|
||||
input: &String,
|
||||
pos: &Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match next_token(input, pos) {
|
||||
(Token::Then, s5, p5) => match parse_expr(&s5, &p5) {
|
||||
Ok((e6, s6, p6)) => match next_token(&s6, &p6) {
|
||||
(Token::Else, s7, p7) => match parse_expr(&s7, &p7) {
|
||||
Ok((e8, s8, p8)) => match next_token(&s8, &p8) {
|
||||
(Token::Fi, s9, p9) => {
|
||||
parse_expr1(Expression::IfElse(box cond, box e6, box e8), s9, p9)
|
||||
}
|
||||
(Token::Fi, s9, p9) => parse_expr1(
|
||||
Node::new(cond.start, p9, Expression::IfElse(box cond, box e6, box e8)),
|
||||
s9,
|
||||
p9,
|
||||
),
|
||||
(t10, _, p10) => Err(Error {
|
||||
expected: vec![Token::Fi],
|
||||
got: t10,
|
||||
|
@ -45,27 +47,37 @@ fn parse_then_else<T: Field>(
|
|||
fn parse_prim_cond<T: Field>(
|
||||
input: &String,
|
||||
pos: &Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match parse_expr(input, pos) {
|
||||
Ok((e2, s2, p2)) => match next_token(&s2, &p2) {
|
||||
(Token::Lt, s3, p3) => match parse_expr(&s3, &p3) {
|
||||
Ok((e4, s4, p4)) => Ok((Expression::Lt(box e2, box e4), s4, p4)),
|
||||
Ok((e4, s4, p4)) => {
|
||||
Ok((Node::new(*pos, p4, Expression::Lt(box e2, box e4)), s4, p4))
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Le, s3, p3) => match parse_expr(&s3, &p3) {
|
||||
Ok((e4, s4, p4)) => Ok((Expression::Le(box e2, box e4), s4, p4)),
|
||||
Ok((e4, s4, p4)) => {
|
||||
Ok((Node::new(*pos, p4, Expression::Le(box e2, box e4)), s4, p4))
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Eqeq, s3, p3) => match parse_expr(&s3, &p3) {
|
||||
Ok((e4, s4, p4)) => Ok((Expression::Eq(box e2, box e4), s4, p4)),
|
||||
Ok((e4, s4, p4)) => {
|
||||
Ok((Node::new(*pos, p4, Expression::Eq(box e2, box e4)), s4, p4))
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Ge, s3, p3) => match parse_expr(&s3, &p3) {
|
||||
Ok((e4, s4, p4)) => Ok((Expression::Ge(box e2, box e4), s4, p4)),
|
||||
Ok((e4, s4, p4)) => {
|
||||
Ok((Node::new(*pos, p4, Expression::Ge(box e2, box e4)), s4, p4))
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Gt, s3, p3) => match parse_expr(&s3, &p3) {
|
||||
Ok((e4, s4, p4)) => Ok((Expression::Gt(box e2, box e4), s4, p4)),
|
||||
Ok((e4, s4, p4)) => {
|
||||
Ok((Node::new(*pos, p4, Expression::Gt(box e2, box e4)), s4, p4))
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(t3, _, p3) => Err(Error {
|
||||
|
@ -81,11 +93,11 @@ fn parse_prim_cond<T: Field>(
|
|||
fn parse_bfactor<T: Field>(
|
||||
input: &String,
|
||||
pos: &Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match next_token::<T>(input, pos) {
|
||||
(Token::Not, s1, p1) => match next_token(&s1, &p1) {
|
||||
(Token::Open, _, _) => match parse_bfactor(&s1, &p1) {
|
||||
Ok((e3, s3, p3)) => Ok((Expression::Not(box e3), s3, p3)),
|
||||
Ok((e3, s3, p3)) => Ok((Node::new(*pos, p3, Expression::Not(box e3)), s3, p3)),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(t2, _, p2) => Err(Error {
|
||||
|
@ -110,13 +122,13 @@ fn parse_bfactor<T: Field>(
|
|||
}
|
||||
|
||||
pub fn parse_bterm1<T: Field>(
|
||||
expr: Expression<T>,
|
||||
expr: ExpressionNode<T>,
|
||||
input: String,
|
||||
pos: Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match next_token::<T>(&input, &pos) {
|
||||
(Token::And, s1, p1) => match parse_bterm(&s1, &p1) {
|
||||
Ok((e, s2, p2)) => Ok((Expression::And(box expr, box e), s2, p2)),
|
||||
Ok((e, s2, p2)) => Ok((Node::new(pos, p2, Expression::And(box expr, box e)), s2, p2)),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
_ => Ok((expr, input, pos)),
|
||||
|
@ -126,7 +138,7 @@ pub fn parse_bterm1<T: Field>(
|
|||
fn parse_bterm<T: Field>(
|
||||
input: &String,
|
||||
pos: &Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match parse_bfactor(input, pos) {
|
||||
Ok((e, s1, p1)) => parse_bterm1(e, s1, p1),
|
||||
Err(err) => Err(err),
|
||||
|
@ -134,13 +146,15 @@ fn parse_bterm<T: Field>(
|
|||
}
|
||||
|
||||
fn parse_bexpr1<T: Field>(
|
||||
expr: Expression<T>,
|
||||
expr: ExpressionNode<T>,
|
||||
input: String,
|
||||
pos: Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match next_token::<T>(&input, &pos) {
|
||||
(Token::Or, s1, p1) => match parse_bterm(&s1, &p1) {
|
||||
Ok((e2, s2, p2)) => parse_bexpr1(Expression::Or(box expr, box e2), s2, p2),
|
||||
Ok((e2, s2, p2)) => {
|
||||
parse_bexpr1(Node::new(pos, p2, Expression::Or(box expr, box e2)), s2, p2)
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
_ => Ok((expr, input, pos)),
|
||||
|
@ -150,15 +164,17 @@ fn parse_bexpr1<T: Field>(
|
|||
fn parse_bexpr<T: Field>(
|
||||
input: &String,
|
||||
pos: &Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match next_token::<T>(input, pos) {
|
||||
(Token::Not, s1, p1) => match next_token(&s1, &p1) {
|
||||
(Token::Open, s2, p2) => match parse_bexpr(&s2, &p2) {
|
||||
Ok((e3, s3, p3)) => match next_token(&s3, &p3) {
|
||||
(Token::Close, s4, p4) => match parse_bterm1(Expression::Not(box e3), s4, p4) {
|
||||
Ok((e5, s5, p5)) => parse_bexpr1(e5, s5, p5),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Close, s4, p4) => {
|
||||
match parse_bterm1(Node::new(*pos, p4, Expression::Not(box e3)), s4, p4) {
|
||||
Ok((e5, s5, p5)) => parse_bexpr1(e5, s5, p5),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
(t4, _, p4) => Err(Error {
|
||||
expected: vec![Token::Close],
|
||||
got: t4,
|
||||
|
@ -211,7 +227,7 @@ fn parse_bexpr<T: Field>(
|
|||
fn parse_if_then_else<T: Field>(
|
||||
input: &String,
|
||||
pos: &Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match next_token(input, pos) {
|
||||
(Token::If, s1, p1) => match parse_bexpr(&s1, &p1) {
|
||||
Ok((e2, s2, p2)) => parse_then_else(e2, &s2, &p2),
|
||||
|
@ -226,17 +242,23 @@ fn parse_if_then_else<T: Field>(
|
|||
}
|
||||
|
||||
fn parse_factor1<T: Field>(
|
||||
expr: Expression<T>,
|
||||
expr: ExpressionNode<T>,
|
||||
input: String,
|
||||
pos: Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match parse_term1(expr.clone(), input.clone(), pos.clone()) {
|
||||
Ok((e1, s1, p1)) => match parse_expr1(e1, s1, p1) {
|
||||
Ok((e2, s2, p2)) => match next_token::<T>(&s2, &p2) {
|
||||
(Token::Pow, s3, p3) => match next_token(&s3, &p3) {
|
||||
(Token::Num(x), s4, p4) => {
|
||||
Ok((Expression::Pow(box e2, box Expression::Number(x)), s4, p4))
|
||||
}
|
||||
(Token::Num(x), s4, p4) => Ok((
|
||||
Node::new(
|
||||
pos,
|
||||
p4,
|
||||
Expression::Pow(box e2, box Node::new(p3, p4, Expression::Number(x))),
|
||||
),
|
||||
s4,
|
||||
p4,
|
||||
)),
|
||||
(t4, _, p4) => Err(Error {
|
||||
expected: vec![Token::ErrNum],
|
||||
got: t4,
|
||||
|
@ -256,18 +278,26 @@ fn parse_identified1<T: Field>(
|
|||
x: String,
|
||||
input: String,
|
||||
position: Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
let ide_initial_pos = Position {
|
||||
col: position.col - x.len(),
|
||||
..position
|
||||
};
|
||||
match next_token::<T>(&input, &position) {
|
||||
(Token::Open, s1, p1) => parse_function_call(x, s1, p1),
|
||||
(Token::LeftBracket, s1, p1) => parse_array_select(x, s1, p1),
|
||||
_ => Ok((Expression::Identifier(x), input, position)),
|
||||
_ => Ok((
|
||||
Node::new(ide_initial_pos, position, Expression::Identifier(x)),
|
||||
input,
|
||||
position,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_factor<T: Field>(
|
||||
input: &String,
|
||||
pos: &Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match next_token(input, pos) {
|
||||
(Token::If, ..) => parse_if_then_else(input, pos),
|
||||
(Token::Open, s1, p1) => match parse_expr(&s1, &p1) {
|
||||
|
@ -285,7 +315,9 @@ fn parse_factor<T: Field>(
|
|||
Ok((e2, s2, p2)) => parse_factor1(e2, s2, p2),
|
||||
e => e,
|
||||
},
|
||||
(Token::Num(x), s1, p1) => parse_factor1(Expression::Number(x), s1, p1),
|
||||
(Token::Num(x), s1, p1) => {
|
||||
parse_factor1(Node::new(*pos, p1, Expression::Number(x)), s1, p1)
|
||||
}
|
||||
(t1, _, p1) => Err(Error {
|
||||
expected: vec![Token::If, Token::Open, Token::ErrIde, Token::ErrNum],
|
||||
got: t1,
|
||||
|
@ -295,17 +327,21 @@ fn parse_factor<T: Field>(
|
|||
}
|
||||
|
||||
pub fn parse_term1<T: Field>(
|
||||
expr: Expression<T>,
|
||||
expr: ExpressionNode<T>,
|
||||
input: String,
|
||||
pos: Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match next_token::<T>(&input, &pos) {
|
||||
(Token::Mult, s1, p1) => match parse_term(&s1, &p1) {
|
||||
Ok((e, s2, p2)) => Ok((Expression::Mult(box expr, box e), s2, p2)),
|
||||
Ok((e, s2, p2)) => Ok((
|
||||
Node::new(pos, p2, Expression::Mult(box expr, box e)),
|
||||
s2,
|
||||
p2,
|
||||
)),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Div, s1, p1) => match parse_term(&s1, &p1) {
|
||||
Ok((e, s2, p2)) => Ok((Expression::Div(box expr, box e), s2, p2)),
|
||||
Ok((e, s2, p2)) => Ok((Node::new(pos, p2, Expression::Div(box expr, box e)), s2, p2)),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
_ => Ok((expr, input, pos)),
|
||||
|
@ -315,7 +351,7 @@ pub fn parse_term1<T: Field>(
|
|||
fn parse_term<T: Field>(
|
||||
input: &String,
|
||||
pos: &Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match parse_factor(input, pos) {
|
||||
Ok((e, s1, p1)) => parse_term1(e, s1, p1),
|
||||
Err(err) => Err(err),
|
||||
|
@ -323,21 +359,33 @@ fn parse_term<T: Field>(
|
|||
}
|
||||
|
||||
pub fn parse_expr1<T: Field>(
|
||||
expr: Expression<T>,
|
||||
expr: ExpressionNode<T>,
|
||||
input: String,
|
||||
pos: Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match next_token::<T>(&input, &pos) {
|
||||
(Token::Add, s1, p1) => match parse_term(&s1, &p1) {
|
||||
Ok((e2, s2, p2)) => parse_expr1(Expression::Add(box expr, box e2), s2, p2),
|
||||
Ok((e2, s2, p2)) => parse_expr1(
|
||||
Node::new(expr.start, p2, Expression::Add(box expr, box e2)),
|
||||
s2,
|
||||
p2,
|
||||
),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Sub, s1, p1) => match parse_term(&s1, &p1) {
|
||||
Ok((e2, s2, p2)) => parse_expr1(Expression::Sub(box expr, box e2), s2, p2),
|
||||
Ok((e2, s2, p2)) => parse_expr1(
|
||||
Node::new(expr.start, p2, Expression::Sub(box expr, box e2)),
|
||||
s2,
|
||||
p2,
|
||||
),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Pow, s1, p1) => match parse_term(&s1, &p1) {
|
||||
Ok((e, s2, p2)) => match parse_term1(Expression::Pow(box expr, box e), s2, p2) {
|
||||
Ok((e, s2, p2)) => match parse_term1(
|
||||
Node::new(expr.start, p2, Expression::Pow(box expr, box e)),
|
||||
s2,
|
||||
p2,
|
||||
) {
|
||||
Ok((e3, s3, p3)) => parse_expr1(e3, s3, p3),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
|
@ -351,7 +399,7 @@ pub fn parse_function_call<T: Field>(
|
|||
ide: String,
|
||||
input: String,
|
||||
pos: Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
// function call can have 0 .. n args
|
||||
let mut args = Vec::new();
|
||||
let mut s: String = input;
|
||||
|
@ -361,7 +409,11 @@ pub fn parse_function_call<T: Field>(
|
|||
match next_token::<T>(&s, &p) {
|
||||
// no arguments
|
||||
(Token::Close, s1, p1) => {
|
||||
return parse_term1(Expression::FunctionCall(ide, args), s1, p1);
|
||||
return parse_term1(
|
||||
Node::new(pos, p1, Expression::FunctionCall(ide, args)),
|
||||
s1,
|
||||
p1,
|
||||
);
|
||||
}
|
||||
// at least one argument
|
||||
(_, _, _) => match parse_expr(&s, &p) {
|
||||
|
@ -373,7 +425,11 @@ pub fn parse_function_call<T: Field>(
|
|||
p = p2;
|
||||
}
|
||||
(Token::Close, s2, p2) => {
|
||||
return parse_term1(Expression::FunctionCall(ide, args), s2, p2);
|
||||
return parse_term1(
|
||||
Node::new(pos, p2, Expression::FunctionCall(ide, args)),
|
||||
s2,
|
||||
p2,
|
||||
);
|
||||
}
|
||||
(t2, _, p2) => {
|
||||
return Err(Error {
|
||||
|
@ -393,7 +449,7 @@ pub fn parse_function_call<T: Field>(
|
|||
pub fn parse_inline_array<T: Field>(
|
||||
input: String,
|
||||
pos: Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
// function call can have 0 .. n args
|
||||
let mut expressions = Vec::new();
|
||||
let mut s: String = input;
|
||||
|
@ -403,7 +459,11 @@ pub fn parse_inline_array<T: Field>(
|
|||
match next_token::<T>(&s, &p) {
|
||||
// no arguments
|
||||
(Token::RightBracket, s1, p1) => {
|
||||
match parse_term1(Expression::InlineArray(expressions), s1, p1) {
|
||||
match parse_term1(
|
||||
Node::new(pos, p1, Expression::InlineArray(expressions)),
|
||||
s1,
|
||||
p1,
|
||||
) {
|
||||
Ok((e2, s2, p2)) => return parse_expr1(e2, s2, p2),
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
|
@ -418,7 +478,11 @@ pub fn parse_inline_array<T: Field>(
|
|||
p = p2;
|
||||
}
|
||||
(Token::RightBracket, s2, p2) => {
|
||||
match parse_term1(Expression::InlineArray(expressions), s2, p2) {
|
||||
match parse_term1(
|
||||
Node::new(pos, p2, Expression::InlineArray(expressions)),
|
||||
s2,
|
||||
p2,
|
||||
) {
|
||||
Ok((e3, s3, p3)) => return parse_expr1(e3, s3, p3),
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
|
@ -442,13 +506,24 @@ pub fn parse_array_select<T: Field>(
|
|||
ide: String,
|
||||
input: String,
|
||||
pos: Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
let ide_initial_pos = Position {
|
||||
col: pos.col - ide.len(),
|
||||
..pos
|
||||
};
|
||||
// array select can have exactly one arg
|
||||
match next_token::<T>(&input, &pos) {
|
||||
(_, _, _) => match parse_expr(&input, &pos) {
|
||||
Ok((e1, s1, p1)) => match next_token::<T>(&s1, &p1) {
|
||||
(Token::RightBracket, s2, p2) => parse_term1(
|
||||
Expression::Select(box Expression::Identifier(ide), box e1),
|
||||
Node::new(
|
||||
pos,
|
||||
p2,
|
||||
Expression::Select(
|
||||
box Node::new(pos, p1, Expression::Identifier(ide)),
|
||||
box e1,
|
||||
),
|
||||
),
|
||||
s2,
|
||||
p2,
|
||||
),
|
||||
|
@ -466,7 +541,7 @@ pub fn parse_array_select<T: Field>(
|
|||
pub fn parse_expr<T: Field>(
|
||||
input: &String,
|
||||
pos: &Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
|
||||
match next_token::<T>(input, pos) {
|
||||
(Token::If, ..) => parse_if_then_else(input, pos),
|
||||
(Token::Open, s1, p1) => match parse_expr(&s1, &p1) {
|
||||
|
@ -490,10 +565,12 @@ pub fn parse_expr<T: Field>(
|
|||
},
|
||||
e => e,
|
||||
},
|
||||
(Token::Num(x), s1, p1) => match parse_term1(Expression::Number(x), s1, p1) {
|
||||
Ok((e2, s2, p2)) => parse_expr1(e2, s2, p2),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Num(x), s1, p1) => {
|
||||
match parse_term1(Node::new(*pos, p1, Expression::Number(x)), s1, p1) {
|
||||
Ok((e2, s2, p2)) => parse_expr1(e2, s2, p2),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
(Token::LeftBracket, s1, p1) => parse_inline_array(s1, p1),
|
||||
(t1, _, p1) => Err(Error {
|
||||
expected: vec![Token::If, Token::Open, Token::ErrIde, Token::ErrNum],
|
||||
|
|
|
@ -5,13 +5,13 @@ use parser::Error;
|
|||
|
||||
use super::expression::parse_expr;
|
||||
|
||||
use absy::ExpressionList;
|
||||
use absy::{ExpressionList, ExpressionListNode, Node};
|
||||
|
||||
// parse an expression list
|
||||
pub fn parse_expression_list<T: Field>(
|
||||
input: String,
|
||||
pos: Position,
|
||||
) -> Result<(ExpressionList<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionListNode<T>, String, Position), Error<T>> {
|
||||
let mut res = ExpressionList::new();
|
||||
parse_comma_separated_expression_list_rec(input, pos, &mut res)
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ fn parse_comma_separated_expression_list_rec<T: Field>(
|
|||
input: String,
|
||||
pos: Position,
|
||||
mut acc: &mut ExpressionList<T>,
|
||||
) -> Result<(ExpressionList<T>, String, Position), Error<T>> {
|
||||
) -> Result<(ExpressionListNode<T>, String, Position), Error<T>> {
|
||||
match parse_expr(&input, &pos) {
|
||||
Ok((e1, s1, p1)) => {
|
||||
acc.expressions.push(e1);
|
||||
|
@ -28,7 +28,7 @@ fn parse_comma_separated_expression_list_rec<T: Field>(
|
|||
(Token::Comma, s2, p2) => {
|
||||
parse_comma_separated_expression_list_rec(s2, p2, &mut acc)
|
||||
}
|
||||
(..) => Ok((acc.clone(), s1, p1)),
|
||||
(..) => Ok((Node::new(pos, p1, acc.clone()), s1, p1)),
|
||||
}
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
|
|
|
@ -13,7 +13,7 @@ use super::expression::{
|
|||
};
|
||||
use super::expression_list::parse_expression_list;
|
||||
|
||||
use absy::{Assignee, Expression, Statement, Variable};
|
||||
use absy::{Assignee, AssigneeNode, Expression, Node, Statement, Variable, VariableNode};
|
||||
use types::Type;
|
||||
|
||||
pub fn parse_statement<T: Field, R: BufRead>(
|
||||
|
@ -109,11 +109,11 @@ pub fn parse_statement<T: Field, R: BufRead>(
|
|||
match next_token(&s8, &p8) {
|
||||
(Token::InlineComment(_), ref s9, _) => {
|
||||
assert_eq!(s9, "");
|
||||
return Ok((vec![Statement::For(Variable::new(x2, t), x4, x6, statements)], s8, p8))
|
||||
return Ok((vec![Statement::For(Node::new(p1, p3, Variable::new(x2, t)), x4, x6, statements)], s8, p8))
|
||||
}
|
||||
(Token::Unknown(ref t9), ref s9, _) if t9 == "" => {
|
||||
assert_eq!(s9, "");
|
||||
return Ok((vec![Statement::For(Variable::new(x2, t), x4, x6, statements)], s8, p8))
|
||||
return Ok((vec![Statement::For(Node::new(p1, p3, Variable::new(x2, t)), x4, x6, statements)], s8, p8))
|
||||
},
|
||||
(t9, _, p9) => return Err(Error { expected: vec![Token::Unknown("".to_string())], got: t9 , pos: p9 }),
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ pub fn parse_statement<T: Field, R: BufRead>(
|
|||
}
|
||||
|
||||
fn parse_definition1<T: Field>(
|
||||
x: Assignee<T>,
|
||||
x: AssigneeNode<T>,
|
||||
input: String,
|
||||
pos: Position,
|
||||
) -> Result<(Vec<Statement<T>>, String, Position), Error<T>> {
|
||||
|
@ -226,20 +226,38 @@ fn parse_definition1<T: Field>(
|
|||
Ok((e1, s1, p1)) => match next_token(&s1, &p1) {
|
||||
(Token::InlineComment(_), ref s2, _) => {
|
||||
assert_eq!(s2, "");
|
||||
match e1 {
|
||||
e @ Expression::FunctionCall(..) => {
|
||||
Ok((vec![Statement::MultipleDefinition(vec![x], e)], s1, p1))
|
||||
}
|
||||
e => Ok((vec![Statement::Definition(x, e)], s1, p1)),
|
||||
match e1.value {
|
||||
e @ Expression::FunctionCall(..) => Ok((
|
||||
vec![Statement::MultipleDefinition(
|
||||
vec![x],
|
||||
Node::new(pos, p1, e),
|
||||
)],
|
||||
s1,
|
||||
p1,
|
||||
)),
|
||||
e => Ok((
|
||||
vec![Statement::Definition(x, Node::new(pos, p1, e))],
|
||||
s1,
|
||||
p1,
|
||||
)),
|
||||
}
|
||||
}
|
||||
(Token::Unknown(ref t2), ref s2, _) if t2 == "" => {
|
||||
assert_eq!(s2, "");
|
||||
match e1 {
|
||||
e @ Expression::FunctionCall(..) => {
|
||||
Ok((vec![Statement::MultipleDefinition(vec![x], e)], s1, p1))
|
||||
}
|
||||
e => Ok((vec![Statement::Definition(x, e)], s1, p1)),
|
||||
match e1.value {
|
||||
e @ Expression::FunctionCall(..) => Ok((
|
||||
vec![Statement::MultipleDefinition(
|
||||
vec![x],
|
||||
Node::new(pos, p1, e),
|
||||
)],
|
||||
s1,
|
||||
p1,
|
||||
)),
|
||||
e => Ok((
|
||||
vec![Statement::Definition(x, Node::new(pos, p1, e))],
|
||||
s1,
|
||||
p1,
|
||||
)),
|
||||
}
|
||||
}
|
||||
(t2, _, p2) => Err(Error {
|
||||
|
@ -263,19 +281,33 @@ fn parse_declaration_definition<T: Field>(
|
|||
Ok((e2, s2, p2)) => match next_token(&s2, &p2) {
|
||||
(Token::InlineComment(_), ref s3, _) => {
|
||||
assert_eq!(s3, "");
|
||||
match e2 {
|
||||
match e2.value {
|
||||
e @ Expression::FunctionCall(..) => Ok((
|
||||
vec![
|
||||
Statement::Declaration(Variable::new(x.clone(), t)),
|
||||
Statement::MultipleDefinition(vec![Assignee::Identifier(x)], e),
|
||||
Statement::Declaration(Node::new(
|
||||
pos,
|
||||
p0,
|
||||
Variable::new(x.clone(), t),
|
||||
)),
|
||||
Statement::MultipleDefinition(
|
||||
vec![Node::new(pos, p1, Assignee::Identifier(x))],
|
||||
Node::new(p1, p2, e),
|
||||
),
|
||||
],
|
||||
s2,
|
||||
p2,
|
||||
)),
|
||||
e => Ok((
|
||||
vec![
|
||||
Statement::Declaration(Variable::new(x.clone(), t)),
|
||||
Statement::Definition(Assignee::Identifier(x), e),
|
||||
Statement::Declaration(Node::new(
|
||||
pos,
|
||||
p0,
|
||||
Variable::new(x.clone(), t),
|
||||
)),
|
||||
Statement::Definition(
|
||||
Node::new(pos, p1, Assignee::Identifier(x)),
|
||||
Node::new(p1, p2, e),
|
||||
),
|
||||
],
|
||||
s2,
|
||||
p2,
|
||||
|
@ -284,19 +316,33 @@ fn parse_declaration_definition<T: Field>(
|
|||
}
|
||||
(Token::Unknown(ref t3), ref s3, _) if t3 == "" => {
|
||||
assert_eq!(s3, "");
|
||||
match e2 {
|
||||
match e2.value {
|
||||
e @ Expression::FunctionCall(..) => Ok((
|
||||
vec![
|
||||
Statement::Declaration(Variable::new(x.clone(), t)),
|
||||
Statement::MultipleDefinition(vec![Assignee::Identifier(x)], e),
|
||||
Statement::Declaration(Node::new(
|
||||
pos,
|
||||
p0,
|
||||
Variable::new(x.clone(), t),
|
||||
)),
|
||||
Statement::MultipleDefinition(
|
||||
vec![Node::new(pos, p1, Assignee::Identifier(x))],
|
||||
Node::new(p1, p2, e),
|
||||
),
|
||||
],
|
||||
s2,
|
||||
p2,
|
||||
)),
|
||||
e => Ok((
|
||||
vec![
|
||||
Statement::Declaration(Variable::new(x.clone(), t)),
|
||||
Statement::Definition(Assignee::Identifier(x), e),
|
||||
Statement::Declaration(Node::new(
|
||||
pos,
|
||||
p0,
|
||||
Variable::new(x.clone(), t),
|
||||
)),
|
||||
Statement::Definition(
|
||||
Node::new(pos, p1, Assignee::Identifier(x)),
|
||||
Node::new(p1, p2, e),
|
||||
),
|
||||
],
|
||||
s2,
|
||||
p2,
|
||||
|
@ -324,10 +370,20 @@ fn parse_declaration_definition<T: Field>(
|
|||
// then we should have an equal sign
|
||||
(Token::Eq, s3, p3) => match parse_expr(&s3, &p3) {
|
||||
Ok((e4, s4, p4)) => {
|
||||
let mut statements: Vec<Statement<T>> =
|
||||
d2.into_iter().map(|v| Statement::Declaration(v)).collect();
|
||||
let mut statements: Vec<Statement<T>> = d2
|
||||
.iter()
|
||||
.map(|v| Statement::Declaration(v.clone()))
|
||||
.collect();
|
||||
statements.push(Statement::MultipleDefinition(
|
||||
e2.into_iter().map(|e| Assignee::Identifier(e)).collect(),
|
||||
d2.iter()
|
||||
.map(|v| {
|
||||
Node::new(
|
||||
v.start,
|
||||
v.end,
|
||||
Assignee::Identifier(v.value.id.clone()),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
e4,
|
||||
));
|
||||
Ok((statements, s4, p4)) // output a multipledefinition with the destructure and the expression
|
||||
|
@ -362,18 +418,36 @@ fn parse_statement1<T: Field>(
|
|||
input: String,
|
||||
pos: Position,
|
||||
) -> Result<(Vec<Statement<T>>, String, Position), Error<T>> {
|
||||
let ide_start_position = Position {
|
||||
line: pos.line - ide.len(),
|
||||
..pos
|
||||
};
|
||||
match next_token::<T>(&input, &pos) {
|
||||
(Token::Eq, s1, p1) => parse_definition1(Assignee::Identifier(ide), s1, p1),
|
||||
(Token::Eq, s1, p1) => parse_definition1(
|
||||
Node::new(ide_start_position, pos, Assignee::Identifier(ide)),
|
||||
s1,
|
||||
p1,
|
||||
),
|
||||
(Token::Comma, s1, p1) => match parse_identifier_list1(ide, None, s1, p1) {
|
||||
// if we find a comma, parse the rest of the destructure
|
||||
Ok((e2, d2, s2, p2)) => match next_token(&s2, &p2) {
|
||||
// then we should have an equal sign
|
||||
(Token::Eq, s3, p3) => match parse_expr(&s3, &p3) {
|
||||
Ok((e4, s4, p4)) => {
|
||||
let mut statements: Vec<Statement<T>> =
|
||||
d2.into_iter().map(|v| Statement::Declaration(v)).collect();
|
||||
let mut statements: Vec<Statement<T>> = d2
|
||||
.iter()
|
||||
.map(|v| Statement::Declaration(v.clone()))
|
||||
.collect();
|
||||
statements.push(Statement::MultipleDefinition(
|
||||
e2.into_iter().map(|e| Assignee::Identifier(e)).collect(),
|
||||
d2.iter()
|
||||
.map(|v| {
|
||||
Node::new(
|
||||
v.start,
|
||||
v.end,
|
||||
Assignee::Identifier(v.value.id.clone()),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
e4,
|
||||
));
|
||||
Ok((statements, s4, p4)) // output a multipledefinition with the destructure and the expression
|
||||
|
@ -454,7 +528,7 @@ fn parse_statement1<T: Field>(
|
|||
},
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Eq, s5, p5) => parse_definition1(Assignee::from(e4), s5, p5),
|
||||
(Token::Eq, s5, p5) => parse_definition1(AssigneeNode::from(e4), s5, p5),
|
||||
(t4, _, p4) => Err(Error {
|
||||
expected: vec![Token::Eqeq],
|
||||
got: t4,
|
||||
|
@ -465,7 +539,11 @@ fn parse_statement1<T: Field>(
|
|||
},
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
_ => match parse_term1(Expression::Identifier(ide), input, pos) {
|
||||
_ => match parse_term1(
|
||||
Node::new(ide_start_position, pos, Expression::Identifier(ide)),
|
||||
input,
|
||||
pos,
|
||||
) {
|
||||
Ok((e2, s2, p2)) => match parse_expr1(e2, s2, p2) {
|
||||
Ok((e3, s3, p3)) => match next_token(&s3, &p3) {
|
||||
(Token::Eqeq, s4, p4) => match parse_expr(&s4, &p4) {
|
||||
|
@ -512,13 +590,17 @@ pub fn parse_identifier_list1<T: Field>(
|
|||
_type: Option<Type>,
|
||||
input: String,
|
||||
pos: Position,
|
||||
) -> Result<(Vec<String>, Vec<Variable>, String, Position), Error<T>> {
|
||||
) -> Result<(Vec<String>, Vec<VariableNode>, String, Position), Error<T>> {
|
||||
let mut res = Vec::new();
|
||||
let mut decl = Vec::new();
|
||||
res.push(head.clone());
|
||||
match _type {
|
||||
Some(t) => {
|
||||
decl.push(Variable::new(head, t));
|
||||
let pos_before = Position {
|
||||
col: pos.col - head.len(),
|
||||
..pos
|
||||
};
|
||||
decl.push(Node::new(pos_before, pos, Variable::new(head, t)));
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
@ -529,13 +611,13 @@ fn parse_comma_separated_identifier_list_rec<T: Field>(
|
|||
input: String,
|
||||
pos: Position,
|
||||
mut acc: &mut Vec<String>,
|
||||
mut decl: &mut Vec<Variable>,
|
||||
) -> Result<(Vec<String>, Vec<Variable>, String, Position), Error<T>> {
|
||||
mut decl: &mut Vec<VariableNode>,
|
||||
) -> Result<(Vec<String>, Vec<VariableNode>, String, Position), Error<T>> {
|
||||
match next_token(&input, &pos) {
|
||||
(Token::Type(t), s1, p1) => match next_token::<T>(&s1, &p1) {
|
||||
(Token::Ide(id), s2, p2) => {
|
||||
acc.push(id.clone());
|
||||
decl.push(Variable::new(id, t));
|
||||
decl.push(Node::new(pos, p2, Variable::new(id, t)));
|
||||
match next_token::<T>(&s2, &p2) {
|
||||
(Token::Comma, s3, p3) => {
|
||||
parse_comma_separated_identifier_list_rec(s3, p3, &mut acc, &mut decl)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::fmt;
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
#[derive(Clone, PartialEq, Copy, Serialize, Deserialize)]
|
||||
pub struct Position {
|
||||
pub line: usize,
|
||||
pub col: usize,
|
||||
|
|
|
@ -14,18 +14,42 @@ use typed_absy::*;
|
|||
use types::Signature;
|
||||
use zokrates_field::field::Field;
|
||||
|
||||
use parser::Position;
|
||||
|
||||
use types::Type;
|
||||
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct Error {
|
||||
message: String,
|
||||
}
|
||||
pub struct Error(Vec<SingleError>);
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.message)
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
self.0
|
||||
.iter()
|
||||
.map(|x| x.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct SingleError {
|
||||
pos: Option<(Position, Position)>,
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for SingleError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let location = self
|
||||
.pos
|
||||
.map(|p| format!("At {}:{} | ", p.0, p.1))
|
||||
.unwrap_or("".to_string());
|
||||
write!(f, "{}{}", location, self.message)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,18 +160,32 @@ impl Checker {
|
|||
});
|
||||
}
|
||||
|
||||
let mut errors = vec![];
|
||||
let mut checked_functions = vec![];
|
||||
|
||||
for func in prog.functions {
|
||||
let checked_func = self.check_function(&func)?;
|
||||
checked_functions.push(checked_func);
|
||||
match self.check_function(&func) {
|
||||
Ok(checked_function) => {
|
||||
checked_functions.push(checked_function);
|
||||
}
|
||||
Err(e) => {
|
||||
errors.push(e);
|
||||
}
|
||||
};
|
||||
self.functions.insert(FunctionDeclaration {
|
||||
id: func.id,
|
||||
signature: func.signature,
|
||||
});
|
||||
}
|
||||
|
||||
self.check_single_main()?;
|
||||
match self.check_single_main() {
|
||||
Ok(()) => {}
|
||||
Err(e) => errors.push(e),
|
||||
};
|
||||
|
||||
if errors.len() > 0 {
|
||||
return Err(Error(errors));
|
||||
}
|
||||
|
||||
Ok(TypedProg {
|
||||
functions: checked_functions,
|
||||
|
@ -156,28 +194,34 @@ impl Checker {
|
|||
})
|
||||
}
|
||||
|
||||
fn check_single_main(&mut self) -> Result<(), Error> {
|
||||
fn check_single_main(&mut self) -> Result<(), SingleError> {
|
||||
match self.functions.iter().filter(|fun| fun.id == "main").count() {
|
||||
1 => Ok(()),
|
||||
0 => Err(Error {
|
||||
0 => Err(SingleError {
|
||||
pos: None,
|
||||
message: format!("No main function found"),
|
||||
}),
|
||||
n => Err(Error {
|
||||
n => Err(SingleError {
|
||||
pos: None,
|
||||
message: format!("Only one main function allowed, found {}", n),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_for_var(&self, var: &Variable) -> Result<(), Error> {
|
||||
match var.get_type() {
|
||||
fn check_for_var(&self, var: &VariableNode) -> Result<(), SingleError> {
|
||||
match var.value.get_type() {
|
||||
Type::FieldElement => Ok(()),
|
||||
t => Err(Error {
|
||||
t => Err(SingleError {
|
||||
pos: Some(var.pos()),
|
||||
message: format!("Variable in for loop cannot have type {}", t),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_function<T: Field>(&mut self, funct: &Function<T>) -> Result<TypedFunction<T>, Error> {
|
||||
fn check_function<T: Field>(
|
||||
&mut self,
|
||||
funct: &Function<T>,
|
||||
) -> Result<TypedFunction<T>, SingleError> {
|
||||
assert_eq!(funct.arguments.len(), funct.signature.inputs.len());
|
||||
|
||||
let query = FunctionQuery::new(
|
||||
|
@ -196,7 +240,8 @@ impl Checker {
|
|||
|
||||
match candidates.len() {
|
||||
1 => {
|
||||
return Err(Error {
|
||||
return Err(SingleError {
|
||||
pos: None,
|
||||
message: format!(
|
||||
"Duplicate definition for function {} with signature {}",
|
||||
funct.id, funct.signature
|
||||
|
@ -234,11 +279,12 @@ impl Checker {
|
|||
&mut self,
|
||||
stat: &Statement<T>,
|
||||
header_return_types: &Vec<Type>,
|
||||
) -> Result<TypedStatement<T>, Error> {
|
||||
) -> Result<TypedStatement<T>, SingleError> {
|
||||
let pos = None;
|
||||
match stat {
|
||||
Statement::Return(ref list) => {
|
||||
let mut expression_list_checked = vec![];
|
||||
for e in list.expressions.clone() {
|
||||
for e in list.value.expressions.clone() {
|
||||
let e_checked = self.check_expression(&e)?;
|
||||
expression_list_checked.push(e_checked);
|
||||
}
|
||||
|
@ -250,7 +296,8 @@ impl Checker {
|
|||
|
||||
match return_statement_types == *header_return_types {
|
||||
true => Ok(TypedStatement::Return(expression_list_checked)),
|
||||
false => Err(Error {
|
||||
false => Err(SingleError {
|
||||
pos,
|
||||
message: format!(
|
||||
"Expected {:?} in return statement, found {:?}",
|
||||
header_return_types, return_statement_types
|
||||
|
@ -258,16 +305,17 @@ impl Checker {
|
|||
}),
|
||||
}
|
||||
}
|
||||
Statement::Declaration(ref var) => match self.insert_scope(var.clone()) {
|
||||
true => Ok(TypedStatement::Declaration(var.clone())),
|
||||
false => Err(Error {
|
||||
message: format!("Duplicate declaration for variable named {}", var.id),
|
||||
Statement::Declaration(ref var) => match self.insert_scope(var.clone().value) {
|
||||
true => Ok(TypedStatement::Declaration(var.clone().value)),
|
||||
false => Err(SingleError {
|
||||
pos,
|
||||
message: format!("Duplicate declaration for variable named {}", var.value.id),
|
||||
}),
|
||||
},
|
||||
Statement::Definition(assignee, expr) => {
|
||||
// we create multidef when rhs is a function call to benefit from inference
|
||||
// check rhs is not a function call here
|
||||
match expr {
|
||||
match expr.value {
|
||||
Expression::FunctionCall(..) => panic!("Parser should not generate Definition where the right hand side is a FunctionCall"),
|
||||
_ => {}
|
||||
}
|
||||
|
@ -284,10 +332,11 @@ impl Checker {
|
|||
// make sure the assignee has the same type as the rhs
|
||||
match var_type == expression_type {
|
||||
true => Ok(TypedStatement::Definition(var, checked_expr)),
|
||||
false => Err(Error {
|
||||
false => Err(SingleError {
|
||||
pos,
|
||||
message: format!(
|
||||
"Expression of type {} cannot be assigned to {} of type {}",
|
||||
expression_type, var, var_type
|
||||
"Expression {} of type {} cannot be assigned to {} of type {}",
|
||||
expr, expression_type, assignee, var_type
|
||||
),
|
||||
}),
|
||||
}
|
||||
|
@ -300,9 +349,12 @@ impl Checker {
|
|||
(ref r, ref l) if r.get_type() == l.get_type() => {
|
||||
Ok(TypedStatement::Condition(checked_lhs, checked_rhs))
|
||||
}
|
||||
(e1, e2) => Err(Error {
|
||||
(e1, e2) => Err(SingleError {
|
||||
pos,
|
||||
message: format!(
|
||||
"cannot compare {:?} to {:?}",
|
||||
"cannot compare {} of type {:?} to {} of type {:?}",
|
||||
lhs,
|
||||
rhs,
|
||||
e1.get_type(),
|
||||
e2.get_type()
|
||||
),
|
||||
|
@ -314,7 +366,7 @@ impl Checker {
|
|||
|
||||
self.check_for_var(&var)?;
|
||||
|
||||
self.insert_scope(var.clone());
|
||||
self.insert_scope(var.clone().value);
|
||||
|
||||
let mut checked_statements = vec![];
|
||||
|
||||
|
@ -325,28 +377,28 @@ impl Checker {
|
|||
|
||||
self.exit_scope();
|
||||
Ok(TypedStatement::For(
|
||||
var.clone(),
|
||||
var.clone().value,
|
||||
from.clone(),
|
||||
to.clone(),
|
||||
checked_statements,
|
||||
))
|
||||
}
|
||||
Statement::MultipleDefinition(assignees, rhs) => {
|
||||
match rhs {
|
||||
match rhs.value {
|
||||
// Right side has to be a function call
|
||||
Expression::FunctionCall(ref fun_id, ref arguments) => {
|
||||
// find lhs types
|
||||
let mut vars_types: Vec<Option<Type>> = vec![];
|
||||
let mut var_names = vec![];
|
||||
for assignee in assignees {
|
||||
let (name, t) = match assignee {
|
||||
Assignee::Identifier(name) => {
|
||||
let (name, t) = match assignee.value {
|
||||
Assignee::Identifier(ref name) => {
|
||||
Ok((name, match self.get_scope(&name) {
|
||||
None => None,
|
||||
Some(sv) => Some(sv.id.get_type())
|
||||
}))
|
||||
}
|
||||
a => Err(Error { message: format!("Left hand side of function return assignment must be a list of identifiers, found {}", a)})
|
||||
ref a => Err(SingleError { pos, message: format!("Left hand side of function return assignment must be a list of identifiers, found {}", a)})
|
||||
}?;
|
||||
vars_types.push(t);
|
||||
var_names.push(name);
|
||||
|
@ -354,7 +406,7 @@ impl Checker {
|
|||
// find arguments types
|
||||
let mut arguments_checked = vec![];
|
||||
for arg in arguments {
|
||||
let arg_checked = self.check_expression(arg)?;
|
||||
let arg_checked = self.check_expression(&arg)?;
|
||||
arguments_checked.push(arg_checked);
|
||||
}
|
||||
|
||||
|
@ -381,11 +433,12 @@ impl Checker {
|
|||
|
||||
Ok(TypedStatement::MultipleDefinition(lhs.collect(), TypedExpressionList::FunctionCall(f.id.clone(), arguments_checked, f.signature.outputs.clone())))
|
||||
},
|
||||
0 => Err(Error { message: format!("Function definition for function {} with signature {} not found.", fun_id, query) }),
|
||||
_ => Err(Error { message: format!("Function call for function {} with arguments {:?} is ambiguous.", fun_id, arguments_types) }),
|
||||
0 => Err(SingleError { pos, message: format!("Function definition for function {} with signature {} not found.", fun_id, query) }),
|
||||
_ => Err(SingleError { pos, message: format!("Function call for function {} with arguments {:?} is ambiguous.", fun_id, arguments_types) }),
|
||||
}
|
||||
}
|
||||
_ => Err(Error {
|
||||
_ => Err(SingleError {
|
||||
pos: None,
|
||||
message: format!("{} should be a FunctionCall", rhs),
|
||||
}),
|
||||
}
|
||||
|
@ -395,23 +448,26 @@ impl Checker {
|
|||
|
||||
fn check_assignee<T: Field>(
|
||||
&mut self,
|
||||
assignee: &Assignee<T>,
|
||||
) -> Result<TypedAssignee<T>, Error> {
|
||||
assignee: &AssigneeNode<T>,
|
||||
) -> Result<TypedAssignee<T>, SingleError> {
|
||||
// check that the assignee is declared
|
||||
match assignee {
|
||||
Assignee::Identifier(variable_name) => match self.get_scope(&variable_name) {
|
||||
match assignee.value {
|
||||
Assignee::Identifier(ref variable_name) => match self.get_scope(&variable_name) {
|
||||
Some(var) => Ok(TypedAssignee::Identifier(var.id.clone())),
|
||||
None => Err(Error {
|
||||
None => Err(SingleError {
|
||||
pos: Some(assignee.pos()),
|
||||
message: format!("Undeclared variable: {:?}", variable_name),
|
||||
}),
|
||||
},
|
||||
Assignee::ArrayElement(box assignee, box index) => {
|
||||
Assignee::ArrayElement(ref assignee, ref index) => {
|
||||
let checked_assignee = self.check_assignee(&assignee)?;
|
||||
let checked_index = self.check_expression(&index)?;
|
||||
|
||||
let checked_typed_index = match checked_index {
|
||||
TypedExpression::FieldElement(e) => Ok(e),
|
||||
e => Err(Error {
|
||||
e => Err(SingleError {
|
||||
pos: Some(assignee.pos()),
|
||||
|
||||
message: format!(
|
||||
"Expected array {} index to have type field, found {}",
|
||||
assignee,
|
||||
|
@ -430,9 +486,9 @@ impl Checker {
|
|||
|
||||
fn check_expression<T: Field>(
|
||||
&mut self,
|
||||
expr: &Expression<T>,
|
||||
) -> Result<TypedExpression<T>, Error> {
|
||||
match expr {
|
||||
expr: &ExpressionNode<T>,
|
||||
) -> Result<TypedExpression<T>, SingleError> {
|
||||
match &expr.value {
|
||||
&Expression::Identifier(ref name) => {
|
||||
// check that `id` is defined in the scope
|
||||
match self.get_scope(&name) {
|
||||
|
@ -445,8 +501,10 @@ impl Checker {
|
|||
Ok(FieldElementArrayExpression::Identifier(n, name.to_string()).into())
|
||||
}
|
||||
},
|
||||
None => Err(Error {
|
||||
message: format!("{} is undefined", name.to_string()),
|
||||
None => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!("Identifier is undefined"),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -458,7 +516,9 @@ impl Checker {
|
|||
(TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => {
|
||||
Ok(FieldElementExpression::Add(box e1, box e2).into())
|
||||
}
|
||||
(t1, t2) => Err(Error {
|
||||
(t1, t2) => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!(
|
||||
"Expected only field elements, found {:?}, {:?}",
|
||||
t1.get_type(),
|
||||
|
@ -475,7 +535,9 @@ impl Checker {
|
|||
(TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => {
|
||||
Ok(FieldElementExpression::Sub(box e1, box e2).into())
|
||||
}
|
||||
(t1, t2) => Err(Error {
|
||||
(t1, t2) => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!(
|
||||
"Expected only field elements, found {:?}, {:?}",
|
||||
t1.get_type(),
|
||||
|
@ -492,7 +554,9 @@ impl Checker {
|
|||
(TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => {
|
||||
Ok(FieldElementExpression::Mult(box e1, box e2).into())
|
||||
}
|
||||
(t1, t2) => Err(Error {
|
||||
(t1, t2) => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!(
|
||||
"Expected only field elements, found {:?}, {:?}",
|
||||
t1.get_type(),
|
||||
|
@ -509,7 +573,9 @@ impl Checker {
|
|||
(TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => {
|
||||
Ok(FieldElementExpression::Div(box e1, box e2).into())
|
||||
}
|
||||
(t1, t2) => Err(Error {
|
||||
(t1, t2) => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!(
|
||||
"Expected only field elements, found {:?}, {:?}",
|
||||
t1.get_type(),
|
||||
|
@ -526,7 +592,9 @@ impl Checker {
|
|||
(TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => Ok(
|
||||
TypedExpression::FieldElement(FieldElementExpression::Pow(box e1, box e2)),
|
||||
),
|
||||
(t1, t2) => Err(Error {
|
||||
(t1, t2) => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!(
|
||||
"Expected only field elements, found {:?}, {:?}",
|
||||
t1.get_type(),
|
||||
|
@ -546,7 +614,9 @@ impl Checker {
|
|||
},
|
||||
(condition, consequence, alternative) =>
|
||||
Err(
|
||||
Error {
|
||||
SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message:
|
||||
format!("if {{condition}} then {{consequence}} else {{alternative}} should have types {}, {}, {}, found {}, {}, {}",
|
||||
Type::Boolean,
|
||||
|
@ -602,7 +672,9 @@ impl Checker {
|
|||
}
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
n => Err(Error {
|
||||
n => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!(
|
||||
"{} returns {} values but is called outside of a definition",
|
||||
f.id, n
|
||||
|
@ -610,7 +682,9 @@ impl Checker {
|
|||
}),
|
||||
}
|
||||
}
|
||||
0 => Err(Error {
|
||||
0 => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!(
|
||||
"Function definition for function {} with signature {} not found.",
|
||||
fun_id, query
|
||||
|
@ -626,7 +700,9 @@ impl Checker {
|
|||
(TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => {
|
||||
Ok(BooleanExpression::Lt(box e1, box e2).into())
|
||||
}
|
||||
(e1, e2) => Err(Error {
|
||||
(e1, e2) => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!("cannot compare {} to {}", e1.get_type(), e2.get_type()),
|
||||
}),
|
||||
}
|
||||
|
@ -638,7 +714,9 @@ impl Checker {
|
|||
(TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => {
|
||||
Ok(BooleanExpression::Le(box e1, box e2).into())
|
||||
}
|
||||
(e1, e2) => Err(Error {
|
||||
(e1, e2) => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!("cannot compare {} to {}", e1.get_type(), e2.get_type()),
|
||||
}),
|
||||
}
|
||||
|
@ -650,7 +728,9 @@ impl Checker {
|
|||
(TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => {
|
||||
Ok(BooleanExpression::Eq(box e1, box e2).into())
|
||||
}
|
||||
(e1, e2) => Err(Error {
|
||||
(e1, e2) => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!("cannot compare {} to {}", e1.get_type(), e2.get_type()),
|
||||
}),
|
||||
}
|
||||
|
@ -662,7 +742,9 @@ impl Checker {
|
|||
(TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => {
|
||||
Ok(BooleanExpression::Ge(box e1, box e2).into())
|
||||
}
|
||||
(e1, e2) => Err(Error {
|
||||
(e1, e2) => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!("Cannot compare {} to {}", e1.get_type(), e2.get_type()),
|
||||
}),
|
||||
}
|
||||
|
@ -674,7 +756,9 @@ impl Checker {
|
|||
(TypedExpression::FieldElement(e1), TypedExpression::FieldElement(e2)) => {
|
||||
Ok(BooleanExpression::Gt(box e1, box e2).into())
|
||||
}
|
||||
(e1, e2) => Err(Error {
|
||||
(e1, e2) => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!("Cannot compare {} to {}", e1.get_type(), e2.get_type()),
|
||||
}),
|
||||
}
|
||||
|
@ -687,7 +771,9 @@ impl Checker {
|
|||
TypedExpression::FieldElementArray(ref a),
|
||||
TypedExpression::FieldElement(ref i),
|
||||
) => Ok(FieldElementExpression::Select(box a.clone(), box i.clone()).into()),
|
||||
(a, e) => Err(Error {
|
||||
(a, e) => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!(
|
||||
"Cannot take element {} on expression of type {}",
|
||||
e,
|
||||
|
@ -717,7 +803,9 @@ impl Checker {
|
|||
for e in expressions_checked {
|
||||
let unwrapped_e = match e {
|
||||
TypedExpression::FieldElement(e) => Ok(e),
|
||||
e => Err(Error {
|
||||
e => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!(
|
||||
"Expected {} to have type {}, but type is {}",
|
||||
e,
|
||||
|
@ -731,7 +819,9 @@ impl Checker {
|
|||
|
||||
Ok(FieldElementArrayExpression::Value(size, unwrapped_expressions).into())
|
||||
}
|
||||
_ => Err(Error {
|
||||
_ => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!(
|
||||
"Only arrays of {} are supported, found {}",
|
||||
Type::FieldElement,
|
||||
|
@ -747,7 +837,9 @@ impl Checker {
|
|||
(TypedExpression::Boolean(e1), TypedExpression::Boolean(e2)) => {
|
||||
Ok(BooleanExpression::And(box e1, box e2).into())
|
||||
}
|
||||
(e1, e2) => Err(Error {
|
||||
(e1, e2) => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!(
|
||||
"cannot apply boolean operators to {} and {}",
|
||||
e1.get_type(),
|
||||
|
@ -763,7 +855,9 @@ impl Checker {
|
|||
(TypedExpression::Boolean(e1), TypedExpression::Boolean(e2)) => {
|
||||
Ok(BooleanExpression::Or(box e1, box e2).into())
|
||||
}
|
||||
(e1, e2) => Err(Error {
|
||||
(e1, e2) => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!("cannot compare {} to {}", e1.get_type(), e2.get_type()),
|
||||
}),
|
||||
}
|
||||
|
@ -772,7 +866,9 @@ impl Checker {
|
|||
let e_checked = self.check_expression(e)?;
|
||||
match e_checked {
|
||||
TypedExpression::Boolean(e) => Ok(BooleanExpression::Not(box e).into()),
|
||||
e => Err(Error {
|
||||
e => Err(SingleError {
|
||||
pos: Some(expr.pos()),
|
||||
|
||||
message: format!("cannot negate {}", e.get_type()),
|
||||
}),
|
||||
}
|
||||
|
@ -839,7 +935,7 @@ mod tests {
|
|||
let mut checker = Checker::new();
|
||||
assert_eq!(
|
||||
checker.check_statement(&statement, &vec![]),
|
||||
Err(Error {
|
||||
Err(SingleError {
|
||||
message: "b is undefined".to_string()
|
||||
})
|
||||
);
|
||||
|
@ -924,7 +1020,7 @@ mod tests {
|
|||
let mut checker = Checker::new();
|
||||
assert_eq!(
|
||||
checker.check_program(prog),
|
||||
Err(Error {
|
||||
Err(SingleError {
|
||||
message: "a is undefined".to_string()
|
||||
})
|
||||
);
|
||||
|
@ -1039,7 +1135,7 @@ mod tests {
|
|||
let mut checker = Checker::new();
|
||||
assert_eq!(
|
||||
checker.check_function(&foo),
|
||||
Err(Error {
|
||||
Err(SingleError {
|
||||
message: "i is undefined".to_string()
|
||||
})
|
||||
);
|
||||
|
@ -1146,7 +1242,7 @@ mod tests {
|
|||
let mut checker = new_with_args(HashSet::new(), 0, functions);
|
||||
assert_eq!(
|
||||
checker.check_function(&bar),
|
||||
Err(Error {
|
||||
Err(SingleError {
|
||||
message:
|
||||
"Function definition for function foo with signature () -> (field) not found."
|
||||
.to_string()
|
||||
|
@ -1190,7 +1286,7 @@ mod tests {
|
|||
let mut checker = new_with_args(HashSet::new(), 0, functions);
|
||||
assert_eq!(
|
||||
checker.check_function(&bar),
|
||||
Err(Error {
|
||||
Err(SingleError {
|
||||
message: "Function definition for function foo with signature () -> (_) not found."
|
||||
.to_string()
|
||||
})
|
||||
|
@ -1223,7 +1319,7 @@ mod tests {
|
|||
let mut checker = new_with_args(HashSet::new(), 0, HashSet::new());
|
||||
assert_eq!(
|
||||
checker.check_function(&bar),
|
||||
Err(Error {
|
||||
Err(SingleError {
|
||||
message:
|
||||
"Function definition for function foo with signature () -> (field) not found."
|
||||
.to_string()
|
||||
|
@ -1297,7 +1393,7 @@ mod tests {
|
|||
let mut checker = new_with_args(HashSet::new(), 0, HashSet::new());
|
||||
assert_eq!(
|
||||
checker.check_program(program),
|
||||
Err(Error {
|
||||
Err(SingleError {
|
||||
message: "x is undefined".to_string()
|
||||
})
|
||||
);
|
||||
|
@ -1326,7 +1422,7 @@ mod tests {
|
|||
let mut checker = new_with_args(HashSet::new(), 0, HashSet::new());
|
||||
assert_eq!(
|
||||
checker.check_function(&bar),
|
||||
Err(Error {
|
||||
Err(SingleError {
|
||||
message: "Function definition for function foo with signature () -> (_) not found."
|
||||
.to_string()
|
||||
})
|
||||
|
@ -1358,7 +1454,7 @@ mod tests {
|
|||
let mut checker = new_with_args(HashSet::new(), 0, HashSet::new());
|
||||
assert_eq!(
|
||||
checker.check_function(&bar),
|
||||
Err(Error {
|
||||
Err(SingleError {
|
||||
message: "a is undefined".to_string()
|
||||
})
|
||||
);
|
||||
|
@ -1491,7 +1587,7 @@ mod tests {
|
|||
let mut checker = new_with_args(HashSet::new(), 0, functions);
|
||||
assert_eq!(
|
||||
checker.check_function(&foo2),
|
||||
Err(Error {
|
||||
Err(SingleError {
|
||||
message:
|
||||
"Duplicate definition for function foo with signature (field, field) -> (field)"
|
||||
.to_string()
|
||||
|
@ -1553,7 +1649,7 @@ mod tests {
|
|||
let mut checker = Checker::new();
|
||||
assert_eq!(
|
||||
checker.check_program(prog),
|
||||
Err(Error {
|
||||
Err(SingleError {
|
||||
message: "Only one main function allowed, found 2".to_string()
|
||||
})
|
||||
);
|
||||
|
@ -1567,17 +1663,17 @@ mod tests {
|
|||
// should fail
|
||||
|
||||
let mut checker = Checker::new();
|
||||
let _: Result<TypedStatement<FieldPrime>, Error> = checker.check_statement(
|
||||
let _: Result<TypedStatement<FieldPrime>, SingleError> = checker.check_statement(
|
||||
&Statement::Declaration(Variable::field_element("a")),
|
||||
&vec![],
|
||||
);
|
||||
let s2_checked: Result<TypedStatement<FieldPrime>, Error> = checker.check_statement(
|
||||
let s2_checked: Result<TypedStatement<FieldPrime>, SingleError> = checker.check_statement(
|
||||
&Statement::Declaration(Variable::field_element("a")),
|
||||
&vec![],
|
||||
);
|
||||
assert_eq!(
|
||||
s2_checked,
|
||||
Err(Error {
|
||||
Err(SingleError {
|
||||
message: "Duplicate declaration for variable named a".to_string()
|
||||
})
|
||||
);
|
||||
|
@ -1591,15 +1687,15 @@ mod tests {
|
|||
// should fail
|
||||
|
||||
let mut checker = Checker::new();
|
||||
let _: Result<TypedStatement<FieldPrime>, Error> = checker.check_statement(
|
||||
let _: Result<TypedStatement<FieldPrime>, SingleError> = checker.check_statement(
|
||||
&Statement::Declaration(Variable::field_element("a")),
|
||||
&vec![],
|
||||
);
|
||||
let s2_checked: Result<TypedStatement<FieldPrime>, Error> =
|
||||
let s2_checked: Result<TypedStatement<FieldPrime>, SingleError> =
|
||||
checker.check_statement(&Statement::Declaration(Variable::boolean("a")), &vec![]);
|
||||
assert_eq!(
|
||||
s2_checked,
|
||||
Err(Error {
|
||||
Err(SingleError {
|
||||
message: "Duplicate declaration for variable named a".to_string()
|
||||
})
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue