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

add multiple errors, add node for all AST, fix tests ignoring positions

This commit is contained in:
schaeff 2019-01-18 11:49:16 +01:00
parent d1295adc49
commit e084165adc
22 changed files with 1824 additions and 1383 deletions

View file

@ -233,7 +233,7 @@ fn main() {
match matches.subcommand() {
("compile", Some(sub_matches)) => {
println!("Compiling {}", sub_matches.value_of("input").unwrap());
println!("Compiling {}\n", sub_matches.value_of("input").unwrap());
let path = PathBuf::from(sub_matches.value_of("input").unwrap());
@ -258,7 +258,10 @@ fn main() {
let program_flattened: ir::Prog<FieldPrime> =
match compile(&mut reader, Some(location), Some(fs_resolve)) {
Ok(p) => p,
Err(why) => panic!("Compilation failed: {}", why),
Err(why) => {
println!("Compilation failed:\n\n{}", why);
std::process::exit(1);
}
};
// number of constraints the flattened program will translate to.

View file

@ -9,21 +9,21 @@ mod node;
pub mod parameter;
pub mod variable;
pub use absy::node::Node;
pub use absy::parameter::Parameter;
pub use absy::node::{Node, NodeValue};
pub use absy::parameter::{Parameter, ParameterNode};
pub use absy::variable::{Variable, VariableNode};
use types::Signature;
use flat_absy::*;
use imports::Import;
use imports::ImportNode;
use std::fmt;
use zokrates_field::field::Field;
#[derive(Clone, PartialEq)]
pub struct Prog<T: Field> {
/// Functions of the program
pub functions: Vec<Function<T>>,
pub imports: Vec<Import>,
pub functions: Vec<FunctionNode<T>>,
pub imports: Vec<ImportNode>,
pub imported_functions: Vec<FlatFunction<T>>,
}
@ -81,13 +81,15 @@ pub struct Function<T: Field> {
/// Name of the program
pub id: String,
/// Arguments of the function
pub arguments: Vec<Parameter>,
pub arguments: Vec<ParameterNode>,
/// Vector of statements that are executed when running the function
pub statements: Vec<Statement<T>>,
pub statements: Vec<StatementNode<T>>,
/// function signature
pub signature: Signature,
}
pub type FunctionNode<T> = Node<Function<T>>;
impl<T: Field> fmt::Display for Function<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
@ -176,10 +178,12 @@ pub enum Statement<T: Field> {
Declaration(VariableNode),
Definition(AssigneeNode<T>, ExpressionNode<T>),
Condition(ExpressionNode<T>, ExpressionNode<T>),
For(VariableNode, T, T, Vec<Statement<T>>),
For(VariableNode, T, T, Vec<StatementNode<T>>),
MultipleDefinition(Vec<AssigneeNode<T>>, ExpressionNode<T>),
}
pub type StatementNode<T> = Node<Statement<T>>;
impl<T: Field> fmt::Display for Statement<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {

View file

@ -1,7 +1,7 @@
use parser::Position;
use std::fmt;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Node<T: fmt::Display> {
pub start: Position,
pub end: Position,
@ -16,7 +16,7 @@ impl<T: fmt::Display> Node<T> {
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)
write!(f, "{}", self.value)
}
}
@ -25,3 +25,38 @@ impl<T: fmt::Display> Node<T> {
Node { start, end, value }
}
}
pub trait NodeValue: fmt::Display + Sized + PartialEq {
fn at(self, line: usize, col: usize, delta: isize) -> Node<Self> {
let start = Position { col, line };
Node::new(start, start.col(delta), self)
}
}
#[cfg(test)]
impl<V: NodeValue> From<V> for Node<V> {
fn from(v: V) -> Node<V> {
let mock_position = Position { col: 42, line: 42 };
Node::new(mock_position, mock_position, v)
}
}
use absy::*;
use imports::*;
use zokrates_field::field::Field;
impl<T: Field> NodeValue for Expression<T> {}
impl<T: Field> NodeValue for ExpressionList<T> {}
impl<T: Field> NodeValue for Assignee<T> {}
impl<T: Field> NodeValue for Statement<T> {}
impl<T: Field> NodeValue for Function<T> {}
impl<T: Field> NodeValue for Prog<T> {}
impl NodeValue for Variable {}
impl NodeValue for Parameter {}
impl NodeValue for Import {}
impl<T: NodeValue> std::cmp::PartialEq for Node<T> {
fn eq(&self, other: &Node<T>) -> bool {
self.value.eq(&other.value)
}
}

View file

@ -1,32 +1,40 @@
use absy::Variable;
use absy::{Node, VariableNode};
use std::fmt;
#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub struct Parameter {
pub id: Variable,
pub id: VariableNode,
pub private: bool,
}
impl Parameter {
pub fn public(v: Variable) -> Self {
Parameter {
id: v,
private: true,
}
}
pub fn private(v: Variable) -> Self {
pub fn public(v: VariableNode) -> Self {
Parameter {
id: v,
private: false,
}
}
pub fn private(v: VariableNode) -> Self {
Parameter {
id: v,
private: true,
}
}
}
pub type ParameterNode = Node<Parameter>;
impl fmt::Display for Parameter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let visibility = if self.private { "private " } else { "" };
write!(f, "{}{} {}", visibility, self.id.get_type(), self.id.id)
write!(
f,
"{}{} {}",
visibility,
self.id.value.get_type(),
self.id.value.id
)
}
}

View file

@ -18,44 +18,106 @@ use std::io::BufRead;
use zokrates_field::field::Field;
#[derive(Debug)]
pub enum CompileError<T: Field> {
pub struct CompileErrors<T: Field>(Vec<CompileError<T>>);
impl<T: Field> From<CompileError<T>> for CompileErrors<T> {
fn from(e: CompileError<T>) -> CompileErrors<T> {
CompileErrors(vec![e])
}
}
impl<T: Field> fmt::Display for CompileErrors<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}",
self.0
.iter()
.map(|e| format!("{}", e))
.collect::<Vec<_>>()
.join("\n\n")
)
}
}
#[derive(Debug)]
pub enum CompileErrorInner<T: Field> {
ParserError(parser::Error<T>),
ImportError(imports::Error),
SemanticError(semantics::Error),
ReadError(io::Error),
}
impl<T: Field> From<parser::Error<T>> for CompileError<T> {
fn from(error: parser::Error<T>) -> Self {
CompileError::ParserError(error)
impl<T: Field> CompileErrorInner<T> {
pub fn with_context(self, context: &Option<String>) -> CompileError<T> {
CompileError {
value: self,
context: context.clone(),
}
}
}
impl<T: Field> From<imports::Error> for CompileError<T> {
fn from(error: imports::Error) -> Self {
CompileError::ImportError(error)
}
#[derive(Debug)]
pub struct CompileError<T: Field> {
context: Option<String>,
value: CompileErrorInner<T>,
}
impl<T: Field> From<io::Error> for CompileError<T> {
fn from(error: io::Error) -> Self {
CompileError::ReadError(error)
}
}
impl<T: Field> From<semantics::Error> for CompileError<T> {
fn from(error: semantics::Error) -> Self {
CompileError::SemanticError(error)
impl<T: Field> CompileErrors<T> {
pub fn with_context(self, context: Option<String>) -> Self {
CompileErrors(
self.0
.into_iter()
.map(|e| CompileError {
context: context.clone(),
..e
})
.collect(),
)
}
}
impl<T: Field> fmt::Display for CompileError<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let context = match self.context {
Some(ref x) => x.clone(),
None => "???".to_string(),
};
write!(f, "{}:{}", context, self.value)
}
}
impl<T: Field> From<parser::Error<T>> for CompileErrorInner<T> {
fn from(error: parser::Error<T>) -> Self {
CompileErrorInner::ParserError(error)
}
}
impl<T: Field> From<imports::Error> for CompileErrorInner<T> {
fn from(error: imports::Error) -> Self {
CompileErrorInner::ImportError(error)
}
}
impl<T: Field> From<io::Error> for CompileErrorInner<T> {
fn from(error: io::Error) -> Self {
CompileErrorInner::ReadError(error)
}
}
impl<T: Field> From<semantics::Error> for CompileErrorInner<T> {
fn from(error: semantics::Error) -> Self {
CompileErrorInner::SemanticError(error)
}
}
impl<T: Field> fmt::Display for CompileErrorInner<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: \n{}\n", e),
CompileError::ReadError(ref e) => format!("Read error: {}", e),
CompileError::ImportError(ref e) => format!("Import error: {}", e),
CompileErrorInner::ParserError(ref e) => format!("{}", e),
CompileErrorInner::SemanticError(ref e) => format!("{}", e),
CompileErrorInner::ReadError(ref e) => format!("{}", e),
CompileErrorInner::ImportError(ref e) => format!("{}", e),
};
write!(f, "{}", res)
}
@ -65,7 +127,7 @@ pub fn compile<T: Field, R: BufRead, S: BufRead, E: Into<imports::Error>>(
reader: &mut R,
location: Option<String>,
resolve_option: Option<fn(&Option<String>, &String) -> Result<(S, String, String), E>>,
) -> Result<ir::Prog<T>, CompileError<T>> {
) -> Result<ir::Prog<T>, CompileErrors<T>> {
let compiled = compile_aux(reader, location, resolve_option)?;
Ok(ir::Prog::from(Optimizer::new().optimize_program(compiled)))
}
@ -74,8 +136,9 @@ pub fn compile_aux<T: Field, R: BufRead, S: BufRead, E: Into<imports::Error>>(
reader: &mut R,
location: Option<String>,
resolve_option: Option<fn(&Option<String>, &String) -> Result<(S, String, String), E>>,
) -> Result<FlatProg<T>, CompileError<T>> {
let program_ast_without_imports: Prog<T> = parse_program(reader)?;
) -> Result<FlatProg<T>, CompileErrors<T>> {
let program_ast_without_imports: Prog<T> = parse_program(reader)
.map_err(|e| CompileErrors::from(CompileErrorInner::from(e).with_context(&location)))?;
let program_ast = Importer::new().apply_imports(
program_ast_without_imports,
@ -84,7 +147,16 @@ pub fn compile_aux<T: Field, R: BufRead, S: BufRead, E: Into<imports::Error>>(
)?;
// check semantics
let typed_ast = Checker::new().check_program(program_ast)?;
let typed_ast = Checker::new()
.check_program(program_ast)
.map_err(|errors| {
CompileErrors(
errors
.into_iter()
.map(|e| CompileErrorInner::from(e).with_context(&location))
.collect(),
)
})?;
// analyse (unroll and constant propagation)
let typed_ast = typed_ast.analyse();
@ -114,7 +186,7 @@ mod test {
"#
.as_bytes(),
);
let res: Result<ir::Prog<FieldPrime>, CompileError<FieldPrime>> = compile(
let res: Result<ir::Prog<FieldPrime>, CompileErrors<FieldPrime>> = compile(
&mut r,
Some(String::from("./path/to/file")),
None::<
@ -124,10 +196,11 @@ mod test {
) -> Result<(BufReader<Empty>, String, String), io::Error>,
>,
);
assert_eq!(
format!("{}", res.unwrap_err()),
"Import error: Can't resolve import without a resolver".to_string()
);
assert!(res
.unwrap_err()
.to_string()
.contains(&"Can't resolve import without a resolver"));
}
#[test]
@ -139,7 +212,7 @@ mod test {
"#
.as_bytes(),
);
let res: Result<ir::Prog<FieldPrime>, CompileError<FieldPrime>> = compile(
let res: Result<ir::Prog<FieldPrime>, CompileErrors<FieldPrime>> = compile(
&mut r,
Some(String::from("./path/to/file")),
None::<

View file

@ -5,8 +5,6 @@
//! @author Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>
//! @date 2017
use absy::parameter::Parameter;
use absy::variable::Variable;
use bimap::BiMap;
use flat_absy::*;
use helpers::{DirectiveStatement, Helper, RustHelper};
@ -1396,6 +1394,7 @@ impl Flattener {
let mut arguments_flattened: Vec<FlatParameter> = Vec::new();
let mut statements_flattened: Vec<FlatStatement<T>> = Vec::new();
// push parameters
for arg in &funct.arguments {
let arg_type = arg.id.get_type();
@ -1508,7 +1507,6 @@ impl Flattener {
#[cfg(test)]
mod tests {
use super::*;
use absy::variable::Variable;
use types::Signature;
use types::Type;
use zokrates_field::field::FieldPrime;

View file

@ -6,8 +6,9 @@
use absy::*;
use compile::compile_aux;
use compile::CompileError;
use compile::{CompileErrorInner, CompileErrors};
use flat_absy::*;
use parser::Position;
use std::fmt;
use std::io;
use std::io::BufRead;
@ -33,27 +34,38 @@ impl<T: Field> CompiledImport<T> {
#[derive(PartialEq, Debug)]
pub struct Error {
pos: Option<(Position, Position)>,
message: String,
}
impl Error {
pub fn new<T: Into<String>>(message: T) -> Error {
Error {
pos: None,
message: message.into(),
}
}
fn with_pos(self, pos: Option<(Position, Position)>) -> Error {
Error { pos, ..self }
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.message)
let location = self
.pos
.map(|p| format!("{}", p.0))
.unwrap_or("?".to_string());
write!(f, "{}\n\t{}", location, self.message)
}
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Self {
Error {
message: format!("I/O Error: {:?}", error),
pos: None,
message: format!("I/O Error: {}", error),
}
}
}
@ -64,6 +76,8 @@ pub struct Import {
alias: Option<String>,
}
pub type ImportNode = Node<Import>;
impl Import {
pub fn new(source: String) -> Import {
Import {
@ -118,72 +132,83 @@ impl Importer {
destination: Prog<T>,
location: Option<String>,
resolve_option: Option<fn(&Option<String>, &String) -> Result<(S, String, String), E>>,
) -> Result<Prog<T>, CompileError<T>> {
) -> Result<Prog<T>, CompileErrors<T>> {
let mut origins: Vec<CompiledImport<T>> = vec![];
for import in destination.imports.iter() {
let pos = import.pos();
let import = &import.value;
// handle the case of special libsnark and packing imports
if import.source.starts_with("LIBSNARK") {
#[cfg(feature = "libsnark")]
{
use helpers::LibsnarkGadgetHelper;
use libsnark::{get_ethsha256_constraints, get_sha256_constraints};
use serde_json::from_str;
use standard::{DirectiveR1CS, R1CS};
use std::io::BufReader;
#[cfg(feature = "libsnark")]
{
if import.source.starts_with("LIBSNARK") {
{
use helpers::LibsnarkGadgetHelper;
use libsnark::{get_ethsha256_constraints, get_sha256_constraints};
use serde_json::from_str;
use standard::{DirectiveR1CS, R1CS};
use std::io::BufReader;
match import.source.as_ref() {
"LIBSNARK/sha256" => {
let r1cs: R1CS = from_str(&get_ethsha256_constraints()).unwrap();
let dr1cs: DirectiveR1CS = DirectiveR1CS {
r1cs,
directive: LibsnarkGadgetHelper::Sha256Ethereum,
};
let compiled = FlatProg::from(dr1cs);
let alias = match import.alias {
Some(ref alias) => alias.clone(),
None => String::from("sha256"),
};
origins.push(CompiledImport::new(compiled, alias));
}
"LIBSNARK/sha256compression" => {
let r1cs: R1CS = from_str(&get_sha256_constraints()).unwrap();
let dr1cs: DirectiveR1CS = DirectiveR1CS {
r1cs,
directive: LibsnarkGadgetHelper::Sha256Compress,
};
let compiled = FlatProg::from(dr1cs);
let alias = match import.alias {
Some(ref alias) => alias.clone(),
None => String::from("sha256compression"),
};
origins.push(CompiledImport::new(compiled, alias));
}
"LIBSNARK/sha256packed" => {
let source = sha_packed_typed();
let mut reader = BufReader::new(source.as_bytes());
let compiled = compile_aux(
&mut reader,
None::<String>,
None::<
fn(&Option<String>, &String) -> Result<(S, String, String), E>,
>,
)?;
let alias = match import.alias {
Some(ref alias) => alias.clone(),
None => String::from("sha256packed"),
};
origins.push(CompiledImport::new(compiled, alias));
}
s => {
return Err(CompileError::ImportError(Error::new(format!(
"Gadget {} not found",
s
))));
match import.source.as_ref() {
"LIBSNARK/sha256" => {
let r1cs: R1CS = from_str(&get_ethsha256_constraints()).unwrap();
let dr1cs: DirectiveR1CS = DirectiveR1CS {
r1cs,
directive: LibsnarkGadgetHelper::Sha256Ethereum,
};
let compiled = FlatProg::from(dr1cs);
let alias = match import.alias {
Some(ref alias) => alias.clone(),
None => String::from("sha256"),
};
origins.push(CompiledImport::new(compiled, alias));
}
"LIBSNARK/sha256compression" => {
let r1cs: R1CS = from_str(&get_sha256_constraints()).unwrap();
let dr1cs: DirectiveR1CS = DirectiveR1CS {
r1cs,
directive: LibsnarkGadgetHelper::Sha256Compress,
};
let compiled = FlatProg::from(dr1cs);
let alias = match import.alias {
Some(ref alias) => alias.clone(),
None => String::from("sha256compression"),
};
origins.push(CompiledImport::new(compiled, alias));
}
"LIBSNARK/sha256packed" => {
let source = sha_packed_typed();
let mut reader = BufReader::new(source.as_bytes());
let compiled = compile_aux(
&mut reader,
None::<String>,
None::<
fn(
&Option<String>,
&String,
)
-> Result<(S, String, String), E>,
>,
)?;
let alias = match import.alias {
Some(ref alias) => alias.clone(),
None => String::from("sha256packed"),
};
origins.push(CompiledImport::new(compiled, alias));
}
s => {
return Err(CompileErrorInner::ImportError(
Error::new(format!("Gadget {} not found", s))
.with_pos(Some(pos)),
)
.with_context(&location)
.into());
}
}
}
}
} else if import.source.starts_with("PACKING") {
}
if import.source.starts_with("PACKING") {
use types::conversions::{pack, unpack};
match import.source.as_ref() {
@ -204,10 +229,12 @@ impl Importer {
origins.push(CompiledImport::new(compiled, alias));
}
s => {
return Err(CompileError::ImportError(Error::new(format!(
"Packing helper {} not found",
s
))));
return Err(CompileErrorInner::ImportError(
Error::new(format!("Packing helper {} not found", s))
.with_pos(Some(pos)),
)
.with_context(&location)
.into());
}
}
} else {
@ -215,18 +242,28 @@ impl Importer {
match resolve_option {
Some(resolve) => match resolve(&location, &import.source) {
Ok((mut reader, location, auto_alias)) => {
let compiled =
compile_aux(&mut reader, Some(location), resolve_option)?;
let compiled = compile_aux(&mut reader, Some(location), resolve_option)
.map_err(|e| e.with_context(Some(import.source.clone())))?;
let alias = match import.alias {
Some(ref alias) => alias.clone(),
None => auto_alias,
};
origins.push(CompiledImport::new(compiled, alias));
}
Err(err) => return Err(CompileError::ImportError(err.into())),
Err(err) => {
return Err(CompileErrorInner::ImportError(
err.into().with_pos(Some(pos)),
)
.with_context(&location)
.into());
}
},
None => {
return Err(Error::new("Can't resolve import without a resolver").into());
return Err(CompileErrorInner::from(Error::new(
"Can't resolve import without a resolver",
))
.with_context(&location)
.into());
}
}
}

View file

@ -14,7 +14,7 @@ impl<T: Field> fmt::Display for Error<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Error at {}: Expected one of {:?}, got {:?}",
"{}\n\tExpected one of {:?}, got {:?}",
self.pos.col(-(self.got.to_string().len() as isize)),
self.expected,
self.got

View file

@ -334,14 +334,18 @@ pub fn parse_term1<T: Field>(
match next_token::<T>(&input, &pos) {
(Token::Mult, s1, p1) => match parse_term(&s1, &p1) {
Ok((e, s2, p2)) => Ok((
Node::new(pos, p2, Expression::Mult(box expr, box e)),
Node::new(expr.start, 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((Node::new(pos, p2, Expression::Div(box expr, box e)), s2, p2)),
Ok((e, s2, p2)) => Ok((
Node::new(expr.start, p2, Expression::Div(box expr, box e)),
s2,
p2,
)),
Err(err) => Err(err),
},
_ => Ok((expr, input, pos)),
@ -400,6 +404,12 @@ pub fn parse_function_call<T: Field>(
input: String,
pos: Position,
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
// backtrack to the beginning of the function identifier, plus one because we're after the `(`
let start_pos = Position {
col: pos.col - ide.len() - 1,
..pos
};
// function call can have 0 .. n args
let mut args = Vec::new();
let mut s: String = input;
@ -410,7 +420,7 @@ pub fn parse_function_call<T: Field>(
// no arguments
(Token::Close, s1, p1) => {
return parse_term1(
Node::new(pos, p1, Expression::FunctionCall(ide, args)),
Node::new(start_pos, p1, Expression::FunctionCall(ide, args)),
s1,
p1,
);
@ -426,7 +436,7 @@ pub fn parse_function_call<T: Field>(
}
(Token::Close, s2, p2) => {
return parse_term1(
Node::new(pos, p2, Expression::FunctionCall(ide, args)),
Node::new(start_pos, p2, Expression::FunctionCall(ide, args)),
s2,
p2,
);
@ -507,10 +517,11 @@ pub fn parse_array_select<T: Field>(
input: String,
pos: Position,
) -> Result<(ExpressionNode<T>, String, Position), Error<T>> {
let ide_initial_pos = Position {
col: pos.col - ide.len(),
let start_pos = Position {
col: pos.col - ide.len() - 1,
..pos
};
// array select can have exactly one arg
match next_token::<T>(&input, &pos) {
(_, _, _) => match parse_expr(&input, &pos) {
@ -520,7 +531,7 @@ pub fn parse_array_select<T: Field>(
pos,
p2,
Expression::Select(
box Node::new(pos, p1, Expression::Identifier(ide)),
box Node::new(start_pos, p1, Expression::Identifier(ide)),
box e1,
),
),
@ -594,11 +605,13 @@ mod tests {
let string = String::from("1 + 2 + 3");
let expr = Expression::Add(
box Expression::Add(
box Expression::Number(FieldPrime::from(1)),
box Expression::Number(FieldPrime::from(2)),
),
box Expression::Number(FieldPrime::from(3)),
);
box Expression::Number(FieldPrime::from(1)).into(),
box Expression::Number(FieldPrime::from(2)).into(),
)
.into(),
box Expression::Number(FieldPrime::from(3)).into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_expr(&string, &pos)
@ -611,11 +624,13 @@ mod tests {
let string = String::from("1 - 2 - 3");
let expr = Expression::Sub(
box Expression::Sub(
box Expression::Number(FieldPrime::from(1)),
box Expression::Number(FieldPrime::from(2)),
),
box Expression::Number(FieldPrime::from(3)),
);
box Expression::Number(FieldPrime::from(1)).into(),
box Expression::Number(FieldPrime::from(2)).into(),
)
.into(),
box Expression::Number(FieldPrime::from(3)).into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_expr(&string, &pos)
@ -627,12 +642,14 @@ mod tests {
let pos = Position { line: 45, col: 121 };
let string = String::from("1 - f(a)");
let expr = Expression::Sub(
box Expression::Number(FieldPrime::from(1)),
box Expression::Number(FieldPrime::from(1)).into(),
box Expression::FunctionCall(
String::from("f"),
vec![Expression::Identifier(String::from("a"))],
),
);
vec![Expression::Identifier(String::from("a")).into()],
)
.into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_expr(&string, &pos)
@ -645,11 +662,13 @@ mod tests {
let string = String::from("1 - f() - 3");
let expr = Expression::Sub(
box Expression::Sub(
box Expression::Number(FieldPrime::from(1)),
box Expression::FunctionCall(String::from("f"), vec![]),
),
box Expression::Number(FieldPrime::from(3)),
);
box Expression::Number(FieldPrime::from(1)).into(),
box Expression::FunctionCall(String::from("f"), vec![]).into(),
)
.into(),
box Expression::Number(FieldPrime::from(3)).into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_expr(&string, &pos)
@ -662,11 +681,13 @@ mod tests {
let string = String::from("1 + f() + 3");
let expr = Expression::Add(
box Expression::Add(
box Expression::Number(FieldPrime::from(1)),
box Expression::FunctionCall(String::from("f"), vec![]),
),
box Expression::Number(FieldPrime::from(3)),
);
box Expression::Number(FieldPrime::from(1)).into(),
box Expression::FunctionCall(String::from("f"), vec![]).into(),
)
.into(),
box Expression::Number(FieldPrime::from(3)).into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_expr(&string, &pos)
@ -679,14 +700,17 @@ mod tests {
let string = String::from("1 - f[2] - 3");
let expr = Expression::Sub(
box Expression::Sub(
box Expression::Number(FieldPrime::from(1)),
box Expression::Number(FieldPrime::from(1)).into(),
box Expression::Select(
box Expression::Identifier(String::from("f")),
box Expression::Number(FieldPrime::from(2)),
),
),
box Expression::Number(FieldPrime::from(3)),
);
box Expression::Identifier(String::from("f")).into(),
box Expression::Number(FieldPrime::from(2)).into(),
)
.into(),
)
.into(),
box Expression::Number(FieldPrime::from(3)).into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_expr(&string, &pos)
@ -699,14 +723,17 @@ mod tests {
let string = String::from("1 + f[2] + 3");
let expr = Expression::Add(
box Expression::Add(
box Expression::Number(FieldPrime::from(1)),
box Expression::Number(FieldPrime::from(1)).into(),
box Expression::Select(
box Expression::Identifier(String::from("f")),
box Expression::Number(FieldPrime::from(2)),
),
),
box Expression::Number(FieldPrime::from(3)),
);
box Expression::Identifier(String::from("f")).into(),
box Expression::Number(FieldPrime::from(2)).into(),
)
.into(),
)
.into(),
box Expression::Number(FieldPrime::from(3)).into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_expr(&string, &pos)
@ -719,11 +746,13 @@ mod tests {
let string = String::from("1 - f - 3");
let expr = Expression::Sub(
box Expression::Sub(
box Expression::Number(FieldPrime::from(1)),
box Expression::Identifier(String::from("f")),
),
box Expression::Number(FieldPrime::from(3)),
);
box Expression::Number(FieldPrime::from(1)).into(),
box Expression::Identifier(String::from("f")).into(),
)
.into(),
box Expression::Number(FieldPrime::from(3)).into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_expr(&string, &pos)
@ -736,11 +765,13 @@ mod tests {
let string = String::from("1 + f + 3");
let expr = Expression::Add(
box Expression::Add(
box Expression::Number(FieldPrime::from(1)),
box Expression::Identifier(String::from("f")),
),
box Expression::Number(FieldPrime::from(3)),
);
box Expression::Number(FieldPrime::from(1)).into(),
box Expression::Identifier(String::from("f")).into(),
)
.into(),
box Expression::Number(FieldPrime::from(3)).into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_expr(&string, &pos)
@ -754,12 +785,14 @@ mod tests {
let string = String::from("if a < b then c else d fi");
let expr = Expression::IfElse::<FieldPrime>(
box Expression::Lt(
box Expression::Identifier(String::from("a")),
box Expression::Identifier(String::from("b")),
),
box Expression::Identifier(String::from("c")),
box Expression::Identifier(String::from("d")),
);
box Expression::Identifier(String::from("a")).into(),
box Expression::Identifier(String::from("b")).into(),
)
.into(),
box Expression::Identifier(String::from("c")).into(),
box Expression::Identifier(String::from("d")).into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_if_then_else(&string, &pos)
@ -774,26 +807,33 @@ mod tests {
let expr = Expression::IfElse::<FieldPrime>(
box Expression::And(
box Expression::Lt(
box Expression::Identifier(String::from("a")),
box Expression::Identifier(String::from("b")),
),
box Expression::Identifier(String::from("a")).into(),
box Expression::Identifier(String::from("b")).into(),
)
.into(),
box Expression::And(
box Expression::Gt(
box Expression::Mult(
box Expression::Number(FieldPrime::from(2)),
box Expression::Identifier(String::from("a")),
),
box Expression::Identifier(String::from("b")),
),
box Expression::Number(FieldPrime::from(2)).into(),
box Expression::Identifier(String::from("a")).into(),
)
.into(),
box Expression::Identifier(String::from("b")).into(),
)
.into(),
box Expression::Gt(
box Expression::Identifier(String::from("b")),
box Expression::Identifier(String::from("a")),
),
),
),
box Expression::Identifier(String::from("c")),
box Expression::Identifier(String::from("d")),
);
box Expression::Identifier(String::from("b")).into(),
box Expression::Identifier(String::from("a")).into(),
)
.into(),
)
.into(),
)
.into(),
box Expression::Identifier(String::from("c")).into(),
box Expression::Identifier(String::from("d")).into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
@ -809,12 +849,14 @@ mod tests {
let pos = Position { line: 45, col: 121 };
let string = String::from("foo[42 + 33]");
let expr = Expression::Select::<FieldPrime>(
box Expression::Identifier(String::from("foo")),
box Expression::Identifier(String::from("foo")).into(),
box Expression::Add(
box Expression::Number(FieldPrime::from(42)),
box Expression::Number(FieldPrime::from(33)),
),
);
box Expression::Number(FieldPrime::from(42)).into(),
box Expression::Number(FieldPrime::from(33)).into(),
)
.into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_expr(&string, &pos)
@ -843,20 +885,25 @@ mod tests {
let expr = Expression::IfElse::<FieldPrime>(
box Expression::Or(
box Expression::Lt(
box Expression::Identifier(String::from("a")),
box Expression::Identifier(String::from("b")),
),
box Expression::Identifier(String::from("a")).into(),
box Expression::Identifier(String::from("b")).into(),
)
.into(),
box Expression::Gt(
box Expression::Mult(
box Expression::Number(FieldPrime::from(2)),
box Expression::Identifier(String::from("a")),
),
box Expression::Identifier(String::from("b")),
),
),
box Expression::Identifier(String::from("c")),
box Expression::Identifier(String::from("d")),
);
box Expression::Number(FieldPrime::from(2)).into(),
box Expression::Identifier(String::from("a")).into(),
)
.into(),
box Expression::Identifier(String::from("b")).into(),
)
.into(),
)
.into(),
box Expression::Identifier(String::from("c")).into(),
box Expression::Identifier(String::from("d")).into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_if_then_else(&string, &pos)
@ -870,20 +917,25 @@ mod tests {
let string = String::from("2 == 3 || 4 == 5 && 6 == 7");
let expr = Or::<FieldPrime>(
box Eq(
box Number(FieldPrime::from(2)),
box Number(FieldPrime::from(3)),
),
box Number(FieldPrime::from(2)).into(),
box Number(FieldPrime::from(3)).into(),
)
.into(),
box And(
box Eq(
box Number(FieldPrime::from(4)),
box Number(FieldPrime::from(5)),
),
box Number(FieldPrime::from(4)).into(),
box Number(FieldPrime::from(5)).into(),
)
.into(),
box Eq(
box Number(FieldPrime::from(6)),
box Number(FieldPrime::from(7)),
),
),
);
box Number(FieldPrime::from(6)).into(),
box Number(FieldPrime::from(7)).into(),
)
.into(),
)
.into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_bexpr(&string, &pos)
@ -899,33 +951,43 @@ mod tests {
box And(
box Eq(
box Add(
box Identifier(String::from("a")),
box Number(FieldPrime::from(2)),
),
box Number(FieldPrime::from(3)),
),
box Identifier(String::from("a")).into(),
box Number(FieldPrime::from(2)).into(),
)
.into(),
box Number(FieldPrime::from(3)).into(),
)
.into(),
box Or(
box Eq(
box Add(
box Mult(
box Identifier(String::from("a")),
box Number(FieldPrime::from(2)),
),
box Number(FieldPrime::from(3)),
),
box Number(FieldPrime::from(2)),
),
box Identifier(String::from("a")).into(),
box Number(FieldPrime::from(2)).into(),
)
.into(),
box Number(FieldPrime::from(3)).into(),
)
.into(),
box Number(FieldPrime::from(2)).into(),
)
.into(),
box Lt(
box Identifier(String::from("a")),
box Number(FieldPrime::from(3)),
),
),
),
box Identifier(String::from("a")).into(),
box Number(FieldPrime::from(3)).into(),
)
.into(),
)
.into(),
)
.into(),
box Lt(
box Number(FieldPrime::from(1)),
box Number(FieldPrime::from(2)),
),
);
box Number(FieldPrime::from(1)).into(),
box Number(FieldPrime::from(2)).into(),
)
.into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_bexpr(&string, &pos)
@ -940,12 +1002,14 @@ mod tests {
let string = String::from("if a < b then c else d fi");
let expr = Expression::IfElse::<FieldPrime>(
box Expression::Lt(
box Expression::Identifier(String::from("a")),
box Expression::Identifier(String::from("b")),
),
box Expression::Identifier(String::from("c")),
box Expression::Identifier(String::from("d")),
);
box Expression::Identifier(String::from("a")).into(),
box Expression::Identifier(String::from("b")).into(),
)
.into(),
box Expression::Identifier(String::from("c")).into(),
box Expression::Identifier(String::from("d")).into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_factor(&string, &pos)
@ -956,12 +1020,14 @@ mod tests {
let pos = Position { line: 45, col: 121 };
let string = String::from("(5 + a * 6)");
let expr = Expression::Add(
box Expression::Number(FieldPrime::from(5)),
box Expression::Number(FieldPrime::from(5)).into(),
box Expression::Mult(
box Expression::Identifier(String::from("a")),
box Expression::Number(FieldPrime::from(6)),
),
);
box Expression::Identifier(String::from("a")).into(),
box Expression::Number(FieldPrime::from(6)).into(),
)
.into(),
)
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_factor(&string, &pos)
@ -971,7 +1037,7 @@ mod tests {
fn ide() {
let pos = Position { line: 45, col: 121 };
let string = String::from("a");
let expr = Expression::Identifier::<FieldPrime>(String::from("a"));
let expr = Expression::Identifier::<FieldPrime>(String::from("a")).into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_factor(&string, &pos)
@ -981,7 +1047,7 @@ mod tests {
fn num() {
let pos = Position { line: 45, col: 121 };
let string = String::from("234");
let expr = Expression::Number(FieldPrime::from(234));
let expr = Expression::Number(FieldPrime::from(234)).into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_factor(&string, &pos)

View file

@ -44,8 +44,8 @@ mod tests {
fn parse_comma_separated_list<T: Field>(
input: String,
pos: Position,
) -> Result<(ExpressionList<T>, String, Position), Error<T>> {
let mut res = ExpressionList::new();
) -> Result<(ExpressionListNode<T>, String, Position), Error<T>> {
let mut res = ExpressionList::new().into();
parse_comma_separated_expression_list_rec(input, pos, &mut res)
}
@ -55,10 +55,11 @@ mod tests {
let string = String::from("b, c");
let expr = ExpressionList::<FieldPrime> {
expressions: vec![
Expression::Identifier(String::from("b")),
Expression::Identifier(String::from("c")),
Expression::Identifier(String::from("b")).into(),
Expression::Identifier(String::from("c")).into(),
],
};
}
.into();
assert_eq!(
Ok((expr, String::from(""), pos.col(string.len() as isize))),
parse_expression_list(string, pos)
@ -70,8 +71,9 @@ mod tests {
let pos = Position { line: 45, col: 121 };
let string = String::from("a");
let exprs = ExpressionList {
expressions: vec![Expression::Identifier(String::from("a"))],
};
expressions: vec![Expression::Identifier(String::from("a")).into()],
}
.into();
assert_eq!(
Ok((exprs, String::from(""), pos.col(string.len() as isize))),
parse_comma_separated_list::<FieldPrime>(string, pos)
@ -84,11 +86,12 @@ mod tests {
let string = String::from("a, b, c");
let exprs = ExpressionList {
expressions: vec![
Expression::Identifier(String::from("a")),
Expression::Identifier(String::from("b")),
Expression::Identifier(String::from("c")),
Expression::Identifier(String::from("a")).into(),
Expression::Identifier(String::from("b")).into(),
Expression::Identifier(String::from("c")).into(),
],
};
}
.into();
assert_eq!(
Ok((exprs, String::from(""), pos.col(string.len() as isize))),
parse_comma_separated_list::<FieldPrime>(string, pos)

View file

@ -8,7 +8,9 @@ use parser::Error;
use super::statement::parse_statement;
use absy::{Function, Parameter, Statement, Variable};
use absy::{
Function, FunctionNode, Node, Parameter, ParameterNode, Statement, Variable, VariableNode,
};
use types::{Signature, Type};
fn parse_function_identifier<T: Field>(
@ -28,7 +30,7 @@ fn parse_function_identifier<T: Field>(
fn parse_function_header<T: Field>(
input: &String,
pos: &Position,
) -> Result<(String, Vec<Parameter>, Signature), Error<T>> {
) -> Result<(String, Vec<ParameterNode>, Signature), Error<T>> {
// parse function identifier
let (id, s, p) = parse_function_identifier(input, pos)?;
@ -90,7 +92,7 @@ fn parse_function_header<T: Field>(
}?;
let sig = Signature {
inputs: args.iter().map(|a| a.id.get_type()).collect(),
inputs: args.iter().map(|a| a.value.id.value.get_type()).collect(),
outputs: return_types,
};
@ -119,13 +121,13 @@ fn parse_function_header<T: Field>(
fn parse_function_argument_variable<T: Field>(
input: &String,
pos: &Position,
) -> Result<(Variable, String, Position), Error<T>> {
) -> Result<(VariableNode, String, Position), Error<T>> {
let s4 = input;
let p4 = pos;
match next_token::<T>(&s4, &p4) {
(Token::Type(t), s5, p5) => match next_token(&s5, &p5) {
(Token::Ide(x), s6, p6) => Ok((Variable::new(x, t), s6, p6)),
(Token::Ide(x), s6, p6) => Ok((Node::new(*pos, p6, Variable::new(x, t)), s6, p6)),
(t6, _, p6) => Err(Error {
expected: vec![Token::Ide(String::from("identifier"))],
got: t6,
@ -143,7 +145,7 @@ fn parse_function_argument_variable<T: Field>(
fn parse_function_arguments<T: Field>(
input: String,
pos: Position,
) -> Result<(Vec<Parameter>, String, Position), Error<T>> {
) -> Result<(Vec<ParameterNode>, String, Position), Error<T>> {
let mut args = Vec::new();
let mut s = input;
let mut p = pos;
@ -152,10 +154,7 @@ fn parse_function_arguments<T: Field>(
match next_token(&s, &p) {
(Token::Private, s1, p1) => {
let (var, s2, p2) = parse_function_argument_variable::<T>(&s1, &p1)?;
args.push(Parameter {
id: var,
private: true,
});
args.push(Node::new(p, p1, Parameter::private(var)));
match next_token::<T>(&s2, &p2) {
(Token::Comma, s3, p3) => {
s = s3;
@ -173,10 +172,7 @@ fn parse_function_arguments<T: Field>(
}
(Token::Type(_), _, _) => {
let (var, s2, p2) = parse_function_argument_variable::<T>(&s, &p)?;
args.push(Parameter {
id: var,
private: false,
});
args.push(Node::new(p, p2, Parameter::public(var)));
match next_token::<T>(&s2, &p2) {
(Token::Comma, s3, p3) => {
s = s3;
@ -255,7 +251,7 @@ pub fn parse_function<T: Field, R: BufRead>(
mut lines: &mut Lines<R>,
input: &String,
pos: &Position,
) -> Result<(Function<T>, Position), Error<T>> {
) -> Result<(FunctionNode<T>, Position), Error<T>> {
let mut current_line = pos.line;
let (id, args, sig) = parse_function_header(input, pos)?;
@ -279,7 +275,7 @@ pub fn parse_function<T: Field, R: BufRead>(
for stat in statements {
stats.push(stat.clone());
}
match statements[0] {
match statements[0].value {
Statement::Return(_) => {
break;
}
@ -296,22 +292,27 @@ pub fn parse_function<T: Field, R: BufRead>(
current_line += 1;
}
match stats.last() {
Some(&Statement::Return(_)) => {}
Some(x) => panic!("Last function statement not Return: {}", x),
None => panic!("Error while checking last function statement"),
match stats.last().clone().unwrap().value {
Statement::Return(_) => {}
ref x => panic!("Last function statement not Return: {}", x),
}
let next_pos = Position {
line: current_line,
col: 1,
};
Ok((
Function {
id: id,
arguments: args,
statements: stats,
signature: sig,
},
Position {
line: current_line,
col: 1,
},
Node::new(
*pos,
next_pos,
Function {
id: id,
arguments: args,
statements: stats,
signature: sig,
},
),
next_pos,
))
}

View file

@ -5,18 +5,22 @@ use parser::Error;
use parser::tokenize::parse_quoted_path;
use imports::Import;
use absy::Node;
use imports::{Import, ImportNode};
pub fn parse_import<T: Field>(
input: &String,
pos: &Position,
) -> Result<(Import, Position), Error<T>> {
) -> Result<(ImportNode, Position), Error<T>> {
match next_token(input, pos) {
(Token::DoubleQuote, s1, p1) => match parse_quoted_path(&s1, &p1) {
(Token::Path(code_path), s2, p2) => match next_token::<T>(&s2, &p2) {
(Token::As, s3, p3) => match next_token(&s3, &p3) {
(Token::Ide(id), _, p4) => {
return Ok((Import::new_with_alias(code_path, &id), p4));
return Ok((
Node::new(*pos, p4, Import::new_with_alias(code_path, &id)),
p4,
));
}
(t4, _, p4) => {
return Err(Error {
@ -26,7 +30,9 @@ pub fn parse_import<T: Field>(
});
}
},
(Token::Unknown(_), _, p3) => return Ok((Import::new(code_path), p3)),
(Token::Unknown(_), _, p3) => {
return Ok((Node::new(*pos, p3, Import::new(code_path)), p3));
}
(t3, _, p3) => {
return Err(Error {
expected: vec![
@ -83,7 +89,7 @@ mod tests {
fn parse_import_test() {
let pos = Position { line: 45, col: 121 };
let string = String::from("\"./foo.code\"");
let import = Import::new("./foo.code".to_string());
let import = Import::new("./foo.code".to_string()).into();
let position = Position {
line: 45,
col: pos.col + 1 + "./foo.code".len() + 1,
@ -99,7 +105,7 @@ mod tests {
let pos = Position { line: 45, col: 121 };
let string = String::from("\"./foo.code\" as myalias");
let alias = "myalias".to_string();
let import = Import::new_with_alias("./foo.code".to_string(), &alias);
let import = Import::new_with_alias("./foo.code".to_string(), &alias).into();
let position = Position {
line: 45,
col: pos.col + string.len(),

View file

@ -13,14 +13,16 @@ use super::expression::{
};
use super::expression_list::parse_expression_list;
use absy::{Assignee, AssigneeNode, Expression, Node, Statement, Variable, VariableNode};
use absy::{
Assignee, AssigneeNode, Expression, Node, Statement, StatementNode, Variable, VariableNode,
};
use types::Type;
pub fn parse_statement<T: Field, R: BufRead>(
lines: &mut Lines<R>,
input: &String,
pos: &Position,
) -> Result<(Vec<Statement<T>>, String, Position), Error<T>> {
) -> Result<(Vec<StatementNode<T>>, String, Position), Error<T>> {
match next_token::<T>(input, pos) {
(Token::Type(t), s1, p1) => parse_declaration_definition(t, s1, p1),
(Token::Ide(x1), s1, p1) => parse_statement1(x1, s1, p1),
@ -30,11 +32,19 @@ pub fn parse_statement<T: Field, R: BufRead>(
Ok((e4, s4, p4)) => match next_token(&s4, &p4) {
(Token::InlineComment(_), ref s5, _) => {
assert_eq!(s5, "");
Ok((vec![Statement::Condition(e2, e4)], s4, p4))
Ok((
vec![Node::new(*pos, p4, Statement::Condition(e2, e4))],
s4,
p4,
))
}
(Token::Unknown(ref t5), ref s5, _) if t5 == "" => {
assert_eq!(s5, "");
Ok((vec![Statement::Condition(e2, e4)], s4, p4))
Ok((
vec![Node::new(*pos, p4, Statement::Condition(e2, e4))],
s4,
p4,
))
}
(t5, _, p5) => Err(Error {
expected: vec![Token::Unknown("".to_string())],
@ -109,11 +119,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(Node::new(p1, p3, Variable::new(x2, t)), x4, x6, statements)], s8, p8))
return Ok((vec![Node::new(*pos, p8, 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(Node::new(p1, p3, Variable::new(x2, t)), x4, x6, statements)], s8, p8))
return Ok((vec![Node::new(*pos, p8, 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 }),
}
@ -184,11 +194,11 @@ pub fn parse_statement<T: Field, R: BufRead>(
Ok((e2, s2, p2)) => match next_token(&s2, &p2) {
(Token::InlineComment(_), ref s3, _) => {
assert_eq!(s3, "");
Ok((vec![Statement::Return(e2)], s2, p2))
Ok((vec![Node::new(*pos, p2, Statement::Return(e2))], s2, p2))
}
(Token::Unknown(ref t3), ref s3, _) if t3 == "" => {
assert_eq!(s3, "");
Ok((vec![Statement::Return(e2)], s2, p2))
Ok((vec![Node::new(*pos, p2, Statement::Return(e2))], s2, p2))
}
(t3, _, p3) => Err(Error {
expected: vec![Token::Unknown("".to_string())],
@ -221,22 +231,27 @@ fn parse_definition1<T: Field>(
x: AssigneeNode<T>,
input: String,
pos: Position,
) -> Result<(Vec<Statement<T>>, String, Position), Error<T>> {
) -> Result<(Vec<StatementNode<T>>, String, Position), Error<T>> {
match parse_expr(&input, &pos) {
Ok((e1, s1, p1)) => match next_token(&s1, &p1) {
(Token::InlineComment(_), ref s2, _) => {
assert_eq!(s2, "");
match e1.value {
e @ Expression::FunctionCall(..) => Ok((
vec![Statement::MultipleDefinition(
vec![x],
Node::new(pos, p1, e),
vec![Node::new(
x.start,
p1,
Statement::MultipleDefinition(vec![x], Node::new(pos, p1, e)),
)],
s1,
p1,
)),
e => Ok((
vec![Statement::Definition(x, Node::new(pos, p1, e))],
vec![Node::new(
x.start,
p1,
Statement::Definition(x, Node::new(pos, p1, e)),
)],
s1,
p1,
)),
@ -246,15 +261,20 @@ fn parse_definition1<T: Field>(
assert_eq!(s2, "");
match e1.value {
e @ Expression::FunctionCall(..) => Ok((
vec![Statement::MultipleDefinition(
vec![x],
Node::new(pos, p1, e),
vec![Node::new(
x.start,
p1,
Statement::MultipleDefinition(vec![x], Node::new(pos, p1, e)),
)],
s1,
p1,
)),
e => Ok((
vec![Statement::Definition(x, Node::new(pos, p1, e))],
vec![Node::new(
x.start,
p1,
Statement::Definition(x, Node::new(pos, p1, e)),
)],
s1,
p1,
)),
@ -274,7 +294,7 @@ fn parse_declaration_definition<T: Field>(
t: Type,
input: String,
pos: Position,
) -> Result<(Vec<Statement<T>>, String, Position), Error<T>> {
) -> Result<(Vec<StatementNode<T>>, String, Position), Error<T>> {
match next_token::<T>(&input, &pos) {
(Token::Ide(x), s0, p0) => match next_token(&s0, &p0) {
(Token::Eq, s1, p1) => match parse_expr(&s1, &p1) {
@ -284,14 +304,22 @@ fn parse_declaration_definition<T: Field>(
match e2.value {
e @ Expression::FunctionCall(..) => Ok((
vec![
Statement::Declaration(Node::new(
Node::new(
pos,
p0,
Variable::new(x.clone(), t),
)),
Statement::MultipleDefinition(
vec![Node::new(pos, p1, Assignee::Identifier(x))],
Node::new(p1, p2, e),
Statement::Declaration(Node::new(
pos,
p0,
Variable::new(x.clone(), t),
)),
),
Node::new(
pos,
p2,
Statement::MultipleDefinition(
vec![Node::new(pos, p1, Assignee::Identifier(x))],
Node::new(p1, p2, e),
),
),
],
s2,
@ -299,14 +327,22 @@ fn parse_declaration_definition<T: Field>(
)),
e => Ok((
vec![
Statement::Declaration(Node::new(
Node::new(
pos,
p0,
Variable::new(x.clone(), t),
)),
Statement::Definition(
Node::new(pos, p1, Assignee::Identifier(x)),
Node::new(p1, p2, e),
Statement::Declaration(Node::new(
pos,
p0,
Variable::new(x.clone(), t),
)),
),
Node::new(
pos,
p2,
Statement::Definition(
Node::new(pos, p1, Assignee::Identifier(x)),
Node::new(p1, p2, e),
),
),
],
s2,
@ -319,14 +355,22 @@ fn parse_declaration_definition<T: Field>(
match e2.value {
e @ Expression::FunctionCall(..) => Ok((
vec![
Statement::Declaration(Node::new(
Node::new(
pos,
p0,
Variable::new(x.clone(), t),
)),
Statement::MultipleDefinition(
vec![Node::new(pos, p1, Assignee::Identifier(x))],
Node::new(p1, p2, e),
Statement::Declaration(Node::new(
pos,
p0,
Variable::new(x.clone(), t),
)),
),
Node::new(
pos,
p2,
Statement::MultipleDefinition(
vec![Node::new(pos, p1, Assignee::Identifier(x))],
Node::new(p1, p2, e),
),
),
],
s2,
@ -334,14 +378,22 @@ fn parse_declaration_definition<T: Field>(
)),
e => Ok((
vec![
Statement::Declaration(Node::new(
Node::new(
pos,
p0,
Variable::new(x.clone(), t),
)),
Statement::Definition(
Node::new(pos, p1, Assignee::Identifier(x)),
Node::new(p1, p2, e),
Statement::Declaration(Node::new(
pos,
p0,
Variable::new(x.clone(), t),
)),
),
Node::new(
pos,
p2,
Statement::Definition(
Node::new(pos, p1, Assignee::Identifier(x)),
Node::new(p1, p2, e),
),
),
],
s2,
@ -370,21 +422,16 @@ 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
let mut statements: Vec<_> = d2
.iter()
.map(|v| Statement::Declaration(v.clone()))
.map(|v| {
Node::new(v.start, v.end, Statement::Declaration(v.clone()))
})
.collect();
statements.push(Statement::MultipleDefinition(
d2.iter()
.map(|v| {
Node::new(
v.start,
v.end,
Assignee::Identifier(v.value.id.clone()),
)
})
.collect(),
e4,
statements.push(Node::new(
pos,
p4,
Statement::MultipleDefinition(e2, e4),
));
Ok((statements, s4, p4)) // output a multipledefinition with the destructure and the expression
}
@ -417,9 +464,9 @@ fn parse_statement1<T: Field>(
ide: String,
input: String,
pos: Position,
) -> Result<(Vec<Statement<T>>, String, Position), Error<T>> {
) -> Result<(Vec<StatementNode<T>>, String, Position), Error<T>> {
let ide_start_position = Position {
line: pos.line - ide.len(),
col: pos.col - ide.len(),
..pos
};
match next_token::<T>(&input, &pos) {
@ -434,22 +481,11 @@ fn parse_statement1<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
let mut statements: Vec<_> = d2
.iter()
.map(|v| Statement::Declaration(v.clone()))
.map(|v| Node::new(v.start, v.end, Statement::Declaration(v.clone())))
.collect();
statements.push(Statement::MultipleDefinition(
d2.iter()
.map(|v| {
Node::new(
v.start,
v.end,
Assignee::Identifier(v.value.id.clone()),
)
})
.collect(),
e4,
));
statements.push(Node::new(pos, p4, Statement::MultipleDefinition(e2, e4)));
Ok((statements, s4, p4)) // output a multipledefinition with the destructure and the expression
}
Err(err) => Err(err),
@ -469,11 +505,19 @@ fn parse_statement1<T: Field>(
Ok((e6, s6, p6)) => match next_token(&s6, &p6) {
(Token::InlineComment(_), ref s7, _) => {
assert_eq!(s7, "");
Ok((vec![Statement::Condition(e4, e6)], s6, p6))
Ok((
vec![Node::new(pos, p6, Statement::Condition(e4, e6))],
s6,
p6,
))
}
(Token::Unknown(ref t7), ref s7, _) if t7 == "" => {
assert_eq!(s7, "");
Ok((vec![Statement::Condition(e4, e6)], s6, p6))
Ok((
vec![Node::new(pos, p6, Statement::Condition(e4, e6))],
s6,
p6,
))
}
(t7, _, p7) => Err(Error {
expected: vec![
@ -507,11 +551,19 @@ fn parse_statement1<T: Field>(
Ok((e6, s6, p6)) => match next_token(&s6, &p6) {
(Token::InlineComment(_), ref s7, _) => {
assert_eq!(s7, "");
Ok((vec![Statement::Condition(e4, e6)], s6, p6))
Ok((
vec![Node::new(pos, p6, Statement::Condition(e4, e6))],
s6,
p6,
))
}
(Token::Unknown(ref t7), ref s7, _) if t7 == "" => {
assert_eq!(s7, "");
Ok((vec![Statement::Condition(e4, e6)], s6, p6))
Ok((
vec![Node::new(pos, p6, Statement::Condition(e4, e6))],
s6,
p6,
))
}
(t7, _, p7) => Err(Error {
expected: vec![
@ -550,11 +602,19 @@ fn parse_statement1<T: Field>(
Ok((e5, s5, p5)) => match next_token(&s5, &p5) {
(Token::InlineComment(_), ref s6, _) => {
assert_eq!(s6, "");
Ok((vec![Statement::Condition(e3, e5)], s5, p5))
Ok((
vec![Node::new(pos, p5, Statement::Condition(e3, e5))],
s5,
p5,
))
}
(Token::Unknown(ref t6), ref s6, _) if t6 == "" => {
assert_eq!(s6, "");
Ok((vec![Statement::Condition(e3, e5)], s5, p5))
Ok((
vec![Node::new(pos, p5, Statement::Condition(e3, e5))],
s5,
p5,
))
}
(t6, _, p6) => Err(Error {
expected: vec![
@ -590,17 +650,23 @@ pub fn parse_identifier_list1<T: Field>(
_type: Option<Type>,
input: String,
pos: Position,
) -> Result<(Vec<String>, Vec<VariableNode>, String, Position), Error<T>> {
) -> Result<(Vec<AssigneeNode<T>>, Vec<VariableNode>, String, Position), Error<T>> {
let mut res = Vec::new();
let mut decl = Vec::new();
res.push(head.clone());
let start_pos = Position {
col: pos.col - head.len(),
..pos
};
res.push(Node::new(
start_pos,
pos,
Assignee::Identifier(head.clone()),
));
match _type {
Some(t) => {
let pos_before = Position {
col: pos.col - head.len(),
..pos
};
decl.push(Node::new(pos_before, pos, Variable::new(head, t)));
decl.push(Node::new(start_pos, pos, Variable::new(head, t)));
}
_ => {}
};
@ -610,13 +676,13 @@ pub fn parse_identifier_list1<T: Field>(
fn parse_comma_separated_identifier_list_rec<T: Field>(
input: String,
pos: Position,
mut acc: &mut Vec<String>,
mut acc: &mut Vec<AssigneeNode<T>>,
mut decl: &mut Vec<VariableNode>,
) -> Result<(Vec<String>, Vec<VariableNode>, String, Position), Error<T>> {
) -> Result<(Vec<AssigneeNode<T>>, 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());
acc.push(Node::new(p1, p2, Assignee::Identifier(id.clone())));
decl.push(Node::new(pos, p2, Variable::new(id, t)));
match next_token::<T>(&s2, &p2) {
(Token::Comma, s3, p3) => {
@ -632,7 +698,7 @@ fn parse_comma_separated_identifier_list_rec<T: Field>(
}),
},
(Token::Ide(id), s1, p1) => {
acc.push(id);
acc.push(Node::new(pos, p1, Assignee::Identifier(id)));
match next_token::<T>(&s1, &p1) {
(Token::Comma, s2, p2) => {
parse_comma_separated_identifier_list_rec(s2, p2, &mut acc, &mut decl)
@ -660,9 +726,10 @@ mod tests {
let pos = Position { line: 45, col: 121 };
let string = String::from("() == 1");
let cond = Statement::Condition(
Expression::FunctionCall(String::from("foo"), vec![]),
Expression::Number(FieldPrime::from(1)),
);
Expression::FunctionCall(String::from("foo"), vec![]).into(),
Expression::Number(FieldPrime::from(1)).into(),
)
.into();
assert_eq!(
Ok((vec![cond], String::from(""), pos.col(string.len() as isize))),
parse_statement1(String::from("foo"), string, pos)
@ -676,13 +743,16 @@ mod tests {
let cond = Statement::Condition(
Expression::Sub(
box Expression::Sub(
box Expression::FunctionCall(String::from("foo"), vec![]),
box Expression::FunctionCall(String::from("g"), vec![]),
),
box Expression::Number(FieldPrime::from(1)),
),
Expression::Number(FieldPrime::from(1)),
);
box Expression::FunctionCall(String::from("foo"), vec![]).into(),
box Expression::FunctionCall(String::from("g"), vec![]).into(),
)
.into(),
box Expression::Number(FieldPrime::from(1)).into(),
)
.into(),
Expression::Number(FieldPrime::from(1)).into(),
)
.into();
assert_eq!(
Ok((vec![cond], String::from(""), pos.col(string.len() as isize))),
parse_statement1(String::from("foo"), string, pos)
@ -697,15 +767,19 @@ mod tests {
Expression::Sub(
box Expression::Sub(
box Expression::Select(
box Expression::Identifier(String::from("foo")),
box Expression::Number(FieldPrime::from(3)),
),
box Expression::FunctionCall(String::from("g"), vec![]),
),
box Expression::Number(FieldPrime::from(1)),
),
Expression::Number(FieldPrime::from(1)),
);
box Expression::Identifier(String::from("foo")).into(),
box Expression::Number(FieldPrime::from(3)).into(),
)
.into(),
box Expression::FunctionCall(String::from("g"), vec![]).into(),
)
.into(),
box Expression::Number(FieldPrime::from(1)).into(),
)
.into(),
Expression::Number(FieldPrime::from(1)).into(),
)
.into();
assert_eq!(
Ok((vec![cond], String::from(""), pos.col(string.len() as isize))),
parse_statement1(String::from("foo"), string, pos)

File diff suppressed because it is too large Load diff

View file

@ -262,7 +262,6 @@ mod tests {
#[cfg(test)]
mod heuristics {
use super::*;
use absy::{Parameter, Variable};
#[test]
fn inline_constant_field() {

View file

@ -4,7 +4,6 @@
//! @author Thibaut Schaeffer <thibaut@schaeff.fr>
//! @date 2018
use absy::variable::Variable;
use std::collections::HashMap;
use typed_absy::folder::*;
use typed_absy::*;

View file

@ -4,7 +4,6 @@
//! @author Thibaut Schaeffer <thibaut@schaeff.fr>
//! @date 2018
use absy::variable::Variable;
use std::collections::HashMap;
use typed_absy::folder::*;
use typed_absy::*;

View file

@ -1,6 +1,5 @@
// Generic walk through a typed AST. Not mutating in place
use absy::variable::Variable;
use typed_absy::*;
use zokrates_field::field::Field;

View file

@ -6,9 +6,11 @@
//! @date 2017
pub mod folder;
mod parameter;
mod variable;
use absy::parameter::Parameter;
use absy::variable::Variable;
pub use typed_absy::parameter::Parameter;
pub use typed_absy::variable::Variable;
use types::Signature;
use flat_absy::*;

View file

@ -0,0 +1,41 @@
use absy;
use std::fmt;
use typed_absy::Variable;
#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub struct Parameter {
pub id: Variable,
pub private: bool,
}
impl Parameter {
#[cfg(test)]
pub fn private(v: Variable) -> Self {
Parameter {
id: v,
private: true,
}
}
}
impl fmt::Display for Parameter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let visibility = if self.private { "private " } else { "" };
write!(f, "{}{} {}", visibility, self.id.get_type(), self.id.id)
}
}
impl fmt::Debug for Parameter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Parameter(variable: {:?})", self.id)
}
}
impl From<absy::Parameter> for Parameter {
fn from(p: absy::Parameter) -> Parameter {
Parameter {
private: p.private,
id: p.id.value.into(),
}
}
}

View file

@ -0,0 +1,57 @@
use absy;
use std::fmt;
use types::Type;
#[derive(Serialize, Deserialize, Clone, PartialEq, Hash, Eq)]
pub struct Variable {
pub id: String,
pub _type: Type,
}
impl Variable {
pub fn field_element<S: Into<String>>(id: S) -> Variable {
Variable {
id: id.into(),
_type: Type::FieldElement,
}
}
pub fn boolean<S: Into<String>>(id: S) -> Variable {
Variable {
id: id.into(),
_type: Type::Boolean,
}
}
pub fn field_array<S: Into<String>>(id: S, size: usize) -> Variable {
Variable {
id: id.into(),
_type: Type::FieldElementArray(size),
}
}
pub fn get_type(&self) -> Type {
self._type.clone()
}
}
impl fmt::Display for Variable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {}", self._type, self.id,)
}
}
impl fmt::Debug for Variable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Variable(type: {:?}, id: {:?})", self._type, self.id,)
}
}
impl From<absy::Variable> for Variable {
fn from(v: absy::Variable) -> Variable {
Variable {
id: v.id,
_type: v._type,
}
}
}

View file

@ -1,7 +1,7 @@
extern crate serde_json;
use std::io;
use zokrates_core::compile::{compile as generic_compile, CompileError};
use zokrates_core::compile::{compile as generic_compile, CompileErrors};
use zokrates_core::ir;
use zokrates_field::field::{Field, FieldPrime};
@ -80,7 +80,7 @@ pub fn read_file(path: &str) -> String {
contents
}
pub fn compile(code: &str) -> Result<ir::Prog<FieldPrime>, CompileError<FieldPrime>> {
pub fn compile(code: &str) -> Result<ir::Prog<FieldPrime>, CompileErrors<FieldPrime>> {
generic_compile::<FieldPrime, &[u8], &[u8], io::Error>(&mut code.as_bytes(), None, None)
}