add multiple errors, add node for all AST, fix tests ignoring positions
This commit is contained in:
parent
d1295adc49
commit
e084165adc
22 changed files with 1824 additions and 1383 deletions
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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::<
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
))
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
@ -262,7 +262,6 @@ mod tests {
|
|||
#[cfg(test)]
|
||||
mod heuristics {
|
||||
use super::*;
|
||||
use absy::{Parameter, Variable};
|
||||
|
||||
#[test]
|
||||
fn inline_constant_field() {
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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::*;
|
||||
|
|
41
zokrates_core/src/typed_absy/parameter.rs
Normal file
41
zokrates_core/src/typed_absy/parameter.rs
Normal 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(),
|
||||
}
|
||||
}
|
||||
}
|
57
zokrates_core/src/typed_absy/variable.rs
Normal file
57
zokrates_core/src/typed_absy/variable.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue