Merge pull request #426 from AleoHQ/feature/imports

Imports module. PR #411 part 1/3
This commit is contained in:
Collin Chin 2020-11-12 12:04:29 -08:00 committed by GitHub
commit b81c7ec25d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
395 changed files with 5205 additions and 4283 deletions

591
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -30,25 +30,32 @@ members = [
"compiler", "compiler",
"core", "core",
"gadgets", "gadgets",
"grammar",
"imports",
"input", "input",
"linter", "linter",
"package", "package",
"typed", "state",
"state" # "symbol-table",
# "type-inference",
] ]
[dependencies.leo-ast]
path = "./ast"
version = "1.0.4"
[dependencies.leo-compiler] [dependencies.leo-compiler]
path = "./compiler" path = "./compiler"
version = "1.0.4" version = "1.0.4"
[dependencies.leo-core]
path = "./core"
version = "1.0.2"
[dependencies.leo-gadgets] [dependencies.leo-gadgets]
path = "./gadgets" path = "./gadgets"
version = "1.0.4" version = "1.0.4"
[dependencies.leo-imports]
path = "./imports"
version = "1.0.4"
[dependencies.leo-input] [dependencies.leo-input]
path = "./input" path = "./input"
version = "1.0.4" version = "1.0.4"

View File

@ -2,7 +2,7 @@
name = "leo-ast" name = "leo-ast"
version = "1.0.4" version = "1.0.4"
authors = [ "The Aleo Team <hello@aleo.org>" ] authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "AST of the Leo programming language" description = "Core AST of the Leo programming language"
homepage = "https://aleo.org" homepage = "https://aleo.org"
repository = "https://github.com/AleoHQ/leo" repository = "https://github.com/AleoHQ/leo"
keywords = [ keywords = [
@ -22,41 +22,38 @@ name = "leo_ast"
path = "src/main.rs" path = "src/main.rs"
[[bench]] [[bench]]
name = "ast" name = "leo_ast"
path = "benches/ast.rs" path = "benches/leo_ast.rs"
harness = false harness = false
[dependencies.from-pest] [dependencies.leo-grammar]
version = "0.3.1" path = "../grammar"
version = "1.0.4"
[dependencies.lazy_static] [dependencies.leo-input]
version = "1.3.0" path = "../input"
version = "1.0.4"
[dependencies.snarkos-errors]
version = "1.1.3"
default-features = false
[dependencies.snarkos-models]
version = "1.1.3"
default-features = false
[dependencies.pest] [dependencies.pest]
version = "2.0" version = "2.0"
[dependencies.pest-ast]
version = "0.3.3"
[dependencies.pest_derive]
version = "2.0"
[dependencies.serde] [dependencies.serde]
version = "1.0" version = "1.0"
features = [ "derive" ]
[dependencies.serde_json] [dependencies.serde_json]
version = "1.0" version = "1.0"
[dependencies.thiserror]
version = "1.0"
[dependencies.tracing]
version = "0.1"
[dev-dependencies.criterion] [dev-dependencies.criterion]
version = "0.3" version = "0.3"
[features] [features]
default = [ ] default = [ ]
ci_skip = [ ] ci_skip = [ "leo-grammar/ci_skip" ]

View File

@ -15,69 +15,69 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::LeoAst; use leo_ast::LeoAst;
use leo_typed::LeoTypedAst; use leo_grammar::Grammar;
use criterion::{criterion_group, criterion_main, Criterion}; use criterion::{criterion_group, criterion_main, Criterion};
use std::{path::Path, time::Duration}; use std::{path::Path, time::Duration};
fn leo_typed_ast<'ast>(ast: &LeoAst<'ast>) -> LeoTypedAst { fn leo_ast<'ast>(ast: &Grammar<'ast>) -> LeoAst {
LeoTypedAst::new("leo_typed_tree", &ast) LeoAst::new("leo_tree", &ast)
} }
fn bench_big_if_else(c: &mut Criterion) { fn bench_big_if_else(c: &mut Criterion) {
let filepath = Path::new("./big_if_else.leo").to_path_buf(); let filepath = Path::new("./big_if_else.leo").to_path_buf();
let program_string = include_str!("./big_if_else.leo"); let program_string = include_str!("./big_if_else.leo");
let ast = LeoAst::new(&filepath, program_string).unwrap(); let ast = Grammar::new(&filepath, program_string).unwrap();
c.bench_function("LeoTypedAst::big_if_else", |b| b.iter(|| leo_typed_ast(&ast))); c.bench_function("LeoAst::big_if_else", |b| b.iter(|| leo_ast(&ast)));
} }
fn bench_big_ternary(c: &mut Criterion) { fn bench_big_ternary(c: &mut Criterion) {
let filepath = Path::new("./big_ternary.leo").to_path_buf(); let filepath = Path::new("./big_ternary.leo").to_path_buf();
let program_string = include_str!("./big_ternary.leo"); let program_string = include_str!("./big_ternary.leo");
let ast = LeoAst::new(&filepath, program_string).unwrap(); let ast = Grammar::new(&filepath, program_string).unwrap();
c.bench_function("LeoTypedAst::big_ternary", |b| b.iter(|| leo_typed_ast(&ast))); c.bench_function("LeoAst::big_ternary", |b| b.iter(|| leo_ast(&ast)));
} }
fn bench_big_circuit(c: &mut Criterion) { fn bench_big_circuit(c: &mut Criterion) {
let filepath = Path::new("./big_circuit.leo").to_path_buf(); let filepath = Path::new("./big_circuit.leo").to_path_buf();
let program_string = include_str!("./big_circuit.leo"); let program_string = include_str!("./big_circuit.leo");
let ast = LeoAst::new(&filepath, program_string).unwrap(); let ast = Grammar::new(&filepath, program_string).unwrap();
c.bench_function("LeoTypedAst::big_circuit", |b| b.iter(|| leo_typed_ast(&ast))); c.bench_function("LeoAst::big_circuit", |b| b.iter(|| leo_ast(&ast)));
} }
fn bench_long_expr(c: &mut Criterion) { fn bench_long_expr(c: &mut Criterion) {
let filepath = Path::new("./long_expr.leo").to_path_buf(); let filepath = Path::new("./long_expr.leo").to_path_buf();
let program_string = include_str!("./long_expr.leo"); let program_string = include_str!("./long_expr.leo");
let ast = LeoAst::new(&filepath, program_string).unwrap(); let ast = Grammar::new(&filepath, program_string).unwrap();
c.bench_function("LeoTypedAst::long_expr", |b| b.iter(|| leo_typed_ast(&ast))); c.bench_function("LeoAst::long_expr", |b| b.iter(|| leo_ast(&ast)));
} }
fn bench_long_array(c: &mut Criterion) { fn bench_long_array(c: &mut Criterion) {
let filepath = Path::new("./long_array.leo").to_path_buf(); let filepath = Path::new("./long_array.leo").to_path_buf();
let program_string = include_str!("./long_array.leo"); let program_string = include_str!("./long_array.leo");
let ast = LeoAst::new(&filepath, program_string).unwrap(); let ast = Grammar::new(&filepath, program_string).unwrap();
c.bench_function("LeoTypedAst::long_array", |b| b.iter(|| leo_typed_ast(&ast))); c.bench_function("LeoAst::long_array", |b| b.iter(|| leo_ast(&ast)));
} }
fn bench_many_foos(c: &mut Criterion) { fn bench_many_foos(c: &mut Criterion) {
let filepath = Path::new("./many_foos.leo").to_path_buf(); let filepath = Path::new("./many_foos.leo").to_path_buf();
let program_string = include_str!("./many_foos.leo"); let program_string = include_str!("./many_foos.leo");
let ast = LeoAst::new(&filepath, program_string).unwrap(); let ast = Grammar::new(&filepath, program_string).unwrap();
c.bench_function("LeoTypedAst::many_foos", |b| b.iter(|| leo_typed_ast(&ast))); c.bench_function("LeoAst::many_foos", |b| b.iter(|| leo_ast(&ast)));
} }
fn bench_many_assigns(c: &mut Criterion) { fn bench_many_assigns(c: &mut Criterion) {
let filepath = Path::new("./many_assigns.leo").to_path_buf(); let filepath = Path::new("./many_assigns.leo").to_path_buf();
let program_string = include_str!("./many_assigns.leo"); let program_string = include_str!("./many_assigns.leo");
let ast = LeoAst::new(&filepath, program_string).unwrap(); let ast = Grammar::new(&filepath, program_string).unwrap();
c.bench_function("LeoTypedAst::many_assigns", |b| b.iter(|| leo_typed_ast(&ast))); c.bench_function("LeoAst::many_assigns", |b| b.iter(|| leo_ast(&ast)));
} }
criterion_group!( criterion_group!(

View File

@ -14,8 +14,8 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Circuit, Function, Identifier, Import, InputVariable, TestFunction}; use crate::{Circuit, Function, FunctionInput, Identifier, ImportStatement, TestFunction};
use leo_ast::{ use leo_grammar::{
annotations::{Annotation, AnnotationArguments, AnnotationName}, annotations::{Annotation, AnnotationArguments, AnnotationName},
definitions::{AnnotatedDefinition, Definition}, definitions::{AnnotatedDefinition, Definition},
}; };
@ -24,11 +24,11 @@ use std::collections::HashMap;
pub fn load_annotation( pub fn load_annotation(
annotated_definition: AnnotatedDefinition, annotated_definition: AnnotatedDefinition,
_imports: &mut Vec<Import>, _imports: &mut Vec<ImportStatement>,
_circuits: &mut HashMap<Identifier, Circuit>, _circuits: &mut HashMap<Identifier, Circuit>,
_functions: &mut HashMap<Identifier, Function>, _functions: &mut HashMap<Identifier, Function>,
tests: &mut HashMap<Identifier, TestFunction>, tests: &mut HashMap<Identifier, TestFunction>,
_expected: &mut Vec<InputVariable>, _expected: &mut Vec<FunctionInput>,
) { ) {
let ast_annotation = annotated_definition.annotation; let ast_annotation = annotated_definition.annotation;
let ast_definition = *annotated_definition.definition; let ast_definition = *annotated_definition.definition;

View File

@ -14,18 +14,39 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, circuits::CircuitMember, common::Identifier, SpanDef}; use crate::{CircuitMember, Identifier};
use leo_grammar::circuits::Circuit as GrammarCircuit;
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest; use std::fmt;
use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::circuit))] pub struct Circuit {
pub struct Circuit<'ast> { pub circuit_name: Identifier,
pub identifier: Identifier<'ast>, pub members: Vec<CircuitMember>,
pub members: Vec<CircuitMember<'ast>>, }
#[pest_ast(outer())]
#[serde(with = "SpanDef")] impl<'ast> From<GrammarCircuit<'ast>> for Circuit {
pub span: Span<'ast>, 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)?;
for field in self.members.iter() {
writeln!(f, " {}", field)?;
}
write!(f, "}}")
}
}
impl fmt::Debug for Circuit {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
} }

View File

@ -14,17 +14,67 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use crate::{Function, Identifier, Type};
ast::Rule, use leo_grammar::circuits::{
circuits::{CircuitFunction, CircuitVariableDefinition}, CircuitFunction as GrammarCircuitFunction,
CircuitMember as GrammarCircuitMember,
CircuitVariableDefinition as GrammarCircuitVariableDefinition,
}; };
use pest_ast::FromPest; use serde::{Deserialize, Serialize};
use serde::Serialize; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::circuit_member))] pub enum CircuitMember {
pub enum CircuitMember<'ast> { // (is_mutable, variable_name, variable_type)
CircuitVariableDefinition(CircuitVariableDefinition<'ast>), CircuitVariable(bool, Identifier, Type),
CircuitFunction(CircuitFunction<'ast>), // (is_static, function)
CircuitFunction(bool, Function),
}
impl<'ast> From<GrammarCircuitVariableDefinition<'ast>> for CircuitMember {
fn from(circuit_value: GrammarCircuitVariableDefinition<'ast>) -> Self {
CircuitMember::CircuitVariable(
circuit_value.mutable.is_some(),
Identifier::from(circuit_value.identifier),
Type::from(circuit_value.type_),
)
}
}
impl<'ast> From<GrammarCircuitFunction<'ast>> for CircuitMember {
fn from(circuit_function: GrammarCircuitFunction<'ast>) -> Self {
CircuitMember::CircuitFunction(
circuit_function._static.is_some(),
Function::from(circuit_function.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 {
CircuitMember::CircuitVariable(ref mutable, ref identifier, ref type_) => {
if *mutable {
write!(f, "mut ")?;
}
write!(f, "{}: {}", identifier, type_)
}
CircuitMember::CircuitFunction(ref static_, ref function) => {
if *static_ {
write!(f, "static ")?;
}
write!(f, "{}", function)
}
}
}
} }

View File

@ -14,24 +14,22 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use crate::{Expression, Identifier};
ast::Rule, use leo_grammar::circuits::CircuitVariable;
common::{Identifier, Mutable},
types::Type,
SpanDef,
};
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest;
use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::circuit_variable_definition))] pub struct CircuitVariableDefinition {
pub struct CircuitVariableDefinition<'ast> { pub identifier: Identifier,
pub mutable: Option<Mutable>, pub expression: Expression,
pub identifier: Identifier<'ast>, }
pub type_: Type<'ast>,
#[pest_ast(outer())] impl<'ast> From<CircuitVariable<'ast>> for CircuitVariableDefinition {
#[serde(with = "SpanDef")] fn from(member: CircuitVariable<'ast>) -> Self {
pub span: Span<'ast>, CircuitVariableDefinition {
identifier: Identifier::from(member.identifier),
expression: Expression::from(member.expression),
}
}
} }

View File

@ -17,14 +17,8 @@
pub mod circuit; pub mod circuit;
pub use circuit::*; pub use circuit::*;
pub mod circuit_variable;
pub use circuit_variable::*;
pub mod circuit_variable_definition; pub mod circuit_variable_definition;
pub use circuit_variable_definition::*; pub use circuit_variable_definition::*;
pub mod circuit_function;
pub use circuit_function::*;
pub mod circuit_member; pub mod circuit_member;
pub use circuit_member::*; pub use circuit_member::*;

View File

@ -0,0 +1,168 @@
// Copyright (C) 2019-2020 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::{PositiveNumber, Span};
use leo_grammar::types::ArrayDimensions as GrammarArrayDimensions;
use leo_input::types::ArrayDimensions as InputArrayDimensions;
use serde::{Deserialize, Serialize};
use std::{
fmt,
hash::{Hash, Hasher},
};
/// A vector of positive numbers that represent array dimensions.
/// Can be used in an array [`Type`] or an array initializer [`Expression`].
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct ArrayDimensions(pub Vec<PositiveNumber>);
impl ArrayDimensions {
///
/// Creates a new `PositiveNumber` from the given `usize` and `Span`.
/// Appends the new `PositiveNumber` to the array dimensions.
///
pub fn push_usize(&mut self, number: usize, span: Span) {
let positive_number = PositiveNumber {
value: number.to_string(),
span,
};
self.0.push(positive_number)
}
///
/// Appends a vector of array dimensions to the self array dimensions.
///
pub fn append(&mut self, other: &mut ArrayDimensions) {
self.0.append(&mut other.0)
}
///
/// Returns the array dimensions as strings.
///
pub fn to_strings(&self) -> Vec<String> {
self.0.iter().map(|number| number.to_string()).collect()
}
///
/// Returns `true` if the all array dimensions have been removed.
///
/// This method is called after repeated calls to `remove_first`.
///
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
///
/// Returns `true` if there is an array dimension equal to zero.
///
pub fn is_zero(&self) -> bool {
self.0.iter().find(|number| number.is_zero()).is_some()
}
///
/// Returns the first dimension of the array.
///
pub fn first(&self) -> Option<&PositiveNumber> {
self.0.first()
}
///
/// Attempts to remove the first dimension from the array.
///
/// If the first dimension exists, then remove and return `Some(PositiveNumber)`.
/// If the first dimension does not exist, then return `None`.
///
pub fn remove_first(&mut self) -> Option<PositiveNumber> {
// If there are no dimensions in the array, then return None.
self.0.first()?;
// Remove the first dimension.
let removed = self.0.remove(0);
// Return the first dimension.
Some(removed)
}
///
/// Attempts to remove the last dimension from the array.
///
/// If the last dimension exists, then remove and return `Some(PositiveNumber)`.
/// If the last dimension does not exist, then return `None`.
///
pub fn remove_last(&mut self) -> Option<PositiveNumber> {
self.0.pop()
}
}
/// 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 {
Self(match dimensions {
InputArrayDimensions::Single(single) => vec![PositiveNumber::from(single.number)],
InputArrayDimensions::Multiple(multiple) => {
multiple.numbers.into_iter().map(PositiveNumber::from).collect()
}
})
}
}
impl fmt::Display for ArrayDimensions {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.0.len() == 1 {
// Write dimensions without parenthesis.
write!(f, "{}", self.0[0])
} else {
// Write dimensions with parenthesis.
let dimensions = self.0.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(", ");
write!(f, "({})", dimensions)
}
}
}
/// Compares two array dimensions and ignores `Span`s.
impl PartialEq for ArrayDimensions {
fn eq(&self, other: &Self) -> bool {
// If the number of dimensions differs return false.
if self.0.len() != other.0.len() {
return false;
}
// Compare all dimensions and ignore `Span`s.
self.0.eq(&other.0)
}
}
impl Eq for ArrayDimensions {}
impl Hash for ArrayDimensions {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state)
}
}

