1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

pass positions to absy, allow one error per function

This commit is contained in:
schaeff 2019-01-16 22:59:20 +01:00
parent f39214df65
commit d1295adc49
10 changed files with 531 additions and 221 deletions

View file

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

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

View file

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

View file

@ -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),
};

View file

@ -4,3 +4,4 @@ mod tokenize;
pub use parser::error::Error;
pub use parser::parse::parse_program;
pub use parser::tokenize::Position;

View file

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

View file

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

View file

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

View file

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

View file

@ -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()
})
);