mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-25 11:12:48 +03:00
resolve all definitions prior to program execution
This commit is contained in:
parent
a422027e12
commit
14f5f448be
@ -82,7 +82,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
|||||||
let path = self.main_file_path;
|
let path = self.main_file_path;
|
||||||
let inputs = self.program_inputs.get_inputs();
|
let inputs = self.program_inputs.get_inputs();
|
||||||
|
|
||||||
generate_constraints(cs, self.program, inputs, self.imported_programs).map_err(|mut error| {
|
generate_constraints(cs, self.program, inputs, &self.imported_programs).map_err(|mut error| {
|
||||||
error.set_path(path);
|
error.set_path(path);
|
||||||
|
|
||||||
error
|
error
|
||||||
@ -90,7 +90,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_test_constraints(self, cs: &mut TestConstraintSystem<F>) -> Result<(), CompilerError> {
|
pub fn compile_test_constraints(self, cs: &mut TestConstraintSystem<F>) -> Result<(), CompilerError> {
|
||||||
generate_test_constraints::<F, G>(cs, self.program, self.imported_programs)
|
generate_test_constraints::<F, G>(cs, self.program, &self.imported_programs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_program(&mut self) -> Result<String, CompilerError> {
|
fn load_program(&mut self) -> Result<String, CompilerError> {
|
||||||
@ -151,7 +151,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compil
|
|||||||
cs,
|
cs,
|
||||||
self.program,
|
self.program,
|
||||||
self.program_inputs.get_inputs(),
|
self.program_inputs.get_inputs(),
|
||||||
self.imported_programs,
|
&self.imported_programs,
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
log::error!("{}", e);
|
log::error!("{}", e);
|
||||||
|
50
compiler/src/constraints/definitions/definitions.rs
Normal file
50
compiler/src/constraints/definitions/definitions.rs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
use crate::{
|
||||||
|
constraints::{new_scope, ConstrainedProgram, ConstrainedValue},
|
||||||
|
errors::ImportError,
|
||||||
|
GroupType,
|
||||||
|
ImportedPrograms,
|
||||||
|
};
|
||||||
|
use leo_types::Program;
|
||||||
|
|
||||||
|
use snarkos_models::curves::{Field, PrimeField};
|
||||||
|
|
||||||
|
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||||
|
pub(crate) fn store_definitions(
|
||||||
|
&mut self,
|
||||||
|
program: Program,
|
||||||
|
imported_programs: &ImportedPrograms,
|
||||||
|
) -> Result<(), ImportError> {
|
||||||
|
let program_name = program.name.clone();
|
||||||
|
|
||||||
|
// evaluate all import statements and store imported definitions
|
||||||
|
program
|
||||||
|
.imports
|
||||||
|
.iter()
|
||||||
|
.map(|import| self.store_import(program_name.clone(), import, imported_programs))
|
||||||
|
.collect::<Result<Vec<_>, ImportError>>()?;
|
||||||
|
|
||||||
|
self.store_all(program_name.clone(), &program);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn store_all(&mut self, scope: String, program: &Program) {
|
||||||
|
// evaluate and store all circuit definitions
|
||||||
|
program.circuits.iter().for_each(|(identifier, circuit)| {
|
||||||
|
let resolved_circuit_name = new_scope(scope.clone(), identifier.to_string());
|
||||||
|
self.store(
|
||||||
|
resolved_circuit_name,
|
||||||
|
ConstrainedValue::CircuitDefinition(circuit.clone()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// evaluate and store all function definitions
|
||||||
|
program.functions.iter().for_each(|(function_name, function)| {
|
||||||
|
let resolved_function_name = new_scope(scope.clone(), function_name.to_string());
|
||||||
|
self.store(
|
||||||
|
resolved_function_name,
|
||||||
|
ConstrainedValue::Function(None, function.clone()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
43
compiler/src/constraints/definitions/import.rs
Normal file
43
compiler/src/constraints/definitions/import.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
use crate::{errors::ImportError, ConstrainedProgram, GroupType, ImportedPrograms, ImportedSymbols};
|
||||||
|
use leo_types::Import;
|
||||||
|
|
||||||
|
use snarkos_models::curves::{Field, PrimeField};
|
||||||
|
|
||||||
|
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||||
|
pub(crate) fn store_import(
|
||||||
|
&mut self,
|
||||||
|
scope: String,
|
||||||
|
import: &Import,
|
||||||
|
imported_programs: &ImportedPrograms,
|
||||||
|
) -> Result<(), ImportError> {
|
||||||
|
println!("program name {}", scope);
|
||||||
|
println!("import {}", import);
|
||||||
|
|
||||||
|
// get imported program name from import
|
||||||
|
// get imported symbols from from import
|
||||||
|
let imported_symbols = ImportedSymbols::from(import);
|
||||||
|
let program_name = imported_symbols.name.clone();
|
||||||
|
println!("symbols {:?}", imported_symbols);
|
||||||
|
|
||||||
|
// get imported program from hashmap
|
||||||
|
let program = imported_programs
|
||||||
|
.get(&program_name)
|
||||||
|
.ok_or(ImportError::unknown_package(import.package.name.clone()))?;
|
||||||
|
|
||||||
|
// resolve imported program's import statements
|
||||||
|
program
|
||||||
|
.imports
|
||||||
|
.iter()
|
||||||
|
.map(|import| self.store_import(program_name.clone(), import, imported_programs))
|
||||||
|
.collect::<Result<Vec<()>, ImportError>>()?;
|
||||||
|
|
||||||
|
// store imported symbols in constrained program
|
||||||
|
imported_symbols
|
||||||
|
.symbols
|
||||||
|
.iter()
|
||||||
|
.map(|symbol| self.store_symbol(scope.clone(), symbol, program))
|
||||||
|
.collect::<Result<Vec<()>, ImportError>>()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
39
compiler/src/constraints/definitions/imported_symbols.rs
Normal file
39
compiler/src/constraints/definitions/imported_symbols.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use leo_types::{Import, ImportSymbol, Package, PackageAccess};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct ImportedSymbols {
|
||||||
|
pub name: String,
|
||||||
|
pub symbols: Vec<ImportSymbol>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ImportedSymbols {
|
||||||
|
fn new(name: String) -> Self {
|
||||||
|
Self { name, symbols: vec![] }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from(import: &Import) -> Self {
|
||||||
|
let mut symbols = Self::new(import.package.name.name.clone());
|
||||||
|
|
||||||
|
symbols.from_package_access(&import.package.access);
|
||||||
|
|
||||||
|
symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_package(&mut self, package: &Package) {
|
||||||
|
self.name = package.name.name.clone();
|
||||||
|
|
||||||
|
self.from_package_access(&package.access);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_package_access(&mut self, access: &PackageAccess) {
|
||||||
|
match access {
|
||||||
|
PackageAccess::SubPackage(package) => self.from_package(package),
|
||||||
|
PackageAccess::Star(span) => {
|
||||||
|
let star = ImportSymbol::star(span);
|
||||||
|
self.symbols.push(star);
|
||||||
|
}
|
||||||
|
PackageAccess::Symbol(symbol) => self.symbols.push(symbol.clone()),
|
||||||
|
PackageAccess::Multiple(packages) => packages.iter().for_each(|access| self.from_package_access(access)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
compiler/src/constraints/definitions/mod.rs
Normal file
9
compiler/src/constraints/definitions/mod.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
pub mod import;
|
||||||
|
pub use self::import::*;
|
||||||
|
|
||||||
|
pub mod imported_symbols;
|
||||||
|
pub(crate) use self::imported_symbols::*;
|
||||||
|
|
||||||
|
pub mod definitions;
|
||||||
|
|
||||||
|
pub mod symbol;
|
47
compiler/src/constraints/definitions/symbol.rs
Normal file
47
compiler/src/constraints/definitions/symbol.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
use crate::{errors::ImportError, new_scope, ConstrainedProgram, ConstrainedValue, GroupType};
|
||||||
|
use leo_types::{ImportSymbol, Program};
|
||||||
|
|
||||||
|
use snarkos_models::curves::{Field, PrimeField};
|
||||||
|
|
||||||
|
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||||
|
pub(crate) fn store_symbol(
|
||||||
|
&mut self,
|
||||||
|
scope: String,
|
||||||
|
symbol: &ImportSymbol,
|
||||||
|
program: &Program,
|
||||||
|
) -> Result<(), ImportError> {
|
||||||
|
if symbol.is_star() {
|
||||||
|
self.store_all(scope, program);
|
||||||
|
} else {
|
||||||
|
let matched_circuit = program
|
||||||
|
.circuits
|
||||||
|
.iter()
|
||||||
|
.find(|(circuit_name, _circuit_def)| symbol.symbol == **circuit_name);
|
||||||
|
|
||||||
|
let value = match matched_circuit {
|
||||||
|
Some((_circuit_name, circuit_def)) => ConstrainedValue::CircuitDefinition(circuit_def.clone()),
|
||||||
|
None => {
|
||||||
|
// see if the imported symbol is a function
|
||||||
|
let matched_function = program
|
||||||
|
.functions
|
||||||
|
.iter()
|
||||||
|
.find(|(function_name, _function)| symbol.symbol == **function_name);
|
||||||
|
|
||||||
|
match matched_function {
|
||||||
|
Some((_function_name, function)) => ConstrainedValue::Function(None, function.clone()),
|
||||||
|
None => return Err(ImportError::unknown_symbol(symbol.to_owned(), scope)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// take the alias if it is present
|
||||||
|
let name = symbol.alias.clone().unwrap_or(symbol.symbol.clone());
|
||||||
|
let resolved_name = new_scope(scope, name.to_string());
|
||||||
|
|
||||||
|
// store imported circuit under resolved name
|
||||||
|
self.store(resolved_name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -4,15 +4,13 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
bool_from_input,
|
bool_from_input,
|
||||||
constraints::{new_scope, ConstrainedProgram, ConstrainedValue},
|
constraints::{new_scope, ConstrainedProgram, ConstrainedValue},
|
||||||
errors::{FunctionError, ImportError},
|
errors::{FunctionError, StatementError},
|
||||||
field_from_input,
|
field_from_input,
|
||||||
group_from_input,
|
group_from_input,
|
||||||
GroupType,
|
GroupType,
|
||||||
ImportedPrograms,
|
|
||||||
};
|
};
|
||||||
use leo_types::{Expression, Function, InputValue, Integer, Program, Span, Type};
|
use leo_types::{Expression, Function, InputValue, Integer, Span, Type};
|
||||||
|
|
||||||
use crate::errors::StatementError;
|
|
||||||
use snarkos_models::{
|
use snarkos_models::{
|
||||||
curves::{Field, PrimeField},
|
curves::{Field, PrimeField},
|
||||||
gadgets::{
|
gadgets::{
|
||||||
@ -272,33 +270,4 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
|
|
||||||
self.enforce_function(cs, scope, function_name, function, input_variables)
|
self.enforce_function(cs, scope, function_name, function, input_variables)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn resolve_definitions(
|
|
||||||
&mut self,
|
|
||||||
program: Program,
|
|
||||||
_imported_programs: ImportedPrograms,
|
|
||||||
) -> Result<(), ImportError> {
|
|
||||||
let program_name = program.name.clone();
|
|
||||||
|
|
||||||
// evaluate all import statements and store imported definitions
|
|
||||||
// program
|
|
||||||
// .imports
|
|
||||||
// .into_iter()
|
|
||||||
// .map(|import| self.store_import(program_name.clone(), import))
|
|
||||||
// .collect::<Result<Vec<_>, ImportError>>()?;
|
|
||||||
|
|
||||||
// evaluate and store all circuit definitions
|
|
||||||
program.circuits.into_iter().for_each(|(identifier, circuit)| {
|
|
||||||
let resolved_circuit_name = new_scope(program_name.clone(), identifier.to_string());
|
|
||||||
self.store(resolved_circuit_name, ConstrainedValue::CircuitDefinition(circuit));
|
|
||||||
});
|
|
||||||
|
|
||||||
// evaluate and store all function definitions
|
|
||||||
program.functions.into_iter().for_each(|(function_name, function)| {
|
|
||||||
let resolved_function_name = new_scope(program_name.clone(), function_name.to_string());
|
|
||||||
self.store(resolved_function_name, ConstrainedValue::Function(None, function));
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
70
compiler/src/constraints/generate_constraints.rs
Normal file
70
compiler/src/constraints/generate_constraints.rs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
use crate::{errors::CompilerError, new_scope, ConstrainedProgram, ConstrainedValue, GroupType, ImportedPrograms};
|
||||||
|
use leo_types::{InputValue, Program};
|
||||||
|
|
||||||
|
use snarkos_models::{
|
||||||
|
curves::{Field, PrimeField},
|
||||||
|
gadgets::r1cs::{ConstraintSystem, TestConstraintSystem},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
||||||
|
cs: &mut CS,
|
||||||
|
program: Program,
|
||||||
|
parameters: Vec<Option<InputValue>>,
|
||||||
|
imported_programs: &ImportedPrograms,
|
||||||
|
) -> Result<ConstrainedValue<F, G>, CompilerError> {
|
||||||
|
let mut resolved_program = ConstrainedProgram::new();
|
||||||
|
let program_name = program.get_name();
|
||||||
|
let main_function_name = new_scope(program_name.clone(), "main".into());
|
||||||
|
|
||||||
|
resolved_program.store_definitions(program, imported_programs)?;
|
||||||
|
|
||||||
|
let main = resolved_program
|
||||||
|
.get(&main_function_name)
|
||||||
|
.ok_or_else(|| CompilerError::NoMain)?;
|
||||||
|
|
||||||
|
match main.clone() {
|
||||||
|
ConstrainedValue::Function(_circuit_identifier, function) => {
|
||||||
|
let result = resolved_program.enforce_main_function(cs, program_name, function, parameters)?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
_ => Err(CompilerError::NoMainFunction),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_test_constraints<F: Field + PrimeField, G: GroupType<F>>(
|
||||||
|
cs: &mut TestConstraintSystem<F>,
|
||||||
|
program: Program,
|
||||||
|
imported_programs: &ImportedPrograms,
|
||||||
|
) -> Result<(), CompilerError> {
|
||||||
|
let mut resolved_program = ConstrainedProgram::<F, G>::new();
|
||||||
|
let program_name = program.get_name();
|
||||||
|
|
||||||
|
let tests = program.tests.clone();
|
||||||
|
|
||||||
|
resolved_program.store_definitions(program, imported_programs)?;
|
||||||
|
|
||||||
|
log::info!("Running {} tests", tests.len());
|
||||||
|
|
||||||
|
for (test_name, test_function) in tests.into_iter() {
|
||||||
|
let full_test_name = format!("{}::{}", program_name.clone(), test_name.to_string());
|
||||||
|
|
||||||
|
let result = resolved_program.enforce_main_function(
|
||||||
|
cs,
|
||||||
|
program_name.clone(),
|
||||||
|
test_function.0,
|
||||||
|
vec![], // test functions should not take any inputs
|
||||||
|
);
|
||||||
|
|
||||||
|
if result.is_ok() {
|
||||||
|
log::info!(
|
||||||
|
"test {} passed. Constraint system satisfied: {}",
|
||||||
|
full_test_name,
|
||||||
|
cs.is_satisfied()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
log::error!("test {} errored: {}", full_test_name, result.unwrap_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -1,96 +1,31 @@
|
|||||||
//! Module containing methods to enforce constraints in an Leo program
|
//! Module containing methods to enforce constraints in an Leo program
|
||||||
|
|
||||||
pub(crate) mod boolean;
|
pub(crate) mod boolean;
|
||||||
pub(crate) use boolean::*;
|
pub(crate) use self::boolean::*;
|
||||||
|
|
||||||
pub mod function;
|
pub mod function;
|
||||||
pub use function::*;
|
pub use self::function::*;
|
||||||
|
|
||||||
pub mod expression;
|
pub mod expression;
|
||||||
pub use expression::*;
|
pub use self::expression::*;
|
||||||
|
|
||||||
pub(crate) mod field;
|
pub(crate) mod field;
|
||||||
pub(crate) use field::*;
|
pub(crate) use self::field::*;
|
||||||
|
|
||||||
|
pub mod generate_constraints;
|
||||||
|
pub use self::generate_constraints::*;
|
||||||
|
|
||||||
pub(crate) mod group;
|
pub(crate) mod group;
|
||||||
pub(crate) use group::*;
|
pub(crate) use self::group::*;
|
||||||
|
|
||||||
|
pub(crate) mod definitions;
|
||||||
|
pub(crate) use self::definitions::*;
|
||||||
|
|
||||||
pub mod program;
|
pub mod program;
|
||||||
pub use program::*;
|
pub use self::program::*;
|
||||||
|
|
||||||
pub mod value;
|
pub mod value;
|
||||||
pub use value::*;
|
pub use self::value::*;
|
||||||
|
|
||||||
pub mod statement;
|
pub mod statement;
|
||||||
pub use statement::*;
|
pub use self::statement::*;
|
||||||
|
|
||||||
use crate::{errors::CompilerError, GroupType, ImportedPrograms};
|
|
||||||
use leo_types::{InputValue, Program};
|
|
||||||
|
|
||||||
use snarkos_models::{
|
|
||||||
curves::{Field, PrimeField},
|
|
||||||
gadgets::r1cs::{ConstraintSystem, TestConstraintSystem},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
|
||||||
cs: &mut CS,
|
|
||||||
program: Program,
|
|
||||||
parameters: Vec<Option<InputValue>>,
|
|
||||||
imported_programs: ImportedPrograms,
|
|
||||||
) -> Result<ConstrainedValue<F, G>, CompilerError> {
|
|
||||||
let mut resolved_program = ConstrainedProgram::new();
|
|
||||||
let program_name = program.get_name();
|
|
||||||
let main_function_name = new_scope(program_name.clone(), "main".into());
|
|
||||||
|
|
||||||
resolved_program.resolve_definitions(program, imported_programs)?;
|
|
||||||
|
|
||||||
let main = resolved_program
|
|
||||||
.get(&main_function_name)
|
|
||||||
.ok_or_else(|| CompilerError::NoMain)?;
|
|
||||||
|
|
||||||
match main.clone() {
|
|
||||||
ConstrainedValue::Function(_circuit_identifier, function) => {
|
|
||||||
let result = resolved_program.enforce_main_function(cs, program_name, function, parameters)?;
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
_ => Err(CompilerError::NoMainFunction),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_test_constraints<F: Field + PrimeField, G: GroupType<F>>(
|
|
||||||
cs: &mut TestConstraintSystem<F>,
|
|
||||||
program: Program,
|
|
||||||
imported_programs: ImportedPrograms,
|
|
||||||
) -> Result<(), CompilerError> {
|
|
||||||
let mut resolved_program = ConstrainedProgram::<F, G>::new();
|
|
||||||
let program_name = program.get_name();
|
|
||||||
|
|
||||||
let tests = program.tests.clone();
|
|
||||||
|
|
||||||
resolved_program.resolve_definitions(program, imported_programs)?;
|
|
||||||
|
|
||||||
log::info!("Running {} tests", tests.len());
|
|
||||||
|
|
||||||
for (test_name, test_function) in tests.into_iter() {
|
|
||||||
let full_test_name = format!("{}::{}", program_name.clone(), test_name.to_string());
|
|
||||||
|
|
||||||
let result = resolved_program.enforce_main_function(
|
|
||||||
cs,
|
|
||||||
program_name.clone(),
|
|
||||||
test_function.0,
|
|
||||||
vec![], // test functions should not take any inputs
|
|
||||||
);
|
|
||||||
|
|
||||||
if result.is_ok() {
|
|
||||||
log::info!(
|
|
||||||
"test {} passed. Constraint system satisfied: {}",
|
|
||||||
full_test_name,
|
|
||||||
cs.is_satisfied()
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
log::error!("test {} errored: {}", full_test_name, result.unwrap_err());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
@ -75,11 +75,9 @@ impl ImportError {
|
|||||||
Self::new_from_span(message, identifier.span)
|
Self::new_from_span(message, identifier.span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unknown_symbol(symbol: ImportSymbol, file: String, file_path: &PathBuf) -> Self {
|
pub fn unknown_symbol(symbol: ImportSymbol, file: String) -> Self {
|
||||||
let message = format!("cannot find imported symbol `{}` in imported file `{}`", symbol, file);
|
let message = format!("cannot find imported symbol `{}` in imported file `{}`", symbol, file);
|
||||||
let mut error = FormattedError::new_from_span(message, symbol.span);
|
let error = FormattedError::new_from_span(message, symbol.span);
|
||||||
|
|
||||||
error.path = Some(format!("{:?}", file_path));
|
|
||||||
|
|
||||||
ImportError::Error(error)
|
ImportError::Error(error)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::{errors::constraints::ImportError, ImportedPrograms};
|
|||||||
use leo_ast::LeoParser;
|
use leo_ast::LeoParser;
|
||||||
use leo_types::{ImportSymbol, Program, Span};
|
use leo_types::{ImportSymbol, Program, Span};
|
||||||
|
|
||||||
use std::{ffi::OsString, fs::DirEntry};
|
use std::{ffi::OsString, fs::DirEntry, path::PathBuf};
|
||||||
|
|
||||||
static LIBRARY_FILE: &str = "src/lib.leo";
|
static LIBRARY_FILE: &str = "src/lib.leo";
|
||||||
static FILE_EXTENSION: &str = "leo";
|
static FILE_EXTENSION: &str = "leo";
|
||||||
@ -54,7 +54,6 @@ impl ImportedPrograms {
|
|||||||
// import * can only be invoked on a package with a library file or a leo file
|
// import * can only be invoked on a package with a library file or a leo file
|
||||||
if is_package || is_leo_file {
|
if is_package || is_leo_file {
|
||||||
// Generate aleo program from file
|
// Generate aleo program from file
|
||||||
let name = format!("{:?}", entry.path());
|
|
||||||
let program = parse_import_file(entry, &span)?;
|
let program = parse_import_file(entry, &span)?;
|
||||||
|
|
||||||
// Store program's imports in imports hashmap
|
// Store program's imports in imports hashmap
|
||||||
@ -65,7 +64,15 @@ impl ImportedPrograms {
|
|||||||
.collect::<Result<Vec<()>, ImportError>>()?;
|
.collect::<Result<Vec<()>, ImportError>>()?;
|
||||||
|
|
||||||
// Store program in imports hashmap
|
// Store program in imports hashmap
|
||||||
self.store(name, program);
|
let file_name_path = PathBuf::from(entry.file_name());
|
||||||
|
let file_name = file_name_path
|
||||||
|
.file_stem()
|
||||||
|
.unwrap()
|
||||||
|
.to_os_string()
|
||||||
|
.into_string()
|
||||||
|
.unwrap(); // the file exists so these will not fail
|
||||||
|
|
||||||
|
self.store(file_name, program);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@ -76,7 +83,6 @@ impl ImportedPrograms {
|
|||||||
|
|
||||||
pub fn parse_import_symbol(&mut self, entry: &DirEntry, symbol: &ImportSymbol) -> Result<(), ImportError> {
|
pub fn parse_import_symbol(&mut self, entry: &DirEntry, symbol: &ImportSymbol) -> Result<(), ImportError> {
|
||||||
// Generate aleo program from file
|
// Generate aleo program from file
|
||||||
let name = format!("{:?}", entry.path());
|
|
||||||
let program = parse_import_file(entry, &symbol.span)?;
|
let program = parse_import_file(entry, &symbol.span)?;
|
||||||
|
|
||||||
// Store program's imports in imports hashmap
|
// Store program's imports in imports hashmap
|
||||||
@ -87,7 +93,15 @@ impl ImportedPrograms {
|
|||||||
.collect::<Result<Vec<()>, ImportError>>()?;
|
.collect::<Result<Vec<()>, ImportError>>()?;
|
||||||
|
|
||||||
// Store program in imports hashmap
|
// Store program in imports hashmap
|
||||||
self.store(name, program);
|
let file_name_path = PathBuf::from(entry.file_name());
|
||||||
|
let file_name = file_name_path
|
||||||
|
.file_stem()
|
||||||
|
.unwrap()
|
||||||
|
.to_os_string()
|
||||||
|
.into_string()
|
||||||
|
.unwrap(); // the file exists so these will not fail
|
||||||
|
|
||||||
|
self.store(file_name, program);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -15,14 +15,14 @@ impl ImportedPrograms {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn store(&mut self, name: String, program: Program) {
|
pub(crate) fn store(&mut self, file_name: String, program: Program) {
|
||||||
// todo: handle conflicting versions for duplicate imports here
|
// todo: handle conflicting versions for duplicate imports here
|
||||||
println!("{}, {:?}", name, program);
|
println!("storing: {},\n {:?}", file_name, program);
|
||||||
let _res = self.imports.insert(name, program);
|
let _res = self.imports.insert(file_name, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, name: &String) -> Option<&Program> {
|
pub fn get(&self, file_name: &String) -> Option<&Program> {
|
||||||
self.imports.get(name)
|
self.imports.get(file_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_program(program: &Program) -> Result<Self, ImportError> {
|
pub fn from_program(program: &Program) -> Result<Self, ImportError> {
|
||||||
|
@ -30,3 +30,31 @@ impl fmt::Display for ImportSymbol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: 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("*")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user