View File

@ -14,32 +14,72 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{access::AssigneeAccess, ast::Rule, common::SelfKeywordOrIdentifier, SpanDef}; use crate::{Identifier, PositiveNumber, RangeOrExpression, Span};
use leo_grammar::{access::AssigneeAccess as GrammarAssigneeAccess, common::Assignee as GrammarAssignee};
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::assignee))] pub enum AssigneeAccess {
pub struct Assignee<'ast> { Array(RangeOrExpression),
pub name: SelfKeywordOrIdentifier<'ast>, Tuple(PositiveNumber, Span),
pub accesses: Vec<AssigneeAccess<'ast>>, Member(Identifier),
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
} }
impl<'ast> fmt::Display for Assignee<'ast> { impl<'ast> From<GrammarAssigneeAccess<'ast>> for AssigneeAccess {
fn from(access: GrammarAssigneeAccess<'ast>) -> Self {
match access {
GrammarAssigneeAccess::Array(array) => AssigneeAccess::Array(RangeOrExpression::from(array.expression)),
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 {
pub identifier: Identifier,
pub accesses: Vec<AssigneeAccess>,
pub span: Span,
}
impl Assignee {
/// Returns the name of the variable being assigned to
pub fn identifier(&self) -> &Identifier {
&self.identifier
}
}
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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name)?; write!(f, "{}", self.identifier)?;
for (i, access) in self.accesses.iter().enumerate() {
write!(f, "{}", access)?; for access in &self.accesses {
if i < self.accesses.len() - 1 { match access {
write!(f, ", ")?; AssigneeAccess::Array(expression) => write!(f, "[{}]", expression)?,
AssigneeAccess::Tuple(index, _span) => write!(f, ".{}", index)?,
AssigneeAccess::Member(member) => write!(f, ".{}", member)?,
} }
} }
write!(f, "") write!(f, "")
} }
} }

View File

@ -14,22 +14,31 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::ast::Rule; use leo_grammar::common::Declare as GrammarDeclare;
use pest_ast::FromPest; use serde::{Deserialize, Serialize};
use serde::Serialize; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::declare))]
pub enum Declare { pub enum Declare {
Const(Const), Const,
Let(Let), Let,
} }
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] impl<'ast> From<GrammarDeclare> for Declare {
#[pest_ast(rule(Rule::const_))] fn from(declare: GrammarDeclare) -> Self {
pub struct Const {} match declare {
GrammarDeclare::Const(_) => Declare::Const,
GrammarDeclare::Let(_) => Declare::Let,
}
}
}
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] impl fmt::Display for Declare {
#[pest_ast(rule(Rule::let_))] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
pub struct Let {} match self {
Declare::Const => write!(f, "const"),
Declare::Let => write!(f, "let"),
}
}
}

View File

@ -14,28 +14,236 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use crate::Span;
ast::{span_into_string, Rule}, use leo_grammar::{
SpanDef, annotations::AnnotationArgument,
common::{Identifier as GrammarIdentifier, KeywordOrIdentifier, SelfKeyword, SelfKeywordOrIdentifier},
expressions::CircuitName,
functions::InputKeyword,
imports::PackageName as GrammarPackageName,
types::SelfType,
};
use leo_input::common::Identifier as InputIdentifier;
use serde::{
de::{self, Visitor},
Deserialize,
Deserializer,
Serialize,
Serializer,
};
use std::{
collections::BTreeMap,
fmt,
hash::{Hash, Hasher},
}; };
use pest::Span; /// An identifier in the constrained program.
use pest_ast::FromPest; ///
use serde::Serialize; /// Attention - When adding or removing fields from this struct,
use std::fmt; /// please remember to update it's Serialize and Deserialize implementation
/// to reflect the new struct instantiation.
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone)]
#[pest_ast(rule(Rule::identifier))] pub struct Identifier {
pub struct Identifier<'ast> { pub name: String,
#[pest_ast(outer(with(span_into_string)))] pub span: Span,
pub value: String,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
} }
impl<'ast> fmt::Display for Identifier<'ast> { impl Identifier {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub fn new(name: String) -> Self {
write!(f, "{}", self.value) Self {
name,
span: Span::default(),
}
}
pub fn new_with_span(name: &str, span: &Span) -> Self {
Self {
name: name.to_owned(),
span: span.to_owned(),
}
}
pub fn is_self_type(&self) -> bool {
self.name == "Self"
}
pub fn is_self(&self) -> bool {
self.is_self_type() || self.name == "self"
}
}
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 {
name: identifier.value,
span: Span::from(identifier.span),
}
}
}
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::SelfKeywordOrIdentifier(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<SelfKeyword<'ast>> for Identifier {
fn from(self_: SelfKeyword<'ast>) -> Self {
Self {
name: self_.keyword,
span: Span::from(self_.span),
}
}
}
impl<'ast> From<InputKeyword<'ast>> for Identifier {
fn from(input: InputKeyword<'ast>) -> Self {
Self {
name: input.keyword,
span: Span::from(input.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)
}
}
impl fmt::Debug for Identifier {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name)
}
}
impl PartialEq for Identifier {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl Eq for Identifier {}
impl Hash for Identifier {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.span.hash(state);
}
}
impl Serialize for Identifier {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
// Converts an element that implements Serialize into a string.
fn to_json_string<E: Serialize, Error: serde::ser::Error>(element: &E) -> Result<String, Error> {
serde_json::to_string(&element).map_err(|e| Error::custom(e.to_string()))
}
// Load the struct elements into a BTreeMap (to preserve serialized ordering of keys).
let mut key: BTreeMap<String, String> = BTreeMap::new();
key.insert("name".to_string(), self.name.clone());
key.insert("span".to_string(), to_json_string(&self.span)?);
// Convert the serialized object into a string for use as a key.
serializer.serialize_str(&to_json_string(&key)?)
}
}
impl<'de> Deserialize<'de> for Identifier {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct IdentifierVisitor;
impl<'de> Visitor<'de> for IdentifierVisitor {
type Value = Identifier;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string encoding the ast Identifier struct")
}
/// Implementation for recovering a string that serializes Identifier.
fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
// Converts a serialized string into an element that implements Deserialize.
fn to_json_string<'a, D: Deserialize<'a>, Error: serde::de::Error>(
serialized: &'a str,
) -> Result<D, Error> {
serde_json::from_str::<'a>(serialized).map_err(|e| Error::custom(e.to_string()))
}
// Convert the serialized string into a BTreeMap to recover Identifier.
let key: BTreeMap<String, String> = to_json_string(value)?;
let name = match key.get("name") {
Some(name) => name.clone(),
None => return Err(E::custom("missing 'name' in serialized Identifier struct")),
};
let span: Span = match key.get("span") {
Some(span) => to_json_string(span)?,
None => return Err(E::custom("missing 'span' in serialized Identifier struct")),
};
Ok(Identifier { name, span })
}
}
deserializer.deserialize_str(IdentifierVisitor)
} }
} }

View File

@ -14,48 +14,30 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
pub mod array_dimensions;
pub use array_dimensions::*;
pub mod assignee; pub mod assignee;
pub use assignee::*; pub use assignee::*;
pub mod declare; pub mod declare;
pub use declare::*; pub use declare::*;
pub mod eoi;
pub use eoi::*;
pub mod identifier; pub mod identifier;
pub use identifier::*; pub use identifier::*;
pub mod keyword_or_identifier; pub mod positive_number;
pub use keyword_or_identifier::*; pub use positive_number::*;
pub mod line_end;
pub use line_end::*;
pub mod mutable;
pub use mutable::*;
pub mod range;
pub use range::*;
pub mod range_or_expression; pub mod range_or_expression;
pub use range_or_expression::*; pub use range_or_expression::*;
pub mod self_keyword; pub mod span;
pub use self_keyword::*; pub use span::*;
pub mod self_keyword_or_identifier;
pub use self_keyword_or_identifier::*;
pub mod spread;
pub use spread::*;
pub mod spread_or_expression; pub mod spread_or_expression;
pub use spread_or_expression::*; pub use spread_or_expression::*;
pub mod static_;
pub use static_::*;
pub mod variables; pub mod variables;
pub use variables::*; pub use variables::*;

View File

@ -0,0 +1,82 @@
// Copyright (C) 2019-2020 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::Span;
use leo_grammar::values::PositiveNumber as GrammarPositiveNumber;
use leo_input::values::PositiveNumber as InputPositiveNumber;
use serde::{Deserialize, Serialize};
use std::{
fmt,
hash::{Hash, Hasher},
};
/// A number string guaranteed to be positive by the pest grammar.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PositiveNumber {
pub value: String,
pub span: Span,
}
impl PositiveNumber {
///
/// Returns `true` if this number is zero.
///
pub fn is_zero(&self) -> bool {
self.value.eq("0")
}
}
/// 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,
span: Span::from(array.span),
}
}
}
/// 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 {
Self {
value: array.value,
span: Span::from(array.span),
}
}
}
impl fmt::Display for PositiveNumber {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value)
}
}
/// Compares two positive numbers and ignores `Span`s.
impl PartialEq for PositiveNumber {
fn eq(&self, other: &Self) -> bool {
self.value.eq(&other.value)
}
}
impl Eq for PositiveNumber {}
impl Hash for PositiveNumber {
fn hash<H: Hasher>(&self, state: &mut H) {
self.value.hash(state)
}
}

View File

@ -14,37 +14,42 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, common::Range, expressions::Expression}; use crate::Expression;
use leo_grammar::common::RangeOrExpression as GrammarRangeOrExpression;
use pest_ast::FromPest; use serde::{Deserialize, Serialize};
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] /// Range or expression enum
#[pest_ast(rule(Rule::range_or_expression))] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum RangeOrExpression<'ast> { pub enum RangeOrExpression {
Range(Range<'ast>), Range(Option<Expression>, Option<Expression>),
Expression(Expression<'ast>), Expression(Expression),
} }
impl<'ast> fmt::Display for RangeOrExpression<'ast> { impl<'ast> From<GrammarRangeOrExpression<'ast>> for RangeOrExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn from(range_or_expression: GrammarRangeOrExpression<'ast>) -> Self {
match *self { match range_or_expression {
RangeOrExpression::Expression(ref expression) => write!(f, "{}", expression), GrammarRangeOrExpression::Range(range) => {
RangeOrExpression::Range(ref range) => write!( RangeOrExpression::Range(range.from.map(Expression::from), range.to.map(Expression::from))
f, }
"{}..{}", GrammarRangeOrExpression::Expression(expression) => {
range RangeOrExpression::Expression(Expression::from(expression))
.from }
.as_ref() }
.map(|v| v.to_string()) }
.unwrap_or_else(|| "".to_string()), }
range
.to impl fmt::Display for RangeOrExpression {
.as_ref() fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
.map(|v| v.to_string()) match *self {
.unwrap_or_else(|| "".to_string()), RangeOrExpression::Range(ref from, ref to) => write!(
), f,
"{}..{}",
from.as_ref().map(|e| e.to_string()).unwrap_or_default(),
to.as_ref().map(|e| e.to_string()).unwrap_or_default()
),
RangeOrExpression::Expression(ref e) => write!(f, "{}", e),
} }
} }
} }

View File

@ -14,11 +14,11 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use pest::Span as AstSpan; use pest::Span as GrammarSpan;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Span { pub struct Span {
/// text of input string /// text of input string
pub text: String, pub text: String,
@ -46,8 +46,8 @@ impl Hash for Span {
} }
} }
impl<'ast> From<AstSpan<'ast>> for Span { impl<'ast> From<GrammarSpan<'ast>> for Span {
fn from(span: AstSpan<'ast>) -> Self { fn from(span: GrammarSpan<'ast>) -> Self {
let mut text = " ".to_string(); let mut text = " ".to_string();
let line_col = span.start_pos().line_col(); let line_col = span.start_pos().line_col();
let end = span.end_pos().line_col().1; let end = span.end_pos().line_col().1;

View File

@ -14,23 +14,45 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, common::Spread, expressions::Expression}; use crate::Expression;
use leo_grammar::{
common::SpreadOrExpression as GrammarSpreadOrExpression,
expressions::Expression as GrammarExpression,
};
use pest_ast::FromPest; use serde::{Deserialize, Serialize};
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] /// Spread or expression
#[pest_ast(rule(Rule::spread_or_expression))] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum SpreadOrExpression<'ast> { pub enum SpreadOrExpression {
Spread(Spread<'ast>), Spread(Expression),
Expression(Expression<'ast>), Expression(Expression),
} }
impl<'ast> fmt::Display for SpreadOrExpression<'ast> { 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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
SpreadOrExpression::Spread(ref spread) => write!(f, "{}", spread), SpreadOrExpression::Spread(ref spread) => write!(f, "...{}", spread),
SpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression), SpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression),
} }
} }

View File

@ -14,30 +14,32 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use crate::common::{Identifier, Span};
ast::Rule, use leo_grammar::common::VariableName as GrammarVariableName;
common::{Identifier, Mutable},
SpanDef,
};
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::variable_name))] pub struct VariableName {
pub struct VariableName<'ast> { pub mutable: bool,
pub mutable: Option<Mutable>, pub identifier: Identifier,
pub identifier: Identifier<'ast>, pub span: Span,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
} }
impl<'ast> fmt::Display for VariableName<'ast> { 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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(ref _mutable) = self.mutable { if self.mutable {
write!(f, "mut ")?; write!(f, "mut ")?;
} }

View File

@ -14,24 +14,30 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, common::VariableName, types::Type, SpanDef}; use crate::{Type, VariableName};
use leo_grammar::common::Variables as GrammarVariables;
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] /// A variable that is assigned to a value in the constrained program
#[pest_ast(rule(Rule::variables))] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Variables<'ast> { pub struct Variables {
pub names: Vec<VariableName<'ast>>, pub names: Vec<VariableName>,
pub type_: Option<Type<'ast>>, pub type_: Option<Type>,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
} }
impl<'ast> fmt::Display for Variables<'ast> { impl<'ast> From<GrammarVariables<'ast>> for Variables {
fn from(variables: GrammarVariables<'ast>) -> Self {
let names = variables.names.into_iter().map(VariableName::from).collect::<Vec<_>>();
let type_ = variables.type_.map(Type::from);
Self { names, type_ }
}
}
impl fmt::Display for Variables {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.names.len() == 1 { if self.names.len() == 1 {
// mut a // mut a

View File

@ -14,31 +14,68 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use crate::{Expression, FormattedString};
ast::Rule, use leo_grammar::console::{
console::{ConsoleAssert, ConsoleDebug, ConsoleError, ConsoleLog}, ConsoleAssert as GrammarConsoleAssert,
ConsoleDebug as GrammarConsoleDebug,
ConsoleError as GrammarConsoleError,
ConsoleFunction as GrammarConsoleFunction,
ConsoleLog as GrammarConsoleLog,
}; };
use pest_ast::FromPest; use serde::{Deserialize, Serialize};
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::console_function))] pub enum ConsoleFunction {
pub enum ConsoleFunction<'ast> { Assert(Expression),
Assert(ConsoleAssert<'ast>), Debug(FormattedString),
Debug(ConsoleDebug<'ast>), Error(FormattedString),
Error(ConsoleError<'ast>), Log(FormattedString),
Log(ConsoleLog<'ast>),
} }
impl<'ast> fmt::Display for ConsoleFunction<'ast> { impl<'ast> From<GrammarConsoleFunction<'ast>> for ConsoleFunction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn from(console_function: GrammarConsoleFunction<'ast>) -> Self {
match self { match console_function {
ConsoleFunction::Assert(assert) => write!(f, "{}", assert), GrammarConsoleFunction::Assert(assert) => ConsoleFunction::from(assert),
ConsoleFunction::Debug(debug) => write!(f, "{}", debug), GrammarConsoleFunction::Debug(debug) => ConsoleFunction::from(debug),
ConsoleFunction::Error(error) => write!(f, "{}", error), GrammarConsoleFunction::Error(error) => ConsoleFunction::from(error),
ConsoleFunction::Log(log) => write!(f, "{}", log), 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 {
ConsoleFunction::Assert(assert) => write!(f, "assert({})", assert),
ConsoleFunction::Debug(debug) => write!(f, "debug({})", debug),
ConsoleFunction::Error(error) => write!(f, "error{})", error),
ConsoleFunction::Log(log) => write!(f, "log({})", log),
} }
} }
} }

View File

@ -14,30 +14,34 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use crate::{ConsoleFunction, Span};
ast::Rule, use leo_grammar::console::ConsoleFunctionCall as GrammarConsoleFunctionCall;
common::LineEnd,
console::{ConsoleFunction, ConsoleKeyword},
SpanDef,
};
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::console_function_call))] pub struct ConsoleFunctionCall {
pub struct ConsoleFunctionCall<'ast> { pub function: ConsoleFunction,
pub keyword: ConsoleKeyword<'ast>, pub span: Span,
pub function: ConsoleFunction<'ast>,
pub line_end: LineEnd,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
} }
impl<'ast> fmt::Display for ConsoleFunctionCall<'ast> { impl<'ast> From<GrammarConsoleFunctionCall<'ast>> for ConsoleFunctionCall {
fn from(console: GrammarConsoleFunctionCall<'ast>) -> Self {
ConsoleFunctionCall {
function: ConsoleFunction::from(console.function),
span: Span::from(console.span),
}
}
}
impl fmt::Display for ConsoleFunctionCall {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "console.{};", self.function)
}
}
impl fmt::Debug for ConsoleFunctionCall {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "console.{};", self.function) write!(f, "console.{};", self.function)
} }

