parser rewrite

This commit is contained in:
Protryon 2021-03-03 09:59:24 -08:00
parent 2622a4be63
commit d400764e00
782 changed files with 7794 additions and 9916 deletions

37
Cargo.lock generated
View File

@ -1196,7 +1196,7 @@ dependencies = [
"criterion",
"indexmap",
"leo-ast",
"leo-grammar",
"leo-parser",
"num-bigint",
"serde",
"serde_json",
@ -1210,7 +1210,6 @@ version = "1.2.3"
dependencies = [
"criterion",
"indexmap",
"leo-grammar",
"leo-input",
"pest",
"serde",
@ -1228,10 +1227,10 @@ dependencies = [
"leo-asg",
"leo-ast",
"leo-gadgets",
"leo-grammar",
"leo-imports",
"leo-input",
"leo-package",
"leo-parser",
"leo-state",
"num-bigint",
"pest",
@ -1266,22 +1265,6 @@ dependencies = [
"thiserror",
]
[[package]]
name = "leo-grammar"
version = "1.2.3"
dependencies = [
"criterion",
"from-pest",
"lazy_static",
"pest",
"pest-ast",
"pest_derive",
"serde",
"serde_json",
"thiserror",
"tracing",
]
[[package]]
name = "leo-imports"
version = "1.2.3"
@ -1289,7 +1272,7 @@ dependencies = [
"indexmap",
"leo-asg",
"leo-ast",
"leo-grammar",
"leo-parser",
"thiserror",
"tracing",
]
@ -1364,6 +1347,20 @@ dependencies = [
"zip",
]
[[package]]
name = "leo-parser"
version = "1.2.3"
dependencies = [
"criterion",
"indexmap",
"lazy_static",
"leo-ast",
"serde",
"serde_json",
"thiserror",
"tracing",
]
[[package]]
name = "leo-state"
version = "1.2.3"

View File

@ -30,11 +30,11 @@ members = [
"ast",
"compiler",
"gadgets",
"grammar",
"imports",
"input",
"linter",
"package",
"parser",
"state",
"synthesizer",
]

View File

@ -33,9 +33,9 @@ version = "1.0"
version = "1.2.3"
path = "../ast"
[dependencies.leo-grammar]
[dependencies.leo-parser]
version = "1.2.3"
path = "../grammar"
path = "../parser"
[dependencies.num-bigint]
version = "0.3"

View File

@ -188,8 +188,30 @@ impl ConstInt {
const_int_map!(value_negate, x, x.checked_neg()?);
const_int_map!(value_bit_negate, x, !x);
const_int_op!(to_usize, Option<usize>, x, (*x).try_into().ok());
const_int_op!(to_u128, u128, x, *x as u128);
const_int_op!(to_u64, u64, x, *x as u64);
const_int_op!(to_u32, u32, x, *x as u32);
const_int_op!(to_u16, u16, x, *x as u16);
const_int_op!(to_u8, u8, x, *x as u8);
const_int_op!(to_i128, i128, x, *x as i128);
const_int_op!(to_i64, i64, x, *x as i64);
const_int_op!(to_i32, i32, x, *x as i32);
const_int_op!(to_i16, i16, x, *x as i16);
const_int_op!(to_i8, i8, x, *x as i8);
const_int_op!(to_string, String, x, (*x).to_string());
const_int_bimap!(value_add, x, y, x.checked_add(*y)?);
@ -226,6 +248,21 @@ impl ConstInt {
}
}
pub fn cast_to(&self, target: &IntegerType) -> ConstInt {
match target {
IntegerType::I8 => ConstInt::I8(self.to_i8()),
IntegerType::I16 => ConstInt::I16(self.to_i16()),
IntegerType::I32 => ConstInt::I32(self.to_i32()),
IntegerType::I64 => ConstInt::I64(self.to_i64()),
IntegerType::I128 => ConstInt::I128(self.to_i128()),
IntegerType::U8 => ConstInt::U8(self.to_u8()),
IntegerType::U16 => ConstInt::U16(self.to_u16()),
IntegerType::U32 => ConstInt::U32(self.to_u32()),
IntegerType::U64 => ConstInt::U64(self.to_u64()),
IntegerType::U128 => ConstInt::U128(self.to_u128()),
}
}
pub fn get_type<'a>(&self) -> Type<'a> {
Type::Integer(self.get_int_type())
}

View File

@ -17,14 +17,11 @@
//! Errors encountered when attempting to convert to an asg from an ast.
use crate::Span;
use leo_ast::{AstError, Error as FormattedError};
use leo_grammar::ParserError;
use leo_ast::{FormattedError, LeoError};
use leo_parser::SyntaxError;
#[derive(Debug, Error)]
pub enum AsgConvertError {
#[error("{}", _0)]
AstError(#[from] AstError),
#[error("{}", _0)]
Error(#[from] FormattedError),
@ -35,12 +32,32 @@ pub enum AsgConvertError {
InternalError(String),
#[error("{}", _0)]
ParserError(#[from] ParserError),
SyntaxError(#[from] SyntaxError),
}
impl LeoError for AsgConvertError {
fn get_path(&self) -> Option<&str> {
match self {
AsgConvertError::Error(error) => error.get_path(),
AsgConvertError::SyntaxError(error) => error.get_path(),
AsgConvertError::ImportError(error) => error.get_path(),
AsgConvertError::InternalError(_) => None,
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
AsgConvertError::Error(error) => error.set_path(path, contents),
AsgConvertError::SyntaxError(error) => error.set_path(path, contents),
AsgConvertError::ImportError(error) => error.set_path(path, contents),
AsgConvertError::InternalError(_) => {}
}
}
}
impl AsgConvertError {
fn new_from_span(message: String, span: &Span) -> Self {
AsgConvertError::Error(FormattedError::new_from_span(message, span.clone()))
AsgConvertError::Error(FormattedError::new_from_span(message, span))
}
pub fn unresolved_circuit(name: &str, span: &Span) -> Self {
@ -256,6 +273,14 @@ impl AsgConvertError {
)
}
pub fn call_test_function(span: &Span) -> Self {
Self::new_from_span("cannot call test function".to_string(), span)
}
pub fn circuit_test_function(span: &Span) -> Self {
Self::new_from_span("cannot have test function as member of circuit".to_string(), span)
}
pub fn parse_index_error() -> Self {
AsgConvertError::InternalError("failed to parse index".to_string())
}

View File

@ -109,7 +109,7 @@ impl<'a> FromAst<'a, leo_ast::CallExpression> for CallExpression<'a> {
return Err(AsgConvertError::unexpected_type(
"circuit",
type_.map(|x| x.to_string()).as_deref(),
&span,
span,
));
}
};
@ -117,26 +117,26 @@ impl<'a> FromAst<'a, leo_ast::CallExpression> for CallExpression<'a> {
let member = circuit.members.borrow();
let member = member
.get(&name.name)
.ok_or_else(|| AsgConvertError::unresolved_circuit_member(&circuit_name, &name.name, &span))?;
.ok_or_else(|| AsgConvertError::unresolved_circuit_member(&circuit_name, &name.name, span))?;
match member {
CircuitMember::Function(body) => {
if body.qualifier == FunctionQualifier::Static {
return Err(AsgConvertError::circuit_static_call_invalid(
&circuit_name,
&name.name,
&span,
span,
));
} else if body.qualifier == FunctionQualifier::MutSelfRef && !target.is_mut_ref() {
return Err(AsgConvertError::circuit_member_mut_call_invalid(
&circuit_name,
&name.name,
&span,
span,
));
}
(Some(target), *body)
}
CircuitMember::Variable(_) => {
return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, &span));
return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, span));
}
}
}
@ -150,27 +150,27 @@ impl<'a> FromAst<'a, leo_ast::CallExpression> for CallExpression<'a> {
.resolve_circuit(&circuit_name.name)
.ok_or_else(|| AsgConvertError::unresolved_circuit(&circuit_name.name, &circuit_name.span))?
} else {
return Err(AsgConvertError::unexpected_type("circuit", None, &span));
return Err(AsgConvertError::unexpected_type("circuit", None, span));
};
let circuit_name = circuit.name.borrow().name.clone();
let member = circuit.members.borrow();
let member = member
.get(&name.name)
.ok_or_else(|| AsgConvertError::unresolved_circuit_member(&circuit_name, &name.name, &span))?;
.ok_or_else(|| AsgConvertError::unresolved_circuit_member(&circuit_name, &name.name, span))?;
match member {
CircuitMember::Function(body) => {
if body.qualifier != FunctionQualifier::Static {
return Err(AsgConvertError::circuit_member_call_invalid(
&circuit_name,
&name.name,
&span,
span,
));
}
(None, *body)
}
CircuitMember::Variable(_) => {
return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, &span));
return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, span));
}
}
}
@ -206,12 +206,15 @@ impl<'a> FromAst<'a, leo_ast::CallExpression> for CallExpression<'a> {
let argument = argument.get().borrow();
let converted = <&Expression<'a>>::from_ast(scope, expr, Some(argument.type_.clone().partial()))?;
if argument.const_ && !converted.is_consty() {
return Err(AsgConvertError::unexpected_nonconst(&expr.span()));
return Err(AsgConvertError::unexpected_nonconst(expr.span()));
}
Ok(Cell::new(converted))
})
.collect::<Result<Vec<_>, AsgConvertError>>()?;
if function.is_test() {
return Err(AsgConvertError::call_test_function(&value.span));
}
Ok(CallExpression {
parent: Cell::new(None),
span: Some(value.span.clone()),

109
asg/src/expression/cast.rs Normal file
View File

@ -0,0 +1,109 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
pub use leo_ast::UnaryOperation;
use std::cell::Cell;
#[derive(Clone)]
pub struct CastExpression<'a> {
pub parent: Cell<Option<&'a Expression<'a>>>,
pub span: Option<Span>,
pub inner: Cell<&'a Expression<'a>>,
pub target_type: Type<'a>,
}
impl<'a> Node for CastExpression<'a> {
fn span(&self) -> Option<&Span> {
self.span.as_ref()
}
}
impl<'a> ExpressionNode<'a> for CastExpression<'a> {
fn set_parent(&self, parent: &'a Expression<'a>) {
self.parent.replace(Some(parent));
}
fn get_parent(&self) -> Option<&'a Expression<'a>> {
self.parent.get()
}
fn enforce_parents(&self, expr: &'a Expression<'a>) {
self.inner.get().set_parent(expr);
}
fn get_type(&self) -> Option<Type<'a>> {
Some(self.target_type.clone())
}
fn is_mut_ref(&self) -> bool {
false
}
fn const_value(&self) -> Option<ConstValue> {
let value = self.inner.get().const_value()?;
match value {
ConstValue::Int(int) => match &self.target_type {
Type::Integer(target) => Some(ConstValue::Int(int.cast_to(target))),
_ => None,
},
_ => None,
}
}
fn is_consty(&self) -> bool {
self.inner.get().is_consty()
}
}
impl<'a> FromAst<'a, leo_ast::CastExpression> for CastExpression<'a> {
fn from_ast(
scope: &'a Scope<'a>,
value: &leo_ast::CastExpression,
expected_type: Option<PartialType<'a>>,
) -> Result<CastExpression<'a>, AsgConvertError> {
let target_type = scope.resolve_ast_type(&value.target_type)?;
if let Some(expected_type) = &expected_type {
if !expected_type.matches(&target_type) {
return Err(AsgConvertError::unexpected_type(
&expected_type.to_string(),
Some(&target_type.to_string()),
&value.span,
));
}
}
let inner = <&Expression<'a>>::from_ast(scope, &*value.inner, None)?;
Ok(CastExpression {
parent: Cell::new(None),
span: Some(value.span.clone()),
inner: Cell::new(inner),
target_type,
})
}
}
impl<'a> Into<leo_ast::CastExpression> for &CastExpression<'a> {
fn into(self) -> leo_ast::CastExpression {
leo_ast::CastExpression {
target_type: (&self.target_type).into(),
inner: Box::new(self.inner.get().into()),
span: self.span.clone().unwrap_or_default(),
}
}
}

View File

@ -99,10 +99,10 @@ impl<'a> FromAst<'a, leo_ast::CircuitInitExpression> for CircuitInitExpression<'
));
}
}
let members: IndexMap<&String, (&Identifier, &leo_ast::Expression)> = value
let members: IndexMap<&String, (&Identifier, Option<&leo_ast::Expression>)> = value
.members
.iter()
.map(|x| (&x.identifier.name, (&x.identifier, &x.expression)))
.map(|x| (&x.identifier.name, (&x.identifier, x.expression.as_ref())))
.collect();
let mut values: Vec<(Identifier, Cell<&'a Expression<'a>>)> = vec![];
@ -125,7 +125,15 @@ impl<'a> FromAst<'a, leo_ast::CircuitInitExpression> for CircuitInitExpression<'
continue;
};
if let Some((identifier, receiver)) = members.get(&name) {
let received = <&Expression<'a>>::from_ast(scope, *receiver, Some(type_.partial()))?;
let received = if let Some(receiver) = *receiver {
<&Expression<'a>>::from_ast(scope, receiver, Some(type_.partial()))?
} else {
<&Expression<'a>>::from_ast(
scope,
&leo_ast::Expression::Identifier((*identifier).clone()),
Some(type_.partial()),
)?
};
values.push(((*identifier).clone(), Cell::new(received)));
} else {
return Err(AsgConvertError::missing_circuit_member(
@ -165,7 +173,7 @@ impl<'a> Into<leo_ast::CircuitInitExpression> for &CircuitInitExpression<'a> {
.iter()
.map(|(name, value)| leo_ast::CircuitImpliedVariableDefinition {
identifier: name.clone(),
expression: value.get().into(),
expression: Some(value.get().into()),
})
.collect(),
span: self.span.clone().unwrap_or_default(),

View File

@ -62,6 +62,9 @@ pub use unary::*;
mod variable_ref;
pub use variable_ref::*;
mod cast;
pub use cast::*;
use crate::{AsgConvertError, ConstValue, FromAst, Node, PartialType, Scope, Span, Type};
#[derive(Clone)]
@ -71,6 +74,7 @@ pub enum Expression<'a> {
Binary(BinaryExpression<'a>),
Unary(UnaryExpression<'a>),
Ternary(TernaryExpression<'a>),
Cast(CastExpression<'a>),
ArrayInline(ArrayInlineExpression<'a>),
ArrayInit(ArrayInitExpression<'a>),
@ -95,6 +99,7 @@ impl<'a> Node for Expression<'a> {
Binary(x) => x.span(),
Unary(x) => x.span(),
Ternary(x) => x.span(),
Cast(x) => x.span(),
ArrayInline(x) => x.span(),
ArrayInit(x) => x.span(),
ArrayAccess(x) => x.span(),
@ -128,6 +133,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
Binary(x) => x.set_parent(parent),
Unary(x) => x.set_parent(parent),
Ternary(x) => x.set_parent(parent),
Cast(x) => x.set_parent(parent),
ArrayInline(x) => x.set_parent(parent),
ArrayInit(x) => x.set_parent(parent),
ArrayAccess(x) => x.set_parent(parent),
@ -148,6 +154,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
Binary(x) => x.get_parent(),
Unary(x) => x.get_parent(),
Ternary(x) => x.get_parent(),
Cast(x) => x.get_parent(),
ArrayInline(x) => x.get_parent(),
ArrayInit(x) => x.get_parent(),
ArrayAccess(x) => x.get_parent(),
@ -168,6 +175,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
Binary(x) => x.enforce_parents(expr),
Unary(x) => x.enforce_parents(expr),
Ternary(x) => x.enforce_parents(expr),
Cast(x) => x.enforce_parents(expr),
ArrayInline(x) => x.enforce_parents(expr),
ArrayInit(x) => x.enforce_parents(expr),
ArrayAccess(x) => x.enforce_parents(expr),
@ -188,6 +196,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
Binary(x) => x.get_type(),
Unary(x) => x.get_type(),
Ternary(x) => x.get_type(),
Cast(x) => x.get_type(),
ArrayInline(x) => x.get_type(),
ArrayInit(x) => x.get_type(),
ArrayAccess(x) => x.get_type(),
@ -208,6 +217,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
Binary(x) => x.is_mut_ref(),
Unary(x) => x.is_mut_ref(),
Ternary(x) => x.is_mut_ref(),
Cast(x) => x.is_mut_ref(),
ArrayInline(x) => x.is_mut_ref(),
ArrayInit(x) => x.is_mut_ref(),
ArrayAccess(x) => x.is_mut_ref(),
@ -228,6 +238,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
Binary(x) => x.const_value(),
Unary(x) => x.const_value(),
Ternary(x) => x.const_value(),
Cast(x) => x.const_value(),
ArrayInline(x) => x.const_value(),
ArrayInit(x) => x.const_value(),
ArrayAccess(x) => x.const_value(),
@ -248,6 +259,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
Binary(x) => x.is_consty(),
Unary(x) => x.is_consty(),
Ternary(x) => x.is_consty(),
Cast(x) => x.is_consty(),
ArrayInline(x) => x.is_consty(),
ArrayInit(x) => x.is_consty(),
ArrayAccess(x) => x.is_consty(),
@ -281,6 +293,9 @@ impl<'a> FromAst<'a, leo_ast::Expression> for &'a Expression<'a> {
Ternary(conditional) => scope.alloc_expression(
TernaryExpression::from_ast(scope, conditional, expected_type).map(Expression::Ternary)?,
),
Cast(cast) => {
scope.alloc_expression(CastExpression::from_ast(scope, cast, expected_type).map(Expression::Cast)?)
}
ArrayInline(array_inline) => scope.alloc_expression(
ArrayInlineExpression::from_ast(scope, array_inline, expected_type).map(Expression::ArrayInline)?,
@ -333,6 +348,7 @@ impl<'a> Into<leo_ast::Expression> for &Expression<'a> {
Binary(x) => leo_ast::Expression::Binary(x.into()),
Unary(x) => leo_ast::Expression::Unary(x.into()),
Ternary(x) => leo_ast::Expression::Ternary(x.into()),
Cast(x) => leo_ast::Expression::Cast(x.into()),
ArrayInline(x) => leo_ast::Expression::ArrayInline(x.into()),
ArrayInit(x) => leo_ast::Expression::ArrayInit(x.into()),
ArrayAccess(x) => leo_ast::Expression::ArrayAccess(x.into()),

View File

@ -69,6 +69,10 @@ impl<'a> ExpressionNode<'a> for UnaryExpression<'a> {
_ => None,
}
}
UnaryOperation::BitNot => match inner {
ConstValue::Int(value) => Some(ConstValue::Int(value.value_bit_negate()?)),
_ => None,
},
}
} else {
None
@ -110,6 +114,17 @@ impl<'a> FromAst<'a, leo_ast::UnaryExpression> for UnaryExpression<'a> {
));
}
},
UnaryOperation::BitNot => match expected_type.map(|x| x.full()).flatten() {
Some(type_ @ Type::Integer(_)) => Some(type_),
None => None,
Some(type_) => {
return Err(AsgConvertError::unexpected_type(
&type_.to_string(),
Some("integer"),
&value.span,
));
}
},
};
Ok(UnaryExpression {
parent: Cell::new(None),

View File

@ -76,8 +76,6 @@ pub use context::*;
pub use leo_ast::{Ast, Identifier, Span};
use std::path::Path;
/// The abstract semantic graph (ASG) for a Leo program.
///
/// The [`Asg`] type represents a Leo program as a series of recursive data types.
@ -92,14 +90,14 @@ pub struct Asg<'a> {
impl<'a> Asg<'a> {
/// Creates a new ASG from a given AST and import resolver.
pub fn new<T: ImportResolver<'a>>(
pub fn new<T: ImportResolver<'a>, Y: AsRef<leo_ast::Program>>(
context: AsgContext<'a>,
ast: &Ast,
ast: Y,
resolver: &mut T,
) -> Result<Self, AsgConvertError> {
Ok(Self {
context,
asg: InternalProgram::new(context, &ast.as_repr(), resolver)?,
asg: InternalProgram::new(context, ast.as_ref(), resolver)?,
})
}
@ -127,10 +125,9 @@ pub fn load_asg<'a, T: ImportResolver<'a>>(
resolver: &mut T,
) -> Result<Program<'a>, AsgConvertError> {
// Parses the Leo file and constructs a grammar ast.
let ast = leo_grammar::Grammar::new(&Path::new("input.leo"), content)
.map_err(|e| AsgConvertError::InternalError(format!("ast: {:?}", e)))?;
let ast = leo_parser::parse_ast("input.leo", content)?;
InternalProgram::new(context, leo_ast::Ast::new("load_ast", &ast)?.as_repr(), resolver)
InternalProgram::new(context, ast.as_repr(), resolver)
}
pub fn new_alloc_context<'a>() -> Arena<ArenaNode<'a>> {

View File

@ -15,7 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::Program;
pub use leo_ast::Error as FormattedError;
pub use leo_ast::FormattedError;
pub trait AsgPass {
fn do_pass(asg: &Program) -> Result<(), FormattedError>;

View File

@ -92,6 +92,9 @@ impl<'a> Circuit<'a> {
}
let asg_function = Function::init(new_scope, function)?;
asg_function.circuit.replace(Some(circuit));
if asg_function.is_test() {
return Err(AsgConvertError::circuit_test_function(&function.identifier.span));
}
members.insert(function.identifier.name.clone(), CircuitMember::Function(asg_function));
}
}

View File

@ -29,6 +29,7 @@ use crate::{
Variable,
};
use indexmap::IndexMap;
pub use leo_ast::Annotation;
use leo_ast::FunctionInput;
use std::cell::{Cell, RefCell};
@ -52,6 +53,7 @@ pub struct Function<'a> {
pub body: Cell<Option<&'a Statement<'a>>>,
pub scope: &'a Scope<'a>,
pub qualifier: FunctionQualifier,
pub annotations: Vec<Annotation>,
}
impl<'a> PartialEq for Function<'a> {
@ -126,6 +128,7 @@ impl<'a> Function<'a> {
qualifier,
scope: new_scope,
span: Some(value.span.clone()),
annotations: value.annotations.clone(),
});
function.scope.function.replace(Some(function));
@ -177,6 +180,10 @@ impl<'a> Function<'a> {
Ok(())
}
pub fn is_test(&self) -> bool {
self.annotations.iter().any(|x| x.name.name == "test")
}
}
impl<'a> Into<leo_ast::Function> for &Function<'a> {
@ -213,6 +220,7 @@ impl<'a> Into<leo_ast::Function> for &Function<'a> {
block: body,
output: Some((&output).into()),
span,
annotations: self.annotations.clone(),
}
}
}

View File

@ -45,9 +45,6 @@ pub struct InternalProgram<'a> {
/// these should generally not be accessed directly, but through scoped imports
pub imported_modules: IndexMap<String, Program<'a>>,
/// Maps test name => test code block.
pub test_functions: IndexMap<String, (&'a Function<'a>, Option<Identifier>)>, // identifier = test input file
/// Maps function name => function code block.
pub functions: IndexMap<String, &'a Function<'a>>,
@ -248,14 +245,6 @@ impl<'a> InternalProgram<'a> {
scope.circuits.borrow_mut().insert(name.name.clone(), asg_circuit);
}
let mut proto_test_functions = IndexMap::new();
for (name, test_function) in program.tests.iter() {
assert_eq!(name.name, test_function.function.identifier.name);
let function = Function::init(scope, &test_function.function)?;
proto_test_functions.insert(name.name.clone(), function);
}
for (name, function) in program.functions.iter() {
assert_eq!(name.name, function.identifier.name);
let function = Function::init(scope, function)?;
@ -264,16 +253,6 @@ impl<'a> InternalProgram<'a> {
}
// Load concrete definitions.
let mut test_functions = IndexMap::new();
for (name, test_function) in program.tests.iter() {
assert_eq!(name.name, test_function.function.identifier.name);
let function = proto_test_functions.get(&name.name).unwrap();
function.fill_from_ast(&test_function.function)?;
test_functions.insert(name.name.clone(), (*function, test_function.input_file.clone()));
}
let mut functions = IndexMap::new();
for (name, function) in program.functions.iter() {
assert_eq!(name.name, function.identifier.name);
@ -298,7 +277,6 @@ impl<'a> InternalProgram<'a> {
context,
id: context.get_id(),
name: program.name.clone(),
test_functions,
functions,
circuits,
imported_modules: resolved_packages
@ -350,7 +328,6 @@ pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program {
let mut all_circuits: IndexMap<String, &'a Circuit<'a>> = IndexMap::new();
let mut all_functions: IndexMap<String, &'a Function<'a>> = IndexMap::new();
let mut all_test_functions: IndexMap<String, (&'a Function<'a>, Option<Identifier>)> = IndexMap::new();
let mut identifiers = InternalIdentifierGenerator { next: 0 };
for (_, program) in all_programs.into_iter() {
for (name, circuit) in program.circuits.iter() {
@ -367,11 +344,6 @@ pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program {
function.name.borrow_mut().name = identifier.clone();
all_functions.insert(identifier, *function);
}
for (name, function) in program.test_functions.iter() {
let identifier = format!("{}{}", identifiers.next().unwrap(), name);
function.0.name.borrow_mut().name = identifier.clone();
all_test_functions.insert(identifier, function.clone());
}
}
leo_ast::Program {
@ -388,15 +360,6 @@ pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program {
})
.collect(),
expected_input: vec![],
tests: all_test_functions
.into_iter()
.map(|(_, (function, ident))| {
(function.name.borrow().clone(), leo_ast::TestFunction {
function: function.into(),
input_file: ident,
})
})
.collect(),
functions: all_functions
.into_iter()
.map(|(_, function)| (function.name.borrow().clone(), function.into()))
@ -424,16 +387,6 @@ impl<'a> Into<leo_ast::Program> for &InternalProgram<'a> {
.iter()
.map(|(_, function)| (function.name.borrow().clone(), (*function).into()))
.collect(),
tests: self
.test_functions
.iter()
.map(|(_, function)| {
(function.0.name.borrow().clone(), leo_ast::TestFunction {
function: function.0.into(),
input_file: function.1.clone(),
})
})
.collect(),
}
}
}

View File

@ -47,6 +47,7 @@ impl<'a, T: Monoid, R: MonoidalReducerExpression<'a, T>> MonoidalDirector<'a, T,
Expression::CircuitAccess(e) => self.reduce_circuit_access(e),
Expression::CircuitInit(e) => self.reduce_circuit_init(e),
Expression::Ternary(e) => self.reduce_ternary_expression(e),
Expression::Cast(e) => self.reduce_cast_expression(e),
Expression::Constant(e) => self.reduce_constant(e),
Expression::TupleAccess(e) => self.reduce_tuple_access(e),
Expression::TupleInit(e) => self.reduce_tuple_init(e),
@ -131,6 +132,12 @@ impl<'a, T: Monoid, R: MonoidalReducerExpression<'a, T>> MonoidalDirector<'a, T,
.reduce_ternary_expression(input, condition, if_true, if_false)
}
pub fn reduce_cast_expression(&mut self, input: &CastExpression<'a>) -> T {
let inner = self.reduce_expression(input.inner.get());
self.reducer.reduce_cast_expression(input, inner)
}
pub fn reduce_constant(&mut self, input: &Constant<'a>) -> T {
self.reducer.reduce_constant(input)
}
@ -299,15 +306,10 @@ impl<'a, T: Monoid, R: MonoidalReducerProgram<'a, T>> MonoidalDirector<'a, T, R>
.iter()
.map(|(_, import)| self.reduce_program(import))
.collect();
let test_functions = input
.test_functions
.iter()
.map(|(_, (f, _))| self.reduce_function(f))
.collect();
let functions = input.functions.iter().map(|(_, f)| self.reduce_function(f)).collect();
let circuits = input.circuits.iter().map(|(_, c)| self.reduce_circuit(c)).collect();
self.reducer
.reduce_program(&input, imported_modules, test_functions, functions, circuits)
.reduce_program(&input, imported_modules, functions, circuits)
}
}

View File

@ -64,6 +64,10 @@ pub trait MonoidalReducerExpression<'a, T: Monoid> {
condition.append(if_true).append(if_false)
}
fn reduce_cast_expression(&mut self, input: &CastExpression<'a>, inner: T) -> T {
inner
}
fn reduce_constant(&mut self, input: &Constant<'a>) -> T {
T::default()
}
@ -157,13 +161,11 @@ pub trait MonoidalReducerProgram<'a, T: Monoid>: MonoidalReducerStatement<'a, T>
&mut self,
input: &InternalProgram,
imported_modules: Vec<T>,
test_functions: Vec<T>,
functions: Vec<T>,
circuits: Vec<T>,
) -> T {
T::default()
.append_all(imported_modules.into_iter())
.append_all(test_functions.into_iter())
.append_all(functions.into_iter())
.append_all(circuits.into_iter())
}

View File

@ -72,6 +72,10 @@ pub trait ExpressionVisitor<'a> {
Default::default()
}
fn visit_cast_expression(&mut self, input: &CastExpression<'a>) -> VisitResult {
Default::default()
}
fn visit_constant(&mut self, input: &Constant<'a>) -> VisitResult {
Default::default()
}

View File

@ -60,6 +60,7 @@ impl<'a, R: ExpressionVisitor<'a>> VisitorDirector<'a, R> {
Expression::CircuitAccess(e) => self.visit_circuit_access(e),
Expression::CircuitInit(e) => self.visit_circuit_init(e),
Expression::Ternary(e) => self.visit_ternary_expression(e),
Expression::Cast(e) => self.visit_cast_expression(e),
Expression::Constant(e) => self.visit_constant(e),
Expression::TupleAccess(e) => self.visit_tuple_access(e),
Expression::TupleInit(e) => self.visit_tuple_init(e),
@ -184,6 +185,16 @@ impl<'a, R: ExpressionVisitor<'a>> VisitorDirector<'a, R> {
}
}
pub fn visit_cast_expression(&mut self, input: &CastExpression<'a>) -> ConcreteVisitResult {
match self.visitor.visit_cast_expression(input) {
VisitResult::VisitChildren => {
self.visit_expression(&input.inner)?;
Ok(())
}
x => x.into(),
}
}
pub fn visit_constant(&mut self, input: &Constant<'a>) -> ConcreteVisitResult {
self.visitor.visit_constant(input).into()
}
@ -419,9 +430,6 @@ impl<'a, R: ProgramVisitor<'a>> VisitorDirector<'a, R> {
for (_, import) in input.imported_modules.iter() {
self.visit_program(import)?;
}
for (_, (function, _)) in input.test_functions.iter() {
self.visit_function(function)?;
}
for (_, function) in input.functions.iter() {
self.visit_function(function)?;
}

