mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-23 23:23:50 +03:00
Merge pull request #622 from AleoHQ/refactor/compiler
Adds ASG struct, updates ASG to support debug
This commit is contained in:
commit
a239e17bb6
@ -26,6 +26,7 @@ path = "leo/main.rs"
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
"asg",
|
||||
"ast",
|
||||
"compiler",
|
||||
"gadgets",
|
||||
@ -34,8 +35,7 @@ members = [
|
||||
"input",
|
||||
"linter",
|
||||
"package",
|
||||
"state",
|
||||
"asg"
|
||||
"state"
|
||||
]
|
||||
|
||||
[dependencies.leo-ast]
|
||||
|
@ -22,6 +22,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ArrayAccessExpression {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -21,6 +21,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ArrayInitExpression {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -22,6 +22,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ArrayInlineExpression {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -22,6 +22,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ArrayRangeAccessExpression {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -22,6 +22,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BinaryExpression {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -36,6 +36,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CallExpression {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -36,6 +36,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CircuitAccessExpression {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -36,6 +36,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CircuitInitExpression {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -34,6 +34,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Constant {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -66,6 +66,7 @@ use crate::{AsgConvertError, ConstValue, FromAst, Node, PartialType, Scope, Span
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Expression {
|
||||
VariableRef(VariableRef),
|
||||
Constant(Constant),
|
||||
|
@ -21,6 +21,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TernaryExpression {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -21,6 +21,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TupleAccessExpression {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -21,6 +21,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TupleInitExpression {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -22,6 +22,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UnaryExpression {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -37,6 +37,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VariableRef {
|
||||
pub parent: RefCell<Option<Weak<Expression>>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -23,7 +23,7 @@ use std::{
|
||||
};
|
||||
|
||||
/// Stores program input values as asg nodes.
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Input {
|
||||
pub registers: Arc<CircuitBody>,
|
||||
pub state: Arc<CircuitBody>,
|
||||
|
@ -67,9 +67,9 @@ pub use type_::*;
|
||||
pub mod variable;
|
||||
pub use variable::*;
|
||||
|
||||
pub use leo_ast::{Identifier, Span};
|
||||
pub use leo_ast::{Ast, Identifier, Span};
|
||||
|
||||
use std::path::Path;
|
||||
use std::{cell::RefCell, path::Path, sync::Arc};
|
||||
|
||||
/// The abstract semantic graph (ASG) for a Leo program.
|
||||
///
|
||||
@ -77,42 +77,41 @@ use std::path::Path;
|
||||
/// These data types form a graph that begins from a [`Program`] type node.
|
||||
///
|
||||
/// A new [`Asg`] can be created from an [`Ast`] generated in the `ast` module.
|
||||
// #[derive(Debug, Eq, PartialEq)]
|
||||
// pub struct Asg {
|
||||
// asg: InnerProgram,
|
||||
// }
|
||||
//
|
||||
// impl Asg {
|
||||
// /// Creates a new asg from a given ast tree and import resolver.
|
||||
// pub fn new<T: ImportResolver + 'static>(
|
||||
// content: leo_ast::Program,
|
||||
// resolver: &mut T,
|
||||
// ) -> Result<Program, AsgConvertError> {
|
||||
// InnerProgram::new(&content, resolver)
|
||||
// }
|
||||
//
|
||||
// /// Returns a reference to the inner program ast representation.
|
||||
// pub fn into_repr(self) -> Program {
|
||||
// self.asg
|
||||
// }
|
||||
// }
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Asg {
|
||||
asg: Arc<RefCell<InternalProgram>>,
|
||||
}
|
||||
|
||||
pub fn load_ast<T: AsRef<Path>, Y: AsRef<str>>(path: T, content: Y) -> Result<leo_ast::Program, AsgConvertError> {
|
||||
impl Asg {
|
||||
/// Creates a new ASG from a given AST and import resolver.
|
||||
pub fn new<T: ImportResolver + 'static>(ast: &Ast, resolver: &mut T) -> Result<Self, AsgConvertError> {
|
||||
Ok(Self {
|
||||
asg: InternalProgram::new(&ast.as_repr(), resolver)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the internal program ASG representation.
|
||||
pub fn as_repr(&self) -> Arc<RefCell<InternalProgram>> {
|
||||
self.asg.clone()
|
||||
}
|
||||
|
||||
// /// Serializes the ast into a JSON string.
|
||||
// pub fn to_json_string(&self) -> Result<String, serde_json::Error> {
|
||||
// serde_json::to_string_pretty(&self.asg)
|
||||
// }
|
||||
//
|
||||
// /// Deserializes the JSON string into a ast.
|
||||
// pub fn from_json_string(json: &str) -> Result<Self, serde_json::Error> {
|
||||
// let ast: Program = serde_json::from_str(json)?;
|
||||
// Ok(Self { ast })
|
||||
// }
|
||||
}
|
||||
|
||||
// TODO (howardwu): Remove this.
|
||||
pub fn load_asg<T: ImportResolver + 'static>(content: &str, resolver: &mut T) -> Result<Program, AsgConvertError> {
|
||||
// Parses the Leo file and constructs a grammar ast.
|
||||
let ast = leo_grammar::Grammar::new(path.as_ref(), content.as_ref())
|
||||
let ast = leo_grammar::Grammar::new(&Path::new("input.leo"), content)
|
||||
.map_err(|e| AsgConvertError::InternalError(format!("ast: {:?}", e)))?;
|
||||
|
||||
// Parses the pest ast and constructs a Leo ast.
|
||||
Ok(leo_ast::Ast::new("load_ast", &ast)?.into_repr())
|
||||
}
|
||||
|
||||
pub fn load_asg_from_ast<T: ImportResolver + 'static>(
|
||||
content: leo_ast::Program,
|
||||
resolver: &mut T,
|
||||
) -> Result<Program, AsgConvertError> {
|
||||
InnerProgram::new(&content, resolver)
|
||||
}
|
||||
|
||||
pub fn load_asg<T: ImportResolver + 'static>(content: &str, resolver: &mut T) -> Result<Program, AsgConvertError> {
|
||||
InnerProgram::new(&load_ast("input.leo", content)?, resolver)
|
||||
InternalProgram::new(leo_ast::Ast::new("load_ast", &ast)?.as_repr(), resolver)
|
||||
}
|
||||
|
@ -14,12 +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/>.
|
||||
|
||||
//todo: we should merge this with core
|
||||
// TODO (protryon): We should merge this with core
|
||||
|
||||
use crate::{AsgConvertError, Program};
|
||||
|
||||
// todo: make asg deep copy so we can cache resolved core modules
|
||||
// todo: figure out how to do headers without bogus returns
|
||||
// TODO (protryon): Make asg deep copy so we can cache resolved core modules
|
||||
// TODO (protryon): Figure out how to do headers without bogus returns
|
||||
|
||||
pub fn resolve_core_module(module: &str) -> Result<Option<Program>, AsgConvertError> {
|
||||
match module {
|
||||
|
@ -23,16 +23,19 @@ use std::{
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CircuitMemberBody {
|
||||
Variable(Type),
|
||||
Function(Arc<FunctionBody>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CircuitMember {
|
||||
Variable(WeakType),
|
||||
Function(Arc<Function>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Circuit {
|
||||
pub id: Uuid,
|
||||
pub name: RefCell<Identifier>,
|
||||
@ -51,6 +54,7 @@ impl PartialEq for Circuit {
|
||||
}
|
||||
impl Eq for Circuit {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CircuitBody {
|
||||
pub scope: Scope,
|
||||
pub span: Option<Span>,
|
||||
|
@ -38,13 +38,14 @@ use std::{
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum FunctionQualifier {
|
||||
SelfRef,
|
||||
MutSelfRef,
|
||||
Static,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Function {
|
||||
pub id: Uuid,
|
||||
pub name: RefCell<Identifier>,
|
||||
@ -66,6 +67,7 @@ impl PartialEq for Function {
|
||||
}
|
||||
impl Eq for Function {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FunctionBody {
|
||||
pub span: Option<Span>,
|
||||
pub function: Arc<Function>,
|
||||
|
@ -32,8 +32,8 @@ use std::{cell::RefCell, sync::Arc};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Stores the Leo program abstract semantic graph (ASG).
|
||||
#[derive(Clone)]
|
||||
pub struct InnerProgram {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct InternalProgram {
|
||||
/// The unique id of the program.
|
||||
pub id: Uuid,
|
||||
|
||||
@ -57,7 +57,7 @@ pub struct InnerProgram {
|
||||
pub scope: Scope,
|
||||
}
|
||||
|
||||
pub type Program = Arc<RefCell<InnerProgram>>;
|
||||
pub type Program = Arc<RefCell<InternalProgram>>;
|
||||
|
||||
/// Enumerates what names are imported from a package.
|
||||
enum ImportSymbol {
|
||||
@ -110,22 +110,22 @@ fn resolve_import_package_access(
|
||||
}
|
||||
}
|
||||
|
||||
impl InnerProgram {
|
||||
/// Returns a new Leo program asg from the given Leo program ast and imports.
|
||||
impl InternalProgram {
|
||||
/// Returns a new Leo program ASG from the given Leo program AST and its imports.
|
||||
///
|
||||
/// stages:
|
||||
/// Stages:
|
||||
/// 1. resolve imports into super scope
|
||||
/// 2. finalize declared types
|
||||
/// 3. finalize declared functions
|
||||
/// 4. resolve all asg nodes
|
||||
///
|
||||
pub fn new<T: ImportResolver + 'static>(
|
||||
value: &leo_ast::Program,
|
||||
program: &leo_ast::Program,
|
||||
import_resolver: &mut T,
|
||||
) -> Result<Program, AsgConvertError> {
|
||||
// Recursively extract imported symbols.
|
||||
let mut imported_symbols: Vec<(Vec<String>, ImportSymbol, Span)> = vec![];
|
||||
for import in value.imports.iter() {
|
||||
for import in program.imports.iter() {
|
||||
resolve_import_package(&mut imported_symbols, vec![], &import.package);
|
||||
}
|
||||
|
||||
@ -213,7 +213,7 @@ impl InnerProgram {
|
||||
|
||||
// Prepare header-like scope entries.
|
||||
let mut proto_circuits = IndexMap::new();
|
||||
for (name, circuit) in value.circuits.iter() {
|
||||
for (name, circuit) in program.circuits.iter() {
|
||||
assert_eq!(name.name, circuit.circuit_name.name);
|
||||
let asg_circuit = Circuit::init(circuit);
|
||||
|
||||
@ -234,7 +234,7 @@ impl InnerProgram {
|
||||
function: None,
|
||||
}));
|
||||
|
||||
for (name, circuit) in value.circuits.iter() {
|
||||
for (name, circuit) in program.circuits.iter() {
|
||||
assert_eq!(name.name, circuit.circuit_name.name);
|
||||
let asg_circuit = proto_circuits.get(&name.name).unwrap();
|
||||
|
||||
@ -242,7 +242,7 @@ impl InnerProgram {
|
||||
}
|
||||
|
||||
let mut proto_test_functions = IndexMap::new();
|
||||
for (name, test_function) in value.tests.iter() {
|
||||
for (name, test_function) in program.tests.iter() {
|
||||
assert_eq!(name.name, test_function.function.identifier.name);
|
||||
let function = Arc::new(Function::from_ast(&scope, &test_function.function)?);
|
||||
|
||||
@ -250,7 +250,7 @@ impl InnerProgram {
|
||||
}
|
||||
|
||||
let mut proto_functions = IndexMap::new();
|
||||
for (name, function) in value.functions.iter() {
|
||||
for (name, function) in program.functions.iter() {
|
||||
assert_eq!(name.name, function.identifier.name);
|
||||
let asg_function = Arc::new(Function::from_ast(&scope, function)?);
|
||||
|
||||
@ -263,7 +263,7 @@ impl InnerProgram {
|
||||
|
||||
// Load concrete definitions.
|
||||
let mut test_functions = IndexMap::new();
|
||||
for (name, test_function) in value.tests.iter() {
|
||||
for (name, test_function) in program.tests.iter() {
|
||||
assert_eq!(name.name, test_function.function.identifier.name);
|
||||
let function = proto_test_functions.get(&name.name).unwrap();
|
||||
|
||||
@ -278,7 +278,7 @@ impl InnerProgram {
|
||||
}
|
||||
|
||||
let mut functions = IndexMap::new();
|
||||
for (name, function) in value.functions.iter() {
|
||||
for (name, function) in program.functions.iter() {
|
||||
assert_eq!(name.name, function.identifier.name);
|
||||
let asg_function = proto_functions.get(&name.name).unwrap();
|
||||
|
||||
@ -289,7 +289,7 @@ impl InnerProgram {
|
||||
}
|
||||
|
||||
let mut circuits = IndexMap::new();
|
||||
for (name, circuit) in value.circuits.iter() {
|
||||
for (name, circuit) in program.circuits.iter() {
|
||||
assert_eq!(name.name, circuit.circuit_name.name);
|
||||
let asg_circuit = proto_circuits.get(&name.name).unwrap();
|
||||
let body = Arc::new(CircuitBody::from_ast(&scope, circuit, asg_circuit.clone())?);
|
||||
@ -298,9 +298,9 @@ impl InnerProgram {
|
||||
circuits.insert(name.name.clone(), body);
|
||||
}
|
||||
|
||||
Ok(Arc::new(RefCell::new(InnerProgram {
|
||||
Ok(Arc::new(RefCell::new(InternalProgram {
|
||||
id: Uuid::new_v4(),
|
||||
name: value.name.clone(),
|
||||
name: program.name.clone(),
|
||||
test_functions,
|
||||
functions,
|
||||
circuits,
|
||||
@ -332,7 +332,7 @@ impl Iterator for InternalIdentifierGenerator {
|
||||
Some(out)
|
||||
}
|
||||
}
|
||||
/// Returns an ast from the given asg program.
|
||||
/// Returns an AST from the given ASG program.
|
||||
pub fn reform_ast(program: &Program) -> leo_ast::Program {
|
||||
let mut all_programs: IndexMap<String, Program> = IndexMap::new();
|
||||
let mut program_stack = program.borrow().imported_modules.clone();
|
||||
@ -417,7 +417,7 @@ pub fn reform_ast(program: &Program) -> leo_ast::Program {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<leo_ast::Program> for &InnerProgram {
|
||||
impl Into<leo_ast::Program> for &InternalProgram {
|
||||
fn into(self) -> leo_ast::Program {
|
||||
leo_ast::Program {
|
||||
name: self.name.clone(),
|
||||
|
@ -157,7 +157,7 @@ pub trait MonoidalReducerProgram<T: Monoid>: MonoidalReducerStatement<T> {
|
||||
|
||||
fn reduce_program(
|
||||
&mut self,
|
||||
input: &InnerProgram,
|
||||
input: &InternalProgram,
|
||||
imported_modules: Vec<T>,
|
||||
test_functions: Vec<T>,
|
||||
functions: Vec<T>,
|
||||
|
@ -21,6 +21,7 @@ use std::{cell::RefCell, sync::Arc};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// An abstract data type that track the current bindings for variables, functions, and circuits.
|
||||
#[derive(Debug)]
|
||||
pub struct InnerScope {
|
||||
/// The unique id of the scope.
|
||||
pub id: Uuid,
|
||||
|
@ -37,6 +37,7 @@ use leo_ast::AssigneeAccess as AstAssigneeAccess;
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AssignAccess {
|
||||
ArrayRange(Option<Arc<Expression>>, Option<Arc<Expression>>),
|
||||
ArrayIndex(Arc<Expression>),
|
||||
@ -44,6 +45,7 @@ pub enum AssignAccess {
|
||||
Member(Identifier),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AssignStatement {
|
||||
pub parent: Option<Weak<Statement>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -18,6 +18,7 @@ use crate::{AsgConvertError, FromAst, InnerScope, Node, PartialType, Scope, Span
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BlockStatement {
|
||||
pub parent: Option<Weak<Statement>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -18,6 +18,7 @@ use crate::{AsgConvertError, BlockStatement, Expression, FromAst, Node, PartialT
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConditionalStatement {
|
||||
pub parent: Option<Weak<Statement>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -19,7 +19,8 @@ use leo_ast::ConsoleFunction as AstConsoleFunction;
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
//todo: refactor to not require/depend on span
|
||||
// TODO (protryon): Refactor to not require/depend on span
|
||||
#[derive(Debug)]
|
||||
pub struct FormattedString {
|
||||
pub string: String,
|
||||
pub containers: Vec<Span>,
|
||||
@ -27,6 +28,7 @@ pub struct FormattedString {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ConsoleFunction {
|
||||
Assert(Arc<Expression>),
|
||||
Debug(FormattedString),
|
||||
@ -34,6 +36,7 @@ pub enum ConsoleFunction {
|
||||
Log(FormattedString),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConsoleStatement {
|
||||
pub parent: Option<Weak<Statement>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -34,6 +34,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DefinitionStatement {
|
||||
pub parent: Option<Weak<Statement>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -18,6 +18,7 @@ use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ExpressionStatement {
|
||||
pub parent: Option<Weak<Statement>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -35,6 +35,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IterationStatement {
|
||||
pub parent: Option<Weak<Statement>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -46,6 +46,7 @@ use crate::{AsgConvertError, FromAst, Node, PartialType, Scope, Span};
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Statement {
|
||||
Return(ReturnStatement),
|
||||
Definition(DefinitionStatement),
|
||||
|
@ -18,6 +18,7 @@ use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ReturnStatement {
|
||||
pub parent: Option<Weak<Statement>>,
|
||||
pub span: Option<Span>,
|
||||
|
@ -22,8 +22,8 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
/// A type in an asg.
|
||||
#[derive(Clone, PartialEq)]
|
||||
/// A type in an ASG.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Type {
|
||||
// Data types
|
||||
Address,
|
||||
@ -38,13 +38,13 @@ pub enum Type {
|
||||
Circuit(Arc<Circuit>),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum WeakType {
|
||||
Type(Type), // circuit not allowed
|
||||
Circuit(Weak<Circuit>),
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum PartialType {
|
||||
Type(Type), // non-array or tuple
|
||||
Integer(Option<IntegerType>, Option<IntegerType>), // specific, context-specific
|
||||
|
@ -24,7 +24,7 @@ use std::{
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Specifies how a program variable was declared.
|
||||
#[derive(PartialEq)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum VariableDeclaration {
|
||||
Definition,
|
||||
IterationDefinition,
|
||||
@ -33,6 +33,7 @@ pub enum VariableDeclaration {
|
||||
}
|
||||
|
||||
/// Stores information on a program variable.
|
||||
#[derive(Debug)]
|
||||
pub struct InnerVariable {
|
||||
pub id: Uuid,
|
||||
pub name: Identifier,
|
||||
|
@ -15,16 +15,28 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_asg::*;
|
||||
use leo_ast::Ast;
|
||||
use leo_grammar::Grammar;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
mod fail;
|
||||
mod pass;
|
||||
|
||||
fn load_asg(content: &str) -> Result<Program, AsgConvertError> {
|
||||
leo_asg::load_asg(content, &mut NullImportResolver)
|
||||
const TESTING_FILEPATH: &str = "input.leo";
|
||||
const TESTING_PROGRAM_NAME: &str = "test_program";
|
||||
|
||||
fn load_asg(program_string: &str) -> Result<Program, AsgConvertError> {
|
||||
load_asg_imports(program_string, &mut NullImportResolver)
|
||||
}
|
||||
|
||||
fn load_asg_imports<T: ImportResolver + 'static>(content: &str, imports: &mut T) -> Result<Program, AsgConvertError> {
|
||||
leo_asg::load_asg(content, imports)
|
||||
fn load_asg_imports<T: ImportResolver + 'static>(
|
||||
program_string: &str,
|
||||
imports: &mut T,
|
||||
) -> Result<Program, AsgConvertError> {
|
||||
let grammar = Grammar::new(Path::new(&TESTING_FILEPATH), program_string)?;
|
||||
let ast = Ast::new(TESTING_PROGRAM_NAME, &grammar)?;
|
||||
InternalProgram::new(&ast.as_repr(), imports)
|
||||
}
|
||||
|
||||
fn mocked_resolver() -> MockedImportResolver {
|
||||
|
@ -15,6 +15,10 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::load_asg;
|
||||
use leo_ast::Ast;
|
||||
use leo_grammar::Grammar;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
#[test]
|
||||
fn test_basic() {
|
||||
@ -73,14 +77,19 @@ fn test_imports() {
|
||||
console.assert(foo() == 1u32);
|
||||
}
|
||||
"#;
|
||||
|
||||
let test_import_grammar = Grammar::new(Path::new("test-import.leo"), test_import).unwrap();
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string(&crate::load_ast("test-import.leo", test_import).unwrap()).unwrap()
|
||||
serde_json::to_string(Ast::new("test-import", &test_import_grammar).unwrap().as_repr()).unwrap()
|
||||
);
|
||||
|
||||
let test_grammar = Grammar::new(Path::new("test.leo"), program_string).unwrap();
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string(&crate::load_ast("test.leo", program_string).unwrap()).unwrap()
|
||||
serde_json::to_string(Ast::new("test", &test_grammar).unwrap().as_repr()).unwrap()
|
||||
);
|
||||
|
||||
let asg = crate::load_asg_imports(program_string, &mut imports).unwrap();
|
||||
let reformed_ast = leo_asg::reform_ast(&asg);
|
||||
println!("{}", serde_json::to_string(&reformed_ast).unwrap());
|
||||
|
@ -63,7 +63,7 @@ pub use node::*;
|
||||
|
||||
use leo_grammar::Grammar;
|
||||
|
||||
/// The abstract syntax tree (ast) for a Leo program.
|
||||
/// The abstract syntax tree (AST) for a Leo program.
|
||||
///
|
||||
/// The [`Ast`] 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.
|
||||
@ -75,16 +75,16 @@ pub struct Ast {
|
||||
}
|
||||
|
||||
impl Ast {
|
||||
/// Creates a new ast from a given program name and grammar tree.
|
||||
pub fn new<'ast>(program_name: &str, ast: &Grammar<'ast>) -> Result<Self, AstError> {
|
||||
/// Creates a new AST from a given program name and grammar tree.
|
||||
pub fn new<'ast>(program_name: &str, grammar: &Grammar<'ast>) -> Result<Self, AstError> {
|
||||
Ok(Self {
|
||||
ast: Program::from(program_name, ast.as_repr())?,
|
||||
ast: Program::from(program_name, grammar.as_repr())?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a reference to the inner program ast representation.
|
||||
pub fn into_repr(self) -> Program {
|
||||
self.ast
|
||||
/// Returns a reference to the inner program AST representation.
|
||||
pub fn as_repr(&self) -> &Program {
|
||||
&self.ast
|
||||
}
|
||||
|
||||
/// Serializes the ast into a JSON string.
|
||||
|
@ -44,7 +44,7 @@ fn test_serialize() {
|
||||
};
|
||||
|
||||
// Serializes the ast into JSON format.
|
||||
let serialized_ast: Program = serde_json::from_value(serde_json::to_value(ast.into_repr()).unwrap()).unwrap();
|
||||
let serialized_ast: Program = serde_json::from_value(serde_json::to_value(ast.as_repr()).unwrap()).unwrap();
|
||||
|
||||
// Load the expected ast.
|
||||
let expected: Program = serde_json::from_str(include_str!("expected_leo_ast.json")).unwrap();
|
||||
|
@ -23,13 +23,13 @@ use crate::{
|
||||
OutputBytes,
|
||||
OutputFile,
|
||||
};
|
||||
use leo_asg::Asg;
|
||||
use leo_ast::{Ast, Input, MainInput, Program};
|
||||
use leo_grammar::Grammar;
|
||||
use leo_input::LeoInputParser;
|
||||
use leo_package::inputs::InputPairs;
|
||||
use leo_state::verify_local_data_commitment;
|
||||
|
||||
use leo_asg::Program as AsgProgram;
|
||||
use snarkvm_dpc::{base_dpc::instantiated::Components, SystemParameters};
|
||||
use snarkvm_errors::gadgets::SynthesisError;
|
||||
use snarkvm_models::{
|
||||
@ -47,12 +47,12 @@ use std::{
|
||||
/// Stores information to compile a Leo program.
|
||||
#[derive(Clone)]
|
||||
pub struct Compiler<F: Field + PrimeField, G: GroupType<F>> {
|
||||
package_name: String,
|
||||
program_name: String,
|
||||
main_file_path: PathBuf,
|
||||
output_directory: PathBuf,
|
||||
program: Program,
|
||||
program_input: Input,
|
||||
asg: Option<AsgProgram>,
|
||||
asg: Option<Asg>,
|
||||
_engine: PhantomData<F>,
|
||||
_group: PhantomData<G>,
|
||||
}
|
||||
@ -63,7 +63,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
///
|
||||
pub fn new(package_name: String, main_file_path: PathBuf, output_directory: PathBuf) -> Self {
|
||||
Self {
|
||||
package_name: package_name.clone(),
|
||||
program_name: package_name.clone(),
|
||||
main_file_path,
|
||||
output_directory,
|
||||
program: Program::new(package_name),
|
||||
@ -88,7 +88,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
) -> Result<Self, CompilerError> {
|
||||
let mut compiler = Self::new(package_name, main_file_path, output_directory);
|
||||
|
||||
compiler.parse_and_check_program()?;
|
||||
compiler.parse_program()?;
|
||||
|
||||
Ok(compiler)
|
||||
}
|
||||
@ -114,7 +114,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
|
||||
compiler.parse_input(input_string, input_path, state_string, state_path)?;
|
||||
|
||||
compiler.parse_and_check_program()?;
|
||||
compiler.parse_program()?;
|
||||
|
||||
Ok(compiler)
|
||||
}
|
||||
@ -156,51 +156,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
///
|
||||
/// Runs program parser and type inference checker consecutively.
|
||||
///
|
||||
pub(crate) fn parse_and_check_program(&mut self) -> Result<(), CompilerError> {
|
||||
self.parse_program()
|
||||
}
|
||||
|
||||
///
|
||||
/// 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> {
|
||||
pub fn parse_program(&mut self) -> Result<(), CompilerError> {
|
||||
// Load the program file.
|
||||
let program_string = Grammar::load_file(&self.main_file_path)?;
|
||||
|
||||
// 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 = Ast::new(&self.package_name, &pest_ast)?;
|
||||
|
||||
// Store the main program file.
|
||||
self.program = core_ast.into_repr();
|
||||
|
||||
tracing::debug!("Program parsing complete\n{:#?}", self.program);
|
||||
|
||||
self.program_asg_generate()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn program_asg_generate(&mut self) -> Result<(), CompilerError> {
|
||||
// Create a new symbol table from the program, imported_programs, and program_input.
|
||||
let asg = leo_asg::InnerProgram::new(&self.program, &mut leo_imports::ImportParser::default())?;
|
||||
|
||||
tracing::debug!("ASG generation complete");
|
||||
|
||||
self.asg = Some(asg);
|
||||
|
||||
Ok(())
|
||||
self.parse_program_from_string(&program_string)
|
||||
}
|
||||
|
||||
///
|
||||
@ -208,52 +173,56 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
/// file path.
|
||||
///
|
||||
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 = Grammar::new(&self.main_file_path, &program_string).map_err(|mut e| {
|
||||
// Use the parser to construct the pest abstract syntax tree (ast).
|
||||
let grammar = Grammar::new(&self.main_file_path, &program_string).map_err(|mut e| {
|
||||
e.set_path(&self.main_file_path);
|
||||
|
||||
e
|
||||
})?;
|
||||
|
||||
// Derive the package name.
|
||||
let package_name = &self.package_name;
|
||||
|
||||
// Construct the core ast from the pest ast.
|
||||
let core_ast = Ast::new(package_name, &ast)?;
|
||||
// Construct the AST from the grammar.
|
||||
let core_ast = Ast::new(&self.program_name, &grammar)?;
|
||||
|
||||
// Store the main program file.
|
||||
self.program = core_ast.into_repr();
|
||||
self.program = core_ast.as_repr().clone();
|
||||
|
||||
tracing::debug!("Program parsing complete\n{:#?}", self.program);
|
||||
|
||||
self.program_asg_generate()?;
|
||||
// Create a new symbol table from the program, imported_programs, and program_input.
|
||||
let asg = Asg::new(&core_ast, &mut leo_imports::ImportParser::default())?;
|
||||
|
||||
tracing::debug!("ASG generation complete");
|
||||
|
||||
// Store the ASG.
|
||||
self.asg = Some(asg);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
///
|
||||
/// Manually sets main function input.
|
||||
/// Synthesizes the circuit with program input to verify correctness.
|
||||
///
|
||||
/// Used for testing only.
|
||||
///
|
||||
pub fn set_main_input(&mut self, input: MainInput) {
|
||||
self.program_input.set_main_input(input);
|
||||
pub fn compile_constraints<CS: ConstraintSystem<F>>(&self, cs: &mut CS) -> Result<OutputBytes, CompilerError> {
|
||||
generate_constraints::<F, G, CS>(cs, &self.asg.as_ref().unwrap(), &self.program_input).map_err(|mut error| {
|
||||
error.set_path(&self.main_file_path);
|
||||
error
|
||||
})
|
||||
}
|
||||
|
||||
///
|
||||
/// Verifies the input to the program.
|
||||
/// Synthesizes the circuit for test functions with program input.
|
||||
///
|
||||
pub fn verify_local_data_commitment(
|
||||
&self,
|
||||
system_parameters: &SystemParameters<Components>,
|
||||
) -> Result<bool, CompilerError> {
|
||||
let result = verify_local_data_commitment(system_parameters, &self.program_input)?;
|
||||
|
||||
Ok(result)
|
||||
pub fn compile_test_constraints(self, input_pairs: InputPairs) -> Result<(u32, u32), CompilerError> {
|
||||
generate_test_constraints::<F, G>(
|
||||
&self.asg.as_ref().unwrap(),
|
||||
input_pairs,
|
||||
&self.main_file_path,
|
||||
&self.output_directory,
|
||||
)
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a Sha256 checksum of the program file.
|
||||
/// Returns a SHA256 checksum of the program file.
|
||||
///
|
||||
pub fn checksum(&self) -> Result<String, CompilerError> {
|
||||
// Read in the main file as string
|
||||
@ -268,43 +237,27 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
Ok(hex::encode(hash))
|
||||
}
|
||||
|
||||
/// TODO (howardwu): Incorporate this for real program executions and intentionally-real
|
||||
/// test executions. Exclude it for test executions on dummy data.
|
||||
///
|
||||
/// Synthesizes the circuit without program input to verify correctness.
|
||||
/// Verifies the input to the program.
|
||||
///
|
||||
pub fn compile_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<OutputBytes, CompilerError> {
|
||||
let path = self.main_file_path;
|
||||
|
||||
generate_constraints::<F, G, CS>(cs, self.asg.as_ref().unwrap(), &self.program_input).map_err(|mut error| {
|
||||
error.set_path(&path);
|
||||
|
||||
error
|
||||
})
|
||||
}
|
||||
|
||||
///
|
||||
/// 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.asg.as_ref().unwrap(),
|
||||
input_pairs,
|
||||
&self.main_file_path,
|
||||
&self.output_directory,
|
||||
)
|
||||
}
|
||||
|
||||
///
|
||||
/// Calls the internal generate_constraints method with arguments.
|
||||
///
|
||||
pub fn generate_constraints_helper<CS: ConstraintSystem<F>>(
|
||||
pub fn verify_local_data_commitment(
|
||||
&self,
|
||||
cs: &mut CS,
|
||||
) -> Result<OutputBytes, CompilerError> {
|
||||
let path = &self.main_file_path;
|
||||
generate_constraints::<_, G, _>(cs, self.asg.as_ref().unwrap(), &self.program_input).map_err(|mut error| {
|
||||
error.set_path(&path);
|
||||
error
|
||||
})
|
||||
system_parameters: &SystemParameters<Components>,
|
||||
) -> Result<bool, CompilerError> {
|
||||
let result = verify_local_data_commitment(system_parameters, &self.program_input)?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
///
|
||||
/// 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,8 +267,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compil
|
||||
///
|
||||
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();
|
||||
let result = self.generate_constraints_helper(cs).map_err(|e| {
|
||||
let package_name = self.program_name.clone();
|
||||
let result = self.compile_constraints(cs).map_err(|e| {
|
||||
tracing::error!("{}", e);
|
||||
SynthesisError::Unsatisfiable
|
||||
})?;
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! Generates R1CS constraints for a compiled Leo program.
|
||||
|
||||
use crate::{errors::CompilerError, ConstrainedProgram, GroupType, OutputBytes, OutputFile};
|
||||
use leo_asg::Program;
|
||||
use leo_asg::Asg;
|
||||
use leo_ast::Input;
|
||||
use leo_input::LeoInputParser;
|
||||
use leo_package::inputs::InputPairs;
|
||||
@ -30,9 +30,10 @@ use std::path::Path;
|
||||
|
||||
pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
program: &Program,
|
||||
asg: &Asg,
|
||||
input: &Input,
|
||||
) -> Result<OutputBytes, CompilerError> {
|
||||
let program = asg.as_repr();
|
||||
let mut resolved_program = ConstrainedProgram::<F, G>::new(program.clone());
|
||||
|
||||
let main = {
|
||||
@ -50,11 +51,12 @@ pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: Constrai
|
||||
}
|
||||
|
||||
pub fn generate_test_constraints<F: Field + PrimeField, G: GroupType<F>>(
|
||||
program: &Program,
|
||||
asg: &Asg,
|
||||
input: InputPairs,
|
||||
main_file_path: &Path,
|
||||
output_directory: &Path,
|
||||
) -> Result<(u32, u32), CompilerError> {
|
||||
let program = asg.as_repr();
|
||||
let mut resolved_program = ConstrainedProgram::<F, G>::new(program.clone());
|
||||
let program_name = program.borrow().name.clone();
|
||||
|
||||
|
@ -146,7 +146,7 @@ pub fn parse_program_with_input_and_state(
|
||||
pub(crate) fn get_output(program: EdwardsTestCompiler) -> OutputBytes {
|
||||
// synthesize the circuit on the test constraint system
|
||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
||||
let output = program.generate_constraints_helper(&mut cs).unwrap();
|
||||
let output = program.compile_constraints(&mut cs).unwrap();
|
||||
|
||||
// assert the constraint system is satisfied
|
||||
assert!(cs.is_satisfied());
|
||||
@ -164,7 +164,7 @@ pub(crate) fn assert_satisfied(program: EdwardsTestCompiler) {
|
||||
|
||||
pub(crate) fn expect_compiler_error(program: EdwardsTestCompiler) -> CompilerError {
|
||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
||||
program.generate_constraints_helper(&mut cs).unwrap_err()
|
||||
program.compile_constraints(&mut cs).unwrap_err()
|
||||
}
|
||||
|
||||
pub(crate) fn expect_asg_error(error: CompilerError) {
|
||||
|
@ -22,8 +22,8 @@ name = "leo_grammar"
|
||||
path = "src/main.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "ast"
|
||||
path = "benches/ast.rs"
|
||||
name = "grammar"
|
||||
path = "benches/grammar.rs"
|
||||
harness = false
|
||||
|
||||
[dependencies.from-pest]
|
||||
|
@ -2,7 +2,7 @@ circuit PedersenHash {
|
||||
parameters: [group; 256],
|
||||
|
||||
// Instantiates a Pedersen hash circuit
|
||||
static function new(parameters: [group; 256]) -> Self {
|
||||
function new(self, parameters: [group; 256]) -> Self {
|
||||
return Self { parameters: parameters }
|
||||
}
|
||||
|
||||
|
@ -44,8 +44,8 @@ use pest::{
|
||||
#[grammar = "leo.pest"]
|
||||
pub struct LanguageParser;
|
||||
|
||||
pub fn parse(input: &str) -> Result<Pairs<Rule>, Error<Rule>> {
|
||||
LanguageParser::parse(Rule::file, input)
|
||||
pub fn parse(program_string: &str) -> Result<Pairs<Rule>, Error<Rule>> {
|
||||
LanguageParser::parse(Rule::file, program_string)
|
||||
}
|
||||
|
||||
pub(crate) fn span_into_string(span: Span) -> String {
|
||||
|
@ -17,8 +17,8 @@
|
||||
use crate::ast::Rule;
|
||||
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize, Deserialize)]
|
||||
#[pest_ast(rule(Rule::EOI))]
|
||||
pub struct EOI;
|
||||
|
@ -53,19 +53,23 @@ pub(crate) use span::*;
|
||||
use from_pest::FromPest;
|
||||
use std::{fs, path::Path};
|
||||
|
||||
/// The pest abstract syntax tree (ast) for a Leo program.
|
||||
///
|
||||
/// The grammar of a Leo program, encoded as an abstract syntax tree (AST).
|
||||
///
|
||||
/// The [`Grammar`] type represents a Leo program as a series of recursive data types.
|
||||
/// These data types form a tree that begins from a [`File`] type root.
|
||||
///
|
||||
/// A new [`Grammar`] type can be created from a `*.leo` file at a [`Path`].
|
||||
/// A [`Grammar`] type can be used to create a new [`Ast`] type.
|
||||
///
|
||||
pub struct Grammar<'ast> {
|
||||
ast: files::File<'ast>,
|
||||
}
|
||||
|
||||
impl<'ast> Grammar<'ast> {
|
||||
/// Creates a new abstract syntax tree given the file path.
|
||||
///
|
||||
/// Creates a new abstract syntax tree from a given program string, and optional 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()))?);
|
||||
@ -83,17 +87,23 @@ impl<'ast> Grammar<'ast> {
|
||||
|
||||
// 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> {
|
||||
fs::read_to_string(file_path).map_err(|_| ParserError::FileReadError(file_path.to_owned()))
|
||||
}
|
||||
|
||||
///
|
||||
/// 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> {
|
||||
Ok(serde_json::to_string_pretty(&self.ast)?)
|
||||
}
|
||||
|
@ -15,11 +15,11 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use pest::Span;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// Provide getters for every private field of the remote struct. The getter must
|
||||
// return either `T` or `&T` where `T` is the type of the field.
|
||||
#[derive(Serialize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "Span")]
|
||||
pub(crate) struct SpanDef<'i> {
|
||||
/// # Attention
|
||||
|
@ -34,7 +34,7 @@ impl ImportParser {
|
||||
return self.parse_package(package.path(), remaining_segments, span);
|
||||
}
|
||||
let program = Self::parse_import_file(package, span)?;
|
||||
let asg = leo_asg::InnerProgram::new(&program, self)?;
|
||||
let asg = leo_asg::InternalProgram::new(&program, self)?;
|
||||
|
||||
Ok(asg)
|
||||
}
|
||||
|
@ -31,18 +31,18 @@ use snarkvm_utilities::{bytes::ToBytes, to_bytes, FromBytes};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Returns `true` if the path to the local data commitment leaf is a valid path in the record
|
||||
/// commitment merkle tree.
|
||||
/// commitment Merkle tree.
|
||||
pub fn verify_local_data_commitment(
|
||||
system_parameters: &SystemParameters<Components>,
|
||||
ast_input: &AstInput,
|
||||
) -> Result<bool, LocalDataVerificationError> {
|
||||
// verify record commitment.
|
||||
// Verify record commitment.
|
||||
let typed_record = ast_input.get_record();
|
||||
let dpc_record_values = verify_record_commitment(system_parameters, typed_record)?;
|
||||
let record_commitment: Vec<u8> = dpc_record_values.commitment;
|
||||
let record_serial_number: Vec<u8> = dpc_record_values.serial_number;
|
||||
|
||||
// parse typed state values.
|
||||
// Parse typed state values.
|
||||
let typed_state = ast_input.get_state();
|
||||
let state_values = StateValues::try_from(typed_state)?;
|
||||
let leaf_index: u32 = state_values.leaf_index;
|
||||
|
Loading…
Reference in New Issue
Block a user