View File

@ -14,22 +14,26 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, SpanDef}; use crate::Span;
use leo_grammar::console::FormattedContainer as GrammarFormattedContainer;
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::formatted_container))] pub struct FormattedContainer {
pub struct FormattedContainer<'ast> { pub span: Span,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
} }
impl<'ast> fmt::Display for FormattedContainer<'ast> { 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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{{}}") write!(f, "{{}}")
} }

View File

@ -14,23 +14,28 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, expressions::Expression, SpanDef}; use crate::{Expression, Span};
use leo_grammar::console::FormattedParameter as GrammarFormattedParameter;
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::formatted_parameter))] pub struct FormattedParameter {
pub struct FormattedParameter<'ast> { pub expression: Expression,
pub expression: Expression<'ast>, pub span: Span,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
} }
impl<'ast> fmt::Display for FormattedParameter<'ast> { impl<'ast> From<GrammarFormattedParameter<'ast>> for FormattedParameter {
fn from(parameter: GrammarFormattedParameter<'ast>) -> Self {
Self {
expression: Expression::from(parameter.expression),
span: Span::from(parameter.span),
}
}
}
impl fmt::Display for FormattedParameter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.expression) write!(f, "{}", self.expression)
} }

View File

@ -14,30 +14,37 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use crate::{FormattedContainer, FormattedParameter, Span};
ast::{span_into_string, Rule}, use leo_grammar::console::FormattedString as GrammarFormattedString;
console::{FormattedContainer, FormattedParameter},
SpanDef,
};
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::formatted_string))] pub struct FormattedString {
pub struct FormattedString<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub string: String, pub string: String,
pub containers: Vec<FormattedContainer<'ast>>, pub containers: Vec<FormattedContainer>,
pub parameters: Vec<FormattedParameter<'ast>>, pub parameters: Vec<FormattedParameter>,
#[pest_ast(outer())] pub span: Span,
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
} }
impl<'ast> fmt::Display for FormattedString<'ast> { 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(FormattedParameter::from).collect();
Self {
string,
containers,
parameters,
span,
}
}
}
impl fmt::Display for FormattedString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.string) write!(f, "{}", self.string)
} }

View File

@ -14,27 +14,12 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
pub mod console_assert;
pub use console_assert::*;
pub mod console_debug;
pub use console_debug::*;
pub mod console_error;
pub use console_error::*;
pub mod console_function; pub mod console_function;
pub use console_function::*; pub use console_function::*;
pub mod console_function_call; pub mod console_function_call;
pub use console_function_call::*; pub use console_function_call::*;
pub mod console_keyword;
pub use console_keyword::*;
pub mod console_log;
pub use console_log::*;
pub mod formatted_container; pub mod formatted_container;
pub use formatted_container::*; pub use formatted_container::*;

View File

@ -14,8 +14,5 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
pub mod parser; pub mod error;
pub use parser::*; pub use error::*;
pub mod syntax;
pub use syntax::*;

View File

@ -15,23 +15,25 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use crate::{
ArrayDimensions,
CircuitVariableDefinition, CircuitVariableDefinition,
GroupValue, GroupValue,
Identifier, Identifier,
IntegerType, IntegerType,
PositiveNumber,
RangeOrExpression, RangeOrExpression,
Span, Span,
SpreadOrExpression, SpreadOrExpression,
}; };
use leo_ast::{ use leo_grammar::{
access::{Access, AssigneeAccess}, access::{Access, AssigneeAccess},
common::{Assignee, Identifier as AstIdentifier}, common::{Assignee, Identifier as GrammarIdentifier},
expressions::{ expressions::{
ArrayInitializerExpression, ArrayInitializerExpression,
ArrayInlineExpression, ArrayInlineExpression,
BinaryExpression, BinaryExpression,
CircuitInlineExpression, CircuitInlineExpression,
Expression as AstExpression, Expression as GrammarExpression,
PostfixExpression, PostfixExpression,
TernaryExpression, TernaryExpression,
UnaryExpression, UnaryExpression,
@ -41,16 +43,14 @@ use leo_ast::{
AddressValue, AddressValue,
BooleanValue, BooleanValue,
FieldValue, FieldValue,
GroupValue as AstGroupValue, GroupValue as GrammarGroupValue,
IntegerValue, IntegerValue,
NumberValue as AstNumber, NumberValue as GrammarNumber,
PositiveNumber as AstPositiveNumber,
Value, Value,
}, },
}; };
use leo_input::{types::ArrayDimensions as InputArrayDimensions, values::PositiveNumber as InputAstPositiveNumber};
use leo_ast::{expressions::TupleExpression, types::ArrayDimensions}; use leo_grammar::{access::TupleAccess, expressions::TupleExpression};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
@ -92,15 +92,17 @@ pub enum Expression {
// Arrays // Arrays
// (array_elements, span) // (array_elements, span)
Array(Vec<SpreadOrExpression>, Span), ArrayInline(Vec<SpreadOrExpression>, Span),
// (array_name, range, span) // ((array element, dimensions), span)
ArrayInitializer(Box<(Expression, ArrayDimensions)>, Span),
// ((array_name, range), span)
ArrayAccess(Box<(Expression, RangeOrExpression)>, Span), ArrayAccess(Box<(Expression, RangeOrExpression)>, Span),
// Tuples // Tuples
// (tuple_elements, span) // (tuple_elements, span)
Tuple(Vec<Expression>, Span), Tuple(Vec<Expression>, Span),
// (tuple_name, index, span) // ((tuple_name, index), span)
TupleAccess(Box<Expression>, usize, Span), TupleAccess(Box<(Expression, PositiveNumber)>, Span),
// Circuits // Circuits
// (defined_circuit_name, circuit_members, span) // (defined_circuit_name, circuit_members, span)
@ -139,11 +141,12 @@ impl Expression {
Expression::Lt(_, old_span) => *old_span = new_span, Expression::Lt(_, old_span) => *old_span = new_span,
Expression::IfElse(_, old_span) => *old_span = new_span, Expression::IfElse(_, old_span) => *old_span = new_span,
Expression::Array(_, old_span) => *old_span = new_span, Expression::ArrayInline(_, old_span) => *old_span = new_span,
Expression::ArrayInitializer(_, old_span) => *old_span = new_span,
Expression::ArrayAccess(_, old_span) => *old_span = new_span, Expression::ArrayAccess(_, old_span) => *old_span = new_span,
Expression::Tuple(_, old_span) => *old_span = new_span, Expression::Tuple(_, old_span) => *old_span = new_span,
Expression::TupleAccess(_, _, old_span) => *old_span = new_span, Expression::TupleAccess(_, old_span) => *old_span = new_span,
Expression::Circuit(_, _, old_span) => *old_span = new_span, Expression::Circuit(_, _, old_span) => *old_span = new_span,
Expression::CircuitMemberAccess(_, _, old_span) => *old_span = new_span, Expression::CircuitMemberAccess(_, _, old_span) => *old_span = new_span,
@ -156,40 +159,6 @@ impl Expression {
} }
} }
impl<'ast> Expression {
pub(crate) fn get_count_from_input_ast(number: InputAstPositiveNumber<'ast>) -> usize {
number
.value
.parse::<usize>()
.expect("Array size should be a positive number")
}
pub(crate) fn get_input_array_dimensions(dimensions: InputArrayDimensions<'ast>) -> Vec<usize> {
match dimensions {
InputArrayDimensions::Single(single) => vec![Self::get_count_from_input_ast(single.number)],
InputArrayDimensions::Multiple(multiple) => multiple
.numbers
.into_iter()
.map(Self::get_count_from_input_ast)
.collect(),
}
}
pub(crate) fn get_count_from_ast(number: AstPositiveNumber<'ast>) -> usize {
number
.value
.parse::<usize>()
.expect("Array size should be a positive number")
}
pub(crate) fn get_array_dimensions(dimensions: ArrayDimensions<'ast>) -> Vec<usize> {
match dimensions {
ArrayDimensions::Single(single) => vec![Self::get_count_from_ast(single.number)],
ArrayDimensions::Multiple(multiple) => multiple.numbers.into_iter().map(Self::get_count_from_ast).collect(),
}
}
}
impl<'ast> fmt::Display for Expression { impl<'ast> fmt::Display for Expression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
@ -228,7 +197,7 @@ impl<'ast> fmt::Display for Expression {
} }
// Arrays // Arrays
Expression::Array(ref array, ref _span) => { Expression::ArrayInline(ref array, ref _span) => {
write!(f, "[")?; write!(f, "[")?;
for (i, e) in array.iter().enumerate() { for (i, e) in array.iter().enumerate() {
write!(f, "{}", e)?; write!(f, "{}", e)?;
@ -238,6 +207,7 @@ impl<'ast> fmt::Display for Expression {
} }
write!(f, "]") write!(f, "]")
} }
Expression::ArrayInitializer(ref array, ref _span) => write!(f, "[{}; {}]", array.0, array.1),
Expression::ArrayAccess(ref array_w_index, ref _span) => { Expression::ArrayAccess(ref array_w_index, ref _span) => {
write!(f, "{}[{}]", array_w_index.0, array_w_index.1) write!(f, "{}[{}]", array_w_index.0, array_w_index.1)
} }
@ -248,7 +218,9 @@ impl<'ast> fmt::Display for Expression {
write!(f, "({})", values) write!(f, "({})", values)
} }
Expression::TupleAccess(ref tuple, ref index, ref _span) => write!(f, "{}.{}", tuple, index), Expression::TupleAccess(ref tuple_w_index, ref _span) => {
write!(f, "{}.{}", tuple_w_index.0, tuple_w_index.1)
}
// Circuits // Circuits
Expression::Circuit(ref var, ref members, ref _span) => { Expression::Circuit(ref var, ref members, ref _span) => {
@ -326,8 +298,7 @@ impl<'ast> From<PostfixExpression<'ast>> for Expression {
// Handle tuple access // Handle tuple access
Access::Tuple(tuple) => Expression::TupleAccess( Access::Tuple(tuple) => Expression::TupleAccess(
Box::new(acc), Box::new((acc, PositiveNumber::from(tuple.number))),
Expression::get_count_from_ast(tuple.number),
Span::from(tuple.span), Span::from(tuple.span),
), ),
@ -356,19 +327,19 @@ impl<'ast> From<PostfixExpression<'ast>> for Expression {
} }
} }
impl<'ast> From<AstExpression<'ast>> for Expression { impl<'ast> From<GrammarExpression<'ast>> for Expression {
fn from(expression: AstExpression<'ast>) -> Self { fn from(expression: GrammarExpression<'ast>) -> Self {
match expression { match expression {
AstExpression::Value(value) => Expression::from(value), GrammarExpression::Value(value) => Expression::from(value),
AstExpression::Identifier(variable) => Expression::from(variable), GrammarExpression::Identifier(variable) => Expression::from(variable),
AstExpression::Unary(expression) => Expression::from(*expression), GrammarExpression::Unary(expression) => Expression::from(*expression),
AstExpression::Binary(expression) => Expression::from(*expression), GrammarExpression::Binary(expression) => Expression::from(*expression),
AstExpression::Ternary(expression) => Expression::from(*expression), GrammarExpression::Ternary(expression) => Expression::from(*expression),
AstExpression::ArrayInline(expression) => Expression::from(expression), GrammarExpression::ArrayInline(expression) => Expression::from(expression),
AstExpression::ArrayInitializer(expression) => Expression::from(*expression), GrammarExpression::ArrayInitializer(expression) => Expression::from(*expression),
AstExpression::Tuple(expression) => Expression::from(expression), GrammarExpression::Tuple(expression) => Expression::from(expression),
AstExpression::CircuitInline(expression) => Expression::from(expression), GrammarExpression::CircuitInline(expression) => Expression::from(expression),
AstExpression::Postfix(expression) => Expression::from(expression), GrammarExpression::Postfix(expression) => Expression::from(expression),
} }
} }
} }
@ -393,9 +364,8 @@ impl<'ast> From<Assignee<'ast>> for Expression {
Span::from(array.span), Span::from(array.span),
), ),
AssigneeAccess::Tuple(tuple) => Expression::TupleAccess( AssigneeAccess::Tuple(tuple) => Expression::TupleAccess(
Box::new(acc), Box::new((acc, PositiveNumber::from(tuple.number))),
Expression::get_count_from_ast(tuple.number), Span::from(tuple.span.clone()),
Span::from(tuple.span),
), ),
}) })
} }
@ -482,7 +452,7 @@ impl<'ast> From<TernaryExpression<'ast>> for Expression {
impl<'ast> From<ArrayInlineExpression<'ast>> for Expression { impl<'ast> From<ArrayInlineExpression<'ast>> for Expression {
fn from(array: ArrayInlineExpression<'ast>) -> Self { fn from(array: ArrayInlineExpression<'ast>) -> Self {
Expression::Array( Expression::ArrayInline(
array.expressions.into_iter().map(SpreadOrExpression::from).collect(), array.expressions.into_iter().map(SpreadOrExpression::from).collect(),
Span::from(array.span), Span::from(array.span),
) )
@ -491,26 +461,13 @@ impl<'ast> From<ArrayInlineExpression<'ast>> for Expression {
impl<'ast> From<ArrayInitializerExpression<'ast>> for Expression { impl<'ast> From<ArrayInitializerExpression<'ast>> for Expression {
fn from(array: ArrayInitializerExpression<'ast>) -> Self { fn from(array: ArrayInitializerExpression<'ast>) -> Self {
let dimensions = Expression::get_array_dimensions(array.dimensions); Expression::ArrayInitializer(
let expression = SpreadOrExpression::from(array.expression); Box::new((
Expression::from(array.expression),
let mut elements = vec![]; ArrayDimensions::from(array.dimensions),
)),
// Initializes an arrays elements using the rust `vec!` macro. Span::from(array.span),
// If there are multiple array dimensions, then `elements` is used as the first expression in a `vec!` macro. )
// This creates a multi-dimensional array by chaining `vec!` macros.
for (i, dimension) in dimensions.into_iter().rev().enumerate() {
if i == 0 {
elements = vec![expression.clone(); dimension];
} else {
let element =
SpreadOrExpression::Expression(Expression::Array(elements, Span::from(array.span.clone())));
elements = vec![element; dimension];
}
}
Expression::Array(elements, Span::from(array.span))
} }
} }
@ -569,17 +526,17 @@ impl<'ast> From<FieldValue<'ast>> for Expression {
} }
} }
impl<'ast> From<AstGroupValue<'ast>> for Expression { impl<'ast> From<GrammarGroupValue<'ast>> for Expression {
fn from(ast_group: AstGroupValue<'ast>) -> Self { fn from(ast_group: GrammarGroupValue<'ast>) -> Self {
Expression::Group(Box::new(GroupValue::from(ast_group))) Expression::Group(Box::new(GroupValue::from(ast_group)))
} }
} }
impl<'ast> From<AstNumber<'ast>> for Expression { impl<'ast> From<GrammarNumber<'ast>> for Expression {
fn from(number: AstNumber<'ast>) -> Self { fn from(number: GrammarNumber<'ast>) -> Self {
let (value, span) = match number { let (value, span) = match number {
AstNumber::Positive(number) => (number.value, number.span), GrammarNumber::Positive(number) => (number.value, number.span),
AstNumber::Negative(number) => (number.value, number.span), GrammarNumber::Negative(number) => (number.value, number.span),
}; };
Expression::Implicit(value, Span::from(span)) Expression::Implicit(value, Span::from(span))
@ -593,8 +550,8 @@ impl<'ast> From<IntegerValue<'ast>> for Expression {
IntegerValue::Signed(integer) => { IntegerValue::Signed(integer) => {
let type_ = IntegerType::from(integer.type_); let type_ = IntegerType::from(integer.type_);
let number = match integer.number { let number = match integer.number {
AstNumber::Negative(number) => number.value, GrammarNumber::Negative(number) => number.value,
AstNumber::Positive(number) => number.value, GrammarNumber::Positive(number) => number.value,
}; };
(type_, number) (type_, number)
@ -611,8 +568,14 @@ impl<'ast> From<IntegerValue<'ast>> for Expression {
} }
} }
impl<'ast> From<AstIdentifier<'ast>> for Expression { impl<'ast> From<TupleAccess<'ast>> for Expression {
fn from(identifier: AstIdentifier<'ast>) -> Self { fn from(tuple: TupleAccess<'ast>) -> Self {
Expression::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)) Expression::Identifier(Identifier::from(identifier))
} }
} }

View File

@ -14,20 +14,79 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, common::Identifier, functions::input::Input, statements::Statement, types::Type, SpanDef}; use crate::{FunctionInput, Identifier, Span, Statement, Type};
use leo_grammar::functions::Function as GrammarFunction;
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest; use std::fmt;
use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, Serialize, Deserialize)]
#[pest_ast(rule(Rule::function))] pub struct Function {
pub struct Function<'ast> { pub identifier: Identifier,
pub identifier: Identifier<'ast>, pub input: Vec<FunctionInput>,
pub parameters: Vec<Input<'ast>>, pub output: Option<Type>,
pub returns: Option<Type<'ast>>, pub statements: Vec<Statement>,
pub statements: Vec<Statement<'ast>>, pub span: Span,
#[pest_ast(outer())] }
#[serde(with = "SpanDef")]
pub span: Span<'ast>, impl PartialEq for Function {
fn eq(&self, other: &Self) -> bool {
self.identifier == other.identifier
}
}
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 statements = function.statements.into_iter().map(Statement::from).collect();
Function {
identifier: function_name,
input: parameters,
output: returns,
statements,
span: Span::from(function.span),
}
}
}
impl Function {
pub fn get_name(&self) -> &str {
&self.identifier.name
}
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "function {}", self.identifier)?;
let parameters = self.input.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",");
let returns = self.output.as_ref().map(|type_| type_.to_string());
let statements = self
.statements
.iter()
.map(|s| format!("\t{}\n", s))
.collect::<Vec<_>>()
.join("");
if returns.is_none() {
write!(f, "({}) {{\n{}}}", parameters, statements,)
} else {
write!(f, "({}) -> {} {{\n{}}}", parameters, returns.unwrap(), statements,)
}
}
}
impl fmt::Display for Function {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}
impl fmt::Debug for Function {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
} }

