mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-23 10:12:21 +03:00
parser rewrite
This commit is contained in:
parent
2622a4be63
commit
d400764e00
37
Cargo.lock
generated
37
Cargo.lock
generated
@ -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"
|
||||
|
@ -30,11 +30,11 @@ members = [
|
||||
"ast",
|
||||
"compiler",
|
||||
"gadgets",
|
||||
"grammar",
|
||||
"imports",
|
||||
"input",
|
||||
"linter",
|
||||
"package",
|
||||
"parser",
|
||||
"state",
|
||||
"synthesizer",
|
||||
]
|
||||
|
@ -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"
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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
109
asg/src/expression/cast.rs
Normal 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(),
|
||||
}
|
||||
}
|
||||
}
|
@ -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(),
|
||||
|
@ -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()),
|
||||
|
@ -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),
|
||||
|
@ -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>> {
|
||||
|
@ -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>;
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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)?;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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(),
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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> {
|
||||
|
@ -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 = [ ]
|
||||
|
@ -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>,
|
||||
}
|
||||
|
@ -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)?;
|
||||
|
@ -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>,
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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 {
|
||||
|
@ -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")
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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(),
|
||||
};
|
||||
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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, ", ")?;
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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 => "~",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -19,6 +19,3 @@ pub use function::*;
|
||||
|
||||
pub mod input;
|
||||
pub use input::*;
|
||||
|
||||
pub mod test_function;
|
||||
pub use test_function::*;
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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() {
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)?;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)?;
|
||||
|
@ -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
|
||||
|
@ -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, "{{")?;
|
||||
|
@ -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)?;
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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, "{{}}")
|
||||
|
@ -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("")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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" ]
|
||||
|
@ -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();
|
||||
|
@ -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(())
|
||||
|
@ -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("{}", ¶meter_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(""))
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
@ -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,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user