mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-30 05:02:04 +03:00
Merge pull request #426 from AleoHQ/feature/imports
Imports module. PR #411 part 1/3
This commit is contained in:
commit
b81c7ec25d
591
Cargo.lock
generated
591
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
19
Cargo.toml
19
Cargo.toml
@ -30,25 +30,32 @@ members = [
|
||||
"compiler",
|
||||
"core",
|
||||
"gadgets",
|
||||
"grammar",
|
||||
"imports",
|
||||
"input",
|
||||
"linter",
|
||||
"package",
|
||||
"typed",
|
||||
"state"
|
||||
"state",
|
||||
# "symbol-table",
|
||||
# "type-inference",
|
||||
]
|
||||
|
||||
[dependencies.leo-ast]
|
||||
path = "./ast"
|
||||
version = "1.0.4"
|
||||
|
||||
[dependencies.leo-compiler]
|
||||
path = "./compiler"
|
||||
version = "1.0.4"
|
||||
|
||||
[dependencies.leo-core]
|
||||
path = "./core"
|
||||
version = "1.0.2"
|
||||
|
||||
[dependencies.leo-gadgets]
|
||||
path = "./gadgets"
|
||||
version = "1.0.4"
|
||||
|
||||
[dependencies.leo-imports]
|
||||
path = "./imports"
|
||||
version = "1.0.4"
|
||||
|
||||
[dependencies.leo-input]
|
||||
path = "./input"
|
||||
version = "1.0.4"
|
||||
|
@ -2,7 +2,7 @@
|
||||
name = "leo-ast"
|
||||
version = "1.0.4"
|
||||
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"
|
||||
repository = "https://github.com/AleoHQ/leo"
|
||||
keywords = [
|
||||
@ -22,41 +22,38 @@ name = "leo_ast"
|
||||
path = "src/main.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "ast"
|
||||
path = "benches/ast.rs"
|
||||
name = "leo_ast"
|
||||
path = "benches/leo_ast.rs"
|
||||
harness = false
|
||||
|
||||
[dependencies.from-pest]
|
||||
version = "0.3.1"
|
||||
[dependencies.leo-grammar]
|
||||
path = "../grammar"
|
||||
version = "1.0.4"
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "1.3.0"
|
||||
[dependencies.leo-input]
|
||||
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]
|
||||
version = "2.0"
|
||||
|
||||
[dependencies.pest-ast]
|
||||
version = "0.3.3"
|
||||
|
||||
[dependencies.pest_derive]
|
||||
version = "2.0"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
features = [ "derive" ]
|
||||
|
||||
[dependencies.serde_json]
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.thiserror]
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.tracing]
|
||||
version = "0.1"
|
||||
|
||||
[dev-dependencies.criterion]
|
||||
version = "0.3"
|
||||
|
||||
[features]
|
||||
default = [ ]
|
||||
ci_skip = [ ]
|
||||
ci_skip = [ "leo-grammar/ci_skip" ]
|
||||
|
@ -15,69 +15,69 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_ast::LeoAst;
|
||||
use leo_typed::LeoTypedAst;
|
||||
use leo_grammar::Grammar;
|
||||
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use std::{path::Path, time::Duration};
|
||||
|
||||
fn leo_typed_ast<'ast>(ast: &LeoAst<'ast>) -> LeoTypedAst {
|
||||
LeoTypedAst::new("leo_typed_tree", &ast)
|
||||
fn leo_ast<'ast>(ast: &Grammar<'ast>) -> LeoAst {
|
||||
LeoAst::new("leo_tree", &ast)
|
||||
}
|
||||
|
||||
fn bench_big_if_else(c: &mut Criterion) {
|
||||
let filepath = Path::new("./big_if_else.leo").to_path_buf();
|
||||
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) {
|
||||
let filepath = Path::new("./big_ternary.leo").to_path_buf();
|
||||
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) {
|
||||
let filepath = Path::new("./big_circuit.leo").to_path_buf();
|
||||
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) {
|
||||
let filepath = Path::new("./long_expr.leo").to_path_buf();
|
||||
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) {
|
||||
let filepath = Path::new("./long_array.leo").to_path_buf();
|
||||
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) {
|
||||
let filepath = Path::new("./many_foos.leo").to_path_buf();
|
||||
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) {
|
||||
let filepath = Path::new("./many_assigns.leo").to_path_buf();
|
||||
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!(
|
@ -14,8 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Circuit, Function, Identifier, Import, InputVariable, TestFunction};
|
||||
use leo_ast::{
|
||||
use crate::{Circuit, Function, FunctionInput, Identifier, ImportStatement, TestFunction};
|
||||
use leo_grammar::{
|
||||
annotations::{Annotation, AnnotationArguments, AnnotationName},
|
||||
definitions::{AnnotatedDefinition, Definition},
|
||||
};
|
||||
@ -24,11 +24,11 @@ use std::collections::HashMap;
|
||||
|
||||
pub fn load_annotation(
|
||||
annotated_definition: AnnotatedDefinition,
|
||||
_imports: &mut Vec<Import>,
|
||||
_imports: &mut Vec<ImportStatement>,
|
||||
_circuits: &mut HashMap<Identifier, Circuit>,
|
||||
_functions: &mut HashMap<Identifier, Function>,
|
||||
tests: &mut HashMap<Identifier, TestFunction>,
|
||||
_expected: &mut Vec<InputVariable>,
|
||||
_expected: &mut Vec<FunctionInput>,
|
||||
) {
|
||||
let ast_annotation = annotated_definition.annotation;
|
||||
let ast_definition = *annotated_definition.definition;
|
@ -14,18 +14,39 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, circuits::CircuitMember, common::Identifier, SpanDef};
|
||||
use crate::{CircuitMember, Identifier};
|
||||
use leo_grammar::circuits::Circuit as GrammarCircuit;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::circuit))]
|
||||
pub struct Circuit<'ast> {
|
||||
pub identifier: Identifier<'ast>,
|
||||
pub members: Vec<CircuitMember<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Circuit {
|
||||
pub circuit_name: Identifier,
|
||||
pub members: Vec<CircuitMember>,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarCircuit<'ast>> for Circuit {
|
||||
fn from(circuit: GrammarCircuit<'ast>) -> Self {
|
||||
let circuit_name = Identifier::from(circuit.identifier);
|
||||
let members = circuit.members.into_iter().map(CircuitMember::from).collect();
|
||||
|
||||
Self { circuit_name, members }
|
||||
}
|
||||
}
|
||||
|
||||
impl Circuit {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f, "circuit {} {{ ", self.circuit_name)?;
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -14,17 +14,67 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
circuits::{CircuitFunction, CircuitVariableDefinition},
|
||||
use crate::{Function, Identifier, Type};
|
||||
use leo_grammar::circuits::{
|
||||
CircuitFunction as GrammarCircuitFunction,
|
||||
CircuitMember as GrammarCircuitMember,
|
||||
CircuitVariableDefinition as GrammarCircuitVariableDefinition,
|
||||
};
|
||||
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::circuit_member))]
|
||||
pub enum CircuitMember<'ast> {
|
||||
CircuitVariableDefinition(CircuitVariableDefinition<'ast>),
|
||||
CircuitFunction(CircuitFunction<'ast>),
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum CircuitMember {
|
||||
// (is_mutable, variable_name, variable_type)
|
||||
CircuitVariable(bool, Identifier, Type),
|
||||
// (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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,24 +14,22 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
common::{Identifier, Mutable},
|
||||
types::Type,
|
||||
SpanDef,
|
||||
};
|
||||
use crate::{Expression, Identifier};
|
||||
use leo_grammar::circuits::CircuitVariable;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::circuit_variable_definition))]
|
||||
pub struct CircuitVariableDefinition<'ast> {
|
||||
pub mutable: Option<Mutable>,
|
||||
pub identifier: Identifier<'ast>,
|
||||
pub type_: Type<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CircuitVariableDefinition {
|
||||
pub identifier: Identifier,
|
||||
pub expression: Expression,
|
||||
}
|
||||
|
||||
impl<'ast> From<CircuitVariable<'ast>> for CircuitVariableDefinition {
|
||||
fn from(member: CircuitVariable<'ast>) -> Self {
|
||||
CircuitVariableDefinition {
|
||||
identifier: Identifier::from(member.identifier),
|
||||
expression: Expression::from(member.expression),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,14 +17,8 @@
|
||||
pub mod circuit;
|
||||
pub use circuit::*;
|
||||
|
||||
pub mod circuit_variable;
|
||||
pub use circuit_variable::*;
|
||||
|
||||
pub mod circuit_variable_definition;
|
||||
pub use circuit_variable_definition::*;
|
||||
|
||||
pub mod circuit_function;
|
||||
pub use circuit_function::*;
|
||||
|
||||
pub mod circuit_member;
|
||||
pub use circuit_member::*;
|
||||
|
168
ast/src/common/array_dimensions.rs
Normal file
168
ast/src/common/array_dimensions.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -14,32 +14,72 @@
|
||||
// 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::{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 pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::assignee))]
|
||||
pub struct Assignee<'ast> {
|
||||
pub name: SelfKeywordOrIdentifier<'ast>,
|
||||
pub accesses: Vec<AssigneeAccess<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum AssigneeAccess {
|
||||
Array(RangeOrExpression),
|
||||
Tuple(PositiveNumber, Span),
|
||||
Member(Identifier),
|
||||
}
|
||||
|
||||
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 {
|
||||
write!(f, "{}", self.name)?;
|
||||
for (i, access) in self.accesses.iter().enumerate() {
|
||||
write!(f, "{}", access)?;
|
||||
if i < self.accesses.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
write!(f, "{}", self.identifier)?;
|
||||
|
||||
for access in &self.accesses {
|
||||
match access {
|
||||
AssigneeAccess::Array(expression) => write!(f, "[{}]", expression)?,
|
||||
AssigneeAccess::Tuple(index, _span) => write!(f, ".{}", index)?,
|
||||
AssigneeAccess::Member(member) => write!(f, ".{}", member)?,
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, "")
|
||||
}
|
||||
}
|
||||
|
@ -14,22 +14,31 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::ast::Rule;
|
||||
use leo_grammar::common::Declare as GrammarDeclare;
|
||||
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::declare))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Declare {
|
||||
Const(Const),
|
||||
Let(Let),
|
||||
Const,
|
||||
Let,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::const_))]
|
||||
pub struct Const {}
|
||||
impl<'ast> From<GrammarDeclare> for Declare {
|
||||
fn from(declare: GrammarDeclare) -> Self {
|
||||
match declare {
|
||||
GrammarDeclare::Const(_) => Declare::Const,
|
||||
GrammarDeclare::Let(_) => Declare::Let,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::let_))]
|
||||
pub struct Let {}
|
||||
impl fmt::Display for Declare {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Declare::Const => write!(f, "const"),
|
||||
Declare::Let => write!(f, "let"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,28 +14,236 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ast::{span_into_string, Rule},
|
||||
SpanDef,
|
||||
use crate::Span;
|
||||
use leo_grammar::{
|
||||
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;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::identifier))]
|
||||
pub struct Identifier<'ast> {
|
||||
#[pest_ast(outer(with(span_into_string)))]
|
||||
pub value: String,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
/// An identifier in the constrained program.
|
||||
///
|
||||
/// Attention - When adding or removing fields from this struct,
|
||||
/// please remember to update it's Serialize and Deserialize implementation
|
||||
/// to reflect the new struct instantiation.
|
||||
#[derive(Clone)]
|
||||
pub struct Identifier {
|
||||
pub name: String,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for Identifier<'ast> {
|
||||
impl Identifier {
|
||||
pub fn new(name: String) -> Self {
|
||||
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.value)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -14,48 +14,30 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
pub mod array_dimensions;
|
||||
pub use array_dimensions::*;
|
||||
|
||||
pub mod assignee;
|
||||
pub use assignee::*;
|
||||
|
||||
pub mod declare;
|
||||
pub use declare::*;
|
||||
|
||||
pub mod eoi;
|
||||
pub use eoi::*;
|
||||
|
||||
pub mod identifier;
|
||||
pub use identifier::*;
|
||||
|
||||
pub mod keyword_or_identifier;
|
||||
pub use keyword_or_identifier::*;
|
||||
|
||||
pub mod line_end;
|
||||
pub use line_end::*;
|
||||
|
||||
pub mod mutable;
|
||||
pub use mutable::*;
|
||||
|
||||
pub mod range;
|
||||
pub use range::*;
|
||||
pub mod positive_number;
|
||||
pub use positive_number::*;
|
||||
|
||||
pub mod range_or_expression;
|
||||
pub use range_or_expression::*;
|
||||
|
||||
pub mod self_keyword;
|
||||
pub use self_keyword::*;
|
||||
|
||||
pub mod self_keyword_or_identifier;
|
||||
pub use self_keyword_or_identifier::*;
|
||||
|
||||
pub mod spread;
|
||||
pub use spread::*;
|
||||
pub mod span;
|
||||
pub use span::*;
|
||||
|
||||
pub mod spread_or_expression;
|
||||
pub use spread_or_expression::*;
|
||||
|
||||
pub mod static_;
|
||||
pub use static_::*;
|
||||
|
||||
pub mod variables;
|
||||
pub use variables::*;
|
||||
|
||||
|
82
ast/src/common/positive_number.rs
Normal file
82
ast/src/common/positive_number.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -14,37 +14,42 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, common::Range, expressions::Expression};
|
||||
use crate::Expression;
|
||||
use leo_grammar::common::RangeOrExpression as GrammarRangeOrExpression;
|
||||
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::range_or_expression))]
|
||||
pub enum RangeOrExpression<'ast> {
|
||||
Range(Range<'ast>),
|
||||
Expression(Expression<'ast>),
|
||||
/// Range or expression enum
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum RangeOrExpression {
|
||||
Range(Option<Expression>, Option<Expression>),
|
||||
Expression(Expression),
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for RangeOrExpression<'ast> {
|
||||
impl<'ast> From<GrammarRangeOrExpression<'ast>> for RangeOrExpression {
|
||||
fn from(range_or_expression: GrammarRangeOrExpression<'ast>) -> Self {
|
||||
match range_or_expression {
|
||||
GrammarRangeOrExpression::Range(range) => {
|
||||
RangeOrExpression::Range(range.from.map(Expression::from), range.to.map(Expression::from))
|
||||
}
|
||||
GrammarRangeOrExpression::Expression(expression) => {
|
||||
RangeOrExpression::Expression(Expression::from(expression))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RangeOrExpression {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
RangeOrExpression::Expression(ref expression) => write!(f, "{}", expression),
|
||||
RangeOrExpression::Range(ref range) => write!(
|
||||
RangeOrExpression::Range(ref from, ref to) => write!(
|
||||
f,
|
||||
"{}..{}",
|
||||
range
|
||||
.from
|
||||
.as_ref()
|
||||
.map(|v| v.to_string())
|
||||
.unwrap_or_else(|| "".to_string()),
|
||||
range
|
||||
.to
|
||||
.as_ref()
|
||||
.map(|v| v.to_string())
|
||||
.unwrap_or_else(|| "".to_string()),
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,11 +14,11 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use pest::Span as AstSpan;
|
||||
use pest::Span as GrammarSpan;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||
pub struct Span {
|
||||
/// text of input string
|
||||
pub text: String,
|
||||
@ -46,8 +46,8 @@ impl Hash for Span {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AstSpan<'ast>> for Span {
|
||||
fn from(span: AstSpan<'ast>) -> Self {
|
||||
impl<'ast> From<GrammarSpan<'ast>> for Span {
|
||||
fn from(span: GrammarSpan<'ast>) -> Self {
|
||||
let mut text = " ".to_string();
|
||||
let line_col = span.start_pos().line_col();
|
||||
let end = span.end_pos().line_col().1;
|
@ -14,23 +14,45 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, common::Spread, expressions::Expression};
|
||||
use crate::Expression;
|
||||
use leo_grammar::{
|
||||
common::SpreadOrExpression as GrammarSpreadOrExpression,
|
||||
expressions::Expression as GrammarExpression,
|
||||
};
|
||||
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::spread_or_expression))]
|
||||
pub enum SpreadOrExpression<'ast> {
|
||||
Spread(Spread<'ast>),
|
||||
Expression(Expression<'ast>),
|
||||
/// Spread or expression
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum SpreadOrExpression {
|
||||
Spread(Expression),
|
||||
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 {
|
||||
match *self {
|
||||
SpreadOrExpression::Spread(ref spread) => write!(f, "{}", spread),
|
||||
SpreadOrExpression::Spread(ref spread) => write!(f, "...{}", spread),
|
||||
SpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression),
|
||||
}
|
||||
}
|
||||
|
@ -14,30 +14,32 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
common::{Identifier, Mutable},
|
||||
SpanDef,
|
||||
};
|
||||
use crate::common::{Identifier, Span};
|
||||
use leo_grammar::common::VariableName as GrammarVariableName;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::variable_name))]
|
||||
pub struct VariableName<'ast> {
|
||||
pub mutable: Option<Mutable>,
|
||||
pub identifier: Identifier<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct VariableName {
|
||||
pub mutable: bool,
|
||||
pub identifier: Identifier,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
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 {
|
||||
if let Some(ref _mutable) = self.mutable {
|
||||
if self.mutable {
|
||||
write!(f, "mut ")?;
|
||||
}
|
||||
|
||||
|
@ -14,24 +14,30 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, common::VariableName, types::Type, SpanDef};
|
||||
use crate::{Type, VariableName};
|
||||
use leo_grammar::common::Variables as GrammarVariables;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::variables))]
|
||||
pub struct Variables<'ast> {
|
||||
pub names: Vec<VariableName<'ast>>,
|
||||
pub type_: Option<Type<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
/// A variable that is assigned to a value in the constrained program
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Variables {
|
||||
pub names: Vec<VariableName>,
|
||||
pub type_: Option<Type>,
|
||||
}
|
||||
|
||||
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 {
|
||||
if self.names.len() == 1 {
|
||||
// mut a
|
||||
|
@ -14,31 +14,68 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
console::{ConsoleAssert, ConsoleDebug, ConsoleError, ConsoleLog},
|
||||
use crate::{Expression, FormattedString};
|
||||
use leo_grammar::console::{
|
||||
ConsoleAssert as GrammarConsoleAssert,
|
||||
ConsoleDebug as GrammarConsoleDebug,
|
||||
ConsoleError as GrammarConsoleError,
|
||||
ConsoleFunction as GrammarConsoleFunction,
|
||||
ConsoleLog as GrammarConsoleLog,
|
||||
};
|
||||
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::console_function))]
|
||||
pub enum ConsoleFunction<'ast> {
|
||||
Assert(ConsoleAssert<'ast>),
|
||||
Debug(ConsoleDebug<'ast>),
|
||||
Error(ConsoleError<'ast>),
|
||||
Log(ConsoleLog<'ast>),
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum ConsoleFunction {
|
||||
Assert(Expression),
|
||||
Debug(FormattedString),
|
||||
Error(FormattedString),
|
||||
Log(FormattedString),
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for ConsoleFunction<'ast> {
|
||||
impl<'ast> From<GrammarConsoleFunction<'ast>> for ConsoleFunction {
|
||||
fn from(console_function: GrammarConsoleFunction<'ast>) -> Self {
|
||||
match console_function {
|
||||
GrammarConsoleFunction::Assert(assert) => ConsoleFunction::from(assert),
|
||||
GrammarConsoleFunction::Debug(debug) => ConsoleFunction::from(debug),
|
||||
GrammarConsoleFunction::Error(error) => ConsoleFunction::from(error),
|
||||
GrammarConsoleFunction::Log(log) => ConsoleFunction::from(log),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarConsoleAssert<'ast>> for ConsoleFunction {
|
||||
fn from(assert: GrammarConsoleAssert<'ast>) -> Self {
|
||||
ConsoleFunction::Assert(Expression::from(assert.expression))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarConsoleDebug<'ast>> for ConsoleFunction {
|
||||
fn from(debug: GrammarConsoleDebug<'ast>) -> Self {
|
||||
ConsoleFunction::Debug(FormattedString::from(debug.string))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarConsoleError<'ast>> for ConsoleFunction {
|
||||
fn from(error: GrammarConsoleError<'ast>) -> Self {
|
||||
ConsoleFunction::Error(FormattedString::from(error.string))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarConsoleLog<'ast>> for ConsoleFunction {
|
||||
fn from(log: GrammarConsoleLog<'ast>) -> Self {
|
||||
ConsoleFunction::Log(FormattedString::from(log.string))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ConsoleFunction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
ConsoleFunction::Assert(assert) => write!(f, "{}", assert),
|
||||
ConsoleFunction::Debug(debug) => write!(f, "{}", debug),
|
||||
ConsoleFunction::Error(error) => write!(f, "{}", error),
|
||||
ConsoleFunction::Log(log) => write!(f, "{}", log),
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,30 +14,34 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
common::LineEnd,
|
||||
console::{ConsoleFunction, ConsoleKeyword},
|
||||
SpanDef,
|
||||
};
|
||||
use crate::{ConsoleFunction, Span};
|
||||
use leo_grammar::console::ConsoleFunctionCall as GrammarConsoleFunctionCall;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::console_function_call))]
|
||||
pub struct ConsoleFunctionCall<'ast> {
|
||||
pub keyword: ConsoleKeyword<'ast>,
|
||||
pub function: ConsoleFunction<'ast>,
|
||||
pub line_end: LineEnd,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct ConsoleFunctionCall {
|
||||
pub function: ConsoleFunction,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
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 {
|
||||
write!(f, "console.{};", self.function)
|
||||
}
|
||||
|
@ -14,22 +14,26 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, SpanDef};
|
||||
use crate::Span;
|
||||
use leo_grammar::console::FormattedContainer as GrammarFormattedContainer;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::formatted_container))]
|
||||
pub struct FormattedContainer<'ast> {
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct FormattedContainer {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
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 {
|
||||
write!(f, "{{}}")
|
||||
}
|
||||
|
@ -14,23 +14,28 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, expressions::Expression, SpanDef};
|
||||
use crate::{Expression, Span};
|
||||
use leo_grammar::console::FormattedParameter as GrammarFormattedParameter;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::formatted_parameter))]
|
||||
pub struct FormattedParameter<'ast> {
|
||||
pub expression: Expression<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct FormattedParameter {
|
||||
pub expression: Expression,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
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 {
|
||||
write!(f, "{}", self.expression)
|
||||
}
|
||||
|
@ -14,30 +14,37 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ast::{span_into_string, Rule},
|
||||
console::{FormattedContainer, FormattedParameter},
|
||||
SpanDef,
|
||||
};
|
||||
use crate::{FormattedContainer, FormattedParameter, Span};
|
||||
use leo_grammar::console::FormattedString as GrammarFormattedString;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::formatted_string))]
|
||||
pub struct FormattedString<'ast> {
|
||||
#[pest_ast(outer(with(span_into_string)))]
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct FormattedString {
|
||||
pub string: String,
|
||||
pub containers: Vec<FormattedContainer<'ast>>,
|
||||
pub parameters: Vec<FormattedParameter<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
pub containers: Vec<FormattedContainer>,
|
||||
pub parameters: Vec<FormattedParameter>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
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 {
|
||||
write!(f, "{}", self.string)
|
||||
}
|
||||
|
@ -14,27 +14,12 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
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 use console_function::*;
|
||||
|
||||
pub mod 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 use formatted_container::*;
|
||||
|
||||
|
@ -14,8 +14,5 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
pub mod parser;
|
||||
pub use parser::*;
|
||||
|
||||
pub mod syntax;
|
||||
pub use syntax::*;
|
||||
pub mod error;
|
||||
pub use error::*;
|
||||
|
@ -15,23 +15,25 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ArrayDimensions,
|
||||
CircuitVariableDefinition,
|
||||
GroupValue,
|
||||
Identifier,
|
||||
IntegerType,
|
||||
PositiveNumber,
|
||||
RangeOrExpression,
|
||||
Span,
|
||||
SpreadOrExpression,
|
||||
};
|
||||
use leo_ast::{
|
||||
use leo_grammar::{
|
||||
access::{Access, AssigneeAccess},
|
||||
common::{Assignee, Identifier as AstIdentifier},
|
||||
common::{Assignee, Identifier as GrammarIdentifier},
|
||||
expressions::{
|
||||
ArrayInitializerExpression,
|
||||
ArrayInlineExpression,
|
||||
BinaryExpression,
|
||||
CircuitInlineExpression,
|
||||
Expression as AstExpression,
|
||||
Expression as GrammarExpression,
|
||||
PostfixExpression,
|
||||
TernaryExpression,
|
||||
UnaryExpression,
|
||||
@ -41,16 +43,14 @@ use leo_ast::{
|
||||
AddressValue,
|
||||
BooleanValue,
|
||||
FieldValue,
|
||||
GroupValue as AstGroupValue,
|
||||
GroupValue as GrammarGroupValue,
|
||||
IntegerValue,
|
||||
NumberValue as AstNumber,
|
||||
PositiveNumber as AstPositiveNumber,
|
||||
NumberValue as GrammarNumber,
|
||||
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 std::fmt;
|
||||
|
||||
@ -92,15 +92,17 @@ pub enum Expression {
|
||||
|
||||
// Arrays
|
||||
// (array_elements, span)
|
||||
Array(Vec<SpreadOrExpression>, Span),
|
||||
// (array_name, range, span)
|
||||
ArrayInline(Vec<SpreadOrExpression>, Span),
|
||||
// ((array element, dimensions), span)
|
||||
ArrayInitializer(Box<(Expression, ArrayDimensions)>, Span),
|
||||
// ((array_name, range), span)
|
||||
ArrayAccess(Box<(Expression, RangeOrExpression)>, Span),
|
||||
|
||||
// Tuples
|
||||
// (tuple_elements, span)
|
||||
Tuple(Vec<Expression>, Span),
|
||||
// (tuple_name, index, span)
|
||||
TupleAccess(Box<Expression>, usize, Span),
|
||||
// ((tuple_name, index), span)
|
||||
TupleAccess(Box<(Expression, PositiveNumber)>, Span),
|
||||
|
||||
// Circuits
|
||||
// (defined_circuit_name, circuit_members, span)
|
||||
@ -139,11 +141,12 @@ impl Expression {
|
||||
Expression::Lt(_, 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::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::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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
@ -228,7 +197,7 @@ impl<'ast> fmt::Display for Expression {
|
||||
}
|
||||
|
||||
// Arrays
|
||||
Expression::Array(ref array, ref _span) => {
|
||||
Expression::ArrayInline(ref array, ref _span) => {
|
||||
write!(f, "[")?;
|
||||
for (i, e) in array.iter().enumerate() {
|
||||
write!(f, "{}", e)?;
|
||||
@ -238,6 +207,7 @@ impl<'ast> fmt::Display for Expression {
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
Expression::ArrayInitializer(ref array, ref _span) => write!(f, "[{}; {}]", array.0, array.1),
|
||||
Expression::ArrayAccess(ref array_w_index, ref _span) => {
|
||||
write!(f, "{}[{}]", array_w_index.0, array_w_index.1)
|
||||
}
|
||||
@ -248,7 +218,9 @@ impl<'ast> fmt::Display for Expression {
|
||||
|
||||
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
|
||||
Expression::Circuit(ref var, ref members, ref _span) => {
|
||||
@ -326,8 +298,7 @@ impl<'ast> From<PostfixExpression<'ast>> for Expression {
|
||||
|
||||
// Handle tuple access
|
||||
Access::Tuple(tuple) => Expression::TupleAccess(
|
||||
Box::new(acc),
|
||||
Expression::get_count_from_ast(tuple.number),
|
||||
Box::new((acc, PositiveNumber::from(tuple.number))),
|
||||
Span::from(tuple.span),
|
||||
),
|
||||
|
||||
@ -356,19 +327,19 @@ impl<'ast> From<PostfixExpression<'ast>> for Expression {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AstExpression<'ast>> for Expression {
|
||||
fn from(expression: AstExpression<'ast>) -> Self {
|
||||
impl<'ast> From<GrammarExpression<'ast>> for Expression {
|
||||
fn from(expression: GrammarExpression<'ast>) -> Self {
|
||||
match expression {
|
||||
AstExpression::Value(value) => Expression::from(value),
|
||||
AstExpression::Identifier(variable) => Expression::from(variable),
|
||||
AstExpression::Unary(expression) => Expression::from(*expression),
|
||||
AstExpression::Binary(expression) => Expression::from(*expression),
|
||||
AstExpression::Ternary(expression) => Expression::from(*expression),
|
||||
AstExpression::ArrayInline(expression) => Expression::from(expression),
|
||||
AstExpression::ArrayInitializer(expression) => Expression::from(*expression),
|
||||
AstExpression::Tuple(expression) => Expression::from(expression),
|
||||
AstExpression::CircuitInline(expression) => Expression::from(expression),
|
||||
AstExpression::Postfix(expression) => Expression::from(expression),
|
||||
GrammarExpression::Value(value) => Expression::from(value),
|
||||
GrammarExpression::Identifier(variable) => Expression::from(variable),
|
||||
GrammarExpression::Unary(expression) => Expression::from(*expression),
|
||||
GrammarExpression::Binary(expression) => Expression::from(*expression),
|
||||
GrammarExpression::Ternary(expression) => Expression::from(*expression),
|
||||
GrammarExpression::ArrayInline(expression) => Expression::from(expression),
|
||||
GrammarExpression::ArrayInitializer(expression) => Expression::from(*expression),
|
||||
GrammarExpression::Tuple(expression) => Expression::from(expression),
|
||||
GrammarExpression::CircuitInline(expression) => Expression::from(expression),
|
||||
GrammarExpression::Postfix(expression) => Expression::from(expression),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -393,9 +364,8 @@ impl<'ast> From<Assignee<'ast>> for Expression {
|
||||
Span::from(array.span),
|
||||
),
|
||||
AssigneeAccess::Tuple(tuple) => Expression::TupleAccess(
|
||||
Box::new(acc),
|
||||
Expression::get_count_from_ast(tuple.number),
|
||||
Span::from(tuple.span),
|
||||
Box::new((acc, PositiveNumber::from(tuple.number))),
|
||||
Span::from(tuple.span.clone()),
|
||||
),
|
||||
})
|
||||
}
|
||||
@ -482,7 +452,7 @@ impl<'ast> From<TernaryExpression<'ast>> for Expression {
|
||||
|
||||
impl<'ast> From<ArrayInlineExpression<'ast>> for Expression {
|
||||
fn from(array: ArrayInlineExpression<'ast>) -> Self {
|
||||
Expression::Array(
|
||||
Expression::ArrayInline(
|
||||
array.expressions.into_iter().map(SpreadOrExpression::from).collect(),
|
||||
Span::from(array.span),
|
||||
)
|
||||
@ -491,26 +461,13 @@ impl<'ast> From<ArrayInlineExpression<'ast>> for Expression {
|
||||
|
||||
impl<'ast> From<ArrayInitializerExpression<'ast>> for Expression {
|
||||
fn from(array: ArrayInitializerExpression<'ast>) -> Self {
|
||||
let dimensions = Expression::get_array_dimensions(array.dimensions);
|
||||
let expression = SpreadOrExpression::from(array.expression);
|
||||
|
||||
let mut elements = vec![];
|
||||
|
||||
// Initializes an arrays elements using the rust `vec!` macro.
|
||||
// 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))
|
||||
Expression::ArrayInitializer(
|
||||
Box::new((
|
||||
Expression::from(array.expression),
|
||||
ArrayDimensions::from(array.dimensions),
|
||||
)),
|
||||
Span::from(array.span),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -569,17 +526,17 @@ impl<'ast> From<FieldValue<'ast>> for Expression {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AstGroupValue<'ast>> for Expression {
|
||||
fn from(ast_group: AstGroupValue<'ast>) -> Self {
|
||||
impl<'ast> From<GrammarGroupValue<'ast>> for Expression {
|
||||
fn from(ast_group: GrammarGroupValue<'ast>) -> Self {
|
||||
Expression::Group(Box::new(GroupValue::from(ast_group)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AstNumber<'ast>> for Expression {
|
||||
fn from(number: AstNumber<'ast>) -> Self {
|
||||
impl<'ast> From<GrammarNumber<'ast>> for Expression {
|
||||
fn from(number: GrammarNumber<'ast>) -> Self {
|
||||
let (value, span) = match number {
|
||||
AstNumber::Positive(number) => (number.value, number.span),
|
||||
AstNumber::Negative(number) => (number.value, number.span),
|
||||
GrammarNumber::Positive(number) => (number.value, number.span),
|
||||
GrammarNumber::Negative(number) => (number.value, number.span),
|
||||
};
|
||||
|
||||
Expression::Implicit(value, Span::from(span))
|
||||
@ -593,8 +550,8 @@ impl<'ast> From<IntegerValue<'ast>> for Expression {
|
||||
IntegerValue::Signed(integer) => {
|
||||
let type_ = IntegerType::from(integer.type_);
|
||||
let number = match integer.number {
|
||||
AstNumber::Negative(number) => number.value,
|
||||
AstNumber::Positive(number) => number.value,
|
||||
GrammarNumber::Negative(number) => number.value,
|
||||
GrammarNumber::Positive(number) => number.value,
|
||||
};
|
||||
|
||||
(type_, number)
|
||||
@ -611,8 +568,14 @@ impl<'ast> From<IntegerValue<'ast>> for Expression {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AstIdentifier<'ast>> for Expression {
|
||||
fn from(identifier: AstIdentifier<'ast>) -> Self {
|
||||
impl<'ast> From<TupleAccess<'ast>> for Expression {
|
||||
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))
|
||||
}
|
||||
}
|
@ -14,20 +14,79 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, 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 pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::function))]
|
||||
pub struct Function<'ast> {
|
||||
pub identifier: Identifier<'ast>,
|
||||
pub parameters: Vec<Input<'ast>>,
|
||||
pub returns: Option<Type<'ast>>,
|
||||
pub statements: Vec<Statement<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct Function {
|
||||
pub identifier: Identifier,
|
||||
pub input: Vec<FunctionInput>,
|
||||
pub output: Option<Type>,
|
||||
pub statements: Vec<Statement>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -14,24 +14,50 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
common::{Identifier, Mutable},
|
||||
types::Type,
|
||||
SpanDef,
|
||||
};
|
||||
use crate::{Identifier, Span, Type};
|
||||
use leo_grammar::functions::FunctionInput as GrammarFunctionInput;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::function_input))]
|
||||
pub struct FunctionInput<'ast> {
|
||||
pub mutable: Option<Mutable>,
|
||||
pub identifier: Identifier<'ast>,
|
||||
pub type_: Type<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct FunctionInputVariable {
|
||||
pub identifier: Identifier,
|
||||
pub mutable: bool,
|
||||
pub type_: Type,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -14,52 +14,52 @@
|
||||
// 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::{FunctionInput, Identifier, Span};
|
||||
use leo_ast::functions::input::Input as AstInput;
|
||||
use crate::{FunctionInputVariable, Identifier, Span};
|
||||
use leo_grammar::functions::input::Input as GrammarInput;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum InputVariable {
|
||||
pub enum FunctionInput {
|
||||
InputKeyword(Identifier),
|
||||
FunctionInput(FunctionInput),
|
||||
Variable(FunctionInputVariable),
|
||||
}
|
||||
|
||||
impl<'ast> From<AstInput<'ast>> for InputVariable {
|
||||
fn from(input: AstInput<'ast>) -> Self {
|
||||
impl<'ast> From<GrammarInput<'ast>> for FunctionInput {
|
||||
fn from(input: GrammarInput<'ast>) -> Self {
|
||||
match input {
|
||||
AstInput::InputKeyword(input_keyword) => {
|
||||
GrammarInput::InputKeyword(input_keyword) => {
|
||||
let id = Identifier {
|
||||
name: input_keyword.keyword,
|
||||
span: Span::from(input_keyword.span),
|
||||
};
|
||||
|
||||
InputVariable::InputKeyword(id)
|
||||
FunctionInput::InputKeyword(id)
|
||||
}
|
||||
AstInput::FunctionInput(function_input) => {
|
||||
InputVariable::FunctionInput(FunctionInput::from(function_input))
|
||||
GrammarInput::FunctionInput(function_input) => {
|
||||
FunctionInput::Variable(FunctionInputVariable::from(function_input))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InputVariable {
|
||||
impl FunctionInput {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
InputVariable::InputKeyword(id) => write!(f, "{}", id),
|
||||
InputVariable::FunctionInput(function_input) => write!(f, "{}", function_input),
|
||||
FunctionInput::InputKeyword(id) => write!(f, "{}", id),
|
||||
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 {
|
||||
self.format(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for InputVariable {
|
||||
impl fmt::Debug for FunctionInput {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.format(f)
|
||||
}
|
@ -14,13 +14,8 @@
|
||||
// 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/>.
|
||||
|
||||
#![allow(clippy::module_inception)]
|
||||
|
||||
pub mod function_input;
|
||||
pub use function_input::*;
|
||||
|
||||
pub mod input;
|
||||
pub use input::*;
|
||||
|
||||
pub mod input_keyword;
|
||||
pub use input_keyword::*;
|
||||
pub mod input_variable;
|
||||
pub use input_variable::*;
|
||||
|
@ -14,17 +14,22 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, functions::Function, SpanDef};
|
||||
use crate::{Function, Identifier};
|
||||
use leo_grammar::functions::TestFunction as GrammarTestFunction;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::test_function))]
|
||||
pub struct TestFunction<'ast> {
|
||||
pub function: Function<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct TestFunction {
|
||||
pub function: Function,
|
||||
pub input_file: Option<Identifier>,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarTestFunction<'ast>> for TestFunction {
|
||||
fn from(test: GrammarTestFunction) -> Self {
|
||||
TestFunction {
|
||||
function: Function::from(test.function),
|
||||
input_file: None, // pass custom input file with `@context` annotation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,12 +15,12 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::common::span::Span;
|
||||
use leo_ast::values::{
|
||||
GroupCoordinate as AstGroupCoordinate,
|
||||
Inferred as AstInferred,
|
||||
NumberValue as AstNumberValue,
|
||||
SignHigh as AstSignHigh,
|
||||
SignLow as AstSignLow,
|
||||
use leo_grammar::values::{
|
||||
GroupCoordinate as GrammarGroupCoordinate,
|
||||
Inferred as GrammarInferred,
|
||||
NumberValue as GrammarNumberValue,
|
||||
SignHigh as GrammarSignHigh,
|
||||
SignLow as GrammarSignLow,
|
||||
};
|
||||
use leo_input::values::{
|
||||
GroupCoordinate as InputGroupCoordinate,
|
||||
@ -41,13 +41,13 @@ pub enum GroupCoordinate {
|
||||
Inferred,
|
||||
}
|
||||
|
||||
impl<'ast> From<AstGroupCoordinate<'ast>> for GroupCoordinate {
|
||||
fn from(coordinate: AstGroupCoordinate<'ast>) -> Self {
|
||||
impl<'ast> From<GrammarGroupCoordinate<'ast>> for GroupCoordinate {
|
||||
fn from(coordinate: GrammarGroupCoordinate<'ast>) -> Self {
|
||||
match coordinate {
|
||||
AstGroupCoordinate::Number(number) => GroupCoordinate::from(number),
|
||||
AstGroupCoordinate::SignHigh(sign_high) => GroupCoordinate::from(sign_high),
|
||||
AstGroupCoordinate::SignLow(sign_low) => GroupCoordinate::from(sign_low),
|
||||
AstGroupCoordinate::Inferred(inferred) => GroupCoordinate::from(inferred),
|
||||
GrammarGroupCoordinate::Number(number) => GroupCoordinate::from(number),
|
||||
GrammarGroupCoordinate::SignHigh(sign_high) => GroupCoordinate::from(sign_high),
|
||||
GrammarGroupCoordinate::SignLow(sign_low) => GroupCoordinate::from(sign_low),
|
||||
GrammarGroupCoordinate::Inferred(inferred) => GroupCoordinate::from(inferred),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -74,8 +74,8 @@ impl fmt::Display for GroupCoordinate {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AstNumberValue<'ast>> for GroupCoordinate {
|
||||
fn from(number: AstNumberValue<'ast>) -> Self {
|
||||
impl<'ast> From<GrammarNumberValue<'ast>> for GroupCoordinate {
|
||||
fn from(number: GrammarNumberValue<'ast>) -> Self {
|
||||
let value = number.to_string();
|
||||
let span = Span::from(number.span().clone());
|
||||
|
||||
@ -83,20 +83,20 @@ impl<'ast> From<AstNumberValue<'ast>> for GroupCoordinate {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AstSignHigh<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: AstSignHigh<'ast>) -> Self {
|
||||
impl<'ast> From<GrammarSignHigh<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: GrammarSignHigh<'ast>) -> Self {
|
||||
GroupCoordinate::SignHigh
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AstSignLow<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: AstSignLow<'ast>) -> Self {
|
||||
impl<'ast> From<GrammarSignLow<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: GrammarSignLow<'ast>) -> Self {
|
||||
GroupCoordinate::SignLow
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AstInferred<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: AstInferred<'ast>) -> Self {
|
||||
impl<'ast> From<GrammarInferred<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: GrammarInferred<'ast>) -> Self {
|
||||
GroupCoordinate::Inferred
|
||||
}
|
||||
}
|
@ -15,10 +15,10 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{common::span::Span, groups::GroupCoordinate};
|
||||
use leo_ast::values::{
|
||||
GroupRepresentation as AstGroupRepresentation,
|
||||
GroupTuple as AstGroupTuple,
|
||||
GroupValue as AstGroupValue,
|
||||
use leo_grammar::values::{
|
||||
GroupRepresentation as GrammarGroupRepresentation,
|
||||
GroupTuple as GrammarGroupTuple,
|
||||
GroupValue as GrammarGroupValue,
|
||||
};
|
||||
use leo_input::values::{
|
||||
GroupRepresentation as InputGroupRepresentation,
|
||||
@ -42,15 +42,22 @@ impl GroupValue {
|
||||
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 {
|
||||
fn from(ast_group: AstGroupValue) -> Self {
|
||||
impl<'ast> From<GrammarGroupValue<'ast>> for GroupValue {
|
||||
fn from(ast_group: GrammarGroupValue) -> Self {
|
||||
let span = Span::from(ast_group.span);
|
||||
|
||||
match ast_group.value {
|
||||
AstGroupRepresentation::Single(number) => GroupValue::Single(number.to_string(), span),
|
||||
AstGroupRepresentation::Tuple(tuple) => GroupValue::Tuple(GroupTuple::from(tuple)),
|
||||
GrammarGroupRepresentation::Single(number) => GroupValue::Single(number.to_string(), span),
|
||||
GrammarGroupRepresentation::Tuple(tuple) => GroupValue::Tuple(GroupTuple::from(tuple)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -82,8 +89,8 @@ pub struct GroupTuple {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<AstGroupTuple<'ast>> for GroupTuple {
|
||||
fn from(ast_group: AstGroupTuple<'ast>) -> Self {
|
||||
impl<'ast> From<GrammarGroupTuple<'ast>> for GroupTuple {
|
||||
fn from(ast_group: GrammarGroupTuple<'ast>) -> Self {
|
||||
let ast_x = ast_group.x;
|
||||
let ast_y = ast_group.y;
|
||||
|
@ -14,18 +14,51 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, common::LineEnd, imports::Package, SpanDef};
|
||||
use crate::{Package, Span};
|
||||
use leo_grammar::imports::Import as GrammarImport;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::import))]
|
||||
pub struct Import<'ast> {
|
||||
pub package: Package<'ast>,
|
||||
pub line_end: LineEnd,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
/// Represents an import statement in a Leo program.
|
||||
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ImportStatement {
|
||||
pub package: Package,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -14,18 +14,63 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, common::Identifier, SpanDef};
|
||||
use crate::{Identifier, Span};
|
||||
use leo_grammar::imports::ImportSymbol as GrammarImportSymbol;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::import_symbol))]
|
||||
pub struct ImportSymbol<'ast> {
|
||||
pub value: Identifier<'ast>,
|
||||
pub alias: Option<Identifier<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ImportSymbol {
|
||||
pub symbol: Identifier,
|
||||
pub alias: Option<Identifier>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarImportSymbol<'ast>> for ImportSymbol {
|
||||
fn from(symbol: GrammarImportSymbol<'ast>) -> Self {
|
||||
ImportSymbol {
|
||||
symbol: Identifier::from(symbol.value),
|
||||
alias: symbol.alias.map(Identifier::from),
|
||||
span: Span::from(symbol.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ImportSymbol {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.alias.is_some() {
|
||||
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("*")
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,3 @@ pub use package::*;
|
||||
|
||||
pub mod package_access;
|
||||
pub use package_access::*;
|
||||
|
||||
pub mod package_name;
|
||||
pub use package_name::*;
|
||||
|
||||
pub mod star;
|
||||
pub use star::*;
|
||||
|
@ -14,22 +14,43 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
imports::{PackageAccess, PackageName},
|
||||
SpanDef,
|
||||
};
|
||||
use crate::{common::Identifier, PackageAccess, Span};
|
||||
use leo_grammar::imports::Package as GrammarPackage;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::package))]
|
||||
pub struct Package<'ast> {
|
||||
pub name: PackageName<'ast>,
|
||||
pub access: PackageAccess<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Package {
|
||||
pub name: Identifier,
|
||||
pub access: PackageAccess,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarPackage<'ast>> for Package {
|
||||
fn from(package: GrammarPackage<'ast>) -> Self {
|
||||
Package {
|
||||
name: Identifier::from(package.name),
|
||||
access: PackageAccess::from(package.access),
|
||||
span: Span::from(package.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Package {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}.{}", self.name, self.access)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -14,19 +14,61 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
imports::{ImportSymbol, Package, Star},
|
||||
};
|
||||
use crate::{ImportSymbol, Package, Span};
|
||||
use leo_grammar::imports::PackageAccess as GrammarPackageAccess;
|
||||
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::package_access))]
|
||||
pub enum PackageAccess<'ast> {
|
||||
Star(Star<'ast>),
|
||||
SubPackage(Box<Package<'ast>>),
|
||||
Symbol(ImportSymbol<'ast>),
|
||||
Multiple(Vec<PackageAccess<'ast>>),
|
||||
#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
pub enum PackageAccess {
|
||||
Star(Span),
|
||||
SubPackage(Box<Package>),
|
||||
Symbol(ImportSymbol),
|
||||
Multiple(Vec<PackageAccess>),
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ impl Input {
|
||||
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> {
|
||||
for entry in file.entries.into_iter() {
|
||||
match entry {
|
@ -14,13 +14,14 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Expression as TypedExpression, GroupValue};
|
||||
use crate::{ArrayDimensions, GroupValue};
|
||||
use leo_input::{
|
||||
errors::InputParserError,
|
||||
expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression, TupleExpression},
|
||||
types::{ArrayType, DataType, IntegerType, TupleType, Type},
|
||||
values::{Address, AddressValue, BooleanValue, FieldValue, GroupValue as InputGroupValue, NumberValue, Value},
|
||||
};
|
||||
use pest::Span;
|
||||
|
||||
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(
|
||||
mut array_type: ArrayType,
|
||||
inline: ArrayInlineExpression,
|
||||
) -> 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.
|
||||
if array_dimensions[0] != inline.expressions.len() {
|
||||
@ -137,14 +145,15 @@ impl InputValue {
|
||||
array_type: ArrayType,
|
||||
initializer: ArrayInitializerExpression,
|
||||
) -> 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
|
||||
Self::from_array_initializer_tuple(array_type, initializer, initializer_dimensions)
|
||||
Self::from_array_initializer_tuple(array_type, initializer, array_dimensions)
|
||||
} else {
|
||||
// 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_dimensions: Vec<usize>,
|
||||
) -> 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.
|
||||
if array_dimensions.ne(&initializer_dimensions) {
|
||||
@ -186,7 +195,11 @@ impl InputValue {
|
||||
initializer: ArrayInitializerExpression,
|
||||
initializer_dimensions: Vec<usize>,
|
||||
) -> 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_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) {
|
||||
let mut current_dimension = TypedExpression::get_input_array_dimensions(array_type.dimensions);
|
||||
///
|
||||
/// Returns a new vector of usize values from an [`ArrayDimensions`] type.
|
||||
///
|
||||
/// 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);
|
||||
|
||||
match *array_type.type_ {
|
||||
Type::Array(next_array_type) => fetch_nested_array_type_dimensions(next_array_type, array_dimensions),
|
||||
type_ => (array_dimensions, type_),
|
||||
type_ => Ok((array_dimensions, type_)),
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Identifier, Span, Type};
|
||||
use leo_input::parameters::Parameter as AstParameter;
|
||||
use leo_input::parameters::Parameter as GrammarParameter;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Parameter {
|
||||
@ -24,8 +24,8 @@ pub struct Parameter {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<AstParameter<'ast>> for Parameter {
|
||||
fn from(parameter: AstParameter<'ast>) -> Self {
|
||||
impl<'ast> From<GrammarParameter<'ast>> for Parameter {
|
||||
fn from(parameter: GrammarParameter<'ast>) -> Self {
|
||||
Self {
|
||||
variable: Identifier::from(parameter.variable),
|
||||
type_: Type::from(parameter.type_),
|
115
ast/src/lib.rs
115
ast/src/lib.rs
@ -14,74 +14,85 @@
|
||||
// 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/>.
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate pest_derive;
|
||||
#[macro_use]
|
||||
extern crate thiserror;
|
||||
//! The abstract syntax tree (ast) for a Leo program.
|
||||
//!
|
||||
//! This module contains the [`LeoAst`] type, a wrapper around the [`Program`] type.
|
||||
//! The [`LeoAst`] type is intended to be parsed and modified by different passes
|
||||
//! of the Leo compiler. The Leo compiler can generate a set of R1CS constraints from any [`LeoAst`].
|
||||
|
||||
pub mod ast;
|
||||
pub mod annotation;
|
||||
pub use self::annotation::*;
|
||||
|
||||
pub mod access;
|
||||
pub mod annotations;
|
||||
pub mod circuits;
|
||||
pub use self::circuits::*;
|
||||
|
||||
pub mod common;
|
||||
pub use self::common::*;
|
||||
|
||||
pub mod console;
|
||||
pub mod definitions;
|
||||
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 use self::console::*;
|
||||
|
||||
pub mod errors;
|
||||
pub use errors::*;
|
||||
pub use self::errors::*;
|
||||
|
||||
pub(crate) mod span;
|
||||
pub(crate) use span::*;
|
||||
pub mod expression;
|
||||
pub use self::expression::*;
|
||||
|
||||
use from_pest::FromPest;
|
||||
use std::{fs, path::Path};
|
||||
pub mod functions;
|
||||
pub use self::functions::*;
|
||||
|
||||
pub struct LeoAst<'ast> {
|
||||
ast: files::File<'ast>,
|
||||
pub mod groups;
|
||||
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> {
|
||||
/// Creates a new abstract syntax tree given the file path.
|
||||
pub fn new(file_path: &'ast Path, program_string: &'ast str) -> Result<Self, ParserError> {
|
||||
// TODO (howardwu): Turn this check back on after fixing the testing module.
|
||||
// assert_eq!(program_string, fs::read_to_string(file_path).map_err(|_| ParserError::FileReadError(file_path.clone()))?);
|
||||
|
||||
// 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 })
|
||||
impl LeoAst {
|
||||
/// Creates a new syntax tree from a given program name and abstract syntax tree.
|
||||
pub fn new<'ast>(program_name: &str, ast: &Grammar<'ast>) -> Self {
|
||||
Self {
|
||||
ast: Program::from(program_name, ast.as_repr()),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO (howardwu): Remove this in favor of a dedicated file loader to verify checksums
|
||||
// and maintain a global cache of program strings during the compilation process.
|
||||
/// Loads the Leo code as a string from the given file path.
|
||||
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 program syntax tree representation.
|
||||
pub fn into_repr(self) -> Program {
|
||||
self.ast
|
||||
}
|
||||
|
||||
/// Returns a reference to the inner abstract syntax tree representation.
|
||||
pub fn as_repr(&self) -> &files::File<'ast> {
|
||||
&self.ast
|
||||
}
|
||||
|
||||
/// Serializes the abstract syntax tree into a JSON string.
|
||||
pub fn to_json_string(&self) -> Result<String, ParserError> {
|
||||
/// Serializes the syntax tree into a JSON string.
|
||||
pub fn to_json_string(&self) -> Result<String, serde_json::Error> {
|
||||
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 })
|
||||
}
|
||||
}
|
||||
|
@ -14,21 +14,25 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_ast::{LeoAst, ParserError};
|
||||
use leo_ast::LeoAst;
|
||||
use leo_grammar::{Grammar, ParserError};
|
||||
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.
|
||||
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.
|
||||
let ast = LeoAst::new(&program_filepath, &program_string)?;
|
||||
// Parses the Leo file and constructs a pest ast.
|
||||
let ast = Grammar::new(&program_filepath, &program_string)?;
|
||||
|
||||
// Serializes the abstract syntax tree into JSON format.
|
||||
let serialized_ast = LeoAst::to_json_string(&ast)?;
|
||||
// Parse the pest ast and constructs a 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> {
|
||||
@ -47,9 +51,9 @@ fn main() -> Result<(), ParserError> {
|
||||
// Construct the input filepath.
|
||||
let input_filepath = Path::new(&cli_arguments[1]);
|
||||
|
||||
// Construct the serialized abstract syntax tree.
|
||||
let serialized_ast = to_leo_ast(&input_filepath)?;
|
||||
println!("{}", serialized_ast);
|
||||
// Construct the serialized syntax tree.
|
||||
let serialized_leo_tree = to_leo_tree(&input_filepath)?;
|
||||
println!("{}", serialized_leo_tree);
|
||||
|
||||
// Determine the output directory.
|
||||
let output_directory = match cli_arguments.len() == 3 {
|
||||
@ -61,8 +65,8 @@ fn main() -> Result<(), ParserError> {
|
||||
false => format!("./{}.json", input_filepath.file_stem().unwrap().to_str().unwrap()),
|
||||
};
|
||||
|
||||
// Write the serialized abstract syntax tree to the output directory.
|
||||
fs::write(Path::new(&output_directory), serialized_ast)?;
|
||||
// Write the serialized syntax tree to the output directory.
|
||||
fs::write(Path::new(&output_directory), serialized_leo_tree)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -14,21 +14,21 @@
|
||||
// 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/>.
|
||||
|
||||
//! A typed Leo program consists of import, circuit, and function definitions.
|
||||
//! Each defined type consists of typed statements and expressions.
|
||||
//! A Leo program consists of import, circuit, and function definitions.
|
||||
//! Each defined type consists of ast statements and expressions.
|
||||
|
||||
use crate::{load_annotation, Circuit, Function, Identifier, Import, InputVariable, TestFunction};
|
||||
use leo_ast::{definitions::Definition, files::File};
|
||||
use crate::{load_annotation, Circuit, Function, FunctionInput, Identifier, ImportStatement, TestFunction};
|
||||
use leo_grammar::{definitions::Definition, files::File};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
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)]
|
||||
pub struct Program {
|
||||
pub name: String,
|
||||
pub expected_input: Vec<InputVariable>,
|
||||
pub imports: Vec<Import>,
|
||||
pub expected_input: Vec<FunctionInput>,
|
||||
pub imports: Vec<ImportStatement>,
|
||||
pub circuits: HashMap<Identifier, Circuit>,
|
||||
pub functions: HashMap<Identifier, Function>,
|
||||
pub tests: HashMap<Identifier, TestFunction>,
|
||||
@ -50,7 +50,7 @@ impl<'ast> Program {
|
||||
.to_owned()
|
||||
.into_iter()
|
||||
.for_each(|definition| match definition {
|
||||
Definition::Import(import) => imports.push(Import::from(import)),
|
||||
Definition::Import(import) => imports.push(ImportStatement::from(import)),
|
||||
Definition::Circuit(circuit) => {
|
||||
circuits.insert(Identifier::from(circuit.identifier.clone()), Circuit::from(circuit));
|
||||
}
|
@ -14,27 +14,42 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
statements::{ConditionalStatement, Statement},
|
||||
};
|
||||
use crate::{ConditionalStatement, Statement};
|
||||
use leo_grammar::statements::ConditionalNestedOrEndStatement as GrammarConditionalNestedOrEndStatement;
|
||||
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::conditional_nested_or_end_statement))]
|
||||
pub enum ConditionalNestedOrEndStatement<'ast> {
|
||||
Nested(Box<ConditionalStatement<'ast>>),
|
||||
End(Vec<Statement<'ast>>),
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum ConditionalNestedOrEndStatement {
|
||||
Nested(Box<ConditionalStatement>),
|
||||
End(Vec<Statement>),
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for ConditionalNestedOrEndStatement<'ast> {
|
||||
impl<'ast> From<GrammarConditionalNestedOrEndStatement<'ast>> for ConditionalNestedOrEndStatement {
|
||||
fn from(statement: GrammarConditionalNestedOrEndStatement<'ast>) -> Self {
|
||||
match statement {
|
||||
GrammarConditionalNestedOrEndStatement::Nested(nested) => {
|
||||
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) => write!(f, "else {{\n \t{:#?}\n }}", statements),
|
||||
ConditionalNestedOrEndStatement::End(ref statements) => {
|
||||
writeln!(f, "else {{")?;
|
||||
for statement in statements.iter() {
|
||||
writeln!(f, "\t\t{}", statement)?;
|
||||
}
|
||||
write!(f, "\t}}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,36 +14,41 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
expressions::Expression,
|
||||
statements::{ConditionalNestedOrEndStatement, Statement},
|
||||
SpanDef,
|
||||
};
|
||||
use crate::{ConditionalNestedOrEndStatement, Expression, Statement};
|
||||
use leo_grammar::statements::ConditionalStatement as GrammarConditionalStatement;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::statement_conditional))]
|
||||
pub struct ConditionalStatement<'ast> {
|
||||
pub condition: Expression<'ast>,
|
||||
pub statements: Vec<Statement<'ast>>,
|
||||
pub next: Option<ConditionalNestedOrEndStatement<'ast>>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct ConditionalStatement {
|
||||
pub condition: Expression,
|
||||
pub statements: Vec<Statement>,
|
||||
pub next: Option<ConditionalNestedOrEndStatement>,
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for ConditionalStatement<'ast> {
|
||||
impl<'ast> From<GrammarConditionalStatement<'ast>> for ConditionalStatement {
|
||||
fn from(statement: GrammarConditionalStatement<'ast>) -> Self {
|
||||
ConditionalStatement {
|
||||
condition: Expression::from(statement.condition),
|
||||
statements: statement.statements.into_iter().map(Statement::from).collect(),
|
||||
next: statement
|
||||
.next
|
||||
.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)?;
|
||||
writeln!(f, "\t{:#?}", self.statements)?;
|
||||
self.next
|
||||
.as_ref()
|
||||
.map(|n_or_e| write!(f, "}} {}", n_or_e))
|
||||
.unwrap_or_else(|| write!(f, "}}"))
|
||||
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}}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,26 +14,11 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
pub mod assign_statement;
|
||||
pub use assign_statement::*;
|
||||
pub mod conditional_nested_or_end_statement;
|
||||
pub use conditional_nested_or_end_statement::*;
|
||||
|
||||
pub mod 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 use statement::*;
|
||||
|
@ -14,34 +14,177 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, console::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::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::statement))]
|
||||
pub enum Statement<'ast> {
|
||||
Return(ReturnStatement<'ast>),
|
||||
Definition(DefinitionStatement<'ast>),
|
||||
Assign(AssignStatement<'ast>),
|
||||
Conditional(ConditionalStatement<'ast>),
|
||||
Iteration(ForStatement<'ast>),
|
||||
Console(ConsoleFunctionCall<'ast>),
|
||||
Expression(ExpressionStatement<'ast>),
|
||||
/// Program statement that defines some action (or expression) to be carried out.
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Statement {
|
||||
Return(Expression, Span),
|
||||
Definition(Declare, Variables, Expression, Span),
|
||||
Assign(Assignee, Expression, Span),
|
||||
Conditional(ConditionalStatement, Span),
|
||||
Iteration(Identifier, Box<(Expression, Expression)>, Vec<Statement>, Span),
|
||||
Console(ConsoleFunctionCall),
|
||||
Expression(Expression, Span),
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for Statement<'ast> {
|
||||
impl<'ast> From<ReturnStatement<'ast>> for Statement {
|
||||
fn from(statement: ReturnStatement<'ast>) -> Self {
|
||||
Statement::Return(Expression::from(statement.expression), Span::from(statement.span))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<DefinitionStatement<'ast>> for Statement {
|
||||
fn from(statement: DefinitionStatement<'ast>) -> Self {
|
||||
let span = Span::from(statement.span);
|
||||
|
||||
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 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),
|
||||
Statement::Iteration(ref statement) => write!(f, "{}", statement),
|
||||
Statement::Console(ref statement) => write!(f, "{}", statement),
|
||||
Statement::Expression(ref statement) => write!(f, "{}", statement.expression),
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,17 +14,116 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
types::{SignedIntegerType, UnsignedIntegerType},
|
||||
use leo_grammar::types::{
|
||||
IntegerType as GrammarIntegerType,
|
||||
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::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::type_integer))]
|
||||
/// Explicit integer type
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum IntegerType {
|
||||
Signed(SignedIntegerType),
|
||||
Unsigned(UnsignedIntegerType),
|
||||
U8,
|
||||
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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,44 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
pub mod 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 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 use type_::*;
|
||||
|
||||
pub mod unsigned_integer_type;
|
||||
pub use unsigned_integer_type::*;
|
||||
|
@ -14,30 +14,220 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, 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::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::type_))]
|
||||
pub enum Type<'ast> {
|
||||
Basic(DataType),
|
||||
Array(ArrayType<'ast>),
|
||||
Tuple(TupleType<'ast>),
|
||||
Circuit(CircuitType<'ast>),
|
||||
SelfType(SelfType<'ast>),
|
||||
/// Explicit type used for defining a variable or expression type
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum Type {
|
||||
// Data types
|
||||
Address,
|
||||
Boolean,
|
||||
Field,
|
||||
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 {
|
||||
///
|
||||
/// Returns `true` if the self `Type` is the `SelfType`.
|
||||
///
|
||||
pub fn is_self(&self) -> bool {
|
||||
matches!(self, Type::SelfType)
|
||||
}
|
||||
|
||||
///
|
||||
/// 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::Basic(ref _type) => write!(f, "basic"),
|
||||
Type::Array(ref _type) => write!(f, "array"),
|
||||
Type::Tuple(ref _type) => write!(f, "tuple"),
|
||||
Type::Circuit(ref _type) => write!(f, "struct"),
|
||||
Type::SelfType(ref type_) => write!(f, "{}", type_.keyword),
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,4 @@
|
||||
// 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/>.
|
||||
|
||||
mod expression;
|
||||
mod function;
|
||||
mod serialization;
|
||||
mod tuple;
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "leo_typed_tree",
|
||||
"name": "leo_tree",
|
||||
"expected_input": [],
|
||||
"imports": [],
|
||||
"circuits": {},
|
||||
@ -7,7 +7,7 @@
|
||||
"{\"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": [],
|
||||
"returns": null,
|
||||
"output": null,
|
||||
"statements": [
|
||||
{
|
||||
"Return": [
|
@ -14,25 +14,81 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_ast::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]
|
||||
#[cfg(not(feature = "ci_skip"))]
|
||||
fn test_serialize() {
|
||||
use leo_ast::LeoAst;
|
||||
use std::path::PathBuf;
|
||||
|
||||
// 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");
|
||||
|
||||
let expected = include_str!("./expected_ast.json");
|
||||
to_ast(&program_filepath)
|
||||
};
|
||||
|
||||
// Loads the Leo code as a string from the given file path.
|
||||
let program_string = LeoAst::load_file(&program_filepath).unwrap();
|
||||
// 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();
|
||||
|
||||
// Parses the Leo file and constructs an abstract syntax tree.
|
||||
let ast = LeoAst::new(&program_filepath, &program_string).unwrap();
|
||||
// Load the expected ast.
|
||||
let expected: Program = serde_json::from_str(include_str!("expected_leo_ast.json")).unwrap();
|
||||
|
||||
// Serializes the abstract syntax tree into JSON format.
|
||||
let serialized_ast = LeoAst::to_json_string(&ast).unwrap();
|
||||
|
||||
assert_eq!(expected, serialized_ast);
|
||||
assert_eq!(expected, serialized_leo_ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "ci_skip"))]
|
||||
fn test_deserialize() {
|
||||
// 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);
|
||||
}
|
||||
|
@ -23,12 +23,20 @@ version = "1.0.4"
|
||||
|
||||
[dependencies.leo-core]
|
||||
path = "../core"
|
||||
version = "1.0.2"
|
||||
version = "1.0.4"
|
||||
|
||||
[dependencies.leo-gadgets]
|
||||
path = "../gadgets"
|
||||
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]
|
||||
path = "../input"
|
||||
version = "1.0.4"
|
||||
@ -37,14 +45,18 @@ version = "1.0.4"
|
||||
path = "../package"
|
||||
version = "1.0.4"
|
||||
|
||||
[dependencies.leo-typed]
|
||||
path = "../typed"
|
||||
version = "1.0.4"
|
||||
|
||||
[dependencies.leo-state]
|
||||
path = "../state"
|
||||
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]
|
||||
version = "1.1.3"
|
||||
default-features = false
|
||||
@ -112,4 +124,4 @@ default-features = false
|
||||
|
||||
[features]
|
||||
default = [ ]
|
||||
ci_skip = [ "leo-ast/ci_skip", "leo-typed/ci_skip" ]
|
||||
ci_skip = [ "leo-grammar/ci_skip", "leo-ast/ci_skip" ]
|
||||
|
@ -20,15 +20,17 @@ use crate::{
|
||||
constraints::{generate_constraints, generate_test_constraints},
|
||||
errors::CompilerError,
|
||||
GroupType,
|
||||
ImportParser,
|
||||
OutputBytes,
|
||||
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_package::inputs::InputPairs;
|
||||
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_errors::gadgets::SynthesisError;
|
||||
@ -44,6 +46,7 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
/// Stores information to compile a Leo program.
|
||||
#[derive(Clone)]
|
||||
pub struct Compiler<F: Field + PrimeField, G: GroupType<F>> {
|
||||
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> {
|
||||
///
|
||||
/// Returns a new Leo program compiler.
|
||||
///
|
||||
pub fn new(package_name: String, main_file_path: PathBuf, output_directory: PathBuf) -> Self {
|
||||
Self {
|
||||
package_name: package_name.clone(),
|
||||
@ -64,14 +70,62 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
output_directory,
|
||||
program: Program::new(package_name),
|
||||
program_input: Input::new(),
|
||||
imported_programs: ImportParser::new(),
|
||||
imported_programs: ImportParser::default(),
|
||||
_engine: 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(
|
||||
&mut self,
|
||||
input_string: &str,
|
||||
@ -104,55 +158,83 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Parses program files.
|
||||
/// Returns a compiler struct that stores the typed program abstract syntax trees (ast).
|
||||
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);
|
||||
///
|
||||
/// Runs program parser and type inference checker consecutively.
|
||||
///
|
||||
pub(crate) fn parse_and_check_program(&mut self) -> Result<(), CompilerError> {
|
||||
self.parse_program()?;
|
||||
|
||||
compiler.parse_program()?;
|
||||
|
||||
Ok(compiler)
|
||||
self.check_program()
|
||||
}
|
||||
|
||||
/// Parses input, state, and program files.
|
||||
/// Returns a compiler struct that stores the typed input and typed program abstract syntax trees (ast).
|
||||
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_program()?;
|
||||
|
||||
Ok(compiler)
|
||||
}
|
||||
|
||||
/// Parses the Leo program file, constructs a syntax tree, and generates a program.
|
||||
#[allow(deprecated)]
|
||||
///
|
||||
/// Parses and stores the main program file, constructs a syntax tree, and generates a program.
|
||||
///
|
||||
/// Parses and stores all programs imported by the main program file.
|
||||
///
|
||||
pub(crate) fn parse_program(&mut self) -> Result<(), CompilerError> {
|
||||
// Use the parser to construct the abstract syntax tree.
|
||||
let program_string = LeoAst::load_file(&self.main_file_path)?;
|
||||
// Load the program file.
|
||||
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.
|
||||
///
|
||||
#[deprecated(note = "Please use the 'parse_program' method instead.")]
|
||||
pub fn parse_program_from_string(&mut self, program_string: &str) -> Result<(), CompilerError> {
|
||||
// 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
|
||||
@ -161,23 +243,38 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
// Derive the package name.
|
||||
let package_name = &self.package_name;
|
||||
|
||||
// Use the typed parser to construct the typed syntax tree.
|
||||
let typed_tree = LeoTypedAst::new(package_name, &ast);
|
||||
// Construct the core ast from the pest 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)?;
|
||||
|
||||
// // 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);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Manually sets main function input
|
||||
///
|
||||
/// Manually sets main function input.
|
||||
///
|
||||
/// Used for testing only.
|
||||
///
|
||||
pub fn set_main_input(&mut self, input: MainInput) {
|
||||
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(
|
||||
&self,
|
||||
system_parameters: &SystemParameters<Components>,
|
||||
@ -187,6 +284,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a Sha256 checksum of the program file.
|
||||
///
|
||||
pub fn checksum(&self) -> Result<String, CompilerError> {
|
||||
// Read in the main file as string
|
||||
let unparsed_file = fs::read_to_string(&self.main_file_path)
|
||||
@ -200,7 +300,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
Ok(hex::encode(hash))
|
||||
}
|
||||
|
||||
///
|
||||
/// Synthesizes the circuit without program input to verify correctness.
|
||||
///
|
||||
pub fn compile_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<OutputBytes, CompilerError> {
|
||||
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.
|
||||
///
|
||||
pub fn compile_test_constraints(self, input_pairs: InputPairs) -> Result<(u32, u32), CompilerError> {
|
||||
generate_test_constraints::<F, G>(
|
||||
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>>(
|
||||
self,
|
||||
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> {
|
||||
///
|
||||
/// Synthesizes the circuit with program input.
|
||||
///
|
||||
fn generate_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
|
||||
let output_directory = self.output_directory.clone();
|
||||
let package_name = self.package_name.clone();
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! Enforces an assert equals statement in a compiled Leo program.
|
||||
|
||||
use crate::{errors::ConsoleError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
|
||||
use leo_typed::{Expression, Span, Type};
|
||||
use leo_ast::{Expression, Span, Type};
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! Evaluates a macro in a compiled Leo program.
|
||||
|
||||
use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType};
|
||||
use leo_typed::{ConsoleFunction, ConsoleFunctionCall};
|
||||
use leo_ast::{ConsoleFunction, ConsoleFunctionCall};
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! Evaluates a formatted string in a compiled Leo program.
|
||||
|
||||
use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType};
|
||||
use leo_typed::FormattedString;
|
||||
use leo_ast::FormattedString;
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
|
@ -22,14 +22,14 @@ use crate::{
|
||||
ConstrainedProgram,
|
||||
ConstrainedValue,
|
||||
GroupType,
|
||||
ImportParser,
|
||||
OutputBytes,
|
||||
OutputFile,
|
||||
};
|
||||
use leo_typed::{Input, Program};
|
||||
|
||||
use leo_ast::{Input, Program};
|
||||
use leo_imports::ImportParser;
|
||||
use leo_input::LeoInputParser;
|
||||
use leo_package::inputs::InputPairs;
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
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)?;
|
||||
|
||||
let main = resolved_program
|
||||
.get(&main_function_name)
|
||||
.ok_or_else(|| CompilerError::NoMain)?;
|
||||
let main = resolved_program.get(&main_function_name).ok_or(CompilerError::NoMain)?;
|
||||
|
||||
match main.clone() {
|
||||
ConstrainedValue::Function(_circuit_identifier, function) => {
|
||||
|
@ -21,7 +21,7 @@ use crate::{
|
||||
value::ConstrainedValue,
|
||||
GroupType,
|
||||
};
|
||||
use leo_typed::Identifier;
|
||||
use leo_ast::Identifier;
|
||||
|
||||
use snarkos_models::curves::{Field, PrimeField};
|
||||
|
||||
|
@ -21,9 +21,9 @@ use crate::{
|
||||
program::{new_scope, ConstrainedProgram},
|
||||
value::ConstrainedValue,
|
||||
GroupType,
|
||||
ImportParser,
|
||||
};
|
||||
use leo_typed::Program;
|
||||
use leo_ast::Program;
|
||||
use leo_imports::ImportParser;
|
||||
|
||||
use snarkos_models::curves::{Field, PrimeField};
|
||||
|
||||
|
@ -15,9 +15,12 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
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_state::LocalDataVerificationError;
|
||||
// use leo_symbol_table::SymbolTableError;
|
||||
// use leo_type_inference::TypeInferenceError;
|
||||
|
||||
use bincode::Error as SerdeError;
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -27,6 +30,9 @@ pub enum CompilerError {
|
||||
#[error("{}", _0)]
|
||||
ImportError(#[from] ImportError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ImportParserError(#[from] ImportParserError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
InputParserError(#[from] InputParserError),
|
||||
|
||||
@ -62,6 +68,11 @@ pub enum CompilerError {
|
||||
|
||||
#[error("{}", _0)]
|
||||
SerdeError(#[from] SerdeError),
|
||||
// #[error("{}", _0)]
|
||||
// SymbolTableError(#[from] SymbolTableError),
|
||||
|
||||
// #[error("{}", _0)]
|
||||
// TypeInferenceError(#[from] TypeInferenceError),
|
||||
}
|
||||
|
||||
impl CompilerError {
|
||||
@ -70,6 +81,8 @@ impl CompilerError {
|
||||
CompilerError::InputParserError(error) => error.set_path(path),
|
||||
CompilerError::FunctionError(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),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::errors::ExpressionError;
|
||||
use leo_typed::{Error as FormattedError, Span};
|
||||
use leo_ast::{Error as FormattedError, Span};
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
|
@ -15,8 +15,8 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::errors::{AddressError, BooleanError, FieldError, FunctionError, GroupError, IntegerError, ValueError};
|
||||
use leo_core::LeoCoreError;
|
||||
use leo_typed::{Error as FormattedError, Identifier, Span};
|
||||
use leo_ast::{ArrayDimensions, Error as FormattedError, Identifier, PositiveNumber, Span};
|
||||
use leo_core::LeoCorePackageError;
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use std::path::Path;
|
||||
@ -45,7 +45,7 @@ pub enum ExpressionError {
|
||||
IntegerError(#[from] IntegerError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
LeoCoreError(#[from] LeoCoreError),
|
||||
LeoCoreError(#[from] LeoCorePackageError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ValueError(#[from] ValueError),
|
||||
@ -109,12 +109,30 @@ impl ExpressionError {
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn invalid_index(actual: String, span: Span) -> Self {
|
||||
let message = format!("index must resolve to an integer, found `{}`", actual);
|
||||
pub fn invalid_dimensions(expected: &ArrayDimensions, actual: &ArrayDimensions, span: Span) -> Self {
|
||||
let message = format!(
|
||||
"expected array dimensions {}, found array dimensions {}",
|
||||
expected, actual
|
||||
);
|
||||
|
||||
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 {
|
||||
let message = format!("expected array length {}, found one with length {}", expected, actual);
|
||||
|
||||
@ -157,6 +175,12 @@ impl ExpressionError {
|
||||
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 {
|
||||
let message = format!(
|
||||
"circuit `{}` must be declared before it is used in an expression",
|
||||
@ -166,10 +190,10 @@ impl ExpressionError {
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn undefined_identifier(identifier: Identifier) -> Self {
|
||||
let message = format!("cannot find value `{}` in this scope", identifier.name);
|
||||
pub fn undefined_first_dimension(span: Span) -> Self {
|
||||
let message = "the first dimension of the array must be a number".to_string();
|
||||
|
||||
Self::new_from_span(message, identifier.span)
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn undefined_function(function: String, span: Span) -> Self {
|
||||
@ -181,6 +205,12 @@ impl ExpressionError {
|
||||
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 {
|
||||
let message = format!("Circuit `{}` has no member `{}`", circuit, member);
|
||||
|
||||
|
@ -25,7 +25,7 @@ use crate::errors::{
|
||||
StatementError,
|
||||
ValueError,
|
||||
};
|
||||
use leo_typed::{Error as FormattedError, Span};
|
||||
use leo_ast::{Error as FormattedError, Span};
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
|
@ -14,11 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_ast::ParserError;
|
||||
use leo_typed::{Error as FormattedError, Identifier, ImportSymbol, Span};
|
||||
|
||||
use leo_core::LeoCoreError;
|
||||
use std::{io, path::Path};
|
||||
use leo_ast::{Error as FormattedError, Identifier, ImportSymbol, Span};
|
||||
use leo_core::LeoCorePackageError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ImportError {
|
||||
@ -26,10 +23,7 @@ pub enum ImportError {
|
||||
Error(#[from] FormattedError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
LeoCoreError(#[from] LeoCoreError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ParserError(#[from] ParserError),
|
||||
LeoCoreError(#[from] LeoCorePackageError),
|
||||
}
|
||||
|
||||
impl ImportError {
|
||||
@ -37,55 +31,6 @@ impl ImportError {
|
||||
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 {
|
||||
let message = format!(
|
||||
"cannot find imported package `{}` in source files or import directory",
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_typed::{Error as FormattedError, Span};
|
||||
use leo_ast::{Error as FormattedError, Span};
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
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;
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_typed::{Error as FormattedError, Span};
|
||||
use leo_ast::{Error as FormattedError, Span};
|
||||
|
||||
use snarkos_errors::{gadgets::SynthesisError, objects::account::AccountError};
|
||||
use std::path::Path;
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_typed::{Error as FormattedError, Span};
|
||||
use leo_ast::{Error as FormattedError, Span};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use std::path::Path;
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_typed::{Error as FormattedError, Span};
|
||||
use leo_ast::{Error as FormattedError, Span};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use std::path::Path;
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_typed::{Error as FormattedError, Span};
|
||||
use leo_ast::{Error as FormattedError, Span};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use std::path::Path;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user