View File

@ -14,24 +14,50 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use crate::{Identifier, Span, Type};
ast::Rule, use leo_grammar::functions::FunctionInput as GrammarFunctionInput;
common::{Identifier, Mutable},
types::Type,
SpanDef,
};
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest; use std::fmt;
use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::function_input))] pub struct FunctionInputVariable {
pub struct FunctionInput<'ast> { pub identifier: Identifier,
pub mutable: Option<Mutable>, pub mutable: bool,
pub identifier: Identifier<'ast>, pub type_: Type,
pub type_: Type<'ast>, pub span: Span,
#[pest_ast(outer())] }
#[serde(with = "SpanDef")]
pub span: Span<'ast>, impl<'ast> From<GrammarFunctionInput<'ast>> for FunctionInputVariable {
fn from(parameter: GrammarFunctionInput<'ast>) -> Self {
FunctionInputVariable {
identifier: Identifier::from(parameter.identifier),
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
if self.mutable {
write!(f, "mut ")?;
}
write!(f, "{}: ", self.identifier)?;
write!(f, "{}", self.type_)
}
}
impl fmt::Display for FunctionInputVariable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}
impl fmt::Debug for FunctionInputVariable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
} }

View File

@ -14,52 +14,52 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{FunctionInput, Identifier, Span}; use crate::{FunctionInputVariable, Identifier, Span};
use leo_ast::functions::input::Input as AstInput; use leo_grammar::functions::input::Input as GrammarInput;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum InputVariable { pub enum FunctionInput {
InputKeyword(Identifier), InputKeyword(Identifier),
FunctionInput(FunctionInput), Variable(FunctionInputVariable),
} }
impl<'ast> From<AstInput<'ast>> for InputVariable { impl<'ast> From<GrammarInput<'ast>> for FunctionInput {
fn from(input: AstInput<'ast>) -> Self { fn from(input: GrammarInput<'ast>) -> Self {
match input { match input {
AstInput::InputKeyword(input_keyword) => { GrammarInput::InputKeyword(input_keyword) => {
let id = Identifier { let id = Identifier {
name: input_keyword.keyword, name: input_keyword.keyword,
span: Span::from(input_keyword.span), span: Span::from(input_keyword.span),
}; };
InputVariable::InputKeyword(id) FunctionInput::InputKeyword(id)
} }
AstInput::FunctionInput(function_input) => { GrammarInput::FunctionInput(function_input) => {
InputVariable::FunctionInput(FunctionInput::from(function_input)) FunctionInput::Variable(FunctionInputVariable::from(function_input))
} }
} }
} }
} }
impl InputVariable { impl FunctionInput {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
InputVariable::InputKeyword(id) => write!(f, "{}", id), FunctionInput::InputKeyword(id) => write!(f, "{}", id),
InputVariable::FunctionInput(function_input) => write!(f, "{}", function_input), FunctionInput::Variable(function_input) => write!(f, "{}", function_input),
} }
} }
} }
impl fmt::Display for InputVariable { impl fmt::Display for FunctionInput {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f) self.format(f)
} }
} }
impl fmt::Debug for InputVariable { impl fmt::Debug for FunctionInput {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f) self.format(f)
} }

View File

@ -14,13 +14,8 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
#![allow(clippy::module_inception)]
pub mod function_input; pub mod function_input;
pub use function_input::*; pub use function_input::*;
pub mod input; pub mod input_variable;
pub use input::*; pub use input_variable::*;
pub mod input_keyword;
pub use input_keyword::*;

View File

@ -14,17 +14,22 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, functions::Function, SpanDef}; use crate::{Function, Identifier};
use leo_grammar::functions::TestFunction as GrammarTestFunction;
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest;
use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::test_function))] pub struct TestFunction {
pub struct TestFunction<'ast> { pub function: Function,
pub function: Function<'ast>, pub input_file: Option<Identifier>,
#[pest_ast(outer())] }
#[serde(with = "SpanDef")]
pub span: Span<'ast>, impl<'ast> From<GrammarTestFunction<'ast>> for TestFunction {
fn from(test: GrammarTestFunction) -> Self {
TestFunction {
function: Function::from(test.function),
input_file: None, // pass custom input file with `@context` annotation
}
}
} }

View File

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

View File

@ -15,10 +15,10 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{common::span::Span, groups::GroupCoordinate}; use crate::{common::span::Span, groups::GroupCoordinate};
use leo_ast::values::{ use leo_grammar::values::{
GroupRepresentation as AstGroupRepresentation, GroupRepresentation as GrammarGroupRepresentation,
GroupTuple as AstGroupTuple, GroupTuple as GrammarGroupTuple,
GroupValue as AstGroupValue, GroupValue as GrammarGroupValue,
}; };
use leo_input::values::{ use leo_input::values::{
GroupRepresentation as InputGroupRepresentation, GroupRepresentation as InputGroupRepresentation,
@ -42,15 +42,22 @@ impl GroupValue {
GroupValue::Tuple(tuple) => tuple.span = new_span, GroupValue::Tuple(tuple) => tuple.span = new_span,
} }
} }
pub fn span(&self) -> &Span {
match self {
GroupValue::Single(_, span) => span,
GroupValue::Tuple(tuple) => &tuple.span,
}
}
} }
impl<'ast> From<AstGroupValue<'ast>> for GroupValue { impl<'ast> From<GrammarGroupValue<'ast>> for GroupValue {
fn from(ast_group: AstGroupValue) -> Self { fn from(ast_group: GrammarGroupValue) -> Self {
let span = Span::from(ast_group.span); let span = Span::from(ast_group.span);
match ast_group.value { match ast_group.value {
AstGroupRepresentation::Single(number) => GroupValue::Single(number.to_string(), span), GrammarGroupRepresentation::Single(number) => GroupValue::Single(number.to_string(), span),
AstGroupRepresentation::Tuple(tuple) => GroupValue::Tuple(GroupTuple::from(tuple)), GrammarGroupRepresentation::Tuple(tuple) => GroupValue::Tuple(GroupTuple::from(tuple)),
} }
} }
} }
@ -82,8 +89,8 @@ pub struct GroupTuple {
pub span: Span, pub span: Span,
} }
impl<'ast> From<AstGroupTuple<'ast>> for GroupTuple { impl<'ast> From<GrammarGroupTuple<'ast>> for GroupTuple {
fn from(ast_group: AstGroupTuple<'ast>) -> Self { fn from(ast_group: GrammarGroupTuple<'ast>) -> Self {
let ast_x = ast_group.x; let ast_x = ast_group.x;
let ast_y = ast_group.y; let ast_y = ast_group.y;

View File

@ -14,18 +14,51 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, common::LineEnd, imports::Package, SpanDef}; use crate::{Package, Span};
use leo_grammar::imports::Import as GrammarImport;
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest; use std::fmt;
use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] /// Represents an import statement in a Leo program.
#[pest_ast(rule(Rule::import))] #[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct Import<'ast> { pub struct ImportStatement {
pub package: Package<'ast>, pub package: Package,
pub line_end: LineEnd, pub span: Span,
#[pest_ast(outer())] }
#[serde(with = "SpanDef")]
pub span: Span<'ast>, impl ImportStatement {
///
/// Returns the the package file name of the self import statement.
///
pub fn get_file_name(&self) -> &str {
&self.package.name.name
}
}
impl<'ast> From<GrammarImport<'ast>> for ImportStatement {
fn from(import: GrammarImport<'ast>) -> Self {
ImportStatement {
package: Package::from(import.package),
span: Span::from(import.span),
}
}
}
impl ImportStatement {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "import {};", self.package)
}
}
impl fmt::Display for ImportStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}
impl fmt::Debug for ImportStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
} }

View File

@ -14,18 +14,63 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, common::Identifier, SpanDef}; use crate::{Identifier, Span};
use leo_grammar::imports::ImportSymbol as GrammarImportSymbol;
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest; use std::fmt;
use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::import_symbol))] pub struct ImportSymbol {
pub struct ImportSymbol<'ast> { pub symbol: Identifier,
pub value: Identifier<'ast>, pub alias: Option<Identifier>,
pub alias: Option<Identifier<'ast>>, pub span: Span,
#[pest_ast(outer())] }
#[serde(with = "SpanDef")]
pub span: Span<'ast>, 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() {
write!(f, "{} as {}", self.symbol, self.alias.as_ref().unwrap())
} else {
write!(f, "{}", self.symbol)
}
}
}
// TODO (collin): remove this
impl fmt::Debug for ImportSymbol {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.alias.is_some() {
write!(f, "{} as {}", self.symbol, self.alias.as_ref().unwrap())
} else {
write!(f, "{}", self.symbol)
}
}
}
impl ImportSymbol {
pub fn star(span: &Span) -> Self {
Self {
symbol: Identifier {
name: "*".to_string(),
span: span.clone(),
},
alias: None,
span: span.clone(),
}
}
pub fn is_star(&self) -> bool {
self.symbol.name.eq("*")
}
} }

View File

@ -25,9 +25,3 @@ pub use package::*;
pub mod package_access; pub mod package_access;
pub use package_access::*; pub use package_access::*;
pub mod package_name;
pub use package_name::*;
pub mod star;
pub use star::*;

View File

@ -14,22 +14,43 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use crate::{common::Identifier, PackageAccess, Span};
ast::Rule, use leo_grammar::imports::Package as GrammarPackage;
imports::{PackageAccess, PackageName},
SpanDef,
};
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest; use std::fmt;
use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::package))] pub struct Package {
pub struct Package<'ast> { pub name: Identifier,
pub name: PackageName<'ast>, pub access: PackageAccess,
pub access: PackageAccess<'ast>, pub span: Span,
#[pest_ast(outer())] }
#[serde(with = "SpanDef")]
pub span: Span<'ast>, 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)
}
}
impl fmt::Display for Package {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}
impl fmt::Debug for Package {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
} }

View File

@ -14,19 +14,61 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use crate::{ImportSymbol, Package, Span};
ast::Rule, use leo_grammar::imports::PackageAccess as GrammarPackageAccess;
imports::{ImportSymbol, Package, Star},
};
use pest_ast::FromPest; use serde::{Deserialize, Serialize};
use serde::Serialize; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::package_access))] pub enum PackageAccess {
pub enum PackageAccess<'ast> { Star(Span),
Star(Star<'ast>), SubPackage(Box<Package>),
SubPackage(Box<Package<'ast>>), Symbol(ImportSymbol),
Symbol(ImportSymbol<'ast>), Multiple(Vec<PackageAccess>),
Multiple(Vec<PackageAccess<'ast>>), }
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(accesses) => {
PackageAccess::Multiple(accesses.into_iter().map(PackageAccess::from).collect())
}
}
}
}
impl PackageAccess {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
PackageAccess::Star(ref _span) => write!(f, "*"),
PackageAccess::SubPackage(ref package) => write!(f, "{}", package),
PackageAccess::Symbol(ref symbol) => write!(f, "{}", symbol),
PackageAccess::Multiple(ref accesses) => {
write!(f, "(")?;
for (i, access) in accesses.iter().enumerate() {
write!(f, "{}", access)?;
if i < accesses.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")
}
}
}
}
impl fmt::Debug for PackageAccess {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}
impl fmt::Display for PackageAccess {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
} }

View File