View File

@ -72,10 +72,10 @@ impl<'a> FromAst<'a, leo_ast::AssignStatement> for &'a Statement<'a> {
let variable = if name == "input" {
if let Some(function) = scope.resolve_current_function() {
if !function.has_input {
return Err(AsgConvertError::unresolved_reference(name, span));
return Err(AsgConvertError::unresolved_reference(name, &span));
}
} else {
return Err(AsgConvertError::unresolved_reference(name, span));
return Err(AsgConvertError::unresolved_reference(name, &span));
}
if let Some(input) = scope.resolve_input() {
input.container
@ -87,7 +87,7 @@ impl<'a> FromAst<'a, leo_ast::AssignStatement> for &'a Statement<'a> {
} else {
scope
.resolve_variable(&name)
.ok_or_else(|| AsgConvertError::unresolved_reference(name, span))?
.ok_or_else(|| AsgConvertError::unresolved_reference(name, &span))?
};
if !variable.borrow().mutable {

View File

@ -15,15 +15,14 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type};
use leo_ast::ConsoleFunction as AstConsoleFunction;
use leo_ast::{ConsoleFunction as AstConsoleFunction, FormattedStringPart};
use std::cell::Cell;
// TODO (protryon): Refactor to not require/depend on span
#[derive(Clone)]
pub struct FormattedString<'a> {
pub string: String,
pub containers: Vec<Span>,
pub parts: Vec<FormattedStringPart>,
pub parameters: Vec<Cell<&'a Expression<'a>>>,
pub span: Span,
}
@ -55,10 +54,15 @@ impl<'a> FromAst<'a, leo_ast::FormattedString> for FormattedString<'a> {
value: &leo_ast::FormattedString,
_expected_type: Option<PartialType<'a>>,
) -> Result<Self, AsgConvertError> {
if value.parameters.len() != value.containers.len() {
let expected_param_len = value
.parts
.iter()
.filter(|x| matches!(x, FormattedStringPart::Container))
.count();
if value.parameters.len() != expected_param_len {
// + 1 for formatting string as to not confuse user
return Err(AsgConvertError::unexpected_call_argument_count(
value.containers.len() + 1,
expected_param_len + 1,
value.parameters.len() + 1,
&value.span,
));
@ -68,8 +72,7 @@ impl<'a> FromAst<'a, leo_ast::FormattedString> for FormattedString<'a> {
parameters.push(Cell::new(<&Expression<'a>>::from_ast(scope, parameter, None)?));
}
Ok(FormattedString {
string: value.string.clone(),
containers: value.containers.iter().map(|x| x.span.clone()).collect(),
parts: value.parts.clone(),
parameters,
span: value.span.clone(),
})
@ -79,12 +82,7 @@ impl<'a> FromAst<'a, leo_ast::FormattedString> for FormattedString<'a> {
impl<'a> Into<leo_ast::FormattedString> for &FormattedString<'a> {
fn into(self) -> leo_ast::FormattedString {
leo_ast::FormattedString {
string: self.string.clone(),
containers: self
.containers
.iter()
.map(|span| leo_ast::FormattedContainer { span: span.clone() })
.collect(),
parts: self.parts.clone(),
parameters: self.parameters.iter().map(|e| e.get().into()).collect(),
span: self.span.clone(),
}

View File

@ -28,7 +28,6 @@ use crate::{
Type,
Variable,
};
use leo_ast::{AstError, DeprecatedError};
use std::cell::{Cell, RefCell};
@ -90,11 +89,6 @@ impl<'a> FromAst<'a, leo_ast::DefinitionStatement> for &'a Statement<'a> {
}
for (variable, type_) in statement.variable_names.iter().zip(output_types.into_iter()) {
if statement.declaration_type == leo_ast::Declare::Const {
return Err(AsgConvertError::AstError(AstError::DeprecatedError(
DeprecatedError::const_statement(&statement.span),
)));
}
variables.push(&*scope.alloc_variable(RefCell::new(InnerVariable {
id: scope.context.get_id(),
name: variable.identifier.clone(),

View File

@ -123,6 +123,10 @@ impl<'a> Type<'a> {
pub fn is_unit(&self) -> bool {
matches!(self, Type::Tuple(t) if t.is_empty())
}
pub fn can_cast_to(&self, to: &Type<'a>) -> bool {
matches!(self, Type::Integer(_)) && matches!(to, Type::Integer(_))
}
}
impl<'a> fmt::Display for Type<'a> {

View File

@ -17,19 +17,6 @@ include = [ "Cargo.toml", "src", "README.md", "LICENSE.md" ]
license = "GPL-3.0"
edition = "2018"
[[bin]]
name = "leo_ast"
path = "src/main.rs"
[[bench]]
name = "leo_ast"
path = "benches/leo_ast.rs"
harness = false
[dependencies.leo-grammar]
path = "../grammar"
version = "1.2.3"
[dependencies.leo-input]
path = "../input"
version = "1.2.3"
@ -43,6 +30,7 @@ version = "2.0"
[dependencies.serde]
version = "1.0"
features = ["derive", "rc"]
[dependencies.serde_json]
version = "1.0"
@ -55,4 +43,4 @@ version = "0.3"
[features]
default = [ ]
ci_skip = [ "leo-grammar/ci_skip" ]
ci_skip = [ ]

View File

@ -14,84 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Circuit, DeprecatedError, Function, FunctionInput, Identifier, ImportStatement, TestFunction};
use leo_grammar::{
annotations::{Annotation, AnnotationArguments, AnnotationName},
definitions::{AnnotatedDefinition, Definition},
};
use crate::{Identifier, Span};
use std::convert::TryFrom;
use serde::{Deserialize, Serialize};
use indexmap::IndexMap;
pub fn load_annotation(
annotated_definition: AnnotatedDefinition,
_imports: &mut Vec<ImportStatement>,
_circuits: &mut IndexMap<Identifier, Circuit>,
_functions: &mut IndexMap<Identifier, Function>,
tests: &mut IndexMap<Identifier, TestFunction>,
_expected: &mut Vec<FunctionInput>,
) -> Result<(), DeprecatedError> {
let ast_annotation = annotated_definition.annotation;
let ast_definition = *annotated_definition.definition;
match ast_definition {
Definition::Import(_) => {
unimplemented!("annotated imports are not supported yet");
}
Definition::Circuit(_) => {
unimplemented!("annotated circuits are not supported yet");
}
Definition::Function(function) => match ast_annotation.name {
// If it's deprecated for more than one type of syntax,
// we could just call it before the match on ast_definition.
AnnotationName::Context(_) => Err(DeprecatedError::try_from(ast_annotation.name).unwrap()),
AnnotationName::Test(_) => {
let ident = Identifier::from(function.identifier.clone());
_functions.remove(&ident);
let test_function = leo_grammar::functions::TestFunction::from(function);
let test = TestFunction::from(test_function);
tests.insert(ident, test.clone());
load_annotated_test(test, ast_annotation, tests);
Ok(())
}
},
Definition::Deprecated(_) => Ok(()),
Definition::Annotated(_) => {
unimplemented!("nested annotations are not supported yet");
}
}
}
pub fn load_annotated_test(test: TestFunction, annotation: Annotation, tests: &mut IndexMap<Identifier, TestFunction>) {
let name = annotation.name;
let ast_arguments = annotation.arguments;
match name {
AnnotationName::Test(_) if ast_arguments.is_some() => {
load_annotated_test_context(test, ast_arguments.unwrap(), tests)
}
_ => (),
}
}
pub fn load_annotated_test_context(
mut test: TestFunction,
ast_arguments: AnnotationArguments,
tests: &mut IndexMap<Identifier, TestFunction>,
) {
let arguments = ast_arguments.arguments;
if arguments.len() != 1 {
panic!("text context annotation must have one argument identifier")
}
let ast_input_file = arguments[0].to_owned();
let input_file = Identifier::from(ast_input_file);
test.input_file = Some(input_file);
tests.insert(test.function.identifier.clone(), test);
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Annotation {
pub span: Span,
pub name: Identifier,
pub arguments: Vec<String>,
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{CircuitMember, Identifier};
use leo_grammar::circuits::Circuit as GrammarCircuit;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -26,15 +25,6 @@ pub struct Circuit {
pub members: Vec<CircuitMember>,
}
impl<'ast> From<GrammarCircuit<'ast>> for Circuit {
fn from(circuit: GrammarCircuit<'ast>) -> Self {
let circuit_name = Identifier::from(circuit.identifier);
let members = circuit.members.into_iter().map(CircuitMember::from).collect();
Self { circuit_name, members }
}
}
impl Circuit {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "circuit {} {{ ", self.circuit_name)?;

View File

@ -15,27 +15,11 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Identifier};
use leo_grammar::circuits::CircuitImpliedVariable;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct CircuitImpliedVariableDefinition {
pub identifier: Identifier,
pub expression: Expression,
}
impl<'ast> From<CircuitImpliedVariable<'ast>> for CircuitImpliedVariableDefinition {
fn from(member: CircuitImpliedVariable<'ast>) -> Self {
match member {
CircuitImpliedVariable::CircuitVariable(circuit_variable) => Self {
identifier: Identifier::from(circuit_variable.identifier),
expression: Expression::from(circuit_variable.expression),
},
CircuitImpliedVariable::Identifier(identifier) => Self {
identifier: Identifier::from(identifier.clone()),
expression: Expression::from(identifier),
},
}
}
pub expression: Option<Expression>,
}

View File

@ -15,10 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Function, Identifier, Type};
use leo_grammar::{
circuits::{CircuitMember as GrammarCircuitMember, CircuitVariableDefinition as GrammarCircuitVariableDefinition},
functions::Function as GrammarFunction,
};
use serde::{Deserialize, Serialize};
use std::fmt;
@ -31,30 +27,6 @@ pub enum CircuitMember {
CircuitFunction(Function),
}
impl<'ast> From<GrammarCircuitVariableDefinition<'ast>> for CircuitMember {
fn from(circuit_value: GrammarCircuitVariableDefinition<'ast>) -> Self {
CircuitMember::CircuitVariable(
Identifier::from(circuit_value.identifier),
Type::from(circuit_value.type_),
)
}
}
impl<'ast> From<GrammarFunction<'ast>> for CircuitMember {
fn from(circuit_function: GrammarFunction<'ast>) -> Self {
CircuitMember::CircuitFunction(Function::from(circuit_function))
}
}
impl<'ast> From<GrammarCircuitMember<'ast>> for CircuitMember {
fn from(object: GrammarCircuitMember<'ast>) -> Self {
match object {
GrammarCircuitMember::CircuitVariableDefinition(circuit_value) => CircuitMember::from(circuit_value),
GrammarCircuitMember::CircuitFunction(circuit_function) => CircuitMember::from(circuit_function),
}
}
}
impl fmt::Display for CircuitMember {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Identifier};
use leo_grammar::circuits::CircuitVariable;
use serde::{Deserialize, Serialize};
@ -24,12 +23,3 @@ pub struct CircuitVariableDefinition {
pub identifier: Identifier,
pub expression: Expression,
}
impl<'ast> From<CircuitVariable<'ast>> for CircuitVariableDefinition {
fn from(member: CircuitVariable<'ast>) -> Self {
CircuitVariableDefinition {
identifier: Identifier::from(member.identifier),
expression: Expression::from(member.expression),
}
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::PositiveNumber;
use leo_grammar::types::ArrayDimensions as GrammarArrayDimensions;
use leo_input::types::ArrayDimensions as InputArrayDimensions;
use serde::{Deserialize, Serialize};
@ -104,18 +103,6 @@ impl ArrayDimensions {
}
}
/// Create a new [`ArrayDimensions`] from a [`GrammarArrayDimensions`] in a Leo program file.
impl<'ast> From<GrammarArrayDimensions<'ast>> for ArrayDimensions {
fn from(dimensions: GrammarArrayDimensions<'ast>) -> Self {
Self(match dimensions {
GrammarArrayDimensions::Single(single) => vec![PositiveNumber::from(single.number)],
GrammarArrayDimensions::Multiple(multiple) => {
multiple.numbers.into_iter().map(PositiveNumber::from).collect()
}
})
}
}
/// Create a new [`ArrayDimensions`] from a [`InputArrayDimensions`] in a Leo program file.
impl<'ast> From<InputArrayDimensions<'ast>> for ArrayDimensions {
fn from(dimensions: InputArrayDimensions<'ast>) -> Self {

View File

@ -14,21 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{InputKeyword, MutSelfKeyword, SelfKeyword, Span};
use leo_grammar::{
annotations::AnnotationArgument,
common::{
Identifier as GrammarIdentifier,
KeywordOrIdentifier,
MutSelfKeyword as GrammarMutSelfKeyword,
SelfKeyword as GrammarSelfKeyword,
SelfKeywordOrIdentifier,
},
expressions::CircuitName,
functions::InputKeyword as GrammarInputKeyword,
imports::PackageName as GrammarPackageName,
types::SelfType,
};
use crate::Span;
use leo_input::common::Identifier as InputIdentifier;
use crate::Node;
@ -74,10 +60,10 @@ impl Identifier {
}
}
pub fn new_with_span(name: &str, span: &Span) -> Self {
pub fn new_with_span(name: &str, span: Span) -> Self {
Self {
name: name.to_owned(),
span: span.to_owned(),
span,
}
}
@ -90,24 +76,6 @@ impl Identifier {
}
}
impl<'ast> From<GrammarIdentifier<'ast>> for Identifier {
fn from(identifier: GrammarIdentifier<'ast>) -> Self {
Self {
name: identifier.value,
span: Span::from(identifier.span),
}
}
}
impl<'ast> From<GrammarPackageName<'ast>> for Identifier {
fn from(name: GrammarPackageName<'ast>) -> Self {
Self {
name: name.value,
span: Span::from(name.span),
}
}
}
impl<'ast> From<InputIdentifier<'ast>> for Identifier {
fn from(identifier: InputIdentifier<'ast>) -> Self {
Self {
@ -117,106 +85,6 @@ impl<'ast> From<InputIdentifier<'ast>> for Identifier {
}
}
impl<'ast> From<AnnotationArgument<'ast>> for Identifier {
fn from(argument: AnnotationArgument<'ast>) -> Self {
Self {
name: argument.value,
span: Span::from(argument.span),
}
}
}
impl<'ast> From<KeywordOrIdentifier<'ast>> for Identifier {
fn from(name: KeywordOrIdentifier<'ast>) -> Self {
match name {
KeywordOrIdentifier::Identifier(keyword) => Identifier::from(keyword),
KeywordOrIdentifier::SelfType(self_type) => Identifier::from(self_type),
KeywordOrIdentifier::Input(keyword) => Identifier::from(keyword),
}
}
}
impl<'ast> From<SelfKeywordOrIdentifier<'ast>> for Identifier {
fn from(name: SelfKeywordOrIdentifier<'ast>) -> Self {
match name {
SelfKeywordOrIdentifier::Identifier(identifier) => Identifier::from(identifier),
SelfKeywordOrIdentifier::SelfKeyword(keyword) => Identifier::from(keyword),
}
}
}
impl<'ast> From<GrammarSelfKeyword<'ast>> for Identifier {
fn from(grammar: GrammarSelfKeyword<'ast>) -> Self {
Self {
name: grammar.keyword,
span: Span::from(grammar.span),
}
}
}
impl From<SelfKeyword> for Identifier {
fn from(keyword: SelfKeyword) -> Self {
Self {
name: keyword.to_string(),
span: keyword.span,
}
}
}
impl<'ast> From<GrammarMutSelfKeyword<'ast>> for Identifier {
fn from(grammar: GrammarMutSelfKeyword<'ast>) -> Self {
Self {
name: grammar.to_string(),
span: Span::from(grammar.span),
}
}
}
impl From<MutSelfKeyword> for Identifier {
fn from(keyword: MutSelfKeyword) -> Self {
Self {
name: keyword.to_string(),
span: keyword.span,
}
}
}
impl<'ast> From<GrammarInputKeyword<'ast>> for Identifier {
fn from(grammar: GrammarInputKeyword<'ast>) -> Self {
Self {
name: grammar.keyword,
span: Span::from(grammar.span),
}
}
}
impl From<InputKeyword> for Identifier {
fn from(keyword: InputKeyword) -> Self {
Self {
name: keyword.to_string(),
span: keyword.span,
}
}
}
impl<'ast> From<CircuitName<'ast>> for Identifier {
fn from(name: CircuitName<'ast>) -> Self {
match name {
CircuitName::SelfType(self_type) => Identifier::from(self_type),
CircuitName::Identifier(identifier) => Identifier::from(identifier),
}
}
}
impl<'ast> From<SelfType<'ast>> for Identifier {
fn from(self_type: SelfType<'ast>) -> Self {
Self {
name: self_type.keyword,
span: Span::from(self_type.span),
}
}
}
impl fmt::Display for Identifier {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name)

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Node, Span};
use leo_grammar::functions::InputKeyword as GrammarInputKeyword;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -27,14 +26,6 @@ pub struct InputKeyword {
pub span: Span,
}
impl<'ast> From<GrammarInputKeyword<'ast>> for InputKeyword {
fn from(grammar: GrammarInputKeyword<'ast>) -> Self {
Self {
span: Span::from(grammar.span),
}
}
}
impl fmt::Display for InputKeyword {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "input")

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Node, Span};
use leo_grammar::common::MutSelfKeyword as GrammarMutSelfKeyword;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -26,14 +25,6 @@ pub struct MutSelfKeyword {
pub span: Span,
}
impl<'ast> From<GrammarMutSelfKeyword<'ast>> for MutSelfKeyword {
fn from(grammar: GrammarMutSelfKeyword<'ast>) -> Self {
Self {
span: Span::from(grammar.span),
}
}
}
impl fmt::Display for MutSelfKeyword {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "mut self")

View File

@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_grammar::values::PositiveNumber as GrammarPositiveNumber;
use leo_input::values::PositiveNumber as InputPositiveNumber;
use serde::{Deserialize, Serialize};
@ -35,13 +34,6 @@ impl PositiveNumber {
}
}
/// Create a new [`PositiveNumber`] from a [`GrammarPositiveNumber`] in a Leo program file.
impl<'ast> From<GrammarPositiveNumber<'ast>> for PositiveNumber {
fn from(array: GrammarPositiveNumber<'ast>) -> Self {
Self { value: array.value }
}
}
/// Create a new [`PositiveNumber`] from an [`InputPositiveNumber`] in a Leo input file.
impl<'ast> From<InputPositiveNumber<'ast>> for PositiveNumber {
fn from(array: InputPositiveNumber<'ast>) -> Self {

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Node, Span};
use leo_grammar::common::SelfKeyword as GrammarSelfKeyword;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -27,14 +26,6 @@ pub struct SelfKeyword {
pub span: Span,
}
impl<'ast> From<GrammarSelfKeyword<'ast>> for SelfKeyword {
fn from(grammar: GrammarSelfKeyword<'ast>) -> Self {
Self {
span: Span::from(grammar.span),
}
}
}
impl fmt::Display for SelfKeyword {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "self")

View File

@ -14,62 +14,84 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use pest::Span as GrammarSpan;
use std::{fmt, rc::Rc};
use serde::{Deserialize, Serialize};
use std::hash::{Hash, Hasher};
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct Span {
/// text of input string
pub text: String,
/// program line
pub line: usize,
/// start column
pub start: usize,
/// end column
pub end: usize,
pub line_start: usize,
pub line_stop: usize,
pub col_start: usize,
pub col_stop: usize,
pub path: Rc<String>,
}
impl PartialEq for Span {
fn eq(&self, other: &Self) -> bool {
self.line == other.line && self.start == other.start && self.end == other.end
impl fmt::Display for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.line_start == self.line_stop {
write!(f, "{}:{}-{}", self.line_start, self.col_start, self.col_stop)
} else {
write!(
f,
"{}:{}-{}:{}",
self.line_start, self.col_start, self.line_stop, self.col_stop
)
}
}
}
impl Eq for Span {}
impl<'ast> From<pest::Span<'ast>> for Span {
fn from(span: pest::Span) -> Self {
let start = span.start_pos().line_col();
let end = span.end_pos().line_col();
impl Hash for Span {
fn hash<H: Hasher>(&self, state: &mut H) {
self.line.hash(state);
self.start.hash(state);
self.end.hash(state);
}
}
impl Span {
pub fn from_internal_string(value: &str) -> Span {
Span {
text: value.to_string(),
line: 0,
start: 0,
end: 0,
line_start: start.0,
line_stop: end.0,
col_start: start.1,
col_stop: end.1,
path: Rc::new(String::new()),
}
}
}
impl<'ast> From<GrammarSpan<'ast>> for Span {
fn from(span: GrammarSpan<'ast>) -> Self {
let mut text = " ".to_string();
let line_col = span.start_pos().line_col();
let end = span.end_pos().line_col().1;
impl std::ops::Add for &Span {
type Output = Span;
text.push_str(span.start_pos().line_of().trim_end());
fn add(self, other: &Span) -> Span {
self.clone() + other.clone()
}
}
Self {
text,
line: line_col.0,
start: line_col.1,
end,
impl std::ops::Add for Span {
type Output = Self;
fn add(self, other: Self) -> Self {
if self.line_start == other.line_stop {
Span {
line_start: self.line_start,
line_stop: self.line_stop,
col_start: self.col_start.min(other.col_start),
col_stop: self.col_stop.max(other.col_stop),
path: self.path,
}
} else if self.line_start < other.line_start {
Span {
line_start: self.line_start,
line_stop: other.line_stop,
col_start: self.col_start,
col_stop: other.col_stop,
path: self.path,
}
} else {
Span {
line_start: other.line_start,
line_stop: self.line_stop,
col_start: other.col_start,
col_stop: self.col_stop,
path: self.path,
}
}
}
}

View File

@ -15,10 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node, Span};
use leo_grammar::{
common::SpreadOrExpression as GrammarSpreadOrExpression,
expressions::Expression as GrammarExpression,
};
use serde::{Deserialize, Serialize};
use std::fmt;
@ -30,25 +26,6 @@ pub enum SpreadOrExpression {
Expression(Expression),
}
impl<'ast> From<GrammarSpreadOrExpression<'ast>> for SpreadOrExpression {
fn from(s_or_e: GrammarSpreadOrExpression<'ast>) -> Self {
match s_or_e {
GrammarSpreadOrExpression::Spread(spread) => {
SpreadOrExpression::Spread(Expression::from(spread.expression))
}
GrammarSpreadOrExpression::Expression(expression) => {
SpreadOrExpression::Expression(Expression::from(expression))
}
}
}
}
impl<'ast> From<GrammarExpression<'ast>> for SpreadOrExpression {
fn from(expression: GrammarExpression<'ast>) -> Self {
SpreadOrExpression::Expression(Expression::from(expression))
}
}
impl fmt::Display for SpreadOrExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {

View File

@ -14,9 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::Span;
use crate::{LeoError, Span};
use std::{fmt, path::Path};
use std::fmt;
pub const INDENT: &str = " ";
@ -28,68 +28,59 @@ pub const INDENT: &str = " ";
/// |
/// = undefined value `x`
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Error {
pub struct FormattedError {
/// File path where error occurred
pub path: Option<String>,
/// Line number
pub line: usize,
/// Line start number
pub line_start: usize,
/// Line end number
pub line_stop: usize,
/// Starting column
pub start: usize,
/// Ending column
pub end: usize,
/// Text of errored line
pub text: String,
/// Text of errored lines
pub text: Option<Vec<String>>,
/// Error explanation
pub message: String,
}
impl Error {
pub fn new_from_span(message: String, span: Span) -> Self {
impl FormattedError {
pub fn new_from_span(message: String, span: &Span) -> Self {
Self {
path: None,
line: span.line,
start: span.start,
end: span.end,
text: span.text,
line_start: span.line_start,
line_stop: span.line_stop,
start: span.col_start,
end: span.col_stop,
text: None,
message,
}
}
}
pub fn new_from_span_with_path(message: String, span: Span, path: &Path) -> Self {
Self {
path: Some(format!("{:?}", path)),
line: span.line,
start: span.start,
end: span.end,
text: span.text,
message,
impl LeoError for FormattedError {
fn set_path(&mut self, path: &str, content: &[String]) {
self.path = Some(path.to_string());
if self.line_stop - 1 > content.len() {
self.text = Some(vec!["corrupt file".to_string()]);
return;
}
assert!(self.line_stop >= self.line_start);
// if self.line_stop == self.line_start {
// self.text = Some(vec![content[self.line_start - 1][self.start - 1..self.end - 1].to_string()]);
// } else {
self.text = Some(
content[self.line_start - 1..self.line_stop]
.iter()
.map(|x| x.to_string())
.collect(),
);
// }
}
pub fn set_path(&mut self, path: &Path) {
self.path = Some(format!("{:?}", path));
}
pub fn format(&self) -> String {
let path = self.path.as_ref().map(|path| format!("{}:", path)).unwrap_or_default();
let underline = underline(self.start, self.end);
format!(
"{indent }--> {path} {line}:{start}\n\
{indent } |\n\
{line:width$} | {text}\n\
{indent } | {underline}\n\
{indent } |\n\
{indent } = {message}",
indent = INDENT,
width = INDENT.len(),
path = path,
line = self.line,
start = self.start,
text = self.text,
underline = underline,
message = self.message,
)
fn get_path(&self) -> Option<&str> {
self.path.as_deref()
}
}
@ -112,13 +103,46 @@ fn underline(mut start: usize, mut end: usize) -> String {
underline
}
impl fmt::Display for Error {
impl fmt::Display for FormattedError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.format())
let path = self.path.as_ref().map(|path| format!("{}:", path)).unwrap_or_default();
let underline = underline(self.start - 1, self.end - 1);
write!(
f,
"{indent }--> {path}{line_start}:{start}\n\
{indent } |\n",
indent = INDENT,
path = path,
line_start = self.line_start,
start = self.start,
)?;
if let Some(lines) = &self.text {
for (line_no, line) in lines.iter().enumerate() {
writeln!(
f,
"{line_no:width$} | {text}",
width = INDENT.len(),
line_no = self.line_start + line_no,
text = line,
)?;
}
}
write!(
f,
"{indent } | {underline}\n\
{indent } |\n\
{indent } = {message}",
indent = INDENT,
underline = underline,
message = self.message,
)
}
}
impl std::error::Error for Error {
impl std::error::Error for FormattedError {
fn description(&self) -> &str {
&self.message
}
@ -126,12 +150,13 @@ impl std::error::Error for Error {
#[test]
fn test_error() {
let err = Error {
let err = FormattedError {
path: Some("file.leo".to_string()),
line: 2,
line_start: 2,
line_stop: 2,
start: 8,
end: 9,
text: "let a = x;".to_string(),
text: Some(vec!["let a = x;".to_string()]),
message: "undefined value `x`".to_string(),
};

View File

@ -14,30 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
pub mod deprecated;
pub use deprecated::*;
pub mod error;
pub use error::*;
use error::Error as FormattedError;
pub trait LeoError {
fn get_path(&self) -> Option<&str>;
use leo_grammar::ParserError;
#[derive(Debug, Error)]
pub enum AstError {
#[error("{}", _0)]
DeprecatedError(#[from] DeprecatedError),
#[error("{}", _0)]
Error(#[from] FormattedError),
#[error("{}", _0)]
IoError(#[from] std::io::Error),
#[error("{}", _0)]
ParserError(#[from] ParserError),
#[error("{}", _0)]
JsonError(#[from] serde_json::error::Error),
fn set_path(&mut self, path: &str, contents: &[String]);
}

View File

@ -31,6 +31,13 @@ pub enum BinaryOperation {
Gt,
Le,
Lt,
BitOr,
BitAnd,
BitXor,
Shr,
ShrSigned,
Shl,
Mod,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
@ -55,6 +62,13 @@ impl AsRef<str> for BinaryOperation {
BinaryOperation::Gt => ">",
BinaryOperation::Le => "<=",
BinaryOperation::Lt => "<",
BinaryOperation::BitOr => "|",
BinaryOperation::BitAnd => "&",
BinaryOperation::BitXor => "^",
BinaryOperation::Shr => ">>",
BinaryOperation::ShrSigned => ">>>",
BinaryOperation::Shl => "<<",
BinaryOperation::Mod => "%",
}
}
}
@ -66,6 +80,13 @@ impl BinaryOperation {
| BinaryOperation::Sub
| BinaryOperation::Mul
| BinaryOperation::Div
| BinaryOperation::BitOr
| BinaryOperation::BitAnd
| BinaryOperation::BitXor
| BinaryOperation::Shr
| BinaryOperation::ShrSigned
| BinaryOperation::Shl
| BinaryOperation::Mod
| BinaryOperation::Pow => BinaryOperationClass::Numeric,
BinaryOperation::Or
| BinaryOperation::And

View File

@ -14,24 +14,29 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, expressions::Expression, SpanDef};
use crate::Type;
use pest::Span;
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt;
use super::*;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::spread))]
pub struct Spread<'ast> {
pub expression: Expression<'ast>,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CastExpression {
pub inner: Box<Expression>,
pub target_type: Type,
pub span: Span,
}
impl<'ast> fmt::Display for Spread<'ast> {
impl fmt::Display for CastExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "...{}", self.expression)
write!(f, "{} as {}", self.inner, self.target_type)
}
}
impl Node for CastExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -27,7 +27,11 @@ impl fmt::Display for CircuitInitExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {{", self.name)?;
for (i, member) in self.members.iter().enumerate() {
write!(f, "{}: {}", member.identifier, member.expression)?;
if let Some(expression) = &member.expression {
write!(f, "{}: {}", member.identifier, expression)?;
} else {
write!(f, "{}", member.identifier)?;
}
if i < self.members.len() - 1 {
write!(f, ", ")?;

View File

@ -24,33 +24,7 @@ use crate::{
Span,
SpreadOrExpression,
};
use leo_grammar::{
access::{Access, AssigneeAccess, SelfAccess},
common::{Assignee, Identifier as GrammarIdentifier, RangeOrExpression as GrammarRangeOrExpression},
expressions::{
ArrayInitializerExpression,
ArrayInlineExpression as GrammarArrayInlineExpression,
BinaryExpression as GrammarBinaryExpression,
CircuitInlineExpression,
Expression as GrammarExpression,
PostfixExpression,
SelfPostfixExpression,
TernaryExpression as GrammarTernaryExpression,
UnaryExpression as GrammarUnaryExpression,
},
operations::{BinaryOperation as GrammarBinaryOperation, UnaryOperation as GrammarUnaryOperation},
values::{
AddressValue,
BooleanValue,
FieldValue,
GroupValue as GrammarGroupValue,
IntegerValue,
NumberValue as GrammarNumber,
Value,
},
};
use leo_grammar::{access::TupleAccess, expressions::TupleExpression};
use serde::{Deserialize, Serialize};
use std::fmt;
@ -84,6 +58,8 @@ mod value;
pub use value::*;
mod call;
pub use call::*;
mod cast;
pub use cast::*;
/// Expression that evaluates to a value
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
@ -93,6 +69,7 @@ pub enum Expression {
Binary(BinaryExpression),
Unary(UnaryExpression),
Ternary(TernaryExpression),
Cast(CastExpression),
ArrayInline(ArrayInlineExpression),
ArrayInit(ArrayInitExpression),
@ -128,6 +105,7 @@ impl Node for Expression {
CircuitMemberAccess(n) => n.span(),
CircuitStaticFunctionAccess(n) => n.span(),
Call(n) => n.span(),
Cast(n) => n.span(),
}
}
@ -149,11 +127,12 @@ impl Node for Expression {
CircuitMemberAccess(n) => n.set_span(span),
CircuitStaticFunctionAccess(n) => n.set_span(span),
Call(n) => n.set_span(span),
Cast(n) => n.set_span(span),
}
}
}
impl<'ast> fmt::Display for Expression {
impl fmt::Display for Expression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Expression::*;
match &self {
@ -172,404 +151,7 @@ impl<'ast> fmt::Display for Expression {
CircuitMemberAccess(n) => n.fmt(f),
CircuitStaticFunctionAccess(n) => n.fmt(f),
Call(n) => n.fmt(f),
Cast(n) => n.fmt(f),
}
}
}
impl<'ast> From<CircuitInlineExpression<'ast>> for Expression {
fn from(expression: CircuitInlineExpression<'ast>) -> Self {
let circuit_name = Identifier::from(expression.name);
let members = expression
.members
.into_iter()
.map(CircuitImpliedVariableDefinition::from)
.collect::<Vec<CircuitImpliedVariableDefinition>>();
Expression::CircuitInit(CircuitInitExpression {
name: circuit_name,
members,
span: Span::from(expression.span),
})
}
}
impl<'ast> From<PostfixExpression<'ast>> for Expression {
fn from(expression: PostfixExpression<'ast>) -> Self {
let variable = Expression::Identifier(Identifier::from(expression.name));
// ast::PostFixExpression contains an array of "accesses": `a(34)[42]` is represented as `[a, [Call(34), Select(42)]]`, but Access call expressions
// are recursive, so it is `Select(Call(a, 34), 42)`. We apply this transformation here
// we start with the id, and we fold the array of accesses by wrapping the current value
expression
.accesses
.into_iter()
.fold(variable, |acc, access| match access {
// Handle array accesses
Access::Array(array) => match array.expression {
GrammarRangeOrExpression::Expression(expression) => {
Expression::ArrayAccess(ArrayAccessExpression {
array: Box::new(acc),
index: Box::new(Expression::from(expression)),
span: Span::from(array.span),
})
}
GrammarRangeOrExpression::Range(range) => {
Expression::ArrayRangeAccess(ArrayRangeAccessExpression {
array: Box::new(acc),
left: range.from.map(Expression::from).map(Box::new),
right: range.to.map(Expression::from).map(Box::new),
span: Span::from(array.span),
})
}
},
// Handle tuple access
Access::Tuple(tuple) => Expression::TupleAccess(TupleAccessExpression {
tuple: Box::new(acc),
index: PositiveNumber::from(tuple.number),
span: Span::from(tuple.span),
}),
// Handle function calls
Access::Call(function) => Expression::Call(CallExpression {
function: Box::new(acc),
arguments: function.expressions.into_iter().map(Expression::from).collect(),
span: Span::from(function.span),
}),
// Handle circuit member accesses
Access::Object(circuit_object) => Expression::CircuitMemberAccess(CircuitMemberAccessExpression {
circuit: Box::new(acc),
name: Identifier::from(circuit_object.identifier),
span: Span::from(circuit_object.span),
}),
Access::StaticObject(circuit_object) => {
Expression::CircuitStaticFunctionAccess(CircuitStaticFunctionAccessExpression {
circuit: Box::new(acc),
name: Identifier::from(circuit_object.identifier),
span: Span::from(circuit_object.span),
})
}
})
}
}
impl<'ast> From<SelfPostfixExpression<'ast>> for Expression {
fn from(expression: SelfPostfixExpression<'ast>) -> Self {
let variable = Expression::Identifier(Identifier::from(expression.name));
// Handle self expression access.
let self_expression = match expression.self_access {
// Handle circuit member accesses
SelfAccess::Object(circuit_object) => Expression::CircuitMemberAccess(CircuitMemberAccessExpression {
circuit: Box::new(variable),
name: Identifier::from(circuit_object.identifier),
span: Span::from(circuit_object.span),
}),
// Handle static access
SelfAccess::StaticObject(circuit_object) => {
Expression::CircuitStaticFunctionAccess(CircuitStaticFunctionAccessExpression {
circuit: Box::new(variable),
name: Identifier::from(circuit_object.identifier),
span: Span::from(circuit_object.span),
})
}
};
// ast::SelfPostFixExpression contains an array of "accesses": `a(34)[42]` is represented as `[a, [Call(34), Select(42)]]`, but Access call expressions
// are recursive, so it is `Select(Call(a, 34), 42)`. We apply this transformation here
// we start with the id, and we fold the array of accesses by wrapping the current value
expression
.accesses
.into_iter()
.fold(self_expression, |acc, access| match access {
// Handle array accesses
Access::Array(array) => match array.expression {
GrammarRangeOrExpression::Expression(expression) => {
Expression::ArrayAccess(ArrayAccessExpression {
array: Box::new(acc),
index: Box::new(Expression::from(expression)),
span: Span::from(array.span),
})
}
GrammarRangeOrExpression::Range(range) => {
Expression::ArrayRangeAccess(ArrayRangeAccessExpression {
array: Box::new(acc),
left: range.from.map(Expression::from).map(Box::new),
right: range.to.map(Expression::from).map(Box::new),
span: Span::from(array.span),
})
}
},
// Handle tuple access
Access::Tuple(tuple) => Expression::TupleAccess(TupleAccessExpression {
tuple: Box::new(acc),
index: PositiveNumber::from(tuple.number),
span: Span::from(tuple.span),
}),
// Handle function calls
Access::Call(function) => Expression::Call(CallExpression {
function: Box::new(acc),
arguments: function.expressions.into_iter().map(Expression::from).collect(),
span: Span::from(function.span),
}),
// Handle circuit member accesses
Access::Object(circuit_object) => Expression::CircuitMemberAccess(CircuitMemberAccessExpression {
circuit: Box::new(acc),
name: Identifier::from(circuit_object.identifier),
span: Span::from(circuit_object.span),
}),
Access::StaticObject(circuit_object) => {
Expression::CircuitStaticFunctionAccess(CircuitStaticFunctionAccessExpression {
circuit: Box::new(acc),
name: Identifier::from(circuit_object.identifier),
span: Span::from(circuit_object.span),
})
}
})
}
}
impl<'ast> From<GrammarExpression<'ast>> for Expression {
fn from(expression: GrammarExpression<'ast>) -> Self {
match expression {
GrammarExpression::Value(value) => Expression::from(value),
GrammarExpression::Identifier(variable) => Expression::from(variable),
GrammarExpression::Unary(expression) => Expression::from(*expression),
GrammarExpression::Binary(expression) => Expression::from(*expression),
GrammarExpression::Ternary(expression) => Expression::from(*expression),
GrammarExpression::ArrayInline(expression) => Expression::from(expression),
GrammarExpression::ArrayInitializer(expression) => Expression::from(*expression),
GrammarExpression::Tuple(expression) => Expression::from(expression),
GrammarExpression::CircuitInline(expression) => Expression::from(expression),
GrammarExpression::Postfix(expression) => Expression::from(expression),
GrammarExpression::SelfPostfix(expression) => Expression::from(expression),
}
}
}
// Assignee -> Expression for operator assign statements
impl<'ast> From<Assignee<'ast>> for Expression {
fn from(assignee: Assignee<'ast>) -> Self {
let variable = Expression::Identifier(Identifier::from(assignee.name));
// we start with the id, and we fold the array of accesses by wrapping the current value
assignee
.accesses
.into_iter()
.fold(variable, |acc, access| match access {
AssigneeAccess::Member(circuit_member) => {
Expression::CircuitMemberAccess(CircuitMemberAccessExpression {
circuit: Box::new(acc),
name: Identifier::from(circuit_member.identifier),
span: Span::from(circuit_member.span),
})
}
AssigneeAccess::Array(array) => match array.expression {
GrammarRangeOrExpression::Expression(expression) => {
Expression::ArrayAccess(ArrayAccessExpression {
array: Box::new(acc),
index: Box::new(Expression::from(expression)),
span: Span::from(array.span),
})
}
GrammarRangeOrExpression::Range(range) => {
Expression::ArrayRangeAccess(ArrayRangeAccessExpression {
array: Box::new(acc),
left: range.from.map(Expression::from).map(Box::new),
right: range.to.map(Expression::from).map(Box::new),
span: Span::from(array.span),
})
}
},
AssigneeAccess::Tuple(tuple) => Expression::TupleAccess(TupleAccessExpression {
tuple: Box::new(acc),
index: PositiveNumber::from(tuple.number),
span: Span::from(tuple.span.clone()),
}),
})
}
}
impl<'ast> From<GrammarBinaryExpression<'ast>> for Expression {
fn from(expression: GrammarBinaryExpression<'ast>) -> Self {
use GrammarBinaryOperation::*;
let operator = match expression.operation {
Or => BinaryOperation::Or,
And => BinaryOperation::And,
Eq => BinaryOperation::Eq,
Ne => BinaryOperation::Ne,
Ge => BinaryOperation::Ge,
Gt => BinaryOperation::Gt,
Le => BinaryOperation::Le,
Lt => BinaryOperation::Lt,
Add => BinaryOperation::Add,
Sub => BinaryOperation::Sub,
Mul => BinaryOperation::Mul,
Div => BinaryOperation::Div,
Pow => BinaryOperation::Pow,
};
Expression::Binary(BinaryExpression {
left: Box::new(Expression::from(expression.left)),
right: Box::new(Expression::from(expression.right)),
op: operator,
span: Span::from(expression.span),
})
}
}
impl<'ast> From<GrammarTernaryExpression<'ast>> for Expression {
fn from(expression: GrammarTernaryExpression<'ast>) -> Self {
Expression::Ternary(TernaryExpression {
condition: Box::new(Expression::from(expression.first)),
if_true: Box::new(Expression::from(expression.second)),
if_false: Box::new(Expression::from(expression.third)),
span: Span::from(expression.span),
})
}
}
impl<'ast> From<GrammarArrayInlineExpression<'ast>> for Expression {
fn from(array: GrammarArrayInlineExpression<'ast>) -> Self {
Expression::ArrayInline(ArrayInlineExpression {
elements: array.expressions.into_iter().map(SpreadOrExpression::from).collect(),
span: Span::from(array.span),
})
}
}
impl<'ast> From<ArrayInitializerExpression<'ast>> for Expression {
fn from(array: ArrayInitializerExpression<'ast>) -> Self {
Expression::ArrayInit(ArrayInitExpression {
element: Box::new(Expression::from(array.expression)),
dimensions: ArrayDimensions::from(array.dimensions),
span: Span::from(array.span),
})
}
}
impl<'ast> From<TupleExpression<'ast>> for Expression {
fn from(tuple: TupleExpression<'ast>) -> Self {
Expression::TupleInit(TupleInitExpression {
elements: tuple.expressions.into_iter().map(Expression::from).collect(),
span: Span::from(tuple.span),
})
}
}
impl<'ast> From<Value<'ast>> for Expression {
fn from(value: Value<'ast>) -> Self {
match value {
Value::Address(address) => Expression::from(address),
Value::Boolean(boolean) => Expression::from(boolean),
Value::Field(field) => Expression::from(field),
Value::Group(group) => Expression::from(group),
Value::Implicit(number) => Expression::from(number),
Value::Integer(integer) => Expression::from(integer),
}
}
}
impl<'ast> From<GrammarUnaryExpression<'ast>> for Expression {
fn from(expression: GrammarUnaryExpression<'ast>) -> Self {
use GrammarUnaryOperation::*;
let operator = match expression.operation {
Not(_) => UnaryOperation::Not,
Negate(_) => UnaryOperation::Negate,
};
Expression::Unary(UnaryExpression {
inner: Box::new(Expression::from(expression.expression)),
op: operator,
span: Span::from(expression.span),
})
}
}
impl<'ast> From<AddressValue<'ast>> for Expression {
fn from(address: AddressValue<'ast>) -> Self {
Expression::Value(ValueExpression::Address(
address.address.value,
Span::from(address.span),
))
}
}
impl<'ast> From<BooleanValue<'ast>> for Expression {
fn from(boolean: BooleanValue<'ast>) -> Self {
Expression::Value(ValueExpression::Boolean(boolean.value, Span::from(boolean.span)))
}
}
impl<'ast> From<FieldValue<'ast>> for Expression {
fn from(field: FieldValue<'ast>) -> Self {
Expression::Value(ValueExpression::Field(field.number.to_string(), Span::from(field.span)))
}
}
impl<'ast> From<GrammarGroupValue<'ast>> for Expression {
fn from(ast_group: GrammarGroupValue<'ast>) -> Self {
Expression::Value(ValueExpression::Group(Box::new(GroupValue::from(ast_group))))
}
}
impl<'ast> From<GrammarNumber<'ast>> for Expression {
fn from(number: GrammarNumber<'ast>) -> Self {
let (value, span) = match number {
GrammarNumber::Positive(number) => (number.value, number.span),
GrammarNumber::Negative(number) => (number.value, number.span),
};
Expression::Value(ValueExpression::Implicit(value, Span::from(span)))
}
}
impl<'ast> From<IntegerValue<'ast>> for Expression {
fn from(integer: IntegerValue<'ast>) -> Self {
let span = Span::from(integer.span().clone());
let (type_, value) = match integer {
IntegerValue::Signed(integer) => {
let type_ = IntegerType::from(integer.type_);
let number = match integer.number {
GrammarNumber::Negative(number) => number.value,
GrammarNumber::Positive(number) => number.value,
};
(type_, number)
}
IntegerValue::Unsigned(integer) => {
let type_ = IntegerType::from(integer.type_);
let number = integer.number.value;
(type_, number)
}
};
Expression::Value(ValueExpression::Integer(type_, value, span))
}
}
impl<'ast> From<TupleAccess<'ast>> for Expression {
fn from(tuple: TupleAccess<'ast>) -> Self {
Expression::Value(ValueExpression::Implicit(
tuple.number.to_string(),
Span::from(tuple.span),
))
}
}
impl<'ast> From<GrammarIdentifier<'ast>> for Expression {
fn from(identifier: GrammarIdentifier<'ast>) -> Self {
Expression::Identifier(Identifier::from(identifier))
}
}
impl From<Identifier> for Expression {
fn from(identifier: Identifier) -> Self {
Expression::Identifier(identifier)
}
}

View File

@ -20,6 +20,7 @@ use super::*;
pub enum UnaryOperation {
Not,
Negate,
BitNot,
}
impl AsRef<str> for UnaryOperation {
@ -27,6 +28,7 @@ impl AsRef<str> for UnaryOperation {
match self {
UnaryOperation::Not => "!",
UnaryOperation::Negate => "-",
UnaryOperation::BitNot => "~",
}
}
}

View File

@ -14,14 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Block, FunctionInput, Identifier, Node, Span, Type};
use leo_grammar::functions::Function as GrammarFunction;
use crate::{Annotation, Block, FunctionInput, Identifier, Node, Span, Type};
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Clone, Serialize, Deserialize)]
pub struct Function {
pub annotations: Vec<Annotation>,
pub identifier: Identifier,
pub input: Vec<FunctionInput>,
pub output: Option<Type>,
@ -37,24 +37,6 @@ impl PartialEq for Function {
impl Eq for Function {}
impl<'ast> From<GrammarFunction<'ast>> for Function {
fn from(function: GrammarFunction<'ast>) -> Self {
let function_name = Identifier::from(function.identifier);
let parameters = function.parameters.into_iter().map(FunctionInput::from).collect();
let returns = function.returns.map(Type::from);
let block = Block::from(function.block);
Function {
identifier: function_name,
input: parameters,
output: returns,
block,
span: Span::from(function.span),
}
}
}
impl Function {
pub fn get_name(&self) -> &str {
&self.identifier.name

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Identifier, Node, Span, Type};
use leo_grammar::functions::FunctionInput as GrammarFunctionInput;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -29,18 +28,6 @@ pub struct FunctionInputVariable {
pub span: Span,
}
impl<'ast> From<GrammarFunctionInput<'ast>> for FunctionInputVariable {
fn from(parameter: GrammarFunctionInput<'ast>) -> Self {
FunctionInputVariable {
identifier: Identifier::from(parameter.identifier),
const_: parameter.const_.is_some(),
mutable: parameter.mutable.is_some(),
type_: Type::from(parameter.type_),
span: Span::from(parameter.span),
}
}
}
impl FunctionInputVariable {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
// mut var: bool

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{FunctionInputVariable, InputKeyword, MutSelfKeyword, Node, SelfKeyword, Span};
use leo_grammar::functions::input::Input as GrammarInput;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -29,19 +28,6 @@ pub enum FunctionInput {
Variable(FunctionInputVariable),
}
impl<'ast> From<GrammarInput<'ast>> for FunctionInput {
fn from(input: GrammarInput<'ast>) -> Self {
match input {
GrammarInput::InputKeyword(keyword) => FunctionInput::InputKeyword(InputKeyword::from(keyword)),
GrammarInput::SelfKeyword(keyword) => FunctionInput::SelfKeyword(SelfKeyword::from(keyword)),
GrammarInput::MutSelfKeyword(keyword) => FunctionInput::MutSelfKeyword(MutSelfKeyword::from(keyword)),
GrammarInput::FunctionInput(function_input) => {
FunctionInput::Variable(FunctionInputVariable::from(function_input))
}
}
}
}
impl FunctionInput {
///
/// Returns `true` if the function input is the `self` or `mut self` keyword.

View File

@ -19,6 +19,3 @@ pub use function::*;
pub mod input;
pub use input::*;
pub mod test_function;
pub use test_function::*;

View File

@ -1,35 +0,0 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Function, Identifier};
use leo_grammar::functions::TestFunction as GrammarTestFunction;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct TestFunction {
pub function: Function,
pub input_file: Option<Identifier>,
}
impl<'ast> From<GrammarTestFunction<'ast>> for TestFunction {
fn from(test: GrammarTestFunction) -> Self {
TestFunction {
function: Function::from(test.function),
input_file: None, // pass custom input file with `@context` annotation
}
}
}

View File

@ -15,13 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::common::span::Span;
use leo_grammar::values::{
GroupCoordinate as GrammarGroupCoordinate,
Inferred as GrammarInferred,
NumberValue as GrammarNumberValue,
SignHigh as GrammarSignHigh,
SignLow as GrammarSignLow,
};
use leo_input::values::{
GroupCoordinate as InputGroupCoordinate,
Inferred as InputInferred,
@ -41,17 +34,6 @@ pub enum GroupCoordinate {
Inferred,
}
impl<'ast> From<GrammarGroupCoordinate<'ast>> for GroupCoordinate {
fn from(coordinate: GrammarGroupCoordinate<'ast>) -> Self {
match coordinate {
GrammarGroupCoordinate::Number(number) => GroupCoordinate::from(number),
GrammarGroupCoordinate::SignHigh(sign_high) => GroupCoordinate::from(sign_high),
GrammarGroupCoordinate::SignLow(sign_low) => GroupCoordinate::from(sign_low),
GrammarGroupCoordinate::Inferred(inferred) => GroupCoordinate::from(inferred),
}
}
}
impl<'ast> From<InputGroupCoordinate<'ast>> for GroupCoordinate {
fn from(coordinate: InputGroupCoordinate<'ast>) -> Self {
match coordinate {
@ -74,33 +56,6 @@ impl fmt::Display for GroupCoordinate {
}
}
impl<'ast> From<GrammarNumberValue<'ast>> for GroupCoordinate {
fn from(number: GrammarNumberValue<'ast>) -> Self {
let value = number.to_string();
let span = Span::from(number.span().clone());
GroupCoordinate::Number(value, span)
}
}
impl<'ast> From<GrammarSignHigh<'ast>> for GroupCoordinate {
fn from(_sign: GrammarSignHigh<'ast>) -> Self {
GroupCoordinate::SignHigh
}
}
impl<'ast> From<GrammarSignLow<'ast>> for GroupCoordinate {
fn from(_sign: GrammarSignLow<'ast>) -> Self {
GroupCoordinate::SignLow
}
}
impl<'ast> From<GrammarInferred<'ast>> for GroupCoordinate {
fn from(_sign: GrammarInferred<'ast>) -> Self {
GroupCoordinate::Inferred
}
}
impl<'ast> From<InputNumberValue<'ast>> for GroupCoordinate {
fn from(number: InputNumberValue<'ast>) -> Self {
let value = number.to_string();

View File

@ -15,11 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{common::span::Span, groups::GroupCoordinate};
use leo_grammar::values::{
GroupRepresentation as GrammarGroupRepresentation,
GroupTuple as GrammarGroupTuple,
GroupValue as GrammarGroupValue,
};
use leo_input::values::{
GroupRepresentation as InputGroupRepresentation,
GroupTuple as InputGroupTuple,
@ -51,17 +46,6 @@ impl GroupValue {
}
}
impl<'ast> From<GrammarGroupValue<'ast>> for GroupValue {
fn from(ast_group: GrammarGroupValue) -> Self {
let span = Span::from(ast_group.span);
match ast_group.value {
GrammarGroupRepresentation::Single(number) => GroupValue::Single(number.to_string(), span),
GrammarGroupRepresentation::Tuple(tuple) => GroupValue::Tuple(GroupTuple::from(tuple)),
}
}
}
impl<'ast> From<InputGroupValue<'ast>> for GroupValue {
fn from(ast_group: InputGroupValue) -> Self {
let span = Span::from(ast_group.span);
@ -89,19 +73,6 @@ pub struct GroupTuple {
pub span: Span,
}
impl<'ast> From<GrammarGroupTuple<'ast>> for GroupTuple {
fn from(ast_group: GrammarGroupTuple<'ast>) -> Self {
let ast_x = ast_group.x;
let ast_y = ast_group.y;
Self {
x: GroupCoordinate::from(ast_x),
y: GroupCoordinate::from(ast_y),
span: Span::from(ast_group.span),
}
}
}
impl<'ast> From<InputGroupTuple<'ast>> for GroupTuple {
fn from(ast_group: InputGroupTuple<'ast>) -> Self {
let ast_x = ast_group.x;

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{PackageOrPackages, Span};
use leo_grammar::imports::Import as GrammarImport;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -39,15 +38,6 @@ impl ImportStatement {
}
}
impl<'ast> From<GrammarImport<'ast>> for ImportStatement {
fn from(import: GrammarImport<'ast>) -> Self {
ImportStatement {
package_or_packages: PackageOrPackages::from(import.package_or_packages),
span: Span::from(import.span),
}
}
}
impl ImportStatement {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "import {};", self.package_or_packages)

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Identifier, Span};
use leo_grammar::imports::ImportSymbol as GrammarImportSymbol;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -27,16 +26,6 @@ pub struct ImportSymbol {
pub span: Span,
}
impl<'ast> From<GrammarImportSymbol<'ast>> for ImportSymbol {
fn from(symbol: GrammarImportSymbol<'ast>) -> Self {
ImportSymbol {
symbol: Identifier::from(symbol.value),
alias: symbol.alias.map(Identifier::from),
span: Span::from(symbol.span),
}
}
}
impl fmt::Display for ImportSymbol {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.alias.is_some() {

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{common::Identifier, PackageAccess, Span};
use leo_grammar::imports::Package as GrammarPackage;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -27,16 +26,6 @@ pub struct Package {
pub span: Span,
}
impl<'ast> From<GrammarPackage<'ast>> for Package {
fn from(package: GrammarPackage<'ast>) -> Self {
Package {
name: Identifier::from(package.name),
access: PackageAccess::from(package.access),
span: Span::from(package.span),
}
}
}
impl Package {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.{}", self.name, self.access)

View File

@ -14,8 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ImportSymbol, Package, Packages, Span};
use leo_grammar::imports::PackageAccess as GrammarPackageAccess;
use crate::{ImportSymbol, Node, Package, Packages, Span};
use serde::{Deserialize, Serialize};
use std::fmt;
@ -28,13 +27,22 @@ pub enum PackageAccess {
Multiple(Packages),
}
impl<'ast> From<GrammarPackageAccess<'ast>> for PackageAccess {
fn from(access: GrammarPackageAccess<'ast>) -> Self {
match access {
GrammarPackageAccess::Star(star) => PackageAccess::Star(Span::from(star.span)),
GrammarPackageAccess::SubPackage(package) => PackageAccess::SubPackage(Box::new(Package::from(*package))),
GrammarPackageAccess::Symbol(symbol) => PackageAccess::Symbol(ImportSymbol::from(symbol)),
GrammarPackageAccess::Multiple(packages) => PackageAccess::Multiple(Packages::from(packages)),
impl Node for PackageAccess {
fn span(&self) -> &Span {
match self {
PackageAccess::Star(span) => span,
PackageAccess::SubPackage(package) => &package.span,
PackageAccess::Symbol(package) => &package.span,
PackageAccess::Multiple(package) => &package.span,
}
}
fn set_span(&mut self, span: Span) {
match self {
PackageAccess::Star(package) => *package = span,
PackageAccess::SubPackage(package) => package.span = span,
PackageAccess::Symbol(package) => package.span = span,
PackageAccess::Multiple(package) => package.span = span,
}
}
}

View File

@ -14,8 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Package, Packages};
use leo_grammar::imports::PackageOrPackages as GrammarPackageOrPackages;
use crate::{Node, Package, Packages, Span};
use serde::{Deserialize, Serialize};
use std::fmt;
@ -26,15 +25,6 @@ pub enum PackageOrPackages {
Packages(Packages),
}
impl<'ast> From<GrammarPackageOrPackages<'ast>> for PackageOrPackages {
fn from(package_or_packages: GrammarPackageOrPackages<'ast>) -> Self {
match package_or_packages {
GrammarPackageOrPackages::Package(package) => PackageOrPackages::Package(Package::from(package)),
GrammarPackageOrPackages::Packages(packages) => PackageOrPackages::Packages(Packages::from(packages)),
}
}
}
impl PackageOrPackages {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
@ -64,3 +54,19 @@ impl fmt::Display for PackageOrPackages {
self.format(f)
}
}
impl Node for PackageOrPackages {
fn span(&self) -> &Span {
match self {
PackageOrPackages::Package(package) => &package.span,
PackageOrPackages::Packages(packages) => &packages.span,
}
}
fn set_span(&mut self, span: Span) {
match self {
PackageOrPackages::Package(package) => package.span = span,
PackageOrPackages::Packages(packages) => packages.span = span,
}
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{common::Identifier, PackageAccess, Span};
use leo_grammar::imports::Packages as GrammarPackages;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -27,16 +26,6 @@ pub struct Packages {
pub span: Span,
}
impl<'ast> From<GrammarPackages<'ast>> for Packages {
fn from(packages: GrammarPackages<'ast>) -> Self {
Packages {
name: Identifier::from(packages.name),
accesses: packages.accesses.into_iter().map(PackageAccess::from).collect(),
span: Span::from(packages.span),
}
}
}
impl Packages {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.(", self.name)?;

View File

@ -114,7 +114,7 @@ impl InputValue {
let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone());
// Convert the array dimensions to usize.
let array_dimensions = parse_array_dimensions(array_dimensions_type, array_type.span.clone())?;
let array_dimensions = parse_array_dimensions(array_dimensions_type, &array_type.span)?;
// Return an error if the outer array dimension does not equal the number of array elements.
if array_dimensions[0] != inline.expressions.len() {
@ -146,7 +146,7 @@ impl InputValue {
initializer: ArrayInitializerExpression,
) -> Result<Self, InputParserError> {
let array_dimensions_type = ArrayDimensions::from(initializer.dimensions.clone());
let array_dimensions = parse_array_dimensions(array_dimensions_type, array_type.span.clone())?;
let array_dimensions = parse_array_dimensions(array_dimensions_type, &array_type.span)?;
if array_dimensions.len() > 1 {
// The expression is an array initializer with tuple syntax
@ -169,7 +169,7 @@ impl InputValue {
return Err(InputParserError::array_init_length(
array_dimensions,
initializer_dimensions,
initializer.span,
&initializer.span,
));
}
@ -199,7 +199,7 @@ impl InputValue {
let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone());
// Convert the array dimensions to usize.
let array_dimensions = parse_array_dimensions(array_dimensions_type, array_type.span.clone())?;
let array_dimensions = parse_array_dimensions(array_dimensions_type, &array_type.span)?;
let current_array_dimension = array_dimensions[0];
let current_initializer_dimension = initializer_dimensions[0];
@ -209,7 +209,7 @@ impl InputValue {
return Err(InputParserError::array_init_length(
array_dimensions,
initializer_dimensions,
initializer.span,
&initializer.span,
));
}
@ -235,11 +235,7 @@ impl InputValue {
let num_values = tuple.expressions.len();
if num_types != num_values {
return Err(InputParserError::tuple_length(
num_types,
num_values,
tuple_type.span.clone(),
));
return Err(InputParserError::tuple_length(num_types, num_values, &tuple_type.span));
}
let mut values = Vec::with_capacity(tuple_type.types_.len());
@ -260,7 +256,7 @@ impl InputValue {
/// is successful, the `usize` value is appended to the return vector. If parsing fails, an error
/// is returned.
///
fn parse_array_dimensions(array_dimensions_type: ArrayDimensions, span: Span) -> Result<Vec<usize>, InputParserError> {
fn parse_array_dimensions(array_dimensions_type: ArrayDimensions, span: &Span) -> Result<Vec<usize>, InputParserError> {
// Convert the array dimensions to usize.
let mut array_dimensions = Vec::with_capacity(array_dimensions_type.0.len());
@ -271,7 +267,7 @@ fn parse_array_dimensions(array_dimensions_type: ArrayDimensions, span: Span) ->
// Convert the string to usize.
let dimension_usize = match dimension_string.parse::<usize>() {
Ok(dimension_usize) => dimension_usize,
Err(_) => return Err(InputParserError::array_index(dimension_string, span.clone())),
Err(_) => return Err(InputParserError::array_index(dimension_string, span)),
};
// Collect dimension usize values.
@ -292,7 +288,7 @@ fn fetch_nested_array_type_dimensions(
let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone());
// Convert the array dimensions to usize.
let mut current_dimension = parse_array_dimensions(array_dimensions_type, array_type.span.clone())?;
let mut current_dimension = parse_array_dimensions(array_dimensions_type, &array_type.span)?;
array_dimensions.append(&mut current_dimension);

View File

@ -19,9 +19,6 @@
//! This module contains the [`Ast`] type, a wrapper around the [`Program`] type.
//! The [`Ast`] type is intended to be parsed and modified by different passes
//! of the Leo compiler. The Leo compiler can generate a set of R1CS constraints from any [`Ast`].
#[macro_use]
extern crate thiserror;
pub mod annotation;
pub use self::annotation::*;
@ -61,8 +58,6 @@ pub use self::types::*;
mod node;
pub use node::*;
use leo_grammar::Grammar;
/// The abstract syntax tree (AST) for a Leo program.
///
/// The [`Ast`] type represents a Leo program as a series of recursive data types.
@ -76,10 +71,8 @@ pub struct Ast {
impl Ast {
/// Creates a new AST from a given program name and grammar tree.
pub fn new<'ast>(program_name: &str, grammar: &Grammar<'ast>) -> Result<Self, AstError> {
Ok(Self {
ast: Program::from(program_name, grammar.as_repr())?,
})
pub fn new(program: Program) -> Self {
Self { ast: program }
}
/// Returns a reference to the inner program AST representation.
@ -87,6 +80,10 @@ impl Ast {
&self.ast
}
pub fn into_repr(self) -> Program {
self.ast
}
/// Serializes the ast into a JSON string.
pub fn to_json_string(&self) -> Result<String, serde_json::Error> {
serde_json::to_string_pretty(&self.ast)
@ -98,3 +95,9 @@ impl Ast {
Ok(Self { ast })
}
}
impl AsRef<Program> for Ast {
fn as_ref(&self) -> &Program {
&self.ast
}
}

View File

@ -1,71 +0,0 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::{Ast, AstError};
use leo_grammar::Grammar;
use std::{env, fs, path::Path};
fn to_leo_tree(filepath: &Path) -> Result<String, AstError> {
// Loads the Leo code as a string from the given file path.
let program_filepath = filepath.to_path_buf();
let program_string = Grammar::load_file(&program_filepath)?;
// Parses the Leo file and constructs a pest ast.
let ast = Grammar::new(&program_filepath, &program_string)?;
// Parse the pest ast and constructs a ast.
let leo_ast = Ast::new("leo_tree", &ast)?;
let serialized_leo_ast = Ast::to_json_string(&leo_ast)?;
Ok(serialized_leo_ast)
}
fn main() -> Result<(), AstError> {
// Parse the command-line arguments as strings.
let cli_arguments = env::args().collect::<Vec<String>>();
// Check that the correct number of command-line arguments were passed in.
if cli_arguments.len() < 2 || cli_arguments.len() > 3 {
eprintln!("Warning - an invalid number of command-line arguments were provided.");
println!(
"\nCommand-line usage:\n\n\tleo_ast {{PATH/TO/INPUT_FILENAME}}.leo {{PATH/TO/OUTPUT_DIRECTORY (optional)}}\n"
);
return Ok(()); // Exit innocently
}
// Construct the input filepath.
let input_filepath = Path::new(&cli_arguments[1]);
// Construct the serialized syntax tree.
let serialized_leo_tree = to_leo_tree(&input_filepath)?;
println!("{}", serialized_leo_tree);
// Determine the output directory.
let output_directory = match cli_arguments.len() == 3 {
true => format!(
"{}/{}.json",
cli_arguments[2],
input_filepath.file_stem().unwrap().to_str().unwrap()
),
false => format!("./{}.json", input_filepath.file_stem().unwrap().to_str().unwrap()),
};
// Write the serialized syntax tree to the output directory.
fs::write(Path::new(&output_directory), serialized_leo_tree)?;
Ok(())
}

View File

@ -17,17 +17,7 @@
//! A Leo program consists of import, circuit, and function definitions.
//! Each defined type consists of ast statements and expressions.
use crate::{
load_annotation,
Circuit,
DeprecatedError,
Function,
FunctionInput,
Identifier,
ImportStatement,
TestFunction,
};
use leo_grammar::{definitions::Definition, files::File};
use crate::{Circuit, Function, FunctionInput, Identifier, ImportStatement};
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
@ -41,7 +31,12 @@ pub struct Program {
pub imports: Vec<ImportStatement>,
pub circuits: IndexMap<Identifier, Circuit>,
pub functions: IndexMap<Identifier, Function>,
pub tests: IndexMap<Identifier, TestFunction>,
}
impl AsRef<Program> for Program {
fn as_ref(&self) -> &Program {
self
}
}
impl fmt::Display for Program {
@ -60,80 +55,10 @@ impl fmt::Display for Program {
function.fmt(f)?;
writeln!(f,)?;
}
for (_, test) in self.tests.iter() {
write!(f, "test ")?;
test.function.fmt(f)?;
writeln!(f,)?;
}
write!(f, "")
}
}
const MAIN_FUNCTION_NAME: &str = "main";
impl<'ast> Program {
//! Logic to convert from an abstract syntax tree (ast) representation to a Leo program.
pub fn from(program_name: &str, program_ast: &File<'ast>) -> Result<Self, DeprecatedError> {
let mut imports = vec![];
let mut circuits = IndexMap::new();
let mut functions = IndexMap::new();
let mut tests = IndexMap::new();
let mut expected_input = vec![];
program_ast
.definitions
.to_owned()
.into_iter()
// Use of Infallible to say we never expect an Some(Ok(...))
.find_map::<Result<std::convert::Infallible, _>, _>(|definition| match definition {
Definition::Import(import) => {
imports.push(ImportStatement::from(import));
None
}
Definition::Circuit(circuit) => {
circuits.insert(Identifier::from(circuit.identifier.clone()), Circuit::from(circuit));
None
}
Definition::Function(function_def) => {
let function = Function::from(function_def);
if function.identifier.name.eq(MAIN_FUNCTION_NAME) {
expected_input = function.input.clone();
}
functions.insert(function.identifier.clone(), function);
None
}
Definition::Deprecated(deprecated) => {
Some(Err(DeprecatedError::from(deprecated)))
}
Definition::Annotated(annotated_definition) => {
let loaded_annotation = load_annotation(
annotated_definition,
&mut imports,
&mut circuits,
&mut functions,
&mut tests,
&mut expected_input,
);
match loaded_annotation {
Ok(_) => None,
Err(deprecated_err) => Some(Err(deprecated_err))
}
}
})
.transpose()?;
Ok(Self {
name: program_name.to_string(),
expected_input,
imports,
circuits,
functions,
tests,
})
}
}
impl Program {
pub fn new(name: String) -> Self {
Self {
@ -142,7 +67,6 @@ impl Program {
imports: vec![],
circuits: IndexMap::new(),
functions: IndexMap::new(),
tests: IndexMap::new(),
}
}

View File

@ -15,10 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Identifier, PositiveNumber, Span};
use leo_grammar::{
access::{ArrayAccess, AssigneeAccess as GrammarAssigneeAccess},
common::{Assignee as GrammarAssignee, Range, RangeOrExpression},
};
use serde::{Deserialize, Serialize};
use std::fmt;
@ -31,25 +27,6 @@ pub enum AssigneeAccess {
Member(Identifier),
}
impl<'ast> From<GrammarAssigneeAccess<'ast>> for AssigneeAccess {
fn from(access: GrammarAssigneeAccess<'ast>) -> Self {
match access {
GrammarAssigneeAccess::Array(ArrayAccess {
expression: RangeOrExpression::Range(Range { from, to, .. }),
..
}) => AssigneeAccess::ArrayRange(from.map(Expression::from), to.map(Expression::from)),
GrammarAssigneeAccess::Array(ArrayAccess {
expression: RangeOrExpression::Expression(index),
..
}) => AssigneeAccess::ArrayIndex(Expression::from(index)),
GrammarAssigneeAccess::Tuple(tuple) => {
AssigneeAccess::Tuple(PositiveNumber::from(tuple.number), Span::from(tuple.span))
}
GrammarAssigneeAccess::Member(member) => AssigneeAccess::Member(Identifier::from(member.identifier)),
}
}
}
/// Definition assignee: v, arr[0..2], Point p.x
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Assignee {
@ -65,20 +42,6 @@ impl Assignee {
}
}
impl<'ast> From<GrammarAssignee<'ast>> for Assignee {
fn from(assignee: GrammarAssignee<'ast>) -> Self {
Assignee {
identifier: Identifier::from(assignee.name),
accesses: assignee
.accesses
.into_iter()
.map(AssigneeAccess::from)
.collect::<Vec<_>>(),
span: Span::from(assignee.span),
}
}
}
impl fmt::Display for Assignee {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.identifier)?;

View File

@ -16,8 +16,6 @@
use crate::{Expression, Node, Span};
pub use leo_grammar::operations::AssignOperation as GrammarAssignOperation;
use leo_grammar::statements::AssignStatement as GrammarAssignStatement;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -32,6 +30,15 @@ pub enum AssignOperation {
Mul,
Div,
Pow,
Or,
And,
BitOr,
BitAnd,
BitXor,
Shr,
ShrSigned,
Shl,
Mod,
}
impl AsRef<str> for AssignOperation {
@ -43,6 +50,15 @@ impl AsRef<str> for AssignOperation {
AssignOperation::Mul => "*=",
AssignOperation::Div => "/=",
AssignOperation::Pow => "**=",
AssignOperation::Or => "||=",
AssignOperation::And => "&&=",
AssignOperation::BitOr => "|=",
AssignOperation::BitAnd => "&=",
AssignOperation::BitXor => "^=",
AssignOperation::Shr => ">>=",
AssignOperation::ShrSigned => ">>>=",
AssignOperation::Shl => "<<=",
AssignOperation::Mod => "%=",
}
}
}
@ -61,24 +77,6 @@ impl fmt::Display for AssignStatement {
}
}
impl<'ast> From<GrammarAssignStatement<'ast>> for AssignStatement {
fn from(statement: GrammarAssignStatement<'ast>) -> Self {
AssignStatement {
operation: match statement.assign {
GrammarAssignOperation::Assign(_) => AssignOperation::Assign,
GrammarAssignOperation::AddAssign(_) => AssignOperation::Add,
GrammarAssignOperation::SubAssign(_) => AssignOperation::Sub,
GrammarAssignOperation::MulAssign(_) => AssignOperation::Mul,
GrammarAssignOperation::DivAssign(_) => AssignOperation::Div,
GrammarAssignOperation::PowAssign(_) => AssignOperation::Pow,
},
assignee: Assignee::from(statement.assignee),
value: Expression::from(statement.expression),
span: Span::from(statement.span),
}
}
}
impl Node for AssignStatement {
fn span(&self) -> &Span {
&self.span

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Node, Span, Statement};
use leo_grammar::statements::Block as GrammarBlock;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -26,15 +25,6 @@ pub struct Block {
pub span: Span,
}
impl<'ast> From<GrammarBlock<'ast>> for Block {
fn from(block: GrammarBlock<'ast>) -> Self {
Block {
statements: block.statements.into_iter().map(Statement::from).collect(),
span: Span::from(block.span),
}
}
}
impl fmt::Display for Block {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "{{")?;

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Block, Expression, Node, Span, Statement};
use leo_grammar::statements::{ConditionalNestedOrEndStatement, ConditionalStatement as GrammarConditionalStatement};
use serde::{Deserialize, Serialize};
use std::fmt;
@ -28,25 +27,6 @@ pub struct ConditionalStatement {
pub span: Span,
}
impl<'ast> From<GrammarConditionalStatement<'ast>> for ConditionalStatement {
fn from(statement: GrammarConditionalStatement<'ast>) -> Self {
ConditionalStatement {
condition: Expression::from(statement.condition),
block: Block::from(statement.block),
next: statement
.next
.map(|nested_statement| match nested_statement {
ConditionalNestedOrEndStatement::Nested(conditional_statement) => {
Statement::Conditional(ConditionalStatement::from(*conditional_statement))
}
ConditionalNestedOrEndStatement::End(block) => Statement::Block(Block::from(block)),
})
.map(Box::new),
span: Span::from(statement.span),
}
}
}
impl fmt::Display for ConditionalStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "if ({}) {}", self.condition, self.block)?;

View File

@ -14,19 +14,12 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, FormattedString};
use leo_grammar::console::{
ConsoleAssert as GrammarConsoleAssert,
ConsoleDebug as GrammarConsoleDebug,
ConsoleError as GrammarConsoleError,
ConsoleFunction as GrammarConsoleFunction,
ConsoleLog as GrammarConsoleLog,
};
use crate::{Expression, FormattedString, Node, Span};
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub enum ConsoleFunction {
Assert(Expression),
Debug(FormattedString),
@ -34,41 +27,6 @@ pub enum ConsoleFunction {
Log(FormattedString),
}
impl<'ast> From<GrammarConsoleFunction<'ast>> for ConsoleFunction {
fn from(console_function: GrammarConsoleFunction<'ast>) -> Self {
match console_function {
GrammarConsoleFunction::Assert(assert) => ConsoleFunction::from(assert),
GrammarConsoleFunction::Debug(debug) => ConsoleFunction::from(debug),
GrammarConsoleFunction::Error(error) => ConsoleFunction::from(error),
GrammarConsoleFunction::Log(log) => ConsoleFunction::from(log),
}
}
}
impl<'ast> From<GrammarConsoleAssert<'ast>> for ConsoleFunction {
fn from(assert: GrammarConsoleAssert<'ast>) -> Self {
ConsoleFunction::Assert(Expression::from(assert.expression))
}
}
impl<'ast> From<GrammarConsoleDebug<'ast>> for ConsoleFunction {
fn from(debug: GrammarConsoleDebug<'ast>) -> Self {
ConsoleFunction::Debug(FormattedString::from(debug.string))
}
}
impl<'ast> From<GrammarConsoleError<'ast>> for ConsoleFunction {
fn from(error: GrammarConsoleError<'ast>) -> Self {
ConsoleFunction::Error(FormattedString::from(error.string))
}
}
impl<'ast> From<GrammarConsoleLog<'ast>> for ConsoleFunction {
fn from(log: GrammarConsoleLog<'ast>) -> Self {
ConsoleFunction::Log(FormattedString::from(log.string))
}
}
impl fmt::Display for ConsoleFunction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
@ -79,3 +37,23 @@ impl fmt::Display for ConsoleFunction {
}
}
}
impl Node for ConsoleFunction {
fn span(&self) -> &Span {
match self {
ConsoleFunction::Assert(assert) => assert.span(),
ConsoleFunction::Debug(formatted) | ConsoleFunction::Error(formatted) | ConsoleFunction::Log(formatted) => {
&formatted.span
}
}
}
fn set_span(&mut self, span: Span) {
match self {
ConsoleFunction::Assert(assert) => assert.set_span(span),
ConsoleFunction::Debug(formatted) | ConsoleFunction::Error(formatted) | ConsoleFunction::Log(formatted) => {
formatted.set_span(span)
}
}
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ConsoleFunction, Node, Span};
use leo_grammar::console::ConsoleFunctionCall as GrammarConsoleFunctionCall;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -26,15 +25,6 @@ pub struct ConsoleStatement {
pub span: Span,
}
impl<'ast> From<GrammarConsoleFunctionCall<'ast>> for ConsoleStatement {
fn from(console: GrammarConsoleFunctionCall<'ast>) -> Self {
ConsoleStatement {
function: ConsoleFunction::from(console.function),
span: Span::from(console.span),
}
}
}
impl fmt::Display for ConsoleStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "console.{};", self.function)

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Node, Span};
use leo_grammar::console::FormattedContainer as GrammarFormattedContainer;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -25,14 +24,6 @@ pub struct FormattedContainer {
pub span: Span,
}
impl<'ast> From<GrammarFormattedContainer<'ast>> for FormattedContainer {
fn from(container: GrammarFormattedContainer<'ast>) -> Self {
Self {
span: Span::from(container.span),
}
}
}
impl fmt::Display for FormattedContainer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{{}}")

View File

@ -14,39 +14,38 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, FormattedContainer, Node, Span};
use leo_grammar::console::FormattedString as GrammarFormattedString;
use crate::{Expression, Node, Span};
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub enum FormattedStringPart {
Const(String),
Container,
}
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct FormattedString {
pub string: String,
pub containers: Vec<FormattedContainer>,
pub parts: Vec<FormattedStringPart>,
pub parameters: Vec<Expression>,
pub span: Span,
}
impl<'ast> From<GrammarFormattedString<'ast>> for FormattedString {
fn from(formatted: GrammarFormattedString<'ast>) -> Self {
let string = formatted.string;
let span = Span::from(formatted.span);
let containers = formatted.containers.into_iter().map(FormattedContainer::from).collect();
let parameters = formatted.parameters.into_iter().map(Expression::from).collect();
Self {
string,
containers,
parameters,
span,
}
}
}
impl fmt::Display for FormattedString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.string)
write!(
f,
"{}",
self.parts
.iter()
.map(|x| match x {
FormattedStringPart::Const(x) => x,
FormattedStringPart::Container => "{}",
})
.collect::<Vec<_>>()
.join("")
)
}
}

View File

@ -14,8 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_grammar::common::Declare as GrammarDeclare;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -25,15 +23,6 @@ pub enum Declare {
Let,
}
impl<'ast> From<GrammarDeclare> for Declare {
fn from(declare: GrammarDeclare) -> Self {
match declare {
GrammarDeclare::Const(_) => Declare::Const,
GrammarDeclare::Let(_) => Declare::Let,
}
}
}
impl fmt::Display for Declare {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {

View File

@ -24,7 +24,6 @@ pub use variable_name::*;
mod declare;
pub use declare::*;
use leo_grammar::statements::DefinitionStatement as GrammarDefinitionStatement;
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct DefinitionStatement {
@ -60,27 +59,6 @@ impl fmt::Display for DefinitionStatement {
}
}
impl<'ast> From<GrammarDefinitionStatement<'ast>> for DefinitionStatement {
fn from(statement: GrammarDefinitionStatement<'ast>) -> Self {
let variable_names = statement
.variables
.names
.into_iter()
.map(VariableName::from)
.collect::<Vec<_>>();
let type_ = statement.variables.type_.map(Type::from);
DefinitionStatement {
declaration_type: Declare::from(statement.declare),
variable_names,
type_,
value: Expression::from(statement.expression),
span: Span::from(statement.span),
}
}
}
impl Node for DefinitionStatement {
fn span(&self) -> &Span {
&self.span

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Identifier, Node, Span};
use leo_grammar::common::VariableName as GrammarVariableName;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -27,16 +26,6 @@ pub struct VariableName {
pub span: Span,
}
impl<'ast> From<GrammarVariableName<'ast>> for VariableName {
fn from(name: GrammarVariableName<'ast>) -> Self {
Self {
mutable: name.mutable.is_some(),
identifier: Identifier::from(name.identifier),
span: Span::from(name.span),
}
}
}
impl fmt::Display for VariableName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.mutable {

View File

@ -16,7 +16,6 @@
use crate::{Expression, Node, Span};
use leo_grammar::statements::ExpressionStatement as GrammarExpressionStatement;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -32,16 +31,6 @@ impl fmt::Display for ExpressionStatement {
}
}
impl<'ast> From<GrammarExpressionStatement<'ast>> for ExpressionStatement {
fn from(statement: GrammarExpressionStatement<'ast>) -> Self {
// why do we have this span-setting logic?
let span = Span::from(statement.span);
let mut expression = Expression::from(statement.expression);
expression.set_span(span.clone());
ExpressionStatement { expression, span }
}
}
impl Node for ExpressionStatement {
fn span(&self) -> &Span {
&self.span

View File

@ -16,7 +16,6 @@
use crate::{Block, Expression, Identifier, Node, Span};
use leo_grammar::statements::ForStatement;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -39,18 +38,6 @@ impl fmt::Display for IterationStatement {
}
}
impl<'ast> From<ForStatement<'ast>> for IterationStatement {
fn from(statement: ForStatement<'ast>) -> Self {
IterationStatement {
variable: Identifier::from(statement.index),
start: Expression::from(statement.start),
stop: Expression::from(statement.stop),
block: Block::from(statement.block),
span: Span::from(statement.span),
}
}
}
impl Node for IterationStatement {
fn span(&self) -> &Span {
&self.span

View File

@ -16,7 +16,6 @@
use crate::{Expression, Node, Span};
use leo_grammar::statements::ReturnStatement as GrammarReturnStatement;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -32,15 +31,6 @@ impl fmt::Display for ReturnStatement {
}
}
impl<'ast> From<GrammarReturnStatement<'ast>> for ReturnStatement {
fn from(statement: GrammarReturnStatement<'ast>) -> Self {
ReturnStatement {
expression: Expression::from(statement.expression),
span: Span::from(statement.span),
}
}
}
impl Node for ReturnStatement {
fn span(&self) -> &Span {
&self.span

View File

@ -16,8 +16,6 @@
use crate::{ConditionalStatement, Node, Span};
use leo_grammar::statements::Statement as GrammarStatement;
use super::*;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -35,21 +33,6 @@ pub enum Statement {
Block(Block),
}
impl<'ast> From<GrammarStatement<'ast>> for Statement {
fn from(statement: GrammarStatement<'ast>) -> Self {
match statement {
GrammarStatement::Return(statement) => Statement::Return(ReturnStatement::from(statement)),
GrammarStatement::Definition(statement) => Statement::Definition(DefinitionStatement::from(statement)),
GrammarStatement::Assign(statement) => Statement::Assign(AssignStatement::from(statement)),
GrammarStatement::Conditional(statement) => Statement::Conditional(ConditionalStatement::from(statement)),
GrammarStatement::Iteration(statement) => Statement::Iteration(IterationStatement::from(statement)),
GrammarStatement::Console(statement) => Statement::Console(ConsoleStatement::from(statement)),
GrammarStatement::Expression(statement) => Statement::Expression(ExpressionStatement::from(statement)),
GrammarStatement::Block(statement) => Statement::Block(Block::from(statement)),
}
}
}
impl fmt::Display for Statement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {

View File

@ -14,11 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_grammar::types::{
IntegerType as GrammarIntegerType,
SignedIntegerType as GrammarSignedIntegerType,
UnsignedIntegerType as GrammarUnsignedIntegerType,
};
use leo_input::types::{
IntegerType as InputIntegerType,
SignedIntegerType as InputSignedIntegerType,
@ -44,39 +39,6 @@ pub enum IntegerType {
I128,
}
impl From<GrammarIntegerType> for IntegerType {
fn from(integer_type: GrammarIntegerType) -> Self {
match integer_type {
GrammarIntegerType::Signed(signed) => Self::from(signed),
GrammarIntegerType::Unsigned(unsigned) => Self::from(unsigned),
}
}
}
impl From<GrammarUnsignedIntegerType> for IntegerType {
fn from(integer_type: GrammarUnsignedIntegerType) -> Self {
match integer_type {
GrammarUnsignedIntegerType::U8Type(_type) => IntegerType::U8,
GrammarUnsignedIntegerType::U16Type(_type) => IntegerType::U16,
GrammarUnsignedIntegerType::U32Type(_type) => IntegerType::U32,
GrammarUnsignedIntegerType::U64Type(_type) => IntegerType::U64,
GrammarUnsignedIntegerType::U128Type(_type) => IntegerType::U128,
}
}
}
impl From<GrammarSignedIntegerType> for IntegerType {
fn from(integer_type: GrammarSignedIntegerType) -> Self {
match integer_type {
GrammarSignedIntegerType::I8Type(_type) => IntegerType::I8,
GrammarSignedIntegerType::I16Type(_type) => IntegerType::I16,
GrammarSignedIntegerType::I32Type(_type) => IntegerType::I32,
GrammarSignedIntegerType::I64Type(_type) => IntegerType::I64,
GrammarSignedIntegerType::I128Type(_type) => IntegerType::I128,
}
}
}
impl From<InputIntegerType> for IntegerType {
fn from(integer_type: InputIntegerType) -> Self {
match integer_type {

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ArrayDimensions, Identifier, IntegerType};
use leo_grammar::types::{ArrayType, CircuitType, DataType, TupleType, Type as GrammarType};
use leo_input::types::{
ArrayType as InputArrayType,
DataType as InputDataType,
@ -102,55 +101,6 @@ impl Type {
}
}
/// pest ast -> Explicit Type for defining circuit members and function params
impl From<DataType> for Type {
fn from(data_type: DataType) -> Self {
match data_type {
DataType::Address(_type) => Type::Address,
DataType::Boolean(_type) => Type::Boolean,
DataType::Field(_type) => Type::Field,
DataType::Group(_type) => Type::Group,
DataType::Integer(_type) => Type::IntegerType(IntegerType::from(_type)),
}
}
}
impl<'ast> From<ArrayType<'ast>> for Type {
fn from(array_type: ArrayType<'ast>) -> Self {
let element_type = Box::new(Type::from(*array_type.type_));
let dimensions = ArrayDimensions::from(array_type.dimensions);
Type::Array(element_type, dimensions)
}
}
impl<'ast> From<TupleType<'ast>> for Type {
fn from(tuple_type: TupleType<'ast>) -> Self {
let types = tuple_type.types.into_iter().map(Type::from).collect();
Type::Tuple(types)
}
}
impl<'ast> From<CircuitType<'ast>> for Type {
fn from(circuit_type: CircuitType<'ast>) -> Self {
Type::Circuit(Identifier::from(circuit_type.identifier))
}
}
impl<'ast> From<GrammarType<'ast>> for Type {
fn from(type_: GrammarType<'ast>) -> Self {
match type_ {
GrammarType::Basic(type_) => Type::from(type_),
GrammarType::Array(type_) => Type::from(type_),
GrammarType::Tuple(type_) => Type::from(type_),
GrammarType::Circuit(type_) => Type::from(type_),
GrammarType::SelfType(_type) => Type::SelfType,
}
}
}
/// input pest ast -> Explicit Type
impl From<InputDataType> for Type {

View File

@ -25,10 +25,6 @@ version = "1.2.3"
path = "../gadgets"
version = "1.2.3"
[dependencies.leo-grammar]
path = "../grammar"
version = "1.2.3"
[dependencies.leo-imports]
path = "../imports"
version = "1.2.3"
@ -49,6 +45,10 @@ version = "1.2.3"
path = "../asg"
version = "1.2.3"
[dependencies.leo-parser]
path = "../parser"
version = "1.2.3"
[dependencies.snarkvm-curves]
version = "0.0.6"
default-features = false
@ -120,4 +120,4 @@ default-features = false
[features]
default = [ ]
ci_skip = [ "leo-grammar/ci_skip", "leo-ast/ci_skip" ]
ci_skip = [ "leo-ast/ci_skip" ]

View File

@ -23,9 +23,9 @@ use crate::{
OutputBytes,
OutputFile,
};
use indexmap::IndexMap;
use leo_asg::Asg;
use leo_ast::{Ast, Input, MainInput, Program};
use leo_grammar::Grammar;
use leo_ast::{Input, LeoError, MainInput, Program};
use leo_input::LeoInputParser;
use leo_package::inputs::InputPairs;
use leo_state::verify_local_data_commitment;
@ -39,9 +39,11 @@ use snarkvm_models::{
use sha2::{Digest, Sha256};
use std::{
cell::RefCell,
fs,
marker::PhantomData,
path::{Path, PathBuf},
rc::Rc,
};
pub use leo_asg::{new_context, AsgContext as Context, AsgContext};
@ -68,6 +70,7 @@ pub struct Compiler<'a, F: PrimeField, G: GroupType<F>> {
program_input: Input,
context: AsgContext<'a>,
asg: Option<Asg<'a>>,
file_contents: RefCell<IndexMap<String, Rc<Vec<String>>>>,
_engine: PhantomData<F>,
_group: PhantomData<G>,
}
@ -90,6 +93,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
program_input: Input::new(),
asg: None,
context,
file_contents: RefCell::new(IndexMap::new()),
_engine: PhantomData,
_group: PhantomData,
}
@ -156,23 +160,35 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
state_path: &Path,
) -> Result<(), CompilerError> {
let input_syntax_tree = LeoInputParser::parse_file(&input_string).map_err(|mut e| {
e.set_path(input_path);
e.set_path(
input_path.to_str().unwrap_or_default(),
&input_string.lines().map(|x| x.to_string()).collect::<Vec<String>>()[..],
);
e
})?;
let state_syntax_tree = LeoInputParser::parse_file(&state_string).map_err(|mut e| {
e.set_path(state_path);
e.set_path(
state_path.to_str().unwrap_or_default(),
&state_string.lines().map(|x| x.to_string()).collect::<Vec<String>>()[..],
);
e
})?;
self.program_input.parse_input(input_syntax_tree).map_err(|mut e| {
e.set_path(input_path);
e.set_path(
input_path.to_str().unwrap_or_default(),
&input_string.lines().map(|x| x.to_string()).collect::<Vec<String>>()[..],
);
e
})?;
self.program_input.parse_state(state_syntax_tree).map_err(|mut e| {
e.set_path(state_path);
e.set_path(
state_path.to_str().unwrap_or_default(),
&state_string.lines().map(|x| x.to_string()).collect::<Vec<String>>()[..],
);
e
})?;
@ -180,6 +196,20 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
Ok(())
}
fn resolve_content(&self, path: &str) -> Result<Rc<Vec<String>>, CompilerError> {
let mut file_contents = self.file_contents.borrow_mut();
if file_contents.contains_key(path) {
// using this pattern because of mutable reference in branch below
Ok(file_contents.get(path).unwrap().clone())
} else {
let content = fs::read_to_string(path).map_err(|e| CompilerError::FileReadError(PathBuf::from(path), e))?;
let content = Rc::new(content.lines().map(|x| x.to_string()).collect::<Vec<String>>());
file_contents.insert(path.to_string(), content);
Ok(file_contents.get(path).unwrap().clone())
}
}
///
/// Parses and stores the main program file, constructs a syntax tree, and generates a program.
///
@ -187,9 +217,10 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
///
pub fn parse_program(&mut self) -> Result<(), CompilerError> {
// Load the program file.
let program_string = Grammar::load_file(&self.main_file_path)?;
let content = fs::read_to_string(&self.main_file_path)
.map_err(|e| CompilerError::FileReadError(self.main_file_path.clone(), e))?;
self.parse_program_from_string(&program_string)
self.parse_program_from_string(&content)
}
///
@ -197,23 +228,23 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
/// file path.
///
pub fn parse_program_from_string(&mut self, program_string: &str) -> Result<(), CompilerError> {
// Use the parser to construct the pest abstract syntax tree (ast).
let grammar = Grammar::new(&self.main_file_path, &program_string).map_err(|mut e| {
e.set_path(&self.main_file_path);
// Use the parser to construct the abstract syntax tree (ast).
let lines = program_string.lines().map(|x| x.to_string()).collect();
self.file_contents.borrow_mut().insert(
self.main_file_path.to_str().map(|x| x.to_string()).unwrap_or_default(),
Rc::new(lines),
);
e
})?;
// Construct the AST from the grammar.
let core_ast = Ast::new(&self.program_name, &grammar)?;
let ast = leo_parser::parse_ast(self.main_file_path.to_str().unwrap_or_default(), program_string)?;
// Store the main program file.
self.program = core_ast.as_repr().clone();
self.program = ast.into_repr();
self.program.name = self.program_name.clone();
tracing::debug!("Program parsing complete\n{:#?}", self.program);
// Create a new symbol table from the program, imported_programs, and program_input.
let asg = Asg::new(self.context, &core_ast, &mut leo_imports::ImportParser::default())?;
let asg = Asg::new(self.context, &self.program, &mut leo_imports::ImportParser::default())?;
tracing::debug!("ASG generation complete");
@ -228,7 +259,13 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
///
pub fn compile_constraints<CS: ConstraintSystem<F>>(&self, cs: &mut CS) -> Result<OutputBytes, CompilerError> {
generate_constraints::<F, G, CS>(cs, &self.asg.as_ref().unwrap(), &self.program_input).map_err(|mut error| {
error.set_path(&self.main_file_path);
if let Some(path) = error.get_path().map(|x| x.to_string()) {
let content = match self.resolve_content(&path) {
Err(e) => return e,
Ok(x) => x,
};
error.set_path(&path, &content[..]);
}
error
})
}
@ -251,7 +288,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
pub fn checksum(&self) -> Result<String, CompilerError> {
// Read in the main file as string
let unparsed_file = fs::read_to_string(&self.main_file_path)
.map_err(|_| CompilerError::FileReadError(self.main_file_path.clone()))?;
.map_err(|e| CompilerError::FileReadError(self.main_file_path.clone(), e))?;
// Hash the file contents
let mut hasher = Sha256::new();

View File

@ -51,16 +51,13 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
let result_option = match assert_expression {
ConstrainedValue::Boolean(boolean) => boolean.get_value(),
_ => {
return Err(ConsoleError::assertion_must_be_boolean(
span.text.clone(),
span.to_owned(),
));
return Err(ConsoleError::assertion_must_be_boolean(span));
}
};
let result_bool = result_option.ok_or_else(|| ConsoleError::assertion_depends_on_input(span.to_owned()))?;
let result_bool = result_option.ok_or_else(|| ConsoleError::assertion_depends_on_input(span))?;
if !result_bool {
return Err(ConsoleError::assertion_failed(span.text.clone(), span.to_owned()));
return Err(ConsoleError::assertion_failed(span));
}
Ok(())

View File

@ -19,6 +19,7 @@
use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType};
use leo_asg::FormattedString;
use leo_ast::FormattedStringPart;
use snarkvm_models::{curves::PrimeField, gadgets::r1cs::ConstraintSystem};
impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
@ -28,30 +29,33 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
formatted: &FormattedString<'a>,
) -> Result<String, ConsoleError> {
// Check that containers and parameters match
if formatted.containers.len() != formatted.parameters.len() {
let container_count = formatted
.parts
.iter()
.filter(|x| matches!(x, FormattedStringPart::Container))
.count();
if container_count != formatted.parameters.len() {
return Err(ConsoleError::length(
formatted.containers.len(),
container_count,
formatted.parameters.len(),
formatted.span.clone(),
&formatted.span,
));
}
// Trim starting double quote `"`
let mut string = formatted.string.as_str();
string = string.trim_start_matches('\"');
// Trim everything after the ending double quote `"`
let string = string.split('\"').next().unwrap();
// Insert the parameter for each container `{}`
let mut result = string.to_string();
let mut executed_containers = Vec::with_capacity(formatted.parameters.len());
for parameter in formatted.parameters.iter() {
let parameter_value = self.enforce_expression(cs, parameter.get())?;
result = result.replacen("{}", &parameter_value.to_string(), 1);
executed_containers.push(self.enforce_expression(cs, parameter.get())?.to_string());
}
Ok(result)
let mut out = vec![];
let mut parameters = executed_containers.iter();
for part in formatted.parts.iter() {
match part {
FormattedStringPart::Const(c) => out.push(&**c),
FormattedStringPart::Container => out.push(&**parameters.next().unwrap()),
}
}
Ok(out.join(""))
}
}

View File

@ -18,7 +18,7 @@
use crate::{errors::CompilerError, ConstrainedProgram, GroupType, OutputBytes, OutputFile};
use leo_asg::Asg;
use leo_ast::Input;
use leo_ast::{Input, LeoError};
use leo_input::LeoInputParser;
use leo_package::inputs::InputPairs;
@ -63,22 +63,33 @@ pub fn generate_test_constraints<'a, F: PrimeField, G: GroupType<F>>(
// Get default input
let default = input.pairs.get(&program_name);
let tests = &program.test_functions;
let tests = program
.functions
.iter()
.filter(|(_name, func)| func.is_test())
.collect::<Vec<_>>();
tracing::info!("Running {} tests", tests.len());
// Count passed and failed tests
let mut passed = 0;
let mut failed = 0;
for (test_name, (function, input_file)) in tests.into_iter() {
for (test_name, function) in tests.into_iter() {
let cs = &mut TestConstraintSystem::<F>::new();
let full_test_name = format!("{}::{}", program_name.clone(), test_name);
let mut output_file_name = program_name.clone();
let input_file = function
.annotations
.iter()
.find(|x| x.name.name == "test")
.unwrap()
.arguments
.get(0);
// get input file name from annotation or use test_name
let input_pair = match input_file {
Some(file_id) => {
let file_name = file_id.name.clone();
let file_name = file_id.clone();
output_file_name = file_name.clone();
@ -129,7 +140,7 @@ pub fn generate_test_constraints<'a, F: PrimeField, G: GroupType<F>>(
(false, _) => {
// Set file location of error
let mut error = result.unwrap_err();
error.set_path(main_file_path);
error.set_path(main_file_path.to_str().unwrap_or_default(), &[]);
tracing::error!("{} failed due to error\n\n{}\n", full_test_name, error);

View File

@ -16,19 +16,19 @@
use crate::errors::{FunctionError, ImportError, OutputBytesError, OutputFileError};
use leo_asg::AsgConvertError;
use leo_ast::AstError;
use leo_grammar::ParserError;
use leo_ast::LeoError;
use leo_imports::ImportParserError;
use leo_input::InputParserError;
use leo_parser::SyntaxError;
use leo_state::LocalDataVerificationError;
use bincode::Error as SerdeError;
use std::path::{Path, PathBuf};
use std::path::PathBuf;
#[derive(Debug, Error)]
pub enum CompilerError {
#[error("{}", _0)]
AstError(#[from] AstError),
SyntaxError(#[from] SyntaxError),
#[error("{}", _0)]
ImportError(#[from] ImportError),
@ -45,8 +45,8 @@ pub enum CompilerError {
#[error("{}", _0)]
FunctionError(#[from] FunctionError),
#[error("Cannot read from the provided file path - {:?}", _0)]
FileReadError(PathBuf),
#[error("Cannot read from the provided file path '{:?}': {}", _0, _1)]
FileReadError(PathBuf, std::io::Error),
#[error("{}", _0)]
LocalDataVerificationError(#[from] LocalDataVerificationError),
@ -66,9 +66,6 @@ pub enum CompilerError {
#[error("{}", _0)]
OutputStringError(#[from] OutputBytesError),
#[error("{}", _0)]
ParserError(#[from] ParserError),
#[error("{}", _0)]
SerdeError(#[from] SerdeError),
@ -76,12 +73,29 @@ pub enum CompilerError {
AsgConvertError(#[from] AsgConvertError),
}
impl CompilerError {
pub fn set_path(&mut self, path: &Path) {
impl LeoError for CompilerError {
fn get_path(&self) -> Option<&str> {
match self {
CompilerError::InputParserError(error) => error.set_path(path),
CompilerError::FunctionError(error) => error.set_path(path),
CompilerError::OutputStringError(error) => error.set_path(path),
CompilerError::SyntaxError(error) => error.get_path(),
CompilerError::ImportError(error) => error.get_path(),
CompilerError::ImportParserError(error) => error.get_path(),
CompilerError::InputParserError(error) => error.get_path(),
CompilerError::FunctionError(error) => error.get_path(),
CompilerError::OutputStringError(error) => error.get_path(),
CompilerError::AsgConvertError(error) => error.get_path(),
_ => None,
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
CompilerError::SyntaxError(error) => error.set_path(path, contents),
CompilerError::ImportError(error) => error.set_path(path, contents),
CompilerError::ImportParserError(error) => error.set_path(path, contents),
CompilerError::InputParserError(error) => error.set_path(path, contents),
CompilerError::FunctionError(error) => error.set_path(path, contents),
CompilerError::OutputStringError(error) => error.set_path(path, contents),
CompilerError::AsgConvertError(error) => error.set_path(path, contents),
_ => {}
}
}

View File

@ -15,9 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::errors::ExpressionError;
use leo_ast::{Error as FormattedError, Span};
use std::path::Path;
use leo_ast::{FormattedError, LeoError, Span};
#[derive(Debug, Error)]
pub enum ConsoleError {
@ -28,19 +26,28 @@ pub enum ConsoleError {
Expression(#[from] ExpressionError),
}
impl ConsoleError {
pub fn set_path(&mut self, path: &Path) {
impl LeoError for ConsoleError {
fn get_path(&self) -> Option<&str> {
match self {
ConsoleError::Expression(error) => error.set_path(path),
ConsoleError::Error(error) => error.set_path(path),
ConsoleError::Error(error) => error.get_path(),
ConsoleError::Expression(error) => error.get_path(),
}
}
fn new_from_span(message: String, span: Span) -> Self {
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
ConsoleError::Error(error) => error.set_path(path, contents),
ConsoleError::Expression(error) => error.set_path(path, contents),
}
}
}
impl ConsoleError {
fn new_from_span(message: String, span: &Span) -> Self {
ConsoleError::Error(FormattedError::new_from_span(message, span))
}
pub fn length(containers: usize, parameters: usize, span: Span) -> Self {
pub fn length(containers: usize, parameters: usize, span: &Span) -> Self {
let message = format!(
"Formatter given {} containers and found {} parameters",
containers, parameters
@ -49,21 +56,21 @@ impl ConsoleError {
Self::new_from_span(message, span)
}
pub fn assertion_depends_on_input(span: Span) -> Self {
pub fn assertion_depends_on_input(span: &Span) -> Self {
let message =
"console.assert() failed to evaluate. This error is caused by empty input file values".to_string();
Self::new_from_span(message, span)
}
pub fn assertion_failed(expression: String, span: Span) -> Self {
let message = format!("Assertion `{}` failed", expression);
pub fn assertion_failed(span: &Span) -> Self {
let message = "Assertion failed".to_string();
Self::new_from_span(message, span)
}
pub fn assertion_must_be_boolean(expression: String, span: Span) -> Self {
let message = format!("Assertion expression `{}` must evaluate to a boolean value", expression);
pub fn assertion_must_be_boolean(span: &Span) -> Self {
let message = "Assertion expression must evaluate to a boolean value".to_string();
Self::new_from_span(message, span)
}

View File

@ -15,10 +15,9 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::errors::{AddressError, BooleanError, FieldError, FunctionError, GroupError, IntegerError, ValueError};
use leo_ast::{ArrayDimensions, Error as FormattedError, Identifier, PositiveNumber, Span};
use leo_ast::{ArrayDimensions, FormattedError, Identifier, LeoError, PositiveNumber, Span};
use snarkvm_errors::gadgets::SynthesisError;
use std::path::Path;
#[derive(Debug, Error)]
pub enum ExpressionError {
@ -47,25 +46,40 @@ pub enum ExpressionError {
ValueError(#[from] ValueError),
}
impl ExpressionError {
pub fn set_path(&mut self, path: &Path) {
impl LeoError for ExpressionError {
fn get_path(&self) -> Option<&str> {
match self {
ExpressionError::AddressError(error) => error.set_path(path),
ExpressionError::BooleanError(error) => error.set_path(path),
ExpressionError::Error(error) => error.set_path(path),
ExpressionError::FieldError(error) => error.set_path(path),
ExpressionError::FunctionError(error) => error.set_path(path),
ExpressionError::GroupError(error) => error.set_path(path),
ExpressionError::IntegerError(error) => error.set_path(path),
ExpressionError::ValueError(error) => error.set_path(path),
ExpressionError::AddressError(error) => error.get_path(),
ExpressionError::BooleanError(error) => error.get_path(),
ExpressionError::Error(error) => error.get_path(),
ExpressionError::FieldError(error) => error.get_path(),
ExpressionError::FunctionError(error) => error.get_path(),
ExpressionError::GroupError(error) => error.get_path(),
ExpressionError::IntegerError(error) => error.get_path(),
ExpressionError::ValueError(error) => error.get_path(),
}
}
fn new_from_span(message: String, span: Span) -> Self {
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
ExpressionError::AddressError(error) => error.set_path(path, contents),
ExpressionError::BooleanError(error) => error.set_path(path, contents),
ExpressionError::Error(error) => error.set_path(path, contents),
ExpressionError::FieldError(error) => error.set_path(path, contents),
ExpressionError::FunctionError(error) => error.set_path(path, contents),
ExpressionError::GroupError(error) => error.set_path(path, contents),
ExpressionError::IntegerError(error) => error.set_path(path, contents),
ExpressionError::ValueError(error) => error.set_path(path, contents),
}
}
}
impl ExpressionError {
fn new_from_span(message: String, span: &Span) -> Self {
ExpressionError::Error(FormattedError::new_from_span(message, span))
}
pub fn cannot_enforce(operation: String, error: SynthesisError, span: Span) -> Self {
pub fn cannot_enforce(operation: String, error: SynthesisError, span: &Span) -> Self {
let message = format!(
"the gadget operation `{}` failed due to synthesis error `{:?}`",
operation, error,
@ -74,37 +88,37 @@ impl ExpressionError {
Self::new_from_span(message, span)
}
pub fn cannot_evaluate(operation: String, span: Span) -> Self {
pub fn cannot_evaluate(operation: String, span: &Span) -> Self {
let message = format!("Mismatched types found for operation `{}`", operation);
Self::new_from_span(message, span)
}
pub fn conditional_boolean(actual: String, span: Span) -> Self {
pub fn conditional_boolean(actual: String, span: &Span) -> Self {
let message = format!("if, else conditional must resolve to a boolean, found `{}`", actual);
Self::new_from_span(message, span)
}
pub fn expected_circuit_member(expected: String, span: Span) -> Self {
pub fn expected_circuit_member(expected: String, span: &Span) -> Self {
let message = format!("expected circuit member `{}`, not found", expected);
Self::new_from_span(message, span)
}
pub fn incompatible_types(operation: String, span: Span) -> Self {
pub fn incompatible_types(operation: String, span: &Span) -> Self {
let message = format!("no implementation for `{}`", operation);
Self::new_from_span(message, span)
}
pub fn index_out_of_bounds(index: usize, span: Span) -> Self {
pub fn index_out_of_bounds(index: usize, span: &Span) -> Self {
let message = format!("cannot access index {} of tuple out of bounds", index);
Self::new_from_span(message, span)
}
pub fn invalid_dimensions(expected: &ArrayDimensions, actual: &ArrayDimensions, span: Span) -> Self {
pub fn invalid_dimensions(expected: &ArrayDimensions, actual: &ArrayDimensions, span: &Span) -> Self {
let message = format!(
"expected array dimensions {}, found array dimensions {}",
expected, actual
@ -113,7 +127,7 @@ impl ExpressionError {
Self::new_from_span(message, span)
}
pub fn invalid_first_dimension(expected: &PositiveNumber, actual: &PositiveNumber, span: Span) -> Self {
pub fn invalid_first_dimension(expected: &PositiveNumber, actual: &PositiveNumber, span: &Span) -> Self {
let message = format!(
"expected array dimension {}, found array dimension {}",
expected, actual
@ -125,58 +139,58 @@ impl ExpressionError {
pub fn invalid_index(actual: String, span: &Span) -> Self {
let message = format!("index must resolve to an integer, found `{}`", actual);
Self::new_from_span(message, span.to_owned())
Self::new_from_span(message, span)
}
pub fn invalid_length(expected: usize, actual: usize, span: Span) -> Self {
pub fn invalid_length(expected: usize, actual: usize, span: &Span) -> Self {
let message = format!("expected array length {}, found one with length {}", expected, actual);
Self::new_from_span(message, span)
}
pub fn invalid_spread(actual: String, span: Span) -> Self {
pub fn invalid_spread(actual: String, span: &Span) -> Self {
let message = format!("spread should contain an array, found `{}`", actual);
Self::new_from_span(message, span)
}
pub fn invalid_member_access(member: String, span: Span) -> Self {
pub fn invalid_member_access(member: String, span: &Span) -> Self {
let message = format!("non-static member `{}` must be accessed using `.` syntax", member);
Self::new_from_span(message, span)
}
pub fn invalid_static_access(member: String, span: Span) -> Self {
pub fn invalid_static_access(member: String, span: &Span) -> Self {
let message = format!("static member `{}` must be accessed using `::` syntax", member);
Self::new_from_span(message, span)
}
pub fn function_no_return(function: String, span: Span) -> Self {
pub fn function_no_return(function: String, span: &Span) -> Self {
let message = format!("inline function call to `{}` did not return", function);
Self::new_from_span(message, span)
}
pub fn self_keyword(span: Span) -> Self {
pub fn self_keyword(span: &Span) -> Self {
let message = "cannot call keyword `Self` outside of a circuit function".to_string();
Self::new_from_span(message, span)
}
pub fn undefined_array(actual: String, span: Span) -> Self {
pub fn undefined_array(actual: String, span: &Span) -> Self {
let message = format!("array `{}` must be declared before it is used in an expression", actual);
Self::new_from_span(message, span)
}
pub fn undefined_tuple(actual: String, span: Span) -> Self {
pub fn undefined_tuple(actual: String, span: &Span) -> Self {
let message = format!("tuple `{}` must be declared before it is used in an expression", actual);
Self::new_from_span(message, span)
}
pub fn undefined_circuit(actual: String, span: Span) -> Self {
pub fn undefined_circuit(actual: String, span: &Span) -> Self {
let message = format!(
"circuit `{}` must be declared before it is used in an expression",
actual
@ -185,13 +199,13 @@ impl ExpressionError {
Self::new_from_span(message, span)
}
pub fn undefined_first_dimension(span: Span) -> Self {
pub fn undefined_first_dimension(span: &Span) -> Self {
let message = "the first dimension of the array must be a number".to_string();
Self::new_from_span(message, span)
}
pub fn undefined_function(function: String, span: Span) -> Self {
pub fn undefined_function(function: String, span: &Span) -> Self {
let message = format!(
"function `{}` must be declared before it is used in an inline expression",
function
@ -203,28 +217,28 @@ impl ExpressionError {
pub fn undefined_identifier(identifier: Identifier) -> Self {
let message = format!("Cannot find value `{}` in this scope", identifier.name);
Self::new_from_span(message, identifier.span)
Self::new_from_span(message, &identifier.span)
}
pub fn undefined_member_access(circuit: String, member: String, span: Span) -> Self {
pub fn undefined_member_access(circuit: String, member: String, span: &Span) -> Self {
let message = format!("Circuit `{}` has no member `{}`", circuit, member);
Self::new_from_span(message, span)
}
pub fn undefined_static_access(circuit: String, member: String, span: Span) -> Self {
pub fn undefined_static_access(circuit: String, member: String, span: &Span) -> Self {
let message = format!("Circuit `{}` has no static member `{}`", circuit, member);
Self::new_from_span(message, span)
}
pub fn unexpected_array(expected: String, span: Span) -> Self {
pub fn unexpected_array(expected: String, span: &Span) -> Self {
let message = format!("expected type `{}`, found array with elements", expected);
Self::new_from_span(message, span)
}
pub fn unexpected_tuple(expected: String, actual: String, span: Span) -> Self {
pub fn unexpected_tuple(expected: String, actual: String, span: &Span) -> Self {
let message = format!("expected type `{}`, found tuple with values `{}`", expected, actual);
Self::new_from_span(message, span)

View File

@ -26,9 +26,7 @@ use crate::errors::{
ValueError,
};
use leo_asg::AsgConvertError;
use leo_ast::{Error as FormattedError, Span};
use std::path::Path;
use leo_ast::{FormattedError, LeoError, Span};
#[derive(Debug, Error)]
pub enum FunctionError {
@ -66,34 +64,52 @@ pub enum FunctionError {
ImportASGError(#[from] AsgConvertError),
}
impl FunctionError {
pub fn set_path(&mut self, path: &Path) {
impl LeoError for FunctionError {
fn get_path(&self) -> Option<&str> {
match self {
FunctionError::AddressError(error) => error.set_path(path),
FunctionError::BooleanError(error) => error.set_path(path),
FunctionError::ExpressionError(error) => error.set_path(path),
FunctionError::Error(error) => error.set_path(path),
FunctionError::FieldError(error) => error.set_path(path),
FunctionError::GroupError(error) => error.set_path(path),
FunctionError::IntegerError(error) => error.set_path(path),
FunctionError::OutputStringError(error) => error.set_path(path),
FunctionError::StatementError(error) => error.set_path(path),
FunctionError::ValueError(error) => error.set_path(path),
FunctionError::ImportASGError(_error) => (),
FunctionError::AddressError(error) => error.get_path(),
FunctionError::BooleanError(error) => error.get_path(),
FunctionError::ExpressionError(error) => error.get_path(),
FunctionError::Error(error) => error.get_path(),
FunctionError::FieldError(error) => error.get_path(),
FunctionError::GroupError(error) => error.get_path(),
FunctionError::IntegerError(error) => error.get_path(),
FunctionError::OutputStringError(error) => error.get_path(),
FunctionError::StatementError(error) => error.get_path(),
FunctionError::ValueError(error) => error.get_path(),
FunctionError::ImportASGError(error) => error.get_path(),
}
}
fn new_from_span(message: String, span: Span) -> Self {
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
FunctionError::AddressError(error) => error.set_path(path, contents),
FunctionError::BooleanError(error) => error.set_path(path, contents),
FunctionError::ExpressionError(error) => error.set_path(path, contents),
FunctionError::Error(error) => error.set_path(path, contents),
FunctionError::FieldError(error) => error.set_path(path, contents),
FunctionError::GroupError(error) => error.set_path(path, contents),
FunctionError::IntegerError(error) => error.set_path(path, contents),
FunctionError::OutputStringError(error) => error.set_path(path, contents),
FunctionError::StatementError(error) => error.set_path(path, contents),
FunctionError::ValueError(error) => error.set_path(path, contents),
FunctionError::ImportASGError(error) => error.set_path(path, contents),
}
}
}
impl FunctionError {
fn new_from_span(message: String, span: &Span) -> Self {
FunctionError::Error(FormattedError::new_from_span(message, span))
}
pub fn invalid_array(actual: String, span: Span) -> Self {
pub fn invalid_array(actual: String, span: &Span) -> Self {
let message = format!("Expected function input array, found `{}`", actual);
Self::new_from_span(message, span)
}
pub fn invalid_input_array_dimensions(expected: usize, actual: usize, span: Span) -> Self {
pub fn invalid_input_array_dimensions(expected: usize, actual: usize, span: &Span) -> Self {
let message = format!(
"Input array dimensions mismatch expected {}, found array dimensions {}",
expected, actual
@ -102,25 +118,25 @@ impl FunctionError {
Self::new_from_span(message, span)
}
pub fn invalid_tuple(actual: String, span: Span) -> Self {
pub fn invalid_tuple(actual: String, span: &Span) -> Self {
let message = format!("Expected function input tuple, found `{}`", actual);
Self::new_from_span(message, span)
}
pub fn return_arguments_length(expected: usize, actual: usize, span: Span) -> Self {
pub fn return_arguments_length(expected: usize, actual: usize, span: &Span) -> Self {
let message = format!("function expected {} returns, found {} returns", expected, actual);
Self::new_from_span(message, span)
}
pub fn return_argument_type(expected: String, actual: String, span: Span) -> Self {
pub fn return_argument_type(expected: String, actual: String, span: &Span) -> Self {
let message = format!("Expected function return type `{}`, found `{}`", expected, actual);
Self::new_from_span(message, span)
}
pub fn input_not_found(expected: String, span: Span) -> Self {
pub fn input_not_found(expected: String, span: &Span) -> Self {
let message = format!("main function input {} not found", expected);
Self::new_from_span(message, span)

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::{Error as FormattedError, Identifier, ImportSymbol, Span};
use leo_ast::{FormattedError, Identifier, ImportSymbol, LeoError, Span};
#[derive(Debug, Error)]
pub enum ImportError {
@ -22,8 +22,22 @@ pub enum ImportError {
Error(#[from] FormattedError),
}
impl LeoError for ImportError {
fn get_path(&self) -> Option<&str> {
match self {
ImportError::Error(error) => error.get_path(),
}
}
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
ImportError::Error(error) => error.set_path(path, contents),
}
}
}
impl ImportError {
fn new_from_span(message: String, span: Span) -> Self {
fn new_from_span(message: String, span: &Span) -> Self {
ImportError::Error(FormattedError::new_from_span(message, span))
}
@ -33,12 +47,12 @@ impl ImportError {
identifier.name
);
Self::new_from_span(message, identifier.span)
Self::new_from_span(message, &identifier.span)
}
pub fn unknown_symbol(symbol: ImportSymbol, file: String) -> Self {
let message = format!("cannot find imported symbol `{}` in imported file `{}`", symbol, file);
let error = FormattedError::new_from_span(message, symbol.span);
let error = FormattedError::new_from_span(message, &symbol.span);
ImportError::Error(error)
}

View File

@ -16,9 +16,7 @@
use crate::errors::ValueError;
use leo_asg::{AsgConvertError, Type};
use leo_ast::{Error as FormattedError, Span};
use std::path::Path;
use leo_ast::{FormattedError, LeoError, Span};
#[derive(Debug, Error)]
pub enum OutputBytesError {
@ -32,26 +30,36 @@ pub enum OutputBytesError {
AsgConvertError(#[from] AsgConvertError),
}
impl OutputBytesError {
pub fn set_path(&mut self, path: &Path) {
impl LeoError for OutputBytesError {
fn get_path(&self) -> Option<&str> {
match self {
OutputBytesError::Error(error) => error.set_path(path),
OutputBytesError::ValueError(error) => error.set_path(path),
OutputBytesError::AsgConvertError(_error) => (),
OutputBytesError::Error(error) => error.get_path(),
OutputBytesError::ValueError(error) => error.get_path(),
OutputBytesError::AsgConvertError(error) => error.get_path(),
}
}
fn new_from_span(message: String, span: Span) -> Self {
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
OutputBytesError::Error(error) => error.set_path(path, contents),
OutputBytesError::ValueError(error) => error.set_path(path, contents),
OutputBytesError::AsgConvertError(error) => error.set_path(path, contents),
}
}
}
impl OutputBytesError {
fn new_from_span(message: String, span: &Span) -> Self {
OutputBytesError::Error(FormattedError::new_from_span(message, span))
}
pub fn not_enough_registers(span: Span) -> Self {
pub fn not_enough_registers(span: &Span) -> Self {
let message = "number of input registers must be greater than or equal to output registers".to_string();
Self::new_from_span(message, span)
}
pub fn mismatched_output_types(left: &Type, right: &Type, span: Span) -> Self {
pub fn mismatched_output_types(left: &Type, right: &Type, span: &Span) -> Self {
let message = format!(
"Mismatched types. Expected register output type `{}`, found type `{}`.",
left, right

View File

@ -16,9 +16,7 @@
use crate::errors::{AddressError, BooleanError, ConsoleError, ExpressionError, IntegerError, ValueError};
use leo_asg::Type;
use leo_ast::{Error as FormattedError, Span};
use std::path::Path;
use leo_ast::{FormattedError, LeoError, Span};
#[derive(Debug, Error)]
pub enum StatementError {
@ -44,48 +42,62 @@ pub enum StatementError {
ValueError(#[from] ValueError),
}
impl StatementError {
pub fn set_path(&mut self, path: &Path) {
impl LeoError for StatementError {
fn get_path(&self) -> Option<&str> {
match self {
StatementError::AddressError(error) => error.set_path(path),
StatementError::BooleanError(error) => error.set_path(path),
StatementError::Error(error) => error.set_path(path),
StatementError::ExpressionError(error) => error.set_path(path),
StatementError::IntegerError(error) => error.set_path(path),
StatementError::MacroError(error) => error.set_path(path),
StatementError::ValueError(error) => error.set_path(path),
StatementError::AddressError(error) => error.get_path(),
StatementError::BooleanError(error) => error.get_path(),
StatementError::Error(error) => error.get_path(),
StatementError::ExpressionError(error) => error.get_path(),
StatementError::IntegerError(error) => error.get_path(),
StatementError::MacroError(error) => error.get_path(),
StatementError::ValueError(error) => error.get_path(),
}
}
fn new_from_span(message: String, span: Span) -> Self {
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
StatementError::AddressError(error) => error.set_path(path, contents),
StatementError::BooleanError(error) => error.set_path(path, contents),
StatementError::Error(error) => error.set_path(path, contents),
StatementError::ExpressionError(error) => error.set_path(path, contents),
StatementError::IntegerError(error) => error.set_path(path, contents),
StatementError::MacroError(error) => error.set_path(path, contents),
StatementError::ValueError(error) => error.set_path(path, contents),
}
}
}
impl StatementError {
fn new_from_span(message: String, span: &Span) -> Self {
StatementError::Error(FormattedError::new_from_span(message, span))
}
pub fn arguments_type(expected: &Type, actual: &Type, span: Span) -> Self {
pub fn arguments_type(expected: &Type, actual: &Type, span: &Span) -> Self {
let message = format!("expected return argument type `{}`, found type `{}`", expected, actual);
Self::new_from_span(message, span)
}
pub fn array_assign_index(span: Span) -> Self {
pub fn array_assign_index(span: &Span) -> Self {
let message = "Cannot assign single index to array of values".to_string();
Self::new_from_span(message, span)
}
pub fn array_assign_interior_index(span: Span) -> Self {
pub fn array_assign_interior_index(span: &Span) -> Self {
let message = "Cannot assign single index to interior of array of values".to_string();
Self::new_from_span(message, span)
}
pub fn array_assign_range(span: Span) -> Self {
pub fn array_assign_range(span: &Span) -> Self {
let message = "Cannot assign range of array values to single value".to_string();
Self::new_from_span(message, span)
}
pub fn array_assign_index_bounds(index: usize, length: usize, span: Span) -> Self {
pub fn array_assign_index_bounds(index: usize, length: usize, span: &Span) -> Self {
let message = format!(
"Array assign index `{}` out of range for array of length `{}`",
index, length
@ -94,7 +106,7 @@ impl StatementError {
Self::new_from_span(message, span)
}
pub fn array_assign_range_order(start: usize, stop: usize, length: usize, span: Span) -> Self {
pub fn array_assign_range_order(start: usize, stop: usize, length: usize, span: &Span) -> Self {
let message = format!(
"Array assign range `{}`..`{}` out of range for array of length `{}`",
start, stop, length
@ -103,31 +115,31 @@ impl StatementError {
Self::new_from_span(message, span)
}
pub fn conditional_boolean(actual: String, span: Span) -> Self {
pub fn conditional_boolean(actual: String, span: &Span) -> Self {
let message = format!("If, else conditional must resolve to a boolean, found `{}`", actual);
Self::new_from_span(message, span)
}
pub fn immutable_assign(name: String, span: Span) -> Self {
pub fn immutable_assign(name: String, span: &Span) -> Self {
let message = format!("Cannot assign to immutable variable `{}`", name);
Self::new_from_span(message, span)
}
pub fn immutable_circuit_function(name: String, span: Span) -> Self {
pub fn immutable_circuit_function(name: String, span: &Span) -> Self {
let message = format!("Cannot mutate circuit function, `{}`", name);
Self::new_from_span(message, span)
}
pub fn immutable_circuit_variable(name: String, span: Span) -> Self {
pub fn immutable_circuit_variable(name: String, span: &Span) -> Self {
let message = format!("Circuit member variable `{}` is immutable", name);
Self::new_from_span(message, span)
}
pub fn indicator_calculation(name: String, span: Span) -> Self {
pub fn indicator_calculation(name: String, span: &Span) -> Self {
let message = format!(
"Constraint system failed to evaluate branch selection indicator `{}`",
name
@ -136,7 +148,7 @@ impl StatementError {
Self::new_from_span(message, span)
}
pub fn invalid_number_of_definitions(expected: usize, actual: usize, span: Span) -> Self {
pub fn invalid_number_of_definitions(expected: usize, actual: usize, span: &Span) -> Self {
let message = format!(
"Multiple definition statement expected {} return values, found {} values",
expected, actual
@ -145,7 +157,7 @@ impl StatementError {
Self::new_from_span(message, span)
}
pub fn invalid_number_of_returns(expected: usize, actual: usize, span: Span) -> Self {
pub fn invalid_number_of_returns(expected: usize, actual: usize, span: &Span) -> Self {
let message = format!(
"Function return statement expected {} return values, found {} values",
expected, actual
@ -154,20 +166,20 @@ impl StatementError {
Self::new_from_span(message, span)
}
pub fn multiple_definition(value: String, span: Span) -> Self {
pub fn multiple_definition(value: String, span: &Span) -> Self {
let message = format!("cannot assign multiple variables to a single value: {}", value,);
Self::new_from_span(message, span)
}
pub fn multiple_returns(span: Span) -> Self {
pub fn multiple_returns(span: &Span) -> Self {
let message = "This function returns multiple times and produces unreachable circuits with undefined behavior."
.to_string();
Self::new_from_span(message, span)
}
pub fn no_returns(expected: &Type, span: Span) -> Self {
pub fn no_returns(expected: &Type, span: &Span) -> Self {
let message = format!(
"function expected `{}` return type but no valid branches returned a result",
expected
@ -176,7 +188,7 @@ impl StatementError {
Self::new_from_span(message, span)
}
pub fn select_fail(first: String, second: String, span: Span) -> Self {
pub fn select_fail(first: String, second: String, span: &Span) -> Self {
let message = format!(
"Conditional select gadget failed to select between `{}` or `{}`",
first, second
@ -185,13 +197,13 @@ impl StatementError {
Self::new_from_span(message, span)
}
pub fn tuple_assign_index(span: Span) -> Self {
pub fn tuple_assign_index(span: &Span) -> Self {
let message = "Cannot assign single index to tuple of values".to_string();
Self::new_from_span(message, span)
}
pub fn tuple_assign_index_bounds(index: usize, length: usize, span: Span) -> Self {
pub fn tuple_assign_index_bounds(index: usize, length: usize, span: &Span) -> Self {
let message = format!(
"Tuple assign index `{}` out of range for tuple of length `{}`",
index, length
@ -200,31 +212,31 @@ impl StatementError {
Self::new_from_span(message, span)
}
pub fn tuple_type(type_: String, span: Span) -> Self {
pub fn tuple_type(type_: String, span: &Span) -> Self {
let message = format!("Expected tuple type, found type `{}`", type_);
Self::new_from_span(message, span)
}
pub fn unassigned(name: String, span: Span) -> Self {
let message = format!("Expected assignment of return values for expression `{}`", name);
pub fn unassigned(span: &Span) -> Self {
let message = "Expected assignment of return values for expression".to_string();
Self::new_from_span(message, span)
}
pub fn undefined_variable(name: String, span: Span) -> Self {
pub fn undefined_variable(name: String, span: &Span) -> Self {
let message = format!("Attempted to assign to unknown variable `{}`", name);
Self::new_from_span(message, span)
}
pub fn undefined_circuit(name: String, span: Span) -> Self {
pub fn undefined_circuit(name: String, span: &Span) -> Self {
let message = format!("Attempted to assign to unknown circuit `{}`", name);
Self::new_from_span(message, span)
}
pub fn undefined_circuit_variable(name: String, span: Span) -> Self {
pub fn undefined_circuit_variable(name: String, span: &Span) -> Self {
let message = format!("Attempted to assign to unknown circuit member variable `{}`", name);
Self::new_from_span(message, span)

View File

@ -14,10 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::{Error as FormattedError, Span};
use leo_ast::{FormattedError, LeoError, Span};
use snarkvm_errors::{gadgets::SynthesisError, objects::account::AccountError};
use std::path::Path;
#[derive(Debug, Error)]
pub enum AddressError {
@ -25,24 +24,32 @@ pub enum AddressError {
Error(#[from] FormattedError),
}
impl AddressError {
pub fn set_path(&mut self, path: &Path) {
impl LeoError for AddressError {
fn get_path(&self) -> Option<&str> {
match self {
AddressError::Error(error) => error.set_path(path),
AddressError::Error(error) => error.get_path(),
}
}
fn new_from_span(message: String, span: Span) -> Self {
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
AddressError::Error(error) => error.set_path(path, contents),
}
}
}
impl AddressError {
fn new_from_span(message: String, span: &Span) -> Self {
AddressError::Error(FormattedError::new_from_span(message, span))
}
pub fn account_error(error: AccountError, span: Span) -> Self {
pub fn account_error(error: AccountError, span: &Span) -> Self {
let message = format!("account creation failed due to `{}`", error);
Self::new_from_span(message, span)
}
pub fn cannot_enforce(operation: String, error: SynthesisError, span: Span) -> Self {
pub fn cannot_enforce(operation: String, error: SynthesisError, span: &Span) -> Self {
let message = format!(
"the address operation `{:?}` failed due to the synthesis error `{}`",
operation, error,
@ -51,19 +58,19 @@ impl AddressError {
Self::new_from_span(message, span)
}
pub fn cannot_evaluate(operation: String, span: Span) -> Self {
pub fn cannot_evaluate(operation: String, span: &Span) -> Self {
let message = format!("no implementation found for `{}`", operation);
Self::new_from_span(message, span)
}
pub fn invalid_address(actual: String, span: Span) -> Self {
pub fn invalid_address(actual: String, span: &Span) -> Self {
let message = format!("expected address input type, found `{}`", actual);
Self::new_from_span(message, span)
}
pub fn missing_address(span: Span) -> Self {
pub fn missing_address(span: &Span) -> Self {
let message = "expected address input not found".to_string();
Self::new_from_span(message, span)

View File

@ -14,10 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::{Error as FormattedError, Span};
use leo_ast::{FormattedError, LeoError, Span};
use snarkvm_errors::gadgets::SynthesisError;
use std::path::Path;
#[derive(Debug, Error)]
pub enum BooleanError {
@ -25,18 +24,26 @@ pub enum BooleanError {
Error(#[from] FormattedError),
}
impl BooleanError {
pub fn set_path(&mut self, path: &Path) {
impl LeoError for BooleanError {
fn get_path(&self) -> Option<&str> {
match self {
BooleanError::Error(error) => error.set_path(path),
BooleanError::Error(error) => error.get_path(),
}
}
fn new_from_span(message: String, span: Span) -> Self {
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
BooleanError::Error(error) => error.set_path(path, contents),
}
}
}
impl BooleanError {
fn new_from_span(message: String, span: &Span) -> Self {
BooleanError::Error(FormattedError::new_from_span(message, span))
}
pub fn cannot_enforce(operation: String, error: SynthesisError, span: Span) -> Self {
pub fn cannot_enforce(operation: String, error: SynthesisError, span: &Span) -> Self {
let message = format!(
"the boolean operation `{}` failed due to the synthesis error `{:?}`",
operation, error,
@ -45,19 +52,19 @@ impl BooleanError {
Self::new_from_span(message, span)
}
pub fn cannot_evaluate(operation: String, span: Span) -> Self {
pub fn cannot_evaluate(operation: String, span: &Span) -> Self {
let message = format!("no implementation found for `{}`", operation);
Self::new_from_span(message, span)
}
pub fn invalid_boolean(actual: String, span: Span) -> Self {
pub fn invalid_boolean(actual: String, span: &Span) -> Self {
let message = format!("expected boolean input type, found `{}`", actual);
Self::new_from_span(message, span)
}
pub fn missing_boolean(expected: String, span: Span) -> Self {
pub fn missing_boolean(expected: String, span: &Span) -> Self {
let message = format!("expected boolean input `{}` not found", expected);
Self::new_from_span(message, span)

View File

@ -14,10 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::{Error as FormattedError, Span};
use leo_ast::{FormattedError, LeoError, Span};
use snarkvm_errors::gadgets::SynthesisError;
use std::path::Path;
#[derive(Debug, Error)]
pub enum FieldError {
@ -25,24 +24,32 @@ pub enum FieldError {
Error(#[from] FormattedError),
}
impl FieldError {
pub fn set_path(&mut self, path: &Path) {
impl LeoError for FieldError {
fn get_path(&self) -> Option<&str> {
match self {
FieldError::Error(error) => error.set_path(path),
FieldError::Error(error) => error.get_path(),
}
}
fn new_from_span(message: String, span: Span) -> Self {
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
FieldError::Error(error) => error.set_path(path, contents),
}
}
}
impl FieldError {
fn new_from_span(message: String, span: &Span) -> Self {
FieldError::Error(FormattedError::new_from_span(message, span))
}
pub fn negate_operation(error: SynthesisError, span: Span) -> Self {
pub fn negate_operation(error: SynthesisError, span: &Span) -> Self {
let message = format!("field negation failed due to synthesis error `{:?}`", error,);
Self::new_from_span(message, span)
}
pub fn binary_operation(operation: String, error: SynthesisError, span: Span) -> Self {
pub fn binary_operation(operation: String, error: SynthesisError, span: &Span) -> Self {
let message = format!(
"the field binary operation `{}` failed due to synthesis error `{:?}`",
operation, error,
@ -51,25 +58,25 @@ impl FieldError {
Self::new_from_span(message, span)
}
pub fn invalid_field(actual: String, span: Span) -> Self {
pub fn invalid_field(actual: String, span: &Span) -> Self {
let message = format!("expected field element input type, found `{}`", actual);
Self::new_from_span(message, span)
}
pub fn missing_field(expected: String, span: Span) -> Self {
pub fn missing_field(expected: String, span: &Span) -> Self {
let message = format!("expected field input `{}` not found", expected);
Self::new_from_span(message, span)
}
pub fn no_inverse(field: String, span: Span) -> Self {
pub fn no_inverse(field: String, span: &Span) -> Self {
let message = format!("no multiplicative inverse found for field `{}`", field);
Self::new_from_span(message, span)
}
pub fn synthesis_error(error: SynthesisError, span: Span) -> Self {
pub fn synthesis_error(error: SynthesisError, span: &Span) -> Self {
let message = format!("compilation failed due to field synthesis error `{:?}`", error);
Self::new_from_span(message, span)

View File

@ -14,10 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::{Error as FormattedError, Span};
use leo_ast::{FormattedError, LeoError, Span};
use snarkvm_errors::gadgets::SynthesisError;
use std::path::Path;
#[derive(Debug, Error)]
pub enum GroupError {
@ -25,24 +24,32 @@ pub enum GroupError {
Error(#[from] FormattedError),
}
impl GroupError {
pub fn set_path(&mut self, path: &Path) {
impl LeoError for GroupError {
fn get_path(&self) -> Option<&str> {
match self {
GroupError::Error(error) => error.set_path(path),
GroupError::Error(error) => error.get_path(),
}
}
fn new_from_span(message: String, span: Span) -> Self {
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
GroupError::Error(error) => error.set_path(path, contents),
}
}
}
impl GroupError {
fn new_from_span(message: String, span: &Span) -> Self {
GroupError::Error(FormattedError::new_from_span(message, span))
}
pub fn negate_operation(error: SynthesisError, span: Span) -> Self {
pub fn negate_operation(error: SynthesisError, span: &Span) -> Self {
let message = format!("group negation failed due to the synthesis error `{:?}`", error,);
Self::new_from_span(message, span)
}
pub fn binary_operation(operation: String, error: SynthesisError, span: Span) -> Self {
pub fn binary_operation(operation: String, error: SynthesisError, span: &Span) -> Self {
let message = format!(
"the group binary operation `{}` failed due to the synthesis error `{:?}`",
operation, error,
@ -51,55 +58,55 @@ impl GroupError {
Self::new_from_span(message, span)
}
pub fn invalid_group(actual: String, span: Span) -> Self {
pub fn invalid_group(actual: String, span: &Span) -> Self {
let message = format!("expected group affine point input type, found `{}`", actual);
Self::new_from_span(message, span)
}
pub fn missing_group(expected: String, span: Span) -> Self {
pub fn missing_group(expected: String, span: &Span) -> Self {
let message = format!("expected group input `{}` not found", expected);
Self::new_from_span(message, span)
}
pub fn synthesis_error(error: SynthesisError, span: Span) -> Self {
pub fn synthesis_error(error: SynthesisError, span: &Span) -> Self {
let message = format!("compilation failed due to group synthesis error `{:?}`", error);
Self::new_from_span(message, span)
}
pub fn x_invalid(x: String, span: Span) -> Self {
pub fn x_invalid(x: String, span: &Span) -> Self {
let message = format!("invalid x coordinate `{}`", x);
Self::new_from_span(message, span)
}
pub fn y_invalid(y: String, span: Span) -> Self {
pub fn y_invalid(y: String, span: &Span) -> Self {
let message = format!("invalid y coordinate `{}`", y);
Self::new_from_span(message, span)
}
pub fn not_on_curve(element: String, span: Span) -> Self {
pub fn not_on_curve(element: String, span: &Span) -> Self {
let message = format!("group element `{}` is not on the supported curve", element);
Self::new_from_span(message, span)
}
pub fn x_recover(span: Span) -> Self {
pub fn x_recover(span: &Span) -> Self {
let message = "could not recover group element from x coordinate".to_string();
Self::new_from_span(message, span)
}
pub fn y_recover(span: Span) -> Self {
pub fn y_recover(span: &Span) -> Self {
let message = "could not recover group element from y coordinate".to_string();
Self::new_from_span(message, span)
}
pub fn n_group(number: String, span: Span) -> Self {
pub fn n_group(number: String, span: &Span) -> Self {
let message = format!("cannot multiply group generator by \"{}\"", number);
Self::new_from_span(message, span)

View File

@ -14,11 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::{error::Error as FormattedError, IntegerType, Span, Type};
use leo_gadgets::errors::SignedIntegerError;
use leo_ast::{FormattedError, IntegerType, LeoError, Span, Type};
use leo_gadgets::errors::SignedIntegerError;
use snarkvm_errors::gadgets::SynthesisError;
use std::path::Path;
#[derive(Debug, Error)]
pub enum IntegerError {
@ -26,18 +25,26 @@ pub enum IntegerError {
Error(#[from] FormattedError),
}
impl IntegerError {
pub fn set_path(&mut self, path: &Path) {
impl LeoError for IntegerError {
fn get_path(&self) -> Option<&str> {
match self {
IntegerError::Error(error) => error.set_path(path),
IntegerError::Error(error) => error.get_path(),
}
}
fn new_from_span(message: String, span: Span) -> Self {
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
IntegerError::Error(error) => error.set_path(path, contents),
}
}
}
impl IntegerError {
fn new_from_span(message: String, span: &Span) -> Self {
IntegerError::Error(FormattedError::new_from_span(message, span))
}
pub fn cannot_enforce(operation: String, error: SynthesisError, span: Span) -> Self {
pub fn cannot_enforce(operation: String, error: SynthesisError, span: &Span) -> Self {
let message = format!(
"the integer operation `{}` failed due to the synthesis error `{:?}`",
operation, error,
@ -46,19 +53,19 @@ impl IntegerError {
Self::new_from_span(message, span)
}
pub fn signed(error: SignedIntegerError, span: Span) -> Self {
pub fn signed(error: SignedIntegerError, span: &Span) -> Self {
let message = format!("integer operation failed due to the signed integer error `{:?}`", error,);
Self::new_from_span(message, span)
}
pub fn synthesis(error: SynthesisError, span: Span) -> Self {
pub fn synthesis(error: SynthesisError, span: &Span) -> Self {
let message = format!("integer operation failed due to the synthesis error `{}`", error,);
Self::new_from_span(message, span)
}
pub fn signed_error(operation: String, error: SignedIntegerError, span: Span) -> Self {
pub fn signed_error(operation: String, error: SignedIntegerError, span: &Span) -> Self {
let message = format!(
"the integer operation `{}` failed due to the signed integer error `{:?}`",
operation, error
@ -67,13 +74,13 @@ impl IntegerError {
Self::new_from_span(message, span)
}
pub fn negate_operation(span: Span) -> Self {
pub fn negate_operation(span: &Span) -> Self {
let message = "integer negation can only be enforced on signed integers".to_string();
Self::new_from_span(message, span)
}
pub fn binary_operation(operation: String, span: Span) -> Self {
pub fn binary_operation(operation: String, span: &Span) -> Self {
let message = format!(
"the integer binary operation `{}` can only be enforced on integers of the same type",
operation
@ -82,7 +89,7 @@ impl IntegerError {
Self::new_from_span(message, span)
}
pub fn invalid_index(span: Span) -> Self {
pub fn invalid_index(span: &Span) -> Self {
let message =
"index must be a constant value unsigned integer. allocated indices produce a circuit of unknown size"
.to_string();
@ -90,27 +97,33 @@ impl IntegerError {
Self::new_from_span(message, span)
}
pub fn invalid_integer(actual: String, span: Span) -> Self {
pub fn invalid_integer(actual: String, span: &Span) -> Self {
let message = format!("failed to parse `{}` as expected integer type", actual);
Self::new_from_span(message, span)
}
pub fn invalid_integer_type(expected: &IntegerType, actual: &IntegerType, span: Span) -> Self {
pub fn invalid_integer_type(expected: &IntegerType, actual: &IntegerType, span: &Span) -> Self {
let message = format!("expected integer type {} found integer type {}", expected, actual);
Self::new_from_span(message, span)
}
pub fn invalid_type(actual: &Type, span: Span) -> Self {
pub fn invalid_type(actual: &Type, span: &Span) -> Self {
let message = format!("expected type {}, found type IntegerType", actual);
Self::new_from_span(message, span)
}
pub fn missing_integer(expected: String, span: Span) -> Self {
pub fn missing_integer(expected: String, span: &Span) -> Self {
let message = format!("expected integer input `{}` not found", expected);
Self::new_from_span(message, span)
}
pub fn cannot_evaluate(operation: String, span: &Span) -> Self {
let message = format!("no implementation found for `{}`", operation);
Self::new_from_span(message, span)
}
}

View File

@ -15,9 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::errors::{AddressError, BooleanError, FieldError, GroupError, IntegerError};
use leo_ast::{Error as FormattedError, Span};
use std::path::Path;
use leo_ast::{FormattedError, LeoError, Span};
#[derive(Debug, Error)]
pub enum ValueError {
@ -40,29 +38,42 @@ pub enum ValueError {
IntegerError(#[from] IntegerError),
}
impl ValueError {
pub fn set_path(&mut self, path: &Path) {
impl LeoError for ValueError {
fn get_path(&self) -> Option<&str> {
match self {
ValueError::AddressError(error) => error.set_path(path),
ValueError::BooleanError(error) => error.set_path(path),
ValueError::Error(error) => error.set_path(path),
ValueError::FieldError(error) => error.set_path(path),
ValueError::GroupError(error) => error.set_path(path),
ValueError::IntegerError(error) => error.set_path(path),
ValueError::AddressError(error) => error.get_path(),
ValueError::BooleanError(error) => error.get_path(),
ValueError::Error(error) => error.get_path(),
ValueError::FieldError(error) => error.get_path(),
ValueError::GroupError(error) => error.get_path(),
ValueError::IntegerError(error) => error.get_path(),
}
}
fn new_from_span(message: String, span: Span) -> Self {
fn set_path(&mut self, path: &str, contents: &[String]) {
match self {
ValueError::AddressError(error) => error.set_path(path, contents),
ValueError::BooleanError(error) => error.set_path(path, contents),
ValueError::Error(error) => error.set_path(path, contents),
ValueError::FieldError(error) => error.set_path(path, contents),
ValueError::GroupError(error) => error.set_path(path, contents),
ValueError::IntegerError(error) => error.set_path(path, contents),
}
}
}
impl ValueError {
fn new_from_span(message: String, span: &Span) -> Self {
ValueError::Error(FormattedError::new_from_span(message, span))
}
pub fn implicit(value: String, span: Span) -> Self {
pub fn implicit(value: String, span: &Span) -> Self {
let message = format!("explicit type needed for `{}`", value);
Self::new_from_span(message, span)
}
pub fn implicit_group(span: Span) -> Self {
pub fn implicit_group(span: &Span) -> Self {
let message = "group coordinates should be in (x, y)group format".to_string();
Self::new_from_span(message, span)

View File

@ -39,7 +39,7 @@ pub fn enforce_add<'a, F: PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
}
(val_1, val_2) => Err(ExpressionError::incompatible_types(
format!("{} + {}", val_1, val_2),
span.to_owned(),
span,
)),
}
}

View File

@ -14,24 +14,19 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, console::FormattedString, SpanDef};
//! Enforces a logical `!` operator in a resolved Leo program.
use pest::Span;
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt;
use crate::{errors::IntegerError, value::ConstrainedValue, GroupType};
use leo_asg::Span;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::console_debug))]
pub struct ConsoleDebug<'ast> {
pub string: FormattedString<'ast>,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
}
use snarkvm_models::curves::PrimeField;
impl<'ast> fmt::Display for ConsoleDebug<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "debug({})", self.string)
pub fn evaluate_bit_not<'a, F: PrimeField, G: GroupType<F>>(
value: ConstrainedValue<'a, F, G>,
span: &Span,
) -> Result<ConstrainedValue<'a, F, G>, IntegerError> {
match value {
// ConstrainedValue::Integer(i) => Ok(ConstrainedValue::Integer(i.not())),
value => Err(IntegerError::cannot_evaluate(format!("~{}", value), span)),
}
}

View File

@ -36,7 +36,7 @@ pub fn enforce_div<'a, F: PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
}
(val_1, val_2) => Err(ExpressionError::incompatible_types(
format!("{} / {}", val_1, val_2,),
span.to_owned(),
span,
)),
}
}

View File

@ -33,3 +33,6 @@ pub use self::div::*;
pub mod pow;
pub use self::pow::*;
pub mod bit_not;
pub use self::bit_not::*;

Some files were not shown because too many files have changed in this diff Show More