mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-28 20:14:11 +03:00
errors are causing a dep cycle those need to be refactored first
This commit is contained in:
parent
d2fe35c0b9
commit
e8ad50446a
@ -1,5 +1,5 @@
|
||||
[hooks]
|
||||
pre-commit = "cargo clippy && cargo +nightly fmt --all -- --check"
|
||||
|
||||
# pre-commit = "cargo clippy && cargo +nightly fmt --all -- --check"
|
||||
# temp disable for this branch
|
||||
[logging]
|
||||
verbose = true
|
||||
|
@ -33,10 +33,6 @@ version = "1.0"
|
||||
version = "1.5.2"
|
||||
path = "../ast"
|
||||
|
||||
[dependencies.leo-parser]
|
||||
version = "1.5.2"
|
||||
path = "../parser"
|
||||
|
||||
[dependencies.num-bigint]
|
||||
version = "0.4"
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
use crate::Span;
|
||||
use leo_ast::{AstError, FormattedError, LeoError};
|
||||
use leo_parser::SyntaxError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AsgConvertError {
|
||||
|
@ -96,11 +96,10 @@ impl<'a> Asg<'a> {
|
||||
pub fn new<T: ImportResolver<'a>, Y: AsRef<leo_ast::Program>>(
|
||||
context: AsgContext<'a>,
|
||||
ast: Y,
|
||||
resolver: &mut T,
|
||||
) -> Result<Self, AsgConvertError> {
|
||||
Ok(Self {
|
||||
context,
|
||||
asg: Program::new(context, ast.as_ref(), resolver)?,
|
||||
asg: Program::new(context, ast.as_ref())?,
|
||||
})
|
||||
}
|
||||
|
||||
@ -134,7 +133,7 @@ pub fn load_asg<'a, T: ImportResolver<'a>>(
|
||||
// Parses the Leo file and constructs a grammar ast.
|
||||
let ast = leo_parser::parse_ast("input.leo", content)?;
|
||||
|
||||
Program::new(context, ast.as_repr(), resolver)
|
||||
Program::new(context, ast.as_repr())
|
||||
}
|
||||
|
||||
pub fn new_alloc_context<'a>() -> Arena<ArenaNode<'a>> {
|
||||
|
@ -35,7 +35,7 @@ use crate::{
|
||||
Scope,
|
||||
Statement,
|
||||
};
|
||||
use leo_ast::{Identifier, PackageAccess, PackageOrPackages, Span};
|
||||
use leo_ast::{PackageAccess, PackageOrPackages, Span};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use std::cell::{Cell, RefCell};
|
||||
@ -67,72 +67,6 @@ pub struct Program<'a> {
|
||||
pub scope: &'a Scope<'a>,
|
||||
}
|
||||
|
||||
/// Enumerates what names are imported from a package.
|
||||
#[derive(Clone)]
|
||||
enum ImportSymbol {
|
||||
/// Import the symbol by name.
|
||||
Direct(String),
|
||||
|
||||
/// Import the symbol by name and store it under an alias.
|
||||
Alias(String, String), // from remote -> to local
|
||||
|
||||
/// Import all symbols from the package.
|
||||
All,
|
||||
}
|
||||
|
||||
fn resolve_import_package(
|
||||
output: &mut Vec<(Vec<String>, ImportSymbol, Span)>,
|
||||
mut package_segments: Vec<String>,
|
||||
package_or_packages: &PackageOrPackages,
|
||||
) {
|
||||
match package_or_packages {
|
||||
PackageOrPackages::Package(package) => {
|
||||
package_segments.push(package.name.name.to_string());
|
||||
resolve_import_package_access(output, package_segments, &package.access);
|
||||
}
|
||||
PackageOrPackages::Packages(packages) => {
|
||||
package_segments.push(packages.name.name.to_string());
|
||||
for access in packages.accesses.clone() {
|
||||
resolve_import_package_access(output, package_segments.clone(), &access);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_import_package_access(
|
||||
output: &mut Vec<(Vec<String>, ImportSymbol, Span)>,
|
||||
mut package_segments: Vec<String>,
|
||||
package: &PackageAccess,
|
||||
) {
|
||||
match package {
|
||||
PackageAccess::Star { span } => {
|
||||
output.push((package_segments, ImportSymbol::All, span.clone()));
|
||||
}
|
||||
PackageAccess::SubPackage(subpackage) => {
|
||||
resolve_import_package(
|
||||
output,
|
||||
package_segments,
|
||||
&PackageOrPackages::Package(*(*subpackage).clone()),
|
||||
);
|
||||
}
|
||||
PackageAccess::Symbol(symbol) => {
|
||||
let span = symbol.symbol.span.clone();
|
||||
let symbol = if let Some(alias) = symbol.alias.as_ref() {
|
||||
ImportSymbol::Alias(symbol.symbol.name.to_string(), alias.name.to_string())
|
||||
} else {
|
||||
ImportSymbol::Direct(symbol.symbol.name.to_string())
|
||||
};
|
||||
output.push((package_segments, symbol, span));
|
||||
}
|
||||
PackageAccess::Multiple(packages) => {
|
||||
package_segments.push(packages.name.name.to_string());
|
||||
for subaccess in packages.accesses.iter() {
|
||||
resolve_import_package_access(output, package_segments.clone(), &subaccess);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Program<'a> {
|
||||
/// Returns a new Leo program ASG from the given Leo program AST and its imports.
|
||||
///
|
||||
@ -142,88 +76,21 @@ impl<'a> Program<'a> {
|
||||
/// 3. finalize declared functions
|
||||
/// 4. resolve all asg nodes
|
||||
///
|
||||
pub fn new<T: ImportResolver<'a>>(
|
||||
context: AsgContext<'a>,
|
||||
program: &leo_ast::Program,
|
||||
import_resolver: &mut T,
|
||||
) -> Result<Program<'a>, AsgConvertError> {
|
||||
// Recursively extract imported symbols.
|
||||
let mut imported_symbols: Vec<(Vec<String>, ImportSymbol, Span)> = vec![];
|
||||
for import in program.imports.iter() {
|
||||
resolve_import_package(&mut imported_symbols, vec![], &import.package_or_packages);
|
||||
}
|
||||
|
||||
// Create package list.
|
||||
let mut deduplicated_imports: IndexMap<Vec<String>, Span> = IndexMap::new();
|
||||
for (package, _symbol, span) in imported_symbols.iter() {
|
||||
deduplicated_imports.insert(package.clone(), span.clone());
|
||||
}
|
||||
|
||||
let mut wrapped_resolver = crate::CoreImportResolver::new(import_resolver);
|
||||
|
||||
// Load imported programs.
|
||||
let mut resolved_packages: IndexMap<Vec<String>, Program> = IndexMap::new();
|
||||
for (package, span) in deduplicated_imports.iter() {
|
||||
let pretty_package = package.join(".");
|
||||
|
||||
let resolved_package = match wrapped_resolver.resolve_package(
|
||||
context,
|
||||
&package.iter().map(|x| &**x).collect::<Vec<_>>()[..],
|
||||
span,
|
||||
)? {
|
||||
Some(x) => x,
|
||||
None => return Err(AsgConvertError::unresolved_import(&*pretty_package, &Span::default())),
|
||||
};
|
||||
|
||||
resolved_packages.insert(package.clone(), resolved_package);
|
||||
}
|
||||
|
||||
pub fn new(context: AsgContext<'a>, program: &leo_ast::Program) -> Result<Program<'a>, AsgConvertError> {
|
||||
let mut imported_functions: IndexMap<String, &'a Function<'a>> = IndexMap::new();
|
||||
let mut imported_circuits: IndexMap<String, &'a Circuit<'a>> = IndexMap::new();
|
||||
let mut imported_global_consts: IndexMap<String, &'a DefinitionStatement<'a>> = IndexMap::new();
|
||||
let mut imported_modules: IndexMap<String, Program> = IndexMap::new();
|
||||
|
||||
// Prepare locally relevant scope of imports.
|
||||
for (package, symbol, span) in imported_symbols.into_iter() {
|
||||
let pretty_package = package.join(".");
|
||||
for (name, program) in program.imports.iter() {
|
||||
let program = Program::new(context, program)?;
|
||||
|
||||
let resolved_package = resolved_packages
|
||||
.get(&package)
|
||||
.expect("could not find preloaded package");
|
||||
match symbol {
|
||||
ImportSymbol::All => {
|
||||
imported_functions.extend(resolved_package.functions.clone().into_iter());
|
||||
imported_circuits.extend(resolved_package.circuits.clone().into_iter());
|
||||
imported_global_consts.extend(resolved_package.global_consts.clone().into_iter());
|
||||
}
|
||||
ImportSymbol::Direct(name) => {
|
||||
if let Some(function) = resolved_package.functions.get(&name) {
|
||||
imported_functions.insert(name.clone(), *function);
|
||||
} else if let Some(circuit) = resolved_package.circuits.get(&name) {
|
||||
imported_circuits.insert(name.clone(), *circuit);
|
||||
} else if let Some(global_const) = resolved_package.global_consts.get(&name) {
|
||||
imported_global_consts.insert(name.clone(), *global_const);
|
||||
} else {
|
||||
return Err(AsgConvertError::unresolved_import(
|
||||
&*format!("{}.{}", pretty_package, name),
|
||||
&span,
|
||||
));
|
||||
}
|
||||
}
|
||||
ImportSymbol::Alias(name, alias) => {
|
||||
if let Some(function) = resolved_package.functions.get(&name) {
|
||||
imported_functions.insert(alias.clone(), *function);
|
||||
} else if let Some(circuit) = resolved_package.circuits.get(&name) {
|
||||
imported_circuits.insert(alias.clone(), *circuit);
|
||||
} else if let Some(global_const) = resolved_package.global_consts.get(&name) {
|
||||
imported_global_consts.insert(alias.clone(), *global_const);
|
||||
} else {
|
||||
return Err(AsgConvertError::unresolved_import(
|
||||
&*format!("{}.{}", pretty_package, name),
|
||||
&span,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO only take the ones specified.
|
||||
imported_functions.extend(program.functions.clone());
|
||||
imported_circuits.extend(program.circuits.clone());
|
||||
imported_global_consts.extend(program.global_consts.clone());
|
||||
|
||||
imported_modules.insert(name.clone(), program);
|
||||
}
|
||||
|
||||
let import_scope = match context.arena.alloc(ArenaNode::Scope(Box::new(Scope {
|
||||
@ -334,10 +201,7 @@ impl<'a> Program<'a> {
|
||||
functions,
|
||||
global_consts,
|
||||
circuits,
|
||||
imported_modules: resolved_packages
|
||||
.into_iter()
|
||||
.map(|(package, program)| (package.join("."), program))
|
||||
.collect(),
|
||||
imported_modules,
|
||||
scope,
|
||||
})
|
||||
}
|
||||
@ -348,135 +212,3 @@ impl<'a> Program<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct InternalIdentifierGenerator {
|
||||
next: usize,
|
||||
}
|
||||
|
||||
impl Iterator for InternalIdentifierGenerator {
|
||||
type Item = String;
|
||||
|
||||
fn next(&mut self) -> Option<String> {
|
||||
let out = format!("$_{}_", self.next);
|
||||
self.next += 1;
|
||||
Some(out)
|
||||
}
|
||||
}
|
||||
/// Returns an AST from the given ASG program.
|
||||
pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program {
|
||||
let mut all_programs: IndexMap<String, Program> = IndexMap::new();
|
||||
let mut program_stack = program.imported_modules.clone();
|
||||
while let Some((module, program)) = program_stack.pop() {
|
||||
if all_programs.contains_key(&module) {
|
||||
continue;
|
||||
}
|
||||
all_programs.insert(module, program.clone());
|
||||
program_stack.extend(program.imported_modules.clone());
|
||||
}
|
||||
all_programs.insert("".to_string(), program.clone());
|
||||
let core_programs: Vec<_> = all_programs
|
||||
.iter()
|
||||
.filter(|(module, _)| module.starts_with("core."))
|
||||
.map(|(module, program)| (module.clone(), program.clone()))
|
||||
.collect();
|
||||
all_programs.retain(|module, _| !module.starts_with("core."));
|
||||
|
||||
let mut all_circuits: IndexMap<String, &'a Circuit<'a>> = IndexMap::new();
|
||||
let mut all_functions: IndexMap<String, &'a Function<'a>> = IndexMap::new();
|
||||
let mut all_global_consts: IndexMap<String, &'a DefinitionStatement<'a>> = IndexMap::new();
|
||||
let mut identifiers = InternalIdentifierGenerator { next: 0 };
|
||||
for (_, program) in all_programs.into_iter() {
|
||||
for (name, circuit) in program.circuits.iter() {
|
||||
let identifier = format!("{}{}", identifiers.next().unwrap(), name);
|
||||
circuit.name.borrow_mut().name = identifier.clone().into();
|
||||
all_circuits.insert(identifier, *circuit);
|
||||
}
|
||||
for (name, function) in program.functions.iter() {
|
||||
let identifier = if name == "main" {
|
||||
"main".to_string()
|
||||
} else {
|
||||
format!("{}{}", identifiers.next().unwrap(), name)
|
||||
};
|
||||
function.name.borrow_mut().name = identifier.clone().into();
|
||||
all_functions.insert(identifier, *function);
|
||||
}
|
||||
|
||||
for (name, global_const) in program.global_consts.iter() {
|
||||
let identifier = format!("{}{}", identifiers.next().unwrap(), name);
|
||||
all_global_consts.insert(identifier, *global_const);
|
||||
}
|
||||
}
|
||||
|
||||
leo_ast::Program {
|
||||
name: "ast_aggregate".to_string(),
|
||||
imports: core_programs
|
||||
.iter()
|
||||
.map(|(module, _)| leo_ast::ImportStatement {
|
||||
package_or_packages: leo_ast::PackageOrPackages::Package(leo_ast::Package {
|
||||
name: Identifier::new(module.clone().into()),
|
||||
access: leo_ast::PackageAccess::Star { span: Span::default() },
|
||||
span: Default::default(),
|
||||
}),
|
||||
span: Span::default(),
|
||||
})
|
||||
.collect(),
|
||||
expected_input: vec![],
|
||||
functions: all_functions
|
||||
.into_iter()
|
||||
.map(|(_, function)| (function.name.borrow().clone(), function.into()))
|
||||
.collect(),
|
||||
circuits: all_circuits
|
||||
.into_iter()
|
||||
.map(|(_, circuit)| (circuit.name.borrow().clone(), circuit.into()))
|
||||
.collect(),
|
||||
global_consts: all_global_consts
|
||||
.into_iter()
|
||||
.map(|(_, global_const)| {
|
||||
(
|
||||
global_const
|
||||
.variables
|
||||
.iter()
|
||||
.fold("".to_string(), |joined, variable_name| {
|
||||
format!("{}, {}", joined, variable_name.borrow().name.name)
|
||||
}),
|
||||
global_const.into(),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Into<leo_ast::Program> for &Program<'a> {
|
||||
fn into(self) -> leo_ast::Program {
|
||||
leo_ast::Program {
|
||||
name: self.name.clone(),
|
||||
imports: vec![],
|
||||
expected_input: vec![],
|
||||
circuits: self
|
||||
.circuits
|
||||
.iter()
|
||||
.map(|(_, circuit)| (circuit.name.borrow().clone(), (*circuit).into()))
|
||||
.collect(),
|
||||
functions: self
|
||||
.functions
|
||||
.iter()
|
||||
.map(|(_, function)| (function.name.borrow().clone(), (*function).into()))
|
||||
.collect(),
|
||||
global_consts: self
|
||||
.global_consts
|
||||
.iter()
|
||||
.map(|(_, global_const)| {
|
||||
(
|
||||
global_const
|
||||
.variables
|
||||
.iter()
|
||||
.fold("".to_string(), |joined, variable_name| {
|
||||
format!("{}, {}", joined, variable_name.borrow().name.name)
|
||||
}),
|
||||
(*global_const).into(),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,90 +0,0 @@
|
||||
// Copyright (C) 2019-2021 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{load_asg, make_test_context};
|
||||
use leo_parser::parse_ast;
|
||||
|
||||
#[test]
|
||||
fn test_basic() {
|
||||
let program_string = include_str!("./circuits/pedersen_mock.leo");
|
||||
let asg = load_asg(program_string).unwrap();
|
||||
let reformed_ast = leo_asg::reform_ast(&asg);
|
||||
println!("{}", reformed_ast);
|
||||
// panic!();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_function_rename() {
|
||||
let program_string = r#"
|
||||
function iteration() -> u32 {
|
||||
let a = 0u32;
|
||||
|
||||
for i in 0..10 {
|
||||
a += 1;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const total = iteration() + iteration();
|
||||
|
||||
console.assert(total == 20);
|
||||
}
|
||||
"#;
|
||||
let asg = load_asg(program_string).unwrap();
|
||||
let reformed_ast = leo_asg::reform_ast(&asg);
|
||||
println!("{}", reformed_ast);
|
||||
// panic!();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_imports() {
|
||||
let import_name = "test-import".to_string();
|
||||
let context = make_test_context();
|
||||
let mut imports = crate::mocked_resolver(&context);
|
||||
let test_import = r#"
|
||||
circuit Point {
|
||||
x: u32;
|
||||
y: u32;
|
||||
}
|
||||
|
||||
function foo() -> u32 {
|
||||
return 1u32;
|
||||
}
|
||||
"#;
|
||||
imports
|
||||
.packages
|
||||
.insert(import_name.clone(), load_asg(test_import).unwrap());
|
||||
let program_string = r#"
|
||||
import test-import.foo;
|
||||
|
||||
function main() {
|
||||
console.assert(foo() == 1u32);
|
||||
}
|
||||
"#;
|
||||
|
||||
let test_import_ast = parse_ast(&import_name, test_import).unwrap();
|
||||
println!("{}", serde_json::to_string(test_import_ast.as_repr()).unwrap());
|
||||
|
||||
let test_ast = parse_ast("test.leo", program_string).unwrap();
|
||||
println!("{}", serde_json::to_string(test_ast.as_repr()).unwrap());
|
||||
|
||||
let asg = crate::load_asg_imports(&context, program_string, &mut imports).unwrap();
|
||||
let reformed_ast = leo_asg::reform_ast(&asg);
|
||||
println!("{}", serde_json::to_string(&reformed_ast).unwrap());
|
||||
// panic!();
|
||||
}
|
@ -22,7 +22,6 @@ pub mod console;
|
||||
pub mod core;
|
||||
pub mod definition;
|
||||
pub mod field;
|
||||
pub mod form_ast;
|
||||
pub mod function;
|
||||
pub mod group;
|
||||
pub mod import;
|
||||
|
@ -21,6 +21,10 @@ edition = "2018"
|
||||
path = "../input"
|
||||
version = "1.5.2"
|
||||
|
||||
[dependencies.leo-parser]
|
||||
path = "../parser"
|
||||
version = "1.5.2"
|
||||
|
||||
[dependencies.indexmap]
|
||||
version = "1.7.0"
|
||||
features = [ "serde-1" ]
|
||||
|
@ -15,6 +15,7 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{CanonicalizeError, CombinerError, FormattedError, LeoError, Span};
|
||||
use leo_parser::SyntaxError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ReducerError {
|
||||
@ -26,6 +27,12 @@ pub enum ReducerError {
|
||||
|
||||
#[error("{}", _0)]
|
||||
CombinerError(#[from] CombinerError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ImportError(FormattedError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
SyntaxError(#[from] SyntaxError),
|
||||
}
|
||||
|
||||
impl LeoError for ReducerError {}
|
||||
@ -47,4 +54,10 @@ impl ReducerError {
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn ast_err() -> Self {
|
||||
let message = "ahhhh";
|
||||
|
||||
Self::new_from_span(mesage, Span::default())
|
||||
}
|
||||
}
|
||||
|
@ -85,6 +85,12 @@ impl Ast {
|
||||
Self { ast: program }
|
||||
}
|
||||
|
||||
/// Mutates the program ast by resolving the imports.
|
||||
pub fn importer<T: ImportResolver>(&mut self, importer: T) -> Result<(), AstError> {
|
||||
self.ast = ReconstructingDirector::new(Importer::new(importer)).reduce_program(self.as_repr())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Mutates the program ast by preforming canonicalization on it.
|
||||
pub fn canonicalize(&mut self) -> Result<(), AstError> {
|
||||
self.ast = ReconstructingDirector::new(Canonicalizer::default()).reduce_program(self.as_repr())?;
|
||||
|
@ -28,7 +28,8 @@ use std::fmt;
|
||||
pub struct Program {
|
||||
pub name: String,
|
||||
pub expected_input: Vec<FunctionInput>,
|
||||
pub imports: Vec<ImportStatement>,
|
||||
pub import_statements: Vec<ImportStatement>,
|
||||
pub imports: IndexMap<String, Program>,
|
||||
pub circuits: IndexMap<Identifier, Circuit>,
|
||||
pub global_consts: IndexMap<String, DefinitionStatement>,
|
||||
pub functions: IndexMap<Identifier, Function>,
|
||||
@ -42,7 +43,12 @@ impl AsRef<Program> for Program {
|
||||
|
||||
impl fmt::Display for Program {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for import in self.imports.iter() {
|
||||
for import in self.import_statements.iter() {
|
||||
import.fmt(f)?;
|
||||
writeln!(f,)?;
|
||||
}
|
||||
writeln!(f,)?;
|
||||
for (_, import) in self.imports.iter() {
|
||||
import.fmt(f)?;
|
||||
writeln!(f,)?;
|
||||
}
|
||||
@ -65,7 +71,8 @@ impl Program {
|
||||
Self {
|
||||
name,
|
||||
expected_input: vec![],
|
||||
imports: vec![],
|
||||
import_statements: vec![],
|
||||
imports: IndexMap::new(),
|
||||
circuits: IndexMap::new(),
|
||||
global_consts: IndexMap::new(),
|
||||
functions: IndexMap::new(),
|
||||
|
205
ast/src/reducer/importer.rs
Normal file
205
ast/src/reducer/importer.rs
Normal file
@ -0,0 +1,205 @@
|
||||
// Copyright (C) 2019-2021 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::*;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
||||
pub struct Importer<T>
|
||||
where
|
||||
T: ImportResolver,
|
||||
{
|
||||
import_resolver: T,
|
||||
functions_to_import: Vec<(String, Option<String>)>,
|
||||
circuits_to_import: Vec<(String, Option<String>)>,
|
||||
global_consts_to_import: Vec<(String, Option<String>)>,
|
||||
}
|
||||
|
||||
impl<T> Importer<T>
|
||||
where
|
||||
T: ImportResolver,
|
||||
{
|
||||
pub fn new(import_resolver: T) -> Self {
|
||||
Self {
|
||||
import_resolver,
|
||||
functions_to_import: Vec::new(),
|
||||
circuits_to_import: Vec::new(),
|
||||
global_consts_to_import: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Enumerates what names are imported from a package.
|
||||
#[derive(Clone)]
|
||||
enum ImportSymbol {
|
||||
/// Import the symbol by name.
|
||||
Direct(String),
|
||||
|
||||
/// Import the symbol by name and store it under an alias.
|
||||
Alias(String, String), // from remote -> to local
|
||||
|
||||
/// Import all symbols from the package.
|
||||
All,
|
||||
}
|
||||
|
||||
fn resolve_import_package(
|
||||
output: &mut Vec<(Vec<String>, ImportSymbol, Span)>,
|
||||
mut package_segments: Vec<String>,
|
||||
package_or_packages: &PackageOrPackages,
|
||||
) {
|
||||
match package_or_packages {
|
||||
PackageOrPackages::Package(package) => {
|
||||
package_segments.push(package.name.name.to_string());
|
||||
resolve_import_package_access(output, package_segments, &package.access);
|
||||
}
|
||||
PackageOrPackages::Packages(packages) => {
|
||||
package_segments.push(packages.name.name.to_string());
|
||||
for access in packages.accesses.clone() {
|
||||
resolve_import_package_access(output, package_segments.clone(), &access);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_import_package_access(
|
||||
output: &mut Vec<(Vec<String>, ImportSymbol, Span)>,
|
||||
mut package_segments: Vec<String>,
|
||||
package: &PackageAccess,
|
||||
) {
|
||||
match package {
|
||||
PackageAccess::Star { span } => {
|
||||
output.push((package_segments, ImportSymbol::All, span.clone()));
|
||||
}
|
||||
PackageAccess::SubPackage(subpackage) => {
|
||||
resolve_import_package(
|
||||
output,
|
||||
package_segments,
|
||||
&PackageOrPackages::Package(*(*subpackage).clone()),
|
||||
);
|
||||
}
|
||||
PackageAccess::Symbol(symbol) => {
|
||||
let span = symbol.symbol.span.clone();
|
||||
let symbol = if let Some(alias) = symbol.alias.as_ref() {
|
||||
ImportSymbol::Alias(symbol.symbol.name.to_string(), alias.name.to_string())
|
||||
} else {
|
||||
ImportSymbol::Direct(symbol.symbol.name.to_string())
|
||||
};
|
||||
output.push((package_segments, symbol, span));
|
||||
}
|
||||
PackageAccess::Multiple(packages) => {
|
||||
package_segments.push(packages.name.name.to_string());
|
||||
for subaccess in packages.accesses.iter() {
|
||||
resolve_import_package_access(output, package_segments.clone(), &subaccess);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ReconstructingReducer for Importer<T>
|
||||
where
|
||||
T: ImportResolver,
|
||||
{
|
||||
fn in_circuit(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn swap_in_circuit(&mut self) {}
|
||||
|
||||
fn reduce_program(
|
||||
&mut self,
|
||||
program: &Program,
|
||||
expected_input: Vec<FunctionInput>,
|
||||
import_statements: Vec<ImportStatement>,
|
||||
empty_imports: IndexMap<String, Program>,
|
||||
circuits: IndexMap<Identifier, Circuit>,
|
||||
functions: IndexMap<Identifier, Function>,
|
||||
global_consts: IndexMap<String, DefinitionStatement>,
|
||||
) -> Result<Program, ReducerError> {
|
||||
if !empty_imports.is_empty() {
|
||||
// TODO THROW ERR
|
||||
}
|
||||
|
||||
let mut imported_symbols: Vec<(Vec<String>, ImportSymbol, Span)> = vec![];
|
||||
for import_statement in import_statements.iter() {
|
||||
resolve_import_package(&mut imported_symbols, vec![], &import_statement.package_or_packages);
|
||||
}
|
||||
|
||||
let mut deduplicated_imports: IndexMap<Vec<String>, Span> = IndexMap::new();
|
||||
for (package, _symbol, span) in imported_symbols.iter() {
|
||||
deduplicated_imports.insert(package.clone(), span.clone());
|
||||
}
|
||||
|
||||
let mut wrapped_resolver = CoreImportResolver::new(&mut self.import_resolver);
|
||||
|
||||
let mut resolved_packages: IndexMap<Vec<String>, Program> = IndexMap::new();
|
||||
for (package, span) in deduplicated_imports {
|
||||
let _pretty_package = package.join(".");
|
||||
|
||||
let resolved_package =
|
||||
match wrapped_resolver.resolve_package(&package.iter().map(|x| &**x).collect::<Vec<_>>()[..], &span)? {
|
||||
Some(x) => x,
|
||||
None => return Err(ReducerError::empty_string(&span)),
|
||||
};
|
||||
|
||||
resolved_packages.insert(package.clone(), resolved_package);
|
||||
}
|
||||
|
||||
// TODO Errors
|
||||
// TODO copyable AST.
|
||||
// TODO should imports be renamed in imported program?
|
||||
for (package, symbol, span) in imported_symbols.into_iter() {
|
||||
let _pretty_package = package.join(".");
|
||||
|
||||
let resolved_package = resolved_packages
|
||||
.get_mut(&package)
|
||||
.expect("could not find preloaded package");
|
||||
match symbol {
|
||||
ImportSymbol::Alias(name, alias) => {
|
||||
let lookup_ident = Identifier::new(name.clone().into());
|
||||
if let Some((ident, function)) = resolved_package.functions.remove_entry(&lookup_ident) {
|
||||
let mut alias_identifier = ident.clone();
|
||||
alias_identifier.name = alias.into();
|
||||
resolved_package.functions.insert(alias_identifier, function.clone());
|
||||
} else if let Some((ident, circuit)) = resolved_package.circuits.remove_entry(&lookup_ident) {
|
||||
let mut alias_identifier = ident.clone();
|
||||
alias_identifier.name = alias.into();
|
||||
resolved_package.circuits.insert(alias_identifier, circuit.clone());
|
||||
} else if let Some(global_const) = resolved_package.global_consts.remove(&name) {
|
||||
resolved_package
|
||||
.global_consts
|
||||
.insert(alias.clone(), global_const.clone());
|
||||
} else {
|
||||
return Err(ReducerError::empty_string(&span));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Program {
|
||||
name: program.name.clone(),
|
||||
expected_input,
|
||||
import_statements,
|
||||
imports: resolved_packages
|
||||
.into_iter()
|
||||
.map(|(package, program)| (package.join("."), program))
|
||||
.collect(),
|
||||
circuits,
|
||||
functions,
|
||||
global_consts,
|
||||
})
|
||||
}
|
||||
}
|
@ -14,11 +14,17 @@
|
||||
// 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 canonicalization;
|
||||
pub mod canonicalization;
|
||||
pub use canonicalization::*;
|
||||
|
||||
mod reconstructing_reducer;
|
||||
pub mod reconstructing_reducer;
|
||||
pub use reconstructing_reducer::*;
|
||||
|
||||
mod reconstructing_director;
|
||||
pub mod reconstructing_director;
|
||||
pub use reconstructing_director::*;
|
||||
|
||||
pub mod importer;
|
||||
pub use self::importer::*;
|
||||
|
||||
pub mod resolver;
|
||||
pub use self::resolver::*;
|
||||
|
@ -437,9 +437,15 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
||||
inputs.push(self.reduce_function_input(input)?);
|
||||
}
|
||||
|
||||
let mut imports = vec![];
|
||||
for import in program.imports.iter() {
|
||||
imports.push(self.reduce_import(import)?);
|
||||
let mut import_statements = vec![];
|
||||
for import in program.import_statements.iter() {
|
||||
import_statements.push(self.reduce_import_statement(import)?);
|
||||
}
|
||||
|
||||
let mut imports = IndexMap::new();
|
||||
for (identifier, program) in program.imports.iter() {
|
||||
let (ident, import) = self.reduce_import(identifier, program)?;
|
||||
imports.insert(ident, import);
|
||||
}
|
||||
|
||||
let mut circuits = IndexMap::new();
|
||||
@ -459,8 +465,15 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
||||
global_consts.insert(name.clone(), self.reduce_definition(&definition)?);
|
||||
}
|
||||
|
||||
self.reducer
|
||||
.reduce_program(program, inputs, imports, circuits, functions, global_consts)
|
||||
self.reducer.reduce_program(
|
||||
program,
|
||||
inputs,
|
||||
import_statements,
|
||||
imports,
|
||||
circuits,
|
||||
functions,
|
||||
global_consts,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn reduce_function_input_variable(
|
||||
@ -504,10 +517,16 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
||||
self.reducer.reduce_package_or_packages(package_or_packages, new)
|
||||
}
|
||||
|
||||
pub fn reduce_import(&mut self, import: &ImportStatement) -> Result<ImportStatement, ReducerError> {
|
||||
pub fn reduce_import_statement(&mut self, import: &ImportStatement) -> Result<ImportStatement, ReducerError> {
|
||||
let package_or_packages = self.reduce_package_or_packages(&import.package_or_packages)?;
|
||||
|
||||
self.reducer.reduce_import(import, package_or_packages)
|
||||
self.reducer.reduce_import_statement(import, package_or_packages)
|
||||
}
|
||||
|
||||
pub fn reduce_import(&mut self, identifier: &str, import: &Program) -> Result<(String, Program), ReducerError> {
|
||||
let new_identifer = identifier.to_string();
|
||||
let new_import = self.reduce_program(import)?;
|
||||
self.reducer.reduce_import(new_identifer, new_import)
|
||||
}
|
||||
|
||||
pub fn reduce_circuit_member(&mut self, circuit_member: &CircuitMember) -> Result<CircuitMember, ReducerError> {
|
||||
|
@ -399,7 +399,8 @@ pub trait ReconstructingReducer {
|
||||
&mut self,
|
||||
program: &Program,
|
||||
expected_input: Vec<FunctionInput>,
|
||||
imports: Vec<ImportStatement>,
|
||||
import_statements: Vec<ImportStatement>,
|
||||
imports: IndexMap<String, Program>,
|
||||
circuits: IndexMap<Identifier, Circuit>,
|
||||
functions: IndexMap<Identifier, Function>,
|
||||
global_consts: IndexMap<String, DefinitionStatement>,
|
||||
@ -407,6 +408,7 @@ pub trait ReconstructingReducer {
|
||||
Ok(Program {
|
||||
name: program.name.clone(),
|
||||
expected_input,
|
||||
import_statements,
|
||||
imports,
|
||||
circuits,
|
||||
functions,
|
||||
@ -445,7 +447,7 @@ pub trait ReconstructingReducer {
|
||||
Ok(new)
|
||||
}
|
||||
|
||||
fn reduce_import(
|
||||
fn reduce_import_statement(
|
||||
&mut self,
|
||||
import: &ImportStatement,
|
||||
package_or_packages: PackageOrPackages,
|
||||
@ -456,6 +458,10 @@ pub trait ReconstructingReducer {
|
||||
})
|
||||
}
|
||||
|
||||
fn reduce_import(&mut self, identifier: String, import: Program) -> Result<(String, Program), ReducerError> {
|
||||
Ok((identifier, import))
|
||||
}
|
||||
|
||||
fn reduce_circuit_member(
|
||||
&mut self,
|
||||
_circuit_member: &CircuitMember,
|
||||
|
83
ast/src/reducer/resolver.rs
Normal file
83
ast/src/reducer/resolver.rs
Normal file
@ -0,0 +1,83 @@
|
||||
// Copyright (C) 2019-2021 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Program, ReducerError, Span};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
||||
pub trait ImportResolver {
|
||||
fn resolve_package(&mut self, package_segments: &[&str], span: &Span) -> Result<Option<Program>, ReducerError>;
|
||||
}
|
||||
|
||||
pub struct NullImportResolver;
|
||||
|
||||
impl ImportResolver for NullImportResolver {
|
||||
fn resolve_package(&mut self, _package_segments: &[&str], _span: &Span) -> Result<Option<Program>, ReducerError> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CoreImportResolver<'a, T: ImportResolver> {
|
||||
inner: &'a mut T,
|
||||
}
|
||||
|
||||
impl<'a, T: ImportResolver> CoreImportResolver<'a, T> {
|
||||
pub fn new(inner: &'a mut T) -> Self {
|
||||
CoreImportResolver { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ImportResolver> ImportResolver for CoreImportResolver<'a, T> {
|
||||
fn resolve_package(&mut self, package_segments: &[&str], span: &Span) -> Result<Option<Program>, ReducerError> {
|
||||
if !package_segments.is_empty() && package_segments.get(0).unwrap() == &"core" {
|
||||
Ok(resolve_core_module(&*package_segments[1..].join("."))?)
|
||||
} else {
|
||||
self.inner.resolve_package(package_segments, span)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MockedImportResolver {
|
||||
pub packages: IndexMap<String, Program>,
|
||||
}
|
||||
|
||||
impl ImportResolver for MockedImportResolver {
|
||||
fn resolve_package(&mut self, package_segments: &[&str], _span: &Span) -> Result<Option<Program>, ReducerError> {
|
||||
Ok(self.packages.get(&package_segments.join(".")).cloned())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_core_module(module: &str) -> Result<Option<Program>, ReducerError> {
|
||||
match module {
|
||||
"unstable.blake2s" => {
|
||||
// let ast = load_asg(
|
||||
// context,
|
||||
// r#"
|
||||
// circuit Blake2s {
|
||||
// function hash(seed: [u8; 32], message: [u8; 32]) -> [u8; 32] {
|
||||
// return [0; 32];
|
||||
// }
|
||||
// }
|
||||
// "#,
|
||||
// &mut crate::NullImportResolver,
|
||||
// )?;
|
||||
// asg.set_core_mapping("blake2s");
|
||||
// Ok(Some(asg))
|
||||
Ok(None)
|
||||
}
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
@ -244,6 +244,8 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
||||
ast.to_json_file(self.output_directory.clone(), "initial_ast.json")?;
|
||||
}
|
||||
|
||||
ast.importer(&mut leo_imports::ImportParser::new(self.main_file_path.clone()))?;
|
||||
|
||||
// Preform compiler optimization via canonicalizing AST if its enabled.
|
||||
if self.options.canonicalization_enabled {
|
||||
ast.canonicalize()?;
|
||||
@ -260,11 +262,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
||||
tracing::debug!("Program parsing complete\n{:#?}", self.program);
|
||||
|
||||
// Create a new symbol table from the program, imported_programs, and program_input.
|
||||
let asg = Asg::new(
|
||||
self.context,
|
||||
&self.program,
|
||||
&mut leo_imports::ImportParser::new(self.main_file_path.clone()),
|
||||
)?;
|
||||
let asg = Asg::new(self.context, &self.program)?;
|
||||
|
||||
if self.ast_snapshot_options.type_inferenced {
|
||||
let new_ast = TypeInferencePhase::default()
|
||||
|
@ -706,6 +706,11 @@ impl<R: ReconstructingReducer, O: CombinerOptions> CombineAstAsgDirector<R, O> {
|
||||
ast: &leo_ast::Program,
|
||||
asg: &leo_asg::Program,
|
||||
) -> Result<leo_ast::Program, leo_ast::ReducerError> {
|
||||
let mut imports = IndexMap::new();
|
||||
for ((ast_ident, ast_program), (_asg_ident, asg_program)) in ast.imports.iter().zip(&asg.imported_modules) {
|
||||
imports.insert(ast_ident.clone(), self.reduce_program(ast_program, asg_program)?);
|
||||
}
|
||||
|
||||
self.ast_reducer.swap_in_circuit();
|
||||
let mut circuits = IndexMap::new();
|
||||
for ((ast_ident, ast_circuit), (_asg_ident, asg_circuit)) in ast.circuits.iter().zip(&asg.circuits) {
|
||||
@ -727,7 +732,8 @@ impl<R: ReconstructingReducer, O: CombinerOptions> CombineAstAsgDirector<R, O> {
|
||||
self.ast_reducer.reduce_program(
|
||||
ast,
|
||||
ast.expected_input.clone(),
|
||||
ast.imports.clone(),
|
||||
ast.import_statements.clone(),
|
||||
imports,
|
||||
circuits,
|
||||
functions,
|
||||
global_consts,
|
||||
|
@ -13,8 +13,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_asg::AsgConvertError;
|
||||
use leo_ast::{AstError, FormattedError, Identifier, LeoError, Span};
|
||||
use leo_ast::{AstError, FormattedError, Identifier, LeoError, Span, ReducerError};
|
||||
use leo_parser::SyntaxError;
|
||||
|
||||
use std::{io, path::Path};
|
||||
@ -31,18 +30,18 @@ pub enum ImportParserError {
|
||||
AstError(#[from] AstError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
AsgConvertError(#[from] AsgConvertError),
|
||||
ReducerError(#[from] ReducerError),
|
||||
}
|
||||
|
||||
impl LeoError for ImportParserError {}
|
||||
|
||||
impl Into<AsgConvertError> for ImportParserError {
|
||||
fn into(self) -> AsgConvertError {
|
||||
impl Into<ReducerError> for ImportParserError {
|
||||
fn into(self) -> ReducerError {
|
||||
match self {
|
||||
ImportParserError::Error(x) => AsgConvertError::ImportError(x),
|
||||
ImportParserError::Error(x) => ReducerError::ImportError(x),
|
||||
ImportParserError::SyntaxError(x) => x.into(),
|
||||
ImportParserError::AstError(x) => AsgConvertError::AstError(x),
|
||||
ImportParserError::AsgConvertError(x) => x,
|
||||
ImportParserError::AstError(x) => ReducerError::ast_err(),
|
||||
ImportParserError::ReducerError(x) => x,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::errors::ImportParserError;
|
||||
use leo_asg::{AsgContext, AsgConvertError, ImportResolver, Program, Span};
|
||||
use leo_ast::{ImportResolver, Program, Span, ReducerError};
|
||||
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
use std::path::PathBuf;
|
||||
@ -25,13 +25,13 @@ use std::path::PathBuf;
|
||||
/// A program can import one or more packages. A package can be found locally in the source
|
||||
/// directory, foreign in the imports directory, or part of the core package list.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct ImportParser<'a> {
|
||||
pub struct ImportParser {
|
||||
program_path: PathBuf,
|
||||
partial_imports: IndexSet<String>,
|
||||
imports: IndexMap<String, Program<'a>>,
|
||||
imports: IndexMap<String, Program>,
|
||||
}
|
||||
|
||||
impl<'a> ImportParser<'a> {
|
||||
impl ImportParser {
|
||||
pub fn new(program_path: PathBuf) -> Self {
|
||||
ImportParser {
|
||||
program_path,
|
||||
@ -41,16 +41,16 @@ impl<'a> ImportParser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ImportResolver<'a> for ImportParser<'a> {
|
||||
impl ImportResolver for ImportParser {
|
||||
fn resolve_package(
|
||||
&mut self,
|
||||
context: AsgContext<'a>,
|
||||
package_segments: &[&str],
|
||||
span: &Span,
|
||||
) -> Result<Option<Program<'a>>, AsgConvertError> {
|
||||
) -> Result<Option<Program>, ReducerError> {
|
||||
let full_path = package_segments.join(".");
|
||||
if self.partial_imports.contains(&full_path) {
|
||||
return Err(ImportParserError::recursive_imports(&full_path, span).into());
|
||||
|
||||
// return Err(ImportParserError::recursive_imports(&full_path, span).into());
|
||||
}
|
||||
if let Some(program) = self.imports.get(&full_path) {
|
||||
return Ok(Some(program.clone()));
|
||||
@ -60,8 +60,8 @@ impl<'a> ImportResolver<'a> for ImportParser<'a> {
|
||||
|
||||
self.partial_imports.insert(full_path.clone());
|
||||
let program = imports
|
||||
.parse_package(context, path, package_segments, span)
|
||||
.map_err(|x| -> AsgConvertError { x.into() })?;
|
||||
.parse_package(path, package_segments, span)
|
||||
.map_err(|x| -> ReducerError { x.into() })?;
|
||||
self.partial_imports.remove(&full_path);
|
||||
self.imports.insert(full_path, program.clone());
|
||||
Ok(Some(program))
|
||||
|
@ -15,7 +15,7 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{errors::ImportParserError, ImportParser};
|
||||
use leo_asg::{AsgContext, Identifier, Program, Span};
|
||||
use leo_ast::{Identifier, ImportResolver, Program, Span, ReducerError};
|
||||
|
||||
use std::{fs, fs::DirEntry, path::PathBuf};
|
||||
|
||||
@ -23,21 +23,18 @@ static SOURCE_FILE_EXTENSION: &str = ".leo";
|
||||
static SOURCE_DIRECTORY_NAME: &str = "src/";
|
||||
static IMPORTS_DIRECTORY_NAME: &str = "imports/";
|
||||
|
||||
impl<'a> ImportParser<'a> {
|
||||
impl ImportParser {
|
||||
fn parse_package_access(
|
||||
&mut self,
|
||||
context: AsgContext<'a>,
|
||||
package: &DirEntry,
|
||||
remaining_segments: &[&str],
|
||||
span: &Span,
|
||||
) -> Result<Program<'a>, ImportParserError> {
|
||||
) -> Result<Program, ImportParserError> {
|
||||
if !remaining_segments.is_empty() {
|
||||
return self.parse_package(context, package.path(), remaining_segments, span);
|
||||
return self.parse_package(package.path(), remaining_segments, span);
|
||||
}
|
||||
let program = Self::parse_import_file(package, span)?;
|
||||
let asg = leo_asg::Program::new(context, &program, self)?;
|
||||
|
||||
Ok(asg)
|
||||
Self::parse_import_file(package, span)
|
||||
}
|
||||
|
||||
///
|
||||
@ -47,11 +44,10 @@ impl<'a> ImportParser<'a> {
|
||||
///
|
||||
pub(crate) fn parse_package(
|
||||
&mut self,
|
||||
context: AsgContext<'a>,
|
||||
mut path: PathBuf,
|
||||
segments: &[&str],
|
||||
span: &Span,
|
||||
) -> Result<Program<'a>, ImportParserError> {
|
||||
) -> Result<Program, ImportParserError> {
|
||||
let error_path = path.clone();
|
||||
let package_name = segments[0];
|
||||
|
||||
@ -114,8 +110,8 @@ impl<'a> ImportParser<'a> {
|
||||
package_name,
|
||||
span.clone(),
|
||||
))),
|
||||
(Some(source_entry), None) => self.parse_package_access(context, &source_entry, &segments[1..], span),
|
||||
(None, Some(import_entry)) => self.parse_package_access(context, &import_entry, &segments[1..], span),
|
||||
(Some(source_entry), None) => self.parse_package_access(&source_entry, &segments[1..], span),
|
||||
(None, Some(import_entry)) => self.parse_package_access(&import_entry, &segments[1..], span),
|
||||
(None, None) => Err(ImportParserError::unknown_package(Identifier::new_with_span(
|
||||
package_name,
|
||||
span.clone(),
|
||||
@ -124,7 +120,7 @@ impl<'a> ImportParser<'a> {
|
||||
} else {
|
||||
// Enforce local package access with no found imports directory
|
||||
match matched_source_entry {
|
||||
Some(source_entry) => self.parse_package_access(context, &source_entry, &segments[1..], span),
|
||||
Some(source_entry) => self.parse_package_access(&source_entry, &segments[1..], span),
|
||||
None => Err(ImportParserError::unknown_package(Identifier::new_with_span(
|
||||
package_name,
|
||||
span.clone(),
|
||||
|
@ -21,7 +21,7 @@ use std::fs::DirEntry;
|
||||
|
||||
static MAIN_FILE: &str = "src/main.leo";
|
||||
|
||||
impl<'a> ImportParser<'a> {
|
||||
impl ImportParser {
|
||||
///
|
||||
/// Returns a Leo syntax tree from a given package.
|
||||
///
|
||||
@ -56,8 +56,6 @@ impl<'a> ImportParser<'a> {
|
||||
&std::fs::read_to_string(&file_path).map_err(|x| ImportParserError::io_error(span, file_path_str, x))?;
|
||||
let mut program = leo_parser::parse(&file_path_str, &program_string)?;
|
||||
program.name = file_name;
|
||||
let mut ast = leo_ast::Ast::new(program);
|
||||
ast.canonicalize()?;
|
||||
Ok(ast.into_repr())
|
||||
Ok(program)
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ impl ParserContext {
|
||||
/// Returns a [`Program`] AST if all tokens can be consumed and represent a valid Leo program.
|
||||
///
|
||||
pub fn parse_program(&mut self) -> SyntaxResult<Program> {
|
||||
let mut imports = Vec::new();
|
||||
let mut import_statements = Vec::new();
|
||||
let mut circuits = IndexMap::new();
|
||||
let mut functions = IndexMap::new();
|
||||
let mut global_consts = IndexMap::new();
|
||||
@ -35,7 +35,7 @@ impl ParserContext {
|
||||
let token = self.peek()?;
|
||||
match &token.token {
|
||||
Token::Import => {
|
||||
imports.push(self.parse_import()?);
|
||||
import_statements.push(self.parse_import_statement()?);
|
||||
}
|
||||
Token::Circuit => {
|
||||
let (id, circuit) = self.parse_circuit()?;
|
||||
@ -49,12 +49,6 @@ impl ParserContext {
|
||||
return Err(SyntaxError::DeprecatedError(DeprecatedError::test_function(
|
||||
&token.span,
|
||||
)));
|
||||
// self.expect(Token::Test)?;
|
||||
// let (id, function) = self.parse_function_declaration()?;
|
||||
// tests.insert(id, TestFunction {
|
||||
// function,
|
||||
// input_file: None,
|
||||
// });
|
||||
}
|
||||
Token::Const => {
|
||||
let (name, global_const) = self.parse_global_const_declaration()?;
|
||||
@ -78,7 +72,8 @@ impl ParserContext {
|
||||
Ok(Program {
|
||||
name: String::new(),
|
||||
expected_input: Vec::new(),
|
||||
imports,
|
||||
import_statements,
|
||||
imports: IndexMap::new(),
|
||||
circuits,
|
||||
functions,
|
||||
global_consts,
|
||||
@ -281,7 +276,7 @@ impl ParserContext {
|
||||
///
|
||||
/// Returns a [`ImportStatement`] AST node if the next tokens represent an import statement.
|
||||
///
|
||||
pub fn parse_import(&mut self) -> SyntaxResult<ImportStatement> {
|
||||
pub fn parse_import_statement(&mut self) -> SyntaxResult<ImportStatement> {
|
||||
self.expect(Token::Import)?;
|
||||
let package_or_packages = self.parse_package_path()?;
|
||||
self.expect(Token::Semicolon)?;
|
||||
|
Loading…
Reference in New Issue
Block a user