@ -80,7 +80,7 @@ impl Input {
Ok(()) Ok(())
} }
/// Parse all input variables included in a file and store them in `self`. /// Parse all state variables included in a file and store them in `self`.
pub fn parse_state(&mut self, file: File) -> Result<(), InputParserError> { pub fn parse_state(&mut self, file: File) -> Result<(), InputParserError> {
for entry in file.entries.into_iter() { for entry in file.entries.into_iter() {
match entry { match entry {

View File

@ -14,13 +14,14 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression as TypedExpression, GroupValue}; use crate::{ArrayDimensions, GroupValue};
use leo_input::{ use leo_input::{
errors::InputParserError, errors::InputParserError,
expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression, TupleExpression}, expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression, TupleExpression},
types::{ArrayType, DataType, IntegerType, TupleType, Type}, types::{ArrayType, DataType, IntegerType, TupleType, Type},
values::{Address, AddressValue, BooleanValue, FieldValue, GroupValue as InputGroupValue, NumberValue, Value}, values::{Address, AddressValue, BooleanValue, FieldValue, GroupValue as InputGroupValue, NumberValue, Value},
}; };
use pest::Span;
use std::fmt; use std::fmt;
@ -102,11 +103,18 @@ impl InputValue {
} }
} }
///
/// Returns a new `InputValue` from the given `ArrayType` and `ArrayInlineExpression`.
///
pub(crate) fn from_array_inline( pub(crate) fn from_array_inline(
mut array_type: ArrayType, mut array_type: ArrayType,
inline: ArrayInlineExpression, inline: ArrayInlineExpression,
) -> Result<Self, InputParserError> { ) -> Result<Self, InputParserError> {
let array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone()); // Create a new `ArrayDimensions` type from the input array_type dimensions.
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())?;
// Return an error if the outer array dimension does not equal the number of array elements. // Return an error if the outer array dimension does not equal the number of array elements.
if array_dimensions[0] != inline.expressions.len() { if array_dimensions[0] != inline.expressions.len() {
@ -137,14 +145,15 @@ impl InputValue {
array_type: ArrayType, array_type: ArrayType,
initializer: ArrayInitializerExpression, initializer: ArrayInitializerExpression,
) -> Result<Self, InputParserError> { ) -> Result<Self, InputParserError> {
let initializer_dimensions = TypedExpression::get_input_array_dimensions(initializer.dimensions.clone()); let array_dimensions_type = ArrayDimensions::from(initializer.dimensions.clone());
let array_dimensions = parse_array_dimensions(array_dimensions_type, array_type.span.clone())?;
if initializer_dimensions.len() > 1 { if array_dimensions.len() > 1 {
// The expression is an array initializer with tuple syntax // The expression is an array initializer with tuple syntax
Self::from_array_initializer_tuple(array_type, initializer, initializer_dimensions) Self::from_array_initializer_tuple(array_type, initializer, array_dimensions)
} else { } else {
// The expression is an array initializer with nested syntax // The expression is an array initializer with nested syntax
Self::from_array_initializer_nested(array_type, initializer, initializer_dimensions) Self::from_array_initializer_nested(array_type, initializer, array_dimensions)
} }
} }
@ -153,7 +162,7 @@ impl InputValue {
initializer: ArrayInitializerExpression, initializer: ArrayInitializerExpression,
initializer_dimensions: Vec<usize>, initializer_dimensions: Vec<usize>,
) -> Result<Self, InputParserError> { ) -> Result<Self, InputParserError> {
let (array_dimensions, array_element_type) = fetch_nested_array_type_dimensions(array_type.clone(), vec![]); let (array_dimensions, array_element_type) = fetch_nested_array_type_dimensions(array_type.clone(), vec![])?;
// Return an error if the dimensions of the array are incorrect. // Return an error if the dimensions of the array are incorrect.
if array_dimensions.ne(&initializer_dimensions) { if array_dimensions.ne(&initializer_dimensions) {
@ -186,7 +195,11 @@ impl InputValue {
initializer: ArrayInitializerExpression, initializer: ArrayInitializerExpression,
initializer_dimensions: Vec<usize>, initializer_dimensions: Vec<usize>,
) -> Result<Self, InputParserError> { ) -> Result<Self, InputParserError> {
let array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone()); // Create a new `ArrayDimensions` type from the input array_type dimensions.
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 current_array_dimension = array_dimensions[0]; let current_array_dimension = array_dimensions[0];
let current_initializer_dimension = initializer_dimensions[0]; let current_initializer_dimension = initializer_dimensions[0];
@ -240,14 +253,52 @@ impl InputValue {
} }
} }
// Recursively fetch all dimensions from the array type ///
fn fetch_nested_array_type_dimensions(array_type: ArrayType, mut array_dimensions: Vec<usize>) -> (Vec<usize>, Type) { /// Returns a new vector of usize values from an [`ArrayDimensions`] type.
let mut current_dimension = TypedExpression::get_input_array_dimensions(array_type.dimensions); ///
/// Attempts to parse each dimension in the array from a `String` to a `usize` value. If parsing
/// 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> {
// Convert the array dimensions to usize.
let mut array_dimensions = Vec::with_capacity(array_dimensions_type.0.len());
for dimension in array_dimensions_type.0 {
// Convert the dimension to a string.
let dimension_string = dimension.to_string();
// 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())),
};
// Collect dimension usize values.
array_dimensions.push(dimension_usize);
}
Ok(array_dimensions)
}
///
/// Recursively fetch all dimensions from the array type.
///
fn fetch_nested_array_type_dimensions(
array_type: ArrayType,
mut array_dimensions: Vec<usize>,
) -> Result<(Vec<usize>, Type), InputParserError> {
// Create a new `ArrayDimensions` type from the input 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())?;
array_dimensions.append(&mut current_dimension); array_dimensions.append(&mut current_dimension);
match *array_type.type_ { match *array_type.type_ {
Type::Array(next_array_type) => fetch_nested_array_type_dimensions(next_array_type, array_dimensions), Type::Array(next_array_type) => fetch_nested_array_type_dimensions(next_array_type, array_dimensions),
type_ => (array_dimensions, type_), type_ => Ok((array_dimensions, type_)),
} }
} }

View File

@ -15,7 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Identifier, Span, Type}; use crate::{Identifier, Span, Type};
use leo_input::parameters::Parameter as AstParameter; use leo_input::parameters::Parameter as GrammarParameter;
#[derive(Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
pub struct Parameter { pub struct Parameter {
@ -24,8 +24,8 @@ pub struct Parameter {
pub span: Span, pub span: Span,
} }
impl<'ast> From<AstParameter<'ast>> for Parameter { impl<'ast> From<GrammarParameter<'ast>> for Parameter {
fn from(parameter: AstParameter<'ast>) -> Self { fn from(parameter: GrammarParameter<'ast>) -> Self {
Self { Self {
variable: Identifier::from(parameter.variable), variable: Identifier::from(parameter.variable),
type_: Type::from(parameter.type_), type_: Type::from(parameter.type_),

View File

@ -14,74 +14,85 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
#[macro_use] //! The abstract syntax tree (ast) for a Leo program.
extern crate lazy_static; //!
#[macro_use] //! This module contains the [`LeoAst`] type, a wrapper around the [`Program`] type.
extern crate pest_derive; //! The [`LeoAst`] type is intended to be parsed and modified by different passes
#[macro_use] //! of the Leo compiler. The Leo compiler can generate a set of R1CS constraints from any [`LeoAst`].
extern crate thiserror;
pub mod ast; pub mod annotation;
pub use self::annotation::*;
pub mod access;
pub mod annotations;
pub mod circuits; pub mod circuits;
pub use self::circuits::*;
pub mod common; pub mod common;
pub use self::common::*;
pub mod console; pub mod console;
pub mod definitions; pub use self::console::*;
pub mod expressions;
pub mod files;
pub mod functions;
pub mod imports;
pub mod operations;
pub mod statements;
pub mod types;
pub mod values;
pub mod errors; pub mod errors;
pub use errors::*; pub use self::errors::*;
pub(crate) mod span; pub mod expression;
pub(crate) use span::*; pub use self::expression::*;
use from_pest::FromPest; pub mod functions;
use std::{fs, path::Path}; pub use self::functions::*;
pub struct LeoAst<'ast> { pub mod groups;
ast: files::File<'ast>, pub use self::groups::*;
pub mod imports;
pub use self::imports::*;
pub mod input;
pub use self::input::*;
pub mod program;
pub use self::program::*;
pub mod statements;
pub use self::statements::*;
pub mod types;
pub use self::types::*;
use leo_grammar::Grammar;
/// The abstract syntax tree (ast) for a Leo program.
///
/// The [`LeoAst`] type represents a Leo program as a series of recursive data types.
/// These data types form a tree that begins from a [`Program`] type root.
///
/// A new [`LeoAst`] can be created from a [`Grammar`] generated by the pest parser in the `grammar` module.
#[derive(Debug, Eq, PartialEq)]
pub struct LeoAst {
ast: Program,
} }
impl<'ast> LeoAst<'ast> { impl LeoAst {
/// Creates a new abstract syntax tree given the file path. /// Creates a new syntax tree from a given program name and abstract syntax tree.
pub fn new(file_path: &'ast Path, program_string: &'ast str) -> Result<Self, ParserError> { pub fn new<'ast>(program_name: &str, ast: &Grammar<'ast>) -> Self {
// TODO (howardwu): Turn this check back on after fixing the testing module. Self {
// assert_eq!(program_string, fs::read_to_string(file_path).map_err(|_| ParserError::FileReadError(file_path.clone()))?); ast: Program::from(program_name, ast.as_repr()),
}
// Parse the file using leo.pest
let file = &mut ast::parse(&program_string)
.map_err(|error| ParserError::from(error.with_path(file_path.to_str().unwrap())))?;
// Builds the abstract syntax tree using pest derivation.
let ast = files::File::<'ast>::from_pest(file).map_err(|_| ParserError::SyntaxTreeError)?;
tracing::debug!("{:#?}", ast);
Ok(Self { ast })
} }
// TODO (howardwu): Remove this in favor of a dedicated file loader to verify checksums /// Returns a reference to the inner program syntax tree representation.
// and maintain a global cache of program strings during the compilation process. pub fn into_repr(self) -> Program {
/// Loads the Leo code as a string from the given file path. self.ast
pub fn load_file(file_path: &'ast Path) -> Result<String, ParserError> {
Ok(fs::read_to_string(file_path).map_err(|_| ParserError::FileReadError(file_path.to_owned()))?)
} }
/// Returns a reference to the inner abstract syntax tree representation. /// Serializes the syntax tree into a JSON string.
pub fn as_repr(&self) -> &files::File<'ast> { pub fn to_json_string(&self) -> Result<String, serde_json::Error> {
&self.ast
}
/// Serializes the abstract syntax tree into a JSON string.
pub fn to_json_string(&self) -> Result<String, ParserError> {
Ok(serde_json::to_string_pretty(&self.ast)?) Ok(serde_json::to_string_pretty(&self.ast)?)
} }
/// Deserializes the JSON string into a syntax tree.
pub fn from_json_string(json: &str) -> Result<Self, serde_json::Error> {
let ast: Program = serde_json::from_str(json)?;
Ok(Self { ast })
}
} }

View File

@ -14,21 +14,25 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::{LeoAst, ParserError}; use leo_ast::LeoAst;
use leo_grammar::{Grammar, ParserError};
use std::{env, fs, path::Path}; use std::{env, fs, path::Path};
fn to_leo_ast(filepath: &Path) -> Result<String, ParserError> { fn to_leo_tree(filepath: &Path) -> Result<String, ParserError> {
// Loads the Leo code as a string from the given file path. // Loads the Leo code as a string from the given file path.
let program_filepath = filepath.to_path_buf(); let program_filepath = filepath.to_path_buf();
let program_string = LeoAst::load_file(&program_filepath)?; let program_string = Grammar::load_file(&program_filepath)?;
// Parses the Leo file and constructs an abstract syntax tree. // Parses the Leo file and constructs a pest ast.
let ast = LeoAst::new(&program_filepath, &program_string)?; let ast = Grammar::new(&program_filepath, &program_string)?;
// Serializes the abstract syntax tree into JSON format. // Parse the pest ast and constructs a ast.
let serialized_ast = LeoAst::to_json_string(&ast)?; let leo_ast = LeoAst::new("leo_tree", &ast);
Ok(serialized_ast) // Serializes the tree into JSON format.
let serialized_leo_ast = LeoAst::to_json_string(&leo_ast)?;
Ok(serialized_leo_ast)
} }
fn main() -> Result<(), ParserError> { fn main() -> Result<(), ParserError> {
@ -47,9 +51,9 @@ fn main() -> Result<(), ParserError> {
// Construct the input filepath. // Construct the input filepath.
let input_filepath = Path::new(&cli_arguments[1]); let input_filepath = Path::new(&cli_arguments[1]);
// Construct the serialized abstract syntax tree. // Construct the serialized syntax tree.
let serialized_ast = to_leo_ast(&input_filepath)?; let serialized_leo_tree = to_leo_tree(&input_filepath)?;
println!("{}", serialized_ast); println!("{}", serialized_leo_tree);
// Determine the output directory. // Determine the output directory.
let output_directory = match cli_arguments.len() == 3 { let output_directory = match cli_arguments.len() == 3 {
@ -61,8 +65,8 @@ fn main() -> Result<(), ParserError> {
false => format!("./{}.json", input_filepath.file_stem().unwrap().to_str().unwrap()), false => format!("./{}.json", input_filepath.file_stem().unwrap().to_str().unwrap()),
}; };
// Write the serialized abstract syntax tree to the output directory. // Write the serialized syntax tree to the output directory.
fs::write(Path::new(&output_directory), serialized_ast)?; fs::write(Path::new(&output_directory), serialized_leo_tree)?;
Ok(()) Ok(())
} }

View File

@ -14,21 +14,21 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
//! A typed Leo program consists of import, circuit, and function definitions. //! A Leo program consists of import, circuit, and function definitions.
//! Each defined type consists of typed statements and expressions. //! Each defined type consists of ast statements and expressions.
use crate::{load_annotation, Circuit, Function, Identifier, Import, InputVariable, TestFunction}; use crate::{load_annotation, Circuit, Function, FunctionInput, Identifier, ImportStatement, TestFunction};
use leo_ast::{definitions::Definition, files::File}; use leo_grammar::{definitions::Definition, files::File};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
/// A simple program with statement expressions, program arguments and program returns. /// Stores the Leo program abstract syntax tree.
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct Program { pub struct Program {
pub name: String, pub name: String,
pub expected_input: Vec<InputVariable>, pub expected_input: Vec<FunctionInput>,
pub imports: Vec<Import>, pub imports: Vec<ImportStatement>,
pub circuits: HashMap<Identifier, Circuit>, pub circuits: HashMap<Identifier, Circuit>,
pub functions: HashMap<Identifier, Function>, pub functions: HashMap<Identifier, Function>,
pub tests: HashMap<Identifier, TestFunction>, pub tests: HashMap<Identifier, TestFunction>,
@ -50,7 +50,7 @@ impl<'ast> Program {
.to_owned() .to_owned()
.into_iter() .into_iter()
.for_each(|definition| match definition { .for_each(|definition| match definition {
Definition::Import(import) => imports.push(Import::from(import)), Definition::Import(import) => imports.push(ImportStatement::from(import)),
Definition::Circuit(circuit) => { Definition::Circuit(circuit) => {
circuits.insert(Identifier::from(circuit.identifier.clone()), Circuit::from(circuit)); circuits.insert(Identifier::from(circuit.identifier.clone()), Circuit::from(circuit));
} }

View File

@ -14,27 +14,42 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use crate::{ConditionalStatement, Statement};
ast::Rule, use leo_grammar::statements::ConditionalNestedOrEndStatement as GrammarConditionalNestedOrEndStatement;
statements::{ConditionalStatement, Statement},
};
use pest_ast::FromPest; use serde::{Deserialize, Serialize};
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::conditional_nested_or_end_statement))] pub enum ConditionalNestedOrEndStatement {
pub enum ConditionalNestedOrEndStatement<'ast> { Nested(Box<ConditionalStatement>),
Nested(Box<ConditionalStatement<'ast>>), End(Vec<Statement>),
End(Vec<Statement<'ast>>),
} }
impl<'ast> fmt::Display for ConditionalNestedOrEndStatement<'ast> { impl<'ast> From<GrammarConditionalNestedOrEndStatement<'ast>> for ConditionalNestedOrEndStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn from(statement: GrammarConditionalNestedOrEndStatement<'ast>) -> Self {
match *self { match statement {
ConditionalNestedOrEndStatement::Nested(ref nested) => write!(f, "else {}", nested), GrammarConditionalNestedOrEndStatement::Nested(nested) => {
ConditionalNestedOrEndStatement::End(ref statements) => write!(f, "else {{\n \t{:#?}\n }}", statements), ConditionalNestedOrEndStatement::Nested(Box::new(ConditionalStatement::from(*nested)))
}
GrammarConditionalNestedOrEndStatement::End(statements) => {
ConditionalNestedOrEndStatement::End(statements.into_iter().map(Statement::from).collect())
}
}
}
}
impl fmt::Display for ConditionalNestedOrEndStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ConditionalNestedOrEndStatement::Nested(ref nested) => write!(f, "else {}", nested),
ConditionalNestedOrEndStatement::End(ref statements) => {
writeln!(f, "else {{")?;
for statement in statements.iter() {
writeln!(f, "\t\t{}", statement)?;
}
write!(f, "\t}}")
}
} }
} }
} }

View File

@ -14,36 +14,41 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use crate::{ConditionalNestedOrEndStatement, Expression, Statement};
ast::Rule, use leo_grammar::statements::ConditionalStatement as GrammarConditionalStatement;
expressions::Expression,
statements::{ConditionalNestedOrEndStatement, Statement},
SpanDef,
};
use pest::Span; use serde::{Deserialize, Serialize};
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
#[pest_ast(rule(Rule::statement_conditional))] pub struct ConditionalStatement {
pub struct ConditionalStatement<'ast> { pub condition: Expression,
pub condition: Expression<'ast>, pub statements: Vec<Statement>,
pub statements: Vec<Statement<'ast>>, pub next: Option<ConditionalNestedOrEndStatement>,
pub next: Option<ConditionalNestedOrEndStatement<'ast>>,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
} }
impl<'ast> fmt::Display for ConditionalStatement<'ast> { impl<'ast> From<GrammarConditionalStatement<'ast>> for ConditionalStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn from(statement: GrammarConditionalStatement<'ast>) -> Self {
writeln!(f, "if ({}) {{", self.condition)?; ConditionalStatement {
writeln!(f, "\t{:#?}", self.statements)?; condition: Expression::from(statement.condition),
self.next statements: statement.statements.into_iter().map(Statement::from).collect(),
.as_ref() next: statement
.map(|n_or_e| write!(f, "}} {}", n_or_e)) .next
.unwrap_or_else(|| write!(f, "}}")) .map(|n_or_e| Some(ConditionalNestedOrEndStatement::from(n_or_e)))
.unwrap_or(None),
}
}
}
impl fmt::Display for ConditionalStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "if ({}) {{", self.condition)?;
for statement in self.statements.iter() {
writeln!(f, "\t\t{}", statement)?;
}
match self.next.clone() {
Some(n_or_e) => write!(f, "\t}} {}", n_or_e),
None => write!(f, "\t}}"),
}
} }
} }

View File

@ -14,26 +14,11 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
pub mod assign_statement; pub mod conditional_nested_or_end_statement;
pub use assign_statement::*; pub use conditional_nested_or_end_statement::*;
pub mod conditional_statement; pub mod conditional_statement;
pub use conditional_statement::*; pub use conditional_statement::*;
pub mod conditional_nested_or_end_statement;
pub use conditional_nested_or_end_statement::*;
pub mod definition_statement;
pub use definition_statement::*;
pub mod expression_statement;
pub use expression_statement::*;
pub mod for_statement;
pub use for_statement::*;
pub mod return_statement;
pub use return_statement::*;
pub mod statement; pub mod statement;
pub use statement::*; pub use statement::*;

View File

@ -14,34 +14,177 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, console::ConsoleFunctionCall, statements::*}; use crate::{Assignee, ConditionalStatement, ConsoleFunctionCall, Declare, Expression, Identifier, Span, Variables};
use leo_grammar::{
console::ConsoleFunctionCall as GrammarConsoleFunctionCall,
operations::AssignOperation,
statements::{
AssignStatement,
DefinitionStatement,
ExpressionStatement,
ForStatement,
ReturnStatement,
Statement as GrammarStatement,
},
};
use pest_ast::FromPest; use serde::{Deserialize, Serialize};
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] /// Program statement that defines some action (or expression) to be carried out.
#[pest_ast(rule(Rule::statement))] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Statement<'ast> { pub enum Statement {
Return(ReturnStatement<'ast>), Return(Expression, Span),
Definition(DefinitionStatement<'ast>), Definition(Declare, Variables, Expression, Span),
Assign(AssignStatement<'ast>), Assign(Assignee, Expression, Span),
Conditional(ConditionalStatement<'ast>), Conditional(ConditionalStatement, Span),
Iteration(ForStatement<'ast>), Iteration(Identifier, Box<(Expression, Expression)>, Vec<Statement>, Span),
Console(ConsoleFunctionCall<'ast>), Console(ConsoleFunctionCall),
Expression(ExpressionStatement<'ast>), Expression(Expression, Span),
} }
impl<'ast> fmt::Display for Statement<'ast> { impl<'ast> From<ReturnStatement<'ast>> for Statement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn from(statement: ReturnStatement<'ast>) -> Self {
match *self { Statement::Return(Expression::from(statement.expression), Span::from(statement.span))
Statement::Return(ref statement) => write!(f, "{}", statement), }
Statement::Definition(ref statement) => write!(f, "{}", statement), }
Statement::Assign(ref statement) => write!(f, "{}", statement),
Statement::Conditional(ref statement) => write!(f, "{}", statement), impl<'ast> From<DefinitionStatement<'ast>> for Statement {
Statement::Iteration(ref statement) => write!(f, "{}", statement), fn from(statement: DefinitionStatement<'ast>) -> Self {
Statement::Console(ref statement) => write!(f, "{}", statement), let span = Span::from(statement.span);
Statement::Expression(ref statement) => write!(f, "{}", statement.expression),
Statement::Definition(
Declare::from(statement.declare),
Variables::from(statement.variables),
Expression::from(statement.expression),
span,
)
}
}
impl<'ast> From<AssignStatement<'ast>> for Statement {
fn from(statement: AssignStatement<'ast>) -> Self {
match statement.assign {
AssignOperation::Assign(ref _assign) => Statement::Assign(
Assignee::from(statement.assignee),
Expression::from(statement.expression),
Span::from(statement.span),
),
operation_assign => {
// convert assignee into postfix expression
let converted = Expression::from(statement.assignee.clone());
match operation_assign {
AssignOperation::AddAssign(ref _assign) => Statement::Assign(
Assignee::from(statement.assignee),
Expression::Add(
Box::new((converted, Expression::from(statement.expression))),
Span::from(statement.span.clone()),
),
Span::from(statement.span),
),
AssignOperation::SubAssign(ref _assign) => Statement::Assign(
Assignee::from(statement.assignee),
Expression::Sub(
Box::new((converted, Expression::from(statement.expression))),
Span::from(statement.span.clone()),
),
Span::from(statement.span),
),
AssignOperation::MulAssign(ref _assign) => Statement::Assign(
Assignee::from(statement.assignee),
Expression::Mul(
Box::new((converted, Expression::from(statement.expression))),
Span::from(statement.span.clone()),
),
Span::from(statement.span),
),
AssignOperation::DivAssign(ref _assign) => Statement::Assign(
Assignee::from(statement.assignee),
Expression::Div(
Box::new((converted, Expression::from(statement.expression))),
Span::from(statement.span.clone()),
),
Span::from(statement.span),
),
AssignOperation::PowAssign(ref _assign) => Statement::Assign(
Assignee::from(statement.assignee),
Expression::Pow(
Box::new((converted, Expression::from(statement.expression))),
Span::from(statement.span.clone()),
),
Span::from(statement.span),
),
AssignOperation::Assign(ref _assign) => unimplemented!("cannot assign twice to assign statement"),
}
}
}
}
}
impl<'ast> From<ForStatement<'ast>> for Statement {
fn from(statement: ForStatement<'ast>) -> Self {
Statement::Iteration(
Identifier::from(statement.index),
Box::new((Expression::from(statement.start), Expression::from(statement.stop))),
statement.statements.into_iter().map(Statement::from).collect(),
Span::from(statement.span),
)
}
}
impl<'ast> From<GrammarConsoleFunctionCall<'ast>> for Statement {
fn from(function_call: GrammarConsoleFunctionCall<'ast>) -> Self {
Statement::Console(ConsoleFunctionCall::from(function_call))
}
}
impl<'ast> From<ExpressionStatement<'ast>> for Statement {
fn from(statement: ExpressionStatement<'ast>) -> Self {
let span = Span::from(statement.span);
let mut expression = Expression::from(statement.expression);
expression.set_span(span.clone());
Statement::Expression(expression, span)
}
}
impl<'ast> From<GrammarStatement<'ast>> for Statement {
fn from(statement: GrammarStatement<'ast>) -> Self {
match statement {
GrammarStatement::Return(statement) => Statement::from(statement),
GrammarStatement::Definition(statement) => Statement::from(statement),
GrammarStatement::Assign(statement) => Statement::from(statement),
GrammarStatement::Conditional(statement) => {
let span = Span::from(statement.span.clone());
Statement::Conditional(ConditionalStatement::from(statement), span)
}
GrammarStatement::Iteration(statement) => Statement::from(statement),
GrammarStatement::Console(console) => Statement::from(console),
GrammarStatement::Expression(statement) => Statement::from(statement),
}
}
}
impl fmt::Display for Statement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Statement::Return(ref expression, ref _span) => write!(f, "return {}", expression),
Statement::Definition(ref declare, ref variable, ref expression, ref _span) => {
write!(f, "{} {} = {};", declare, variable, expression)
}
Statement::Assign(ref variable, ref statement, ref _span) => write!(f, "{} = {};", variable, statement),
Statement::Conditional(ref statement, ref _span) => write!(f, "{}", statement),
Statement::Iteration(ref var, ref start_stop, ref list, ref _span) => {
writeln!(f, "for {} in {}..{} {{", var, start_stop.0, start_stop.1)?;
for l in list {
writeln!(f, "\t\t{}", l)?;
}
write!(f, "\t}}")
}
Statement::Console(ref console) => write!(f, "{}", console),
Statement::Expression(ref expression, ref _span) => write!(f, "{};", expression),
} }
} }
} }

View File

@ -14,17 +14,116 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ use leo_grammar::types::{
ast::Rule, IntegerType as GrammarIntegerType,
types::{SignedIntegerType, UnsignedIntegerType}, SignedIntegerType as GrammarSignedIntegerType,
UnsignedIntegerType as GrammarUnsignedIntegerType,
};
use leo_input::types::{
IntegerType as InputIntegerType,
SignedIntegerType as InputSignedIntegerType,
UnsignedIntegerType as InputUnsignedIntegerType,
}; };
use pest_ast::FromPest; use serde::{Deserialize, Serialize};
use serde::Serialize; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] /// Explicit integer type
#[pest_ast(rule(Rule::type_integer))] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum IntegerType { pub enum IntegerType {
Signed(SignedIntegerType), U8,
Unsigned(UnsignedIntegerType), U16,
U32,
U64,
U128,
I8,
I16,
I32,
I64,
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 {
InputIntegerType::Signed(signed) => Self::from(signed),
InputIntegerType::Unsigned(unsigned) => Self::from(unsigned),
}
}
}
impl From<InputUnsignedIntegerType> for IntegerType {
fn from(integer_type: InputUnsignedIntegerType) -> Self {
match integer_type {
InputUnsignedIntegerType::U8Type(_type) => IntegerType::U8,
InputUnsignedIntegerType::U16Type(_type) => IntegerType::U16,
InputUnsignedIntegerType::U32Type(_type) => IntegerType::U32,
InputUnsignedIntegerType::U64Type(_type) => IntegerType::U64,
InputUnsignedIntegerType::U128Type(_type) => IntegerType::U128,
}
}
}
impl From<InputSignedIntegerType> for IntegerType {
fn from(integer_type: InputSignedIntegerType) -> Self {
match integer_type {
InputSignedIntegerType::I8Type(_type) => IntegerType::I8,
InputSignedIntegerType::I16Type(_type) => IntegerType::I16,
InputSignedIntegerType::I32Type(_type) => IntegerType::I32,
InputSignedIntegerType::I64Type(_type) => IntegerType::I64,
InputSignedIntegerType::I128Type(_type) => IntegerType::I128,
}
}
}
impl fmt::Display for IntegerType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
IntegerType::U8 => write!(f, "u8"),
IntegerType::U16 => write!(f, "u16"),
IntegerType::U32 => write!(f, "u32"),
IntegerType::U64 => write!(f, "u64"),
IntegerType::U128 => write!(f, "u128"),
IntegerType::I8 => write!(f, "i8"),
IntegerType::I16 => write!(f, "i16"),
IntegerType::I32 => write!(f, "i32"),
IntegerType::I64 => write!(f, "i64"),
IntegerType::I128 => write!(f, "i128"),
}
}
} }

View File

@ -14,44 +14,8 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
pub mod address_type;
pub use address_type::*;
pub mod array_dimensions;
pub use array_dimensions::*;
pub mod array_type;
pub use array_type::*;
pub mod boolean_type;
pub use boolean_type::*;
pub mod circuit_type;
pub use circuit_type::*;
pub mod data_type;
pub use data_type::*;
pub mod field_type;
pub use field_type::*;
pub mod group_type;
pub use group_type::*;
pub mod integer_type; pub mod integer_type;
pub use integer_type::*; pub use integer_type::*;
pub mod self_type;
pub use self_type::*;
pub mod signed_integer_type;
pub use signed_integer_type::*;
pub mod tuple_type;
pub use tuple_type::*;
pub mod type_; pub mod type_;
pub use type_::*; pub use type_::*;
pub mod unsigned_integer_type;
pub use unsigned_integer_type::*;

View File

@ -14,30 +14,220 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, types::*}; 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,
TupleType as InputTupleType,
Type as InputType,
};
use pest_ast::FromPest; use serde::{Deserialize, Serialize};
use serde::Serialize;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] /// Explicit type used for defining a variable or expression type
#[pest_ast(rule(Rule::type_))] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Type<'ast> { pub enum Type {
Basic(DataType), // Data types
Array(ArrayType<'ast>), Address,
Tuple(TupleType<'ast>), Boolean,
Circuit(CircuitType<'ast>), Field,
SelfType(SelfType<'ast>), Group,
IntegerType(IntegerType),
// Data type wrappers
Array(Box<Type>, ArrayDimensions),
Tuple(Vec<Type>),
Circuit(Identifier),
SelfType,
} }
impl<'ast> fmt::Display for Type<'ast> { impl Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ///
match *self { /// Returns `true` if the self `Type` is the `SelfType`.
Type::Basic(ref _type) => write!(f, "basic"), ///
Type::Array(ref _type) => write!(f, "array"), pub fn is_self(&self) -> bool {
Type::Tuple(ref _type) => write!(f, "tuple"), matches!(self, Type::SelfType)
Type::Circuit(ref _type) => write!(f, "struct"), }
Type::SelfType(ref type_) => write!(f, "{}", type_.keyword),
///
/// Returns `true` if the self `Type` is a `Circuit`.
///
pub fn is_circuit(&self) -> bool {
matches!(self, Type::Circuit(_))
}
///
/// Returns `true` if the self `Type` is equal to the other `Type`.
///
/// Flattens array syntax: `[[u8; 1]; 2] == [u8; (2, 1)] == true`
///
pub fn eq_flat(&self, other: &Self) -> bool {
match (self, other) {
(Type::Address, Type::Address) => true,
(Type::Boolean, Type::Boolean) => true,
(Type::Field, Type::Field) => true,
(Type::Group, Type::Group) => true,
(Type::IntegerType(left), Type::IntegerType(right)) => left.eq(&right),
(Type::Circuit(left), Type::Circuit(right)) => left.eq(&right),
(Type::SelfType, Type::SelfType) => true,
(Type::Array(left_type, left_dim), Type::Array(right_type, right_dim)) => {
// Convert array dimensions to owned.
let mut left_dim_owned = left_dim.to_owned();
let mut right_dim_owned = right_dim.to_owned();
// Remove the first element from both dimensions.
let left_first = left_dim_owned.remove_first();
let right_first = right_dim_owned.remove_first();
// Compare the first dimensions.
if left_first.ne(&right_first) {
return false;
}
// Create a new array type from the remaining array dimensions.
let left_new_type = inner_array_type(*left_type.to_owned(), left_dim_owned);
let right_new_type = inner_array_type(*right_type.to_owned(), right_dim_owned);
// Call eq_flat() on the new left and right types.
left_new_type.eq_flat(&right_new_type)
}
(Type::Tuple(left), Type::Tuple(right)) => left
.iter()
.zip(right)
.all(|(left_type, right_type)| left_type.eq_flat(right_type)),
_ => false,
} }
} }
} }
/// 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 {
fn from(data_type: InputDataType) -> Self {
match data_type {
InputDataType::Address(_type) => Type::Address,
InputDataType::Boolean(_type) => Type::Boolean,
InputDataType::Field(_type) => Type::Field,
InputDataType::Group(_type) => Type::Group,
InputDataType::Integer(type_) => Type::IntegerType(IntegerType::from(type_)),
}
}
}
impl<'ast> From<InputArrayType<'ast>> for Type {
fn from(array_type: InputArrayType<'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<InputTupleType<'ast>> for Type {
fn from(tuple_type: InputTupleType<'ast>) -> Self {
let types = tuple_type.types_.into_iter().map(Type::from).collect();
Type::Tuple(types)
}
}
impl<'ast> From<InputType<'ast>> for Type {
fn from(type_: InputType<'ast>) -> Self {
match type_ {
InputType::Basic(type_) => Type::from(type_),
InputType::Array(type_) => Type::from(type_),
InputType::Tuple(type_) => Type::from(type_),
}
}
}
impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Type::Address => write!(f, "address"),
Type::Boolean => write!(f, "bool"),
Type::Field => write!(f, "field"),
Type::Group => write!(f, "group"),
Type::IntegerType(ref integer_type) => write!(f, "{}", integer_type),
Type::Circuit(ref variable) => write!(f, "circuit {}", variable),
Type::SelfType => write!(f, "SelfType"),
Type::Array(ref array, ref dimensions) => write!(f, "[{}; {}]", *array, dimensions),
Type::Tuple(ref tuple) => {
let types = tuple.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(", ");
write!(f, "({})", types)
}
}
}
}
///
/// Returns the type of the inner array given an array element and array dimensions.
///
/// If the array has no dimensions, then an inner array does not exist. Simply return the given
/// element type.
///
/// If the array has dimensions, then an inner array exists. Create a new type for the
/// inner array. The element type of the new array should be the same as the old array. The
/// dimensions of the new array should be the old array dimensions with the first dimension removed.
///
pub fn inner_array_type(element_type: Type, dimensions: ArrayDimensions) -> Type {
if dimensions.is_empty() {
// The array has one dimension.
element_type
} else {
// The array has multiple dimensions.
Type::Array(Box::new(element_type), dimensions)
}
}

View File

@ -14,7 +14,4 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
mod expression;
mod function;
mod serialization; mod serialization;
mod tuple;

View File

@ -1,5 +1,5 @@
{ {
"name": "leo_typed_tree", "name": "leo_tree",
"expected_input": [], "expected_input": [],
"imports": [], "imports": [],
"circuits": {}, "circuits": {},
@ -7,7 +7,7 @@
"{\"name\":\"main\",\"span\":\"{\\\"text\\\":\\\" function main() {\\\",\\\"line\\\":1,\\\"start\\\":10,\\\"end\\\":14}\"}": { "{\"name\":\"main\",\"span\":\"{\\\"text\\\":\\\" function main() {\\\",\\\"line\\\":1,\\\"start\\\":10,\\\"end\\\":14}\"}": {
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"text\\\":\\\" function main() {\\\",\\\"line\\\":1,\\\"start\\\":10,\\\"end\\\":14}\"}", "identifier": "{\"name\":\"main\",\"span\":\"{\\\"text\\\":\\\" function main() {\\\",\\\"line\\\":1,\\\"start\\\":10,\\\"end\\\":14}\"}",
"input": [], "input": [],
"returns": null, "output": null,
"statements": [ "statements": [
{ {
"Return": [ "Return": [

View File

@ -14,25 +14,81 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::LeoAst;
#[cfg(not(feature = "ci_skip"))]
use leo_ast::Program;
use leo_grammar::Grammar;
use std::path::{Path, PathBuf};
fn to_ast(program_filepath: &Path) -> LeoAst {
// Loads the Leo code as a string from the given file path.
let program_string = Grammar::load_file(program_filepath).unwrap();
// Parses the Leo file and constructs a grammar ast.
let ast = Grammar::new(&program_filepath, &program_string).unwrap();
// Parses the pest ast and constructs a Leo ast.
LeoAst::new("leo_tree", &ast)
}
#[test] #[test]
#[cfg(not(feature = "ci_skip"))] #[cfg(not(feature = "ci_skip"))]
fn test_serialize() { fn test_serialize() {
use leo_ast::LeoAst; // Construct a ast from the given test file.
use std::path::PathBuf; let leo_ast = {
let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
program_filepath.push("tests/serialization/main.leo");
let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR")); to_ast(&program_filepath)
program_filepath.push("tests/serialization/main.leo"); };
let expected = include_str!("./expected_ast.json"); // Serializes the ast into JSON format.
let serialized_leo_ast: Program =
serde_json::from_value(serde_json::to_value(leo_ast.into_repr()).unwrap()).unwrap();
// Loads the Leo code as a string from the given file path. // Load the expected ast.
let program_string = LeoAst::load_file(&program_filepath).unwrap(); let expected: Program = serde_json::from_str(include_str!("expected_leo_ast.json")).unwrap();
// Parses the Leo file and constructs an abstract syntax tree. assert_eq!(expected, serialized_leo_ast);
let ast = LeoAst::new(&program_filepath, &program_string).unwrap(); }
// Serializes the abstract syntax tree into JSON format. #[test]
let serialized_ast = LeoAst::to_json_string(&ast).unwrap(); #[cfg(not(feature = "ci_skip"))]
fn test_deserialize() {
assert_eq!(expected, serialized_ast); // Load the expected ast.
let expected_leo_ast = {
let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
program_filepath.push("tests/serialization/main.leo");
to_ast(&program_filepath)
};
// Construct an ast by deserializing a ast JSON file.
let serialized_ast = include_str!("expected_leo_ast.json");
let leo_ast = LeoAst::from_json_string(serialized_ast).unwrap();
assert_eq!(expected_leo_ast, leo_ast);
}
#[test]
fn test_serialize_deserialize_serialize() {
// Construct a ast from the given test file.
let leo_ast = {
let mut program_filepath = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
program_filepath.push("tests/serialization/main.leo");
to_ast(&program_filepath)
};
// Serializes the ast into JSON format.
let serialized_leo_ast = leo_ast.to_json_string().unwrap();
// Deserializes the serialized ast into a LeoAst.
let leo_ast = LeoAst::from_json_string(&serialized_leo_ast).unwrap();
// Reserializes the ast into JSON format.
let reserialized_leo_ast = leo_ast.to_json_string().unwrap();
assert_eq!(serialized_leo_ast, reserialized_leo_ast);
} }

View File

@ -23,12 +23,20 @@ version = "1.0.4"
[dependencies.leo-core] [dependencies.leo-core]
path = "../core" path = "../core"
version = "1.0.2" version = "1.0.4"
[dependencies.leo-gadgets] [dependencies.leo-gadgets]
path = "../gadgets" path = "../gadgets"
version = "1.0.4" version = "1.0.4"
[dependencies.leo-grammar]
path = "../grammar"
version = "1.0.4"
[dependencies.leo-imports]
path = "../imports"
version = "1.0.4"
[dependencies.leo-input] [dependencies.leo-input]
path = "../input" path = "../input"
version = "1.0.4" version = "1.0.4"
@ -37,14 +45,18 @@ version = "1.0.4"
path = "../package" path = "../package"
version = "1.0.4" version = "1.0.4"
[dependencies.leo-typed]
path = "../typed"
version = "1.0.4"
[dependencies.leo-state] [dependencies.leo-state]
path = "../state" path = "../state"
version = "1.0.4" version = "1.0.4"
#[dependencies.leo-symbol-table]
#path = "../symbol-table"
#version = "1.0.4"
#[dependencies.leo-type-inference]
#path = "../type-inference"
#version = "1.0.4"
[dependencies.snarkos-curves] [dependencies.snarkos-curves]
version = "1.1.3" version = "1.1.3"
default-features = false default-features = false
@ -112,4 +124,4 @@ default-features = false
[features] [features]
default = [ ] default = [ ]
ci_skip = [ "leo-ast/ci_skip", "leo-typed/ci_skip" ] ci_skip = [ "leo-grammar/ci_skip", "leo-ast/ci_skip" ]

View File

@ -20,15 +20,17 @@ use crate::{
constraints::{generate_constraints, generate_test_constraints}, constraints::{generate_constraints, generate_test_constraints},
errors::CompilerError, errors::CompilerError,
GroupType, GroupType,
ImportParser,
OutputBytes, OutputBytes,
OutputFile, OutputFile,
}; };
use leo_ast::LeoAst; use leo_ast::{Input, LeoAst, MainInput, Program};
use leo_grammar::Grammar;
use leo_imports::ImportParser;
use leo_input::LeoInputParser; use leo_input::LeoInputParser;
use leo_package::inputs::InputPairs; use leo_package::inputs::InputPairs;
use leo_state::verify_local_data_commitment; use leo_state::verify_local_data_commitment;
use leo_typed::{Input, LeoTypedAst, MainInput, Program}; // use leo_symbol_table::SymbolTable;
// use leo_type_inference::TypeInference;
use snarkos_dpc::{base_dpc::instantiated::Components, SystemParameters}; use snarkos_dpc::{base_dpc::instantiated::Components, SystemParameters};
use snarkos_errors::gadgets::SynthesisError; use snarkos_errors::gadgets::SynthesisError;
@ -44,6 +46,7 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
/// Stores information to compile a Leo program.
#[derive(Clone)] #[derive(Clone)]
pub struct Compiler<F: Field + PrimeField, G: GroupType<F>> { pub struct Compiler<F: Field + PrimeField, G: GroupType<F>> {
package_name: String, package_name: String,
@ -57,6 +60,9 @@ pub struct Compiler<F: Field + PrimeField, G: GroupType<F>> {
} }
impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> { impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
///
/// Returns a new Leo program compiler.
///
pub fn new(package_name: String, main_file_path: PathBuf, output_directory: PathBuf) -> Self { pub fn new(package_name: String, main_file_path: PathBuf, output_directory: PathBuf) -> Self {
Self { Self {
package_name: package_name.clone(), package_name: package_name.clone(),
@ -64,14 +70,62 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
output_directory, output_directory,
program: Program::new(package_name), program: Program::new(package_name),
program_input: Input::new(), program_input: Input::new(),
imported_programs: ImportParser::new(), imported_programs: ImportParser::default(),
_engine: PhantomData, _engine: PhantomData,
_group: PhantomData, _group: PhantomData,
} }
} }
/// Parse the input and state files. ///
/// Stores a typed ast of all input variables to the program. /// Returns a new `Compiler` from the given main file path.
///
/// Parses and stores a program from the main file path.
/// Parses and stores all imported programs.
/// Performs type inference checking on the program and imported programs.
///
pub fn parse_program_without_input(
package_name: String,
main_file_path: PathBuf,
output_directory: PathBuf,
) -> Result<Self, CompilerError> {
let mut compiler = Self::new(package_name, main_file_path, output_directory);
compiler.parse_and_check_program()?;
Ok(compiler)
}
///
/// Returns a new `Compiler` from the given main file path.
///
/// Parses and stores program input from from the input file path and state file path
/// Parses and stores a program from the main file path.
/// Parses and stores all imported programs.
/// Performs type inference checking on the program, imported programs, and program input.
///
pub fn parse_program_with_input(
package_name: String,
main_file_path: PathBuf,
output_directory: PathBuf,
input_string: &str,
input_path: &Path,
state_string: &str,
state_path: &Path,
) -> Result<Self, CompilerError> {
let mut compiler = Self::new(package_name, main_file_path, output_directory);
compiler.parse_input(input_string, input_path, state_string, state_path)?;
compiler.parse_and_check_program()?;
Ok(compiler)
}
///
/// Parses and stores program input from from the input file path and state file path
///
/// Calls `set_path()` on compiler errors with the given input file path or state file path
///
pub fn parse_input( pub fn parse_input(
&mut self, &mut self,
input_string: &str, input_string: &str,
@ -104,55 +158,83 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
Ok(()) Ok(())
} }
/// Parses program files. ///
/// Returns a compiler struct that stores the typed program abstract syntax trees (ast). /// Runs program parser and type inference checker consecutively.
pub fn parse_program_without_input( ///
package_name: String, pub(crate) fn parse_and_check_program(&mut self) -> Result<(), CompilerError> {
main_file_path: PathBuf, self.parse_program()?;
output_directory: PathBuf,
) -> Result<Self, CompilerError> {
let mut compiler = Self::new(package_name, main_file_path, output_directory);
compiler.parse_program()?; self.check_program()
Ok(compiler)
} }
/// Parses input, state, and program files. ///
/// Returns a compiler struct that stores the typed input and typed program abstract syntax trees (ast). /// Parses and stores the main program file, constructs a syntax tree, and generates a program.
pub fn parse_program_with_input( ///
package_name: String, /// Parses and stores all programs imported by the main program file.
main_file_path: PathBuf, ///
output_directory: PathBuf,
input_string: &str,
input_path: &Path,
state_string: &str,
state_path: &Path,
) -> Result<Self, CompilerError> {
let mut compiler = Self::new(package_name, main_file_path, output_directory);
compiler.parse_input(input_string, input_path, state_string, state_path)?;
compiler.parse_program()?;
Ok(compiler)
}
/// Parses the Leo program file, constructs a syntax tree, and generates a program.
#[allow(deprecated)]
pub(crate) fn parse_program(&mut self) -> Result<(), CompilerError> { pub(crate) fn parse_program(&mut self) -> Result<(), CompilerError> {
// Use the parser to construct the abstract syntax tree. // Load the program file.
let program_string = LeoAst::load_file(&self.main_file_path)?; let program_string = Grammar::load_file(&self.main_file_path)?;
self.parse_program_from_string(&program_string) // Use the parser to construct the pest abstract syntax tree (ast).
let pest_ast = Grammar::new(&self.main_file_path, &program_string).map_err(|mut e| {
e.set_path(&self.main_file_path);
e
})?;
// Construct the core ast from the pest ast.
let core_ast = LeoAst::new(&self.package_name, &pest_ast);
// Store the main program file.
self.program = core_ast.into_repr();
// Parse and store all programs imported by the main program file.
self.imported_programs = ImportParser::parse(&self.program)?;
tracing::debug!("Program parsing complete\n{:#?}", self.program);
Ok(())
} }
/// Parses the Leo program string, constructs a syntax tree, and generates a program. ///
/// Runs a type check on the program, imports, and input.
///
/// First, a symbol table of all user defined types is created.
/// Second, a type inference check is run on the program - inferring a data type for all implicit types and
/// catching type mismatch errors.
///
pub(crate) fn check_program(&self) -> Result<(), CompilerError> {
// // Create a new symbol table from the program, imported_programs, and program_input.
// let _symbol_table =
// SymbolTable::new(&self.program, &self.imported_programs, &self.program_input).map_err(|mut e| {
// e.set_path(&self.main_file_path);
//
// e
// })?;
// // Run type inference check on program.
// TypeInference::new(&self.program, symbol_table).map_err(|mut e| {
// e.set_path(&self.main_file_path);
//
// e
// })?;
tracing::debug!("Program checks complete");
Ok(())
}
///
/// Equivalent to parse_and_check_program but uses the given program_string instead of a main
/// file path.
///
/// Used for testing only. /// Used for testing only.
///
#[deprecated(note = "Please use the 'parse_program' method instead.")] #[deprecated(note = "Please use the 'parse_program' method instead.")]
pub fn parse_program_from_string(&mut self, program_string: &str) -> Result<(), CompilerError> { pub fn parse_program_from_string(&mut self, program_string: &str) -> Result<(), CompilerError> {
// Use the given bytes to construct the abstract syntax tree. // Use the given bytes to construct the abstract syntax tree.
let ast = LeoAst::new(&self.main_file_path, &program_string).map_err(|mut e| { let ast = Grammar::new(&self.main_file_path, &program_string).map_err(|mut e| {
e.set_path(&self.main_file_path); e.set_path(&self.main_file_path);
e e
@ -161,23 +243,38 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
// Derive the package name. // Derive the package name.
let package_name = &self.package_name; let package_name = &self.package_name;
// Use the typed parser to construct the typed syntax tree. // Construct the core ast from the pest ast.
let typed_tree = LeoTypedAst::new(package_name, &ast); let core_ast = LeoAst::new(package_name, &ast);
self.program = typed_tree.into_repr(); // Store the main program file.
self.program = core_ast.into_repr();
// Parse and store all programs imported by the main program file.
self.imported_programs = ImportParser::parse(&self.program)?; self.imported_programs = ImportParser::parse(&self.program)?;
// // Create a new symbol table from the program, imported programs, and program input.
// let _symbol_table = SymbolTable::new(&self.program, &self.imported_programs, &self.program_input)?;
// // Run type inference check on program.
// TypeInference::new(&self.program, symbol_table)?;
tracing::debug!("Program parsing complete\n{:#?}", self.program); tracing::debug!("Program parsing complete\n{:#?}", self.program);
Ok(()) Ok(())
} }
/// Manually sets main function input ///
/// Manually sets main function input.
///
/// Used for testing only.
///
pub fn set_main_input(&mut self, input: MainInput) { pub fn set_main_input(&mut self, input: MainInput) {
self.program_input.set_main_input(input); self.program_input.set_main_input(input);
} }
/// Verifies the input to the program ///
/// Verifies the input to the program.
///
pub fn verify_local_data_commitment( pub fn verify_local_data_commitment(
&self, &self,
system_parameters: &SystemParameters<Components>, system_parameters: &SystemParameters<Components>,
@ -187,6 +284,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
Ok(result) Ok(result)
} }
///
/// Returns a Sha256 checksum of the program file.
///
pub fn checksum(&self) -> Result<String, CompilerError> { pub fn checksum(&self) -> Result<String, CompilerError> {
// Read in the main file as string // Read in the main file as string
let unparsed_file = fs::read_to_string(&self.main_file_path) let unparsed_file = fs::read_to_string(&self.main_file_path)
@ -200,7 +300,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
Ok(hex::encode(hash)) Ok(hex::encode(hash))
} }
///
/// Synthesizes the circuit without program input to verify correctness. /// Synthesizes the circuit without program input to verify correctness.
///
pub fn compile_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<OutputBytes, CompilerError> { pub fn compile_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<OutputBytes, CompilerError> {
let path = self.main_file_path; let path = self.main_file_path;
@ -213,7 +315,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
) )
} }
///
/// Synthesizes the circuit for test functions with program input. /// Synthesizes the circuit for test functions with program input.
///
pub fn compile_test_constraints(self, input_pairs: InputPairs) -> Result<(u32, u32), CompilerError> { pub fn compile_test_constraints(self, input_pairs: InputPairs) -> Result<(u32, u32), CompilerError> {
generate_test_constraints::<F, G>( generate_test_constraints::<F, G>(
self.program, self.program,
@ -224,7 +328,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
) )
} }
/// Calls the internal generate_constraints method with arguments ///
/// Calls the internal generate_constraints method with arguments.
///
pub fn generate_constraints_helper<CS: ConstraintSystem<F>>( pub fn generate_constraints_helper<CS: ConstraintSystem<F>>(
self, self,
cs: &mut CS, cs: &mut CS,
@ -237,30 +343,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}, },
) )
} }
pub fn to_bytes(&self) -> Result<Vec<u8>, CompilerError> {
Ok(bincode::serialize(&self.program)?)
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, CompilerError> {
let program: Program = bincode::deserialize(bytes)?;
let program_input = Input::new();
Ok(Self {
package_name: program.name.clone(),
main_file_path: PathBuf::new(),
output_directory: PathBuf::new(),
program,
program_input,
imported_programs: ImportParser::new(),
_engine: PhantomData,
_group: PhantomData,
})
}
} }
impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<F, G> { impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<F, G> {
///
/// Synthesizes the circuit with program input. /// Synthesizes the circuit with program input.
///
fn generate_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<(), SynthesisError> { fn generate_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
let output_directory = self.output_directory.clone(); let output_directory = self.output_directory.clone();
let package_name = self.package_name.clone(); let package_name = self.package_name.clone();

View File

@ -17,7 +17,7 @@
//! Enforces an assert equals statement in a compiled Leo program. //! Enforces an assert equals statement in a compiled Leo program.
use crate::{errors::ConsoleError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; use crate::{errors::ConsoleError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
use leo_typed::{Expression, Span, Type}; use leo_ast::{Expression, Span, Type};
use snarkos_models::{ use snarkos_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},

View File

@ -17,7 +17,7 @@
//! Evaluates a macro in a compiled Leo program. //! Evaluates a macro in a compiled Leo program.
use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType}; use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType};
use leo_typed::{ConsoleFunction, ConsoleFunctionCall}; use leo_ast::{ConsoleFunction, ConsoleFunctionCall};
use snarkos_models::{ use snarkos_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},

View File

@ -17,7 +17,7 @@
//! Evaluates a formatted string in a compiled Leo program. //! Evaluates a formatted string in a compiled Leo program.
use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType}; use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType};
use leo_typed::FormattedString; use leo_ast::FormattedString;
use snarkos_models::{ use snarkos_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},

View File

@ -22,14 +22,14 @@ use crate::{
ConstrainedProgram, ConstrainedProgram,
ConstrainedValue, ConstrainedValue,
GroupType, GroupType,
ImportParser,
OutputBytes, OutputBytes,
OutputFile, OutputFile,
}; };
use leo_typed::{Input, Program}; use leo_ast::{Input, Program};
use leo_imports::ImportParser;
use leo_input::LeoInputParser; use leo_input::LeoInputParser;
use leo_package::inputs::InputPairs; use leo_package::inputs::InputPairs;
use snarkos_models::{ use snarkos_models::{
curves::{Field, PrimeField}, curves::{Field, PrimeField},
gadgets::r1cs::{ConstraintSystem, TestConstraintSystem}, gadgets::r1cs::{ConstraintSystem, TestConstraintSystem},
@ -48,9 +48,7 @@ pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: Constrai
resolved_program.store_definitions(program, imported_programs)?; resolved_program.store_definitions(program, imported_programs)?;
let main = resolved_program let main = resolved_program.get(&main_function_name).ok_or(CompilerError::NoMain)?;
.get(&main_function_name)
.ok_or_else(|| CompilerError::NoMain)?;
match main.clone() { match main.clone() {
ConstrainedValue::Function(_circuit_identifier, function) => { ConstrainedValue::Function(_circuit_identifier, function) => {

View File

@ -21,7 +21,7 @@ use crate::{
value::ConstrainedValue, value::ConstrainedValue,
GroupType, GroupType,
}; };
use leo_typed::Identifier; use leo_ast::Identifier;
use snarkos_models::curves::{Field, PrimeField}; use snarkos_models::curves::{Field, PrimeField};

View File

@ -21,9 +21,9 @@ use crate::{
program::{new_scope, ConstrainedProgram}, program::{new_scope, ConstrainedProgram},
value::ConstrainedValue, value::ConstrainedValue,
GroupType, GroupType,
ImportParser,
}; };
use leo_typed::Program; use leo_ast::Program;
use leo_imports::ImportParser;
use snarkos_models::curves::{Field, PrimeField}; use snarkos_models::curves::{Field, PrimeField};

View File

@ -15,9 +15,12 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::errors::{FunctionError, ImportError, OutputBytesError, OutputFileError}; use crate::errors::{FunctionError, ImportError, OutputBytesError, OutputFileError};
use leo_ast::ParserError; use leo_grammar::ParserError;
use leo_imports::ImportParserError;
use leo_input::InputParserError; use leo_input::InputParserError;
use leo_state::LocalDataVerificationError; use leo_state::LocalDataVerificationError;
// use leo_symbol_table::SymbolTableError;
// use leo_type_inference::TypeInferenceError;
use bincode::Error as SerdeError; use bincode::Error as SerdeError;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -27,6 +30,9 @@ pub enum CompilerError {
#[error("{}", _0)] #[error("{}", _0)]
ImportError(#[from] ImportError), ImportError(#[from] ImportError),
#[error("{}", _0)]
ImportParserError(#[from] ImportParserError),
#[error("{}", _0)] #[error("{}", _0)]
InputParserError(#[from] InputParserError), InputParserError(#[from] InputParserError),
@ -62,6 +68,11 @@ pub enum CompilerError {
#[error("{}", _0)] #[error("{}", _0)]
SerdeError(#[from] SerdeError), SerdeError(#[from] SerdeError),
// #[error("{}", _0)]
// SymbolTableError(#[from] SymbolTableError),
// #[error("{}", _0)]
// TypeInferenceError(#[from] TypeInferenceError),
} }
impl CompilerError { impl CompilerError {
@ -70,6 +81,8 @@ impl CompilerError {
CompilerError::InputParserError(error) => error.set_path(path), CompilerError::InputParserError(error) => error.set_path(path),
CompilerError::FunctionError(error) => error.set_path(path), CompilerError::FunctionError(error) => error.set_path(path),
CompilerError::OutputStringError(error) => error.set_path(path), CompilerError::OutputStringError(error) => error.set_path(path),
// CompilerError::SymbolTableError(error) => error.set_path(path),
// CompilerError::TypeInferenceError(error) => error.set_path(path),
_ => {} _ => {}
} }
} }

View File

@ -15,7 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::errors::ExpressionError; use crate::errors::ExpressionError;
use leo_typed::{Error as FormattedError, Span}; use leo_ast::{Error as FormattedError, Span};
use std::path::Path; use std::path::Path;

View File

@ -15,8 +15,8 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::errors::{AddressError, BooleanError, FieldError, FunctionError, GroupError, IntegerError, ValueError}; use crate::errors::{AddressError, BooleanError, FieldError, FunctionError, GroupError, IntegerError, ValueError};
use leo_core::LeoCoreError; use leo_ast::{ArrayDimensions, Error as FormattedError, Identifier, PositiveNumber, Span};
use leo_typed::{Error as FormattedError, Identifier, Span}; use leo_core::LeoCorePackageError;
use snarkos_errors::gadgets::SynthesisError; use snarkos_errors::gadgets::SynthesisError;
use std::path::Path; use std::path::Path;
@ -45,7 +45,7 @@ pub enum ExpressionError {
IntegerError(#[from] IntegerError), IntegerError(#[from] IntegerError),
#[error("{}", _0)] #[error("{}", _0)]
LeoCoreError(#[from] LeoCoreError), LeoCoreError(#[from] LeoCorePackageError),
#[error("{}", _0)] #[error("{}", _0)]
ValueError(#[from] ValueError), ValueError(#[from] ValueError),
@ -109,12 +109,30 @@ impl ExpressionError {
Self::new_from_span(message, span) Self::new_from_span(message, span)
} }
pub fn invalid_index(actual: String, span: Span) -> Self { pub fn invalid_dimensions(expected: &ArrayDimensions, actual: &ArrayDimensions, span: Span) -> Self {
let message = format!("index must resolve to an integer, found `{}`", actual); let message = format!(
"expected array dimensions {}, found array dimensions {}",
expected, actual
);
Self::new_from_span(message, span) Self::new_from_span(message, span)
} }
pub fn invalid_first_dimension(expected: &PositiveNumber, actual: &PositiveNumber) -> Self {
let message = format!(
"expected array dimension {}, found array dimension {}",
expected, actual
);
Self::new_from_span(message, actual.span.to_owned())
}
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())
}
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); let message = format!("expected array length {}, found one with length {}", expected, actual);
@ -157,6 +175,12 @@ impl ExpressionError {
Self::new_from_span(message, span) Self::new_from_span(message, span)
} }
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!( let message = format!(
"circuit `{}` must be declared before it is used in an expression", "circuit `{}` must be declared before it is used in an expression",
@ -166,10 +190,10 @@ impl ExpressionError {
Self::new_from_span(message, span) Self::new_from_span(message, span)
} }
pub fn undefined_identifier(identifier: Identifier) -> Self { pub fn undefined_first_dimension(span: Span) -> Self {
let message = format!("cannot find value `{}` in this scope", identifier.name); let message = "the first dimension of the array must be a number".to_string();
Self::new_from_span(message, identifier.span) Self::new_from_span(message, span)
} }
pub fn undefined_function(function: String, span: Span) -> Self { pub fn undefined_function(function: String, span: Span) -> Self {
@ -181,6 +205,12 @@ impl ExpressionError {
Self::new_from_span(message, span) Self::new_from_span(message, span)
} }
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)
}
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); let message = format!("Circuit `{}` has no member `{}`", circuit, member);

View File

@ -25,7 +25,7 @@ use crate::errors::{
StatementError, StatementError,
ValueError, ValueError,
}; };
use leo_typed::{Error as FormattedError, Span}; use leo_ast::{Error as FormattedError, Span};
use std::path::Path; use std::path::Path;

View File

@ -14,11 +14,8 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::ParserError; use leo_ast::{Error as FormattedError, Identifier, ImportSymbol, Span};
use leo_typed::{Error as FormattedError, Identifier, ImportSymbol, Span}; use leo_core::LeoCorePackageError;
use leo_core::LeoCoreError;
use std::{io, path::Path};
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum ImportError { pub enum ImportError {
@ -26,10 +23,7 @@ pub enum ImportError {
Error(#[from] FormattedError), Error(#[from] FormattedError),
#[error("{}", _0)] #[error("{}", _0)]
LeoCoreError(#[from] LeoCoreError), LeoCoreError(#[from] LeoCorePackageError),
#[error("{}", _0)]
ParserError(#[from] ParserError),
} }
impl ImportError { impl ImportError {
@ -37,55 +31,6 @@ impl ImportError {
ImportError::Error(FormattedError::new_from_span(message, span)) ImportError::Error(FormattedError::new_from_span(message, span))
} }
fn new_from_span_with_path(message: String, span: Span, path: &Path) -> Self {
ImportError::Error(FormattedError::new_from_span_with_path(message, span, path))
}
pub fn conflicting_imports(identifier: Identifier) -> Self {
let message = format!("conflicting imports found for `{}`", identifier.name);
Self::new_from_span(message, identifier.span)
}
pub fn convert_os_string(span: Span) -> Self {
let message = "failed to convert file string name, maybe an illegal character?".to_string();
Self::new_from_span(message, span)
}
pub fn current_directory_error(error: io::Error) -> Self {
let span = Span {
text: "".to_string(),
line: 0,
start: 0,
end: 0,
};
let message = format!("compilation failed trying to find current directory - {:?}", error);
Self::new_from_span(message, span)
}
pub fn directory_error(error: io::Error, span: Span, path: &Path) -> Self {
let message = format!("compilation failed due to directory error - {:?}", error);
Self::new_from_span_with_path(message, span, path)
}
pub fn star(path: &Path, span: Span) -> Self {
let message = format!("cannot import `*` from path `{:?}`", path);
Self::new_from_span(message, span)
}
pub fn expected_lib_file(entry: String, span: Span) -> Self {
let message = format!(
"expected library file`{}` when looking for symbol `{}`",
entry, span.text
);
Self::new_from_span(message, span)
}
pub fn unknown_package(identifier: Identifier) -> Self { pub fn unknown_package(identifier: Identifier) -> Self {
let message = format!( let message = format!(
"cannot find imported package `{}` in source files or import directory", "cannot find imported package `{}` in source files or import directory",

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_typed::{Error as FormattedError, Span}; use leo_ast::{Error as FormattedError, Span};
use std::path::Path; use std::path::Path;

View File

@ -15,7 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::errors::{AddressError, BooleanError, ConsoleError, ExpressionError, IntegerError, ValueError}; use crate::errors::{AddressError, BooleanError, ConsoleError, ExpressionError, IntegerError, ValueError};
use leo_typed::{Error as FormattedError, Span, Type}; use leo_ast::{Error as FormattedError, Span, Type};
use std::path::Path; use std::path::Path;

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_typed::{Error as FormattedError, Span}; use leo_ast::{Error as FormattedError, Span};
use snarkos_errors::{gadgets::SynthesisError, objects::account::AccountError}; use snarkos_errors::{gadgets::SynthesisError, objects::account::AccountError};
use std::path::Path; use std::path::Path;

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_typed::{Error as FormattedError, Span}; use leo_ast::{Error as FormattedError, Span};
use snarkos_errors::gadgets::SynthesisError; use snarkos_errors::gadgets::SynthesisError;
use std::path::Path; use std::path::Path;

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_typed::{Error as FormattedError, Span}; use leo_ast::{Error as FormattedError, Span};
use snarkos_errors::gadgets::SynthesisError; use snarkos_errors::gadgets::SynthesisError;
use std::path::Path; use std::path::Path;

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_typed::{Error as FormattedError, Span}; use leo_ast::{Error as FormattedError, Span};
use snarkos_errors::gadgets::SynthesisError; use snarkos_errors::gadgets::SynthesisError;
use std::path::Path; use std::path::Path;

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