mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-23 23:23:50 +03:00
impl import package syntax for ast and types
This commit is contained in:
parent
d9b5c15d73
commit
b5d90b857b
@ -1,8 +1,4 @@
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
common::LineEnd,
|
||||
imports::{ImportSource, ImportSymbol},
|
||||
};
|
||||
use crate::{ast::Rule, common::LineEnd, imports::Package};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
@ -10,8 +6,7 @@ use pest_ast::FromPest;
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::import))]
|
||||
pub struct Import<'ast> {
|
||||
pub source: ImportSource<'ast>,
|
||||
pub symbols: Vec<ImportSymbol<'ast>>,
|
||||
pub package: Package<'ast>,
|
||||
pub line_end: LineEnd,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
|
@ -1,13 +0,0 @@
|
||||
use crate::ast::{span_into_string, Rule};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::import_source))]
|
||||
pub struct ImportSource<'ast> {
|
||||
#[pest_ast(outer(with(span_into_string)))]
|
||||
pub value: String,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
@ -1,8 +1,14 @@
|
||||
pub mod import;
|
||||
pub use import::*;
|
||||
|
||||
pub mod import_source;
|
||||
pub use import_source::*;
|
||||
|
||||
pub mod import_symbol;
|
||||
pub use import_symbol::*;
|
||||
|
||||
pub mod package;
|
||||
pub use package::*;
|
||||
|
||||
pub mod package_access;
|
||||
pub use package_access::*;
|
||||
|
||||
pub mod star;
|
||||
pub use star::*;
|
||||
|
13
ast/src/imports/package.rs
Normal file
13
ast/src/imports/package.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use crate::{ast::Rule, common::Identifier, imports::PackageAccess};
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::package))]
|
||||
pub struct Package<'ast> {
|
||||
pub name: Identifier<'ast>,
|
||||
pub access: PackageAccess<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
15
ast/src/imports/package_access.rs
Normal file
15
ast/src/imports/package_access.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
imports::{ImportSymbol, Package, Star},
|
||||
};
|
||||
|
||||
use pest_ast::FromPest;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::package_access))]
|
||||
pub enum PackageAccess<'ast> {
|
||||
Star(Star),
|
||||
SubPackage(Box<Package<'ast>>),
|
||||
Multiple(Vec<Package<'ast>>),
|
||||
Symbol(ImportSymbol<'ast>),
|
||||
}
|
7
ast/src/imports/star.rs
Normal file
7
ast/src/imports/star.rs
Normal file
@ -0,0 +1,7 @@
|
||||
use crate::ast::Rule;
|
||||
|
||||
use pest_ast::FromPest;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::star))]
|
||||
pub struct Star {}
|
@ -286,14 +286,25 @@ test_function = { "test" ~ function_definition }
|
||||
/// Imports
|
||||
|
||||
// Declared in imports/import.rs
|
||||
import = { "from" ~ "\"" ~ import_source ~ "\"" ~ "import" ~ ("*" | ("{" ~ NEWLINE* ~ import_symbol_tuple ~ NEWLINE* ~ "}") | import_symbol) ~ LINE_END}
|
||||
import = { "import" ~ package ~ LINE_END}
|
||||
|
||||
// Declared in imports/import_source.rs
|
||||
import_source = @{ (!"\"" ~ ANY)* }
|
||||
// Declared in imports/package.rs
|
||||
package = { identifier ~ "." ~ package_access }
|
||||
package_tuple = _{ "(" ~ package ~ ("," ~ NEWLINE* ~ package)* ~ ")" }
|
||||
|
||||
// Declared in imports/package_access
|
||||
package_access = {
|
||||
star
|
||||
| package // subpackage
|
||||
| package_tuple
|
||||
| import_symbol
|
||||
}
|
||||
|
||||
// Declared in imports/star.rs
|
||||
star = {"*"}
|
||||
|
||||
// Declared in imports/import_symbol.rs
|
||||
import_symbol = { identifier ~ ("as" ~ identifier)? }
|
||||
import_symbol_tuple = _{ import_symbol ~ ("," ~ NEWLINE* ~ import_symbol)* }
|
||||
|
||||
/// Utilities
|
||||
|
||||
|
@ -5,87 +5,100 @@ use crate::{
|
||||
GroupType,
|
||||
};
|
||||
use leo_ast::LeoParser;
|
||||
use leo_types::{Import, Program};
|
||||
use leo_types::{Import, Package, Program};
|
||||
|
||||
use snarkos_models::curves::{Field, PrimeField};
|
||||
use std::env::current_dir;
|
||||
|
||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
// pub fn enforce_package(&mut self, scope: String, package: Package) -> Result<(), ImportError> {
|
||||
// let path = current_dir().map_err(|error| ImportError::directory_error(error, import.span.clone()))?;
|
||||
//
|
||||
// // Sanitize the package path to the imports directory
|
||||
// let mut package_path = path.clone();
|
||||
// if package_path.is_file() {
|
||||
// package_path.pop();
|
||||
// }
|
||||
//
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
pub fn enforce_import(&mut self, scope: String, import: Import) -> Result<(), ImportError> {
|
||||
let path = current_dir().map_err(|error| ImportError::directory_error(error, import.span.clone()))?;
|
||||
|
||||
// Sanitize the package path to the imports directory
|
||||
let mut package_path = path.clone();
|
||||
if package_path.is_file() {
|
||||
package_path.pop();
|
||||
}
|
||||
|
||||
// Construct the path to the import file in the import directory
|
||||
let mut main_file_path = package_path.clone();
|
||||
main_file_path.push(import.path_string_full());
|
||||
|
||||
println!("Compiling import - {:?}", main_file_path);
|
||||
|
||||
// Build the abstract syntax tree
|
||||
let file_path = &main_file_path;
|
||||
let input_file = &LeoParser::load_file(file_path)?;
|
||||
let syntax_tree = LeoParser::parse_file(file_path, input_file)?;
|
||||
|
||||
// Generate aleo program from file
|
||||
let mut program = Program::from(syntax_tree, import.path_string.clone());
|
||||
|
||||
// Use same namespace as calling function for imported symbols
|
||||
program = program.name(scope);
|
||||
|
||||
// * -> import all imports, circuits, functions in the current scope
|
||||
if import.is_star() {
|
||||
// recursively evaluate program statements
|
||||
self.resolve_definitions(program)
|
||||
} else {
|
||||
let program_name = program.name.clone();
|
||||
|
||||
// match each import symbol to a symbol in the imported file
|
||||
for symbol in import.symbols.into_iter() {
|
||||
// see if the imported symbol is a circuit
|
||||
let matched_circuit = program
|
||||
.circuits
|
||||
.clone()
|
||||
.into_iter()
|
||||
.find(|(circuit_name, _circuit_def)| symbol.symbol == *circuit_name);
|
||||
|
||||
let value = match matched_circuit {
|
||||
Some((_circuit_name, circuit_def)) => ConstrainedValue::CircuitDefinition(circuit_def),
|
||||
None => {
|
||||
// see if the imported symbol is a function
|
||||
let matched_function = program
|
||||
.functions
|
||||
.clone()
|
||||
.into_iter()
|
||||
.find(|(function_name, _function)| symbol.symbol.name == *function_name.name);
|
||||
|
||||
match matched_function {
|
||||
Some((_function_name, function)) => ConstrainedValue::Function(None, function),
|
||||
None => return Err(ImportError::unknown_symbol(symbol, program_name, file_path)),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// take the alias if it is present
|
||||
let resolved_name = symbol.alias.unwrap_or(symbol.symbol);
|
||||
let resolved_circuit_name = new_scope(program_name.clone(), resolved_name.to_string());
|
||||
|
||||
// store imported circuit under resolved name
|
||||
self.store(resolved_circuit_name, value);
|
||||
}
|
||||
|
||||
// evaluate all import statements in imported file
|
||||
program
|
||||
.imports
|
||||
.into_iter()
|
||||
.map(|nested_import| self.enforce_import(program_name.clone(), nested_import))
|
||||
.collect::<Result<Vec<_>, ImportError>>()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
// let path = current_dir().map_err(|error| ImportError::directory_error(error, import.span.clone()))?;
|
||||
//
|
||||
// // Sanitize the package path to the imports directory
|
||||
// let mut package_path = path.clone();
|
||||
// if package_path.is_file() {
|
||||
// package_path.pop();
|
||||
// }
|
||||
//
|
||||
// // Construct the path to the import file in the import directory
|
||||
// let mut main_file_path = package_path.clone();
|
||||
// main_file_path.push(import.path_string_full());
|
||||
//
|
||||
// println!("Compiling import - {:?}", main_file_path);
|
||||
//
|
||||
// // Build the abstract syntax tree
|
||||
// let file_path = &main_file_path;
|
||||
// let input_file = &LeoParser::load_file(file_path)?;
|
||||
// let syntax_tree = LeoParser::parse_file(file_path, input_file)?;
|
||||
//
|
||||
// // Generate aleo program from file
|
||||
// let mut program = Program::from(syntax_tree, import.path_string.clone());
|
||||
//
|
||||
// // Use same namespace as calling function for imported symbols
|
||||
// program = program.name(scope);
|
||||
//
|
||||
// // * -> import all imports, circuits, functions in the current scope
|
||||
// if import.is_star() {
|
||||
// // recursively evaluate program statements
|
||||
// self.resolve_definitions(program)
|
||||
// } else {
|
||||
// let program_name = program.name.clone();
|
||||
//
|
||||
// // match each import symbol to a symbol in the imported file
|
||||
// for symbol in import.symbols.into_iter() {
|
||||
// // see if the imported symbol is a circuit
|
||||
// let matched_circuit = program
|
||||
// .circuits
|
||||
// .clone()
|
||||
// .into_iter()
|
||||
// .find(|(circuit_name, _circuit_def)| symbol.symbol == *circuit_name);
|
||||
//
|
||||
// let value = match matched_circuit {
|
||||
// Some((_circuit_name, circuit_def)) => ConstrainedValue::CircuitDefinition(circuit_def),
|
||||
// None => {
|
||||
// // see if the imported symbol is a function
|
||||
// let matched_function = program
|
||||
// .functions
|
||||
// .clone()
|
||||
// .into_iter()
|
||||
// .find(|(function_name, _function)| symbol.symbol.name == *function_name.name);
|
||||
//
|
||||
// match matched_function {
|
||||
// Some((_function_name, function)) => ConstrainedValue::Function(None, function),
|
||||
// None => return Err(ImportError::unknown_symbol(symbol, program_name, file_path)),
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// // take the alias if it is present
|
||||
// let resolved_name = symbol.alias.unwrap_or(symbol.symbol);
|
||||
// let resolved_circuit_name = new_scope(program_name.clone(), resolved_name.to_string());
|
||||
//
|
||||
// // store imported circuit under resolved name
|
||||
// self.store(resolved_circuit_name, value);
|
||||
// }
|
||||
//
|
||||
// // evaluate all import statements in imported file
|
||||
// program
|
||||
// .imports
|
||||
// .into_iter()
|
||||
// .map(|nested_import| self.enforce_import(program_name.clone(), nested_import))
|
||||
// .collect::<Result<Vec<_>, ImportError>>()?;
|
||||
//
|
||||
// Ok(())
|
||||
// }
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! The import type for a Leo program.
|
||||
|
||||
use crate::{ImportSymbol, Span};
|
||||
use crate::{ImportSymbol, Package, Span};
|
||||
use leo_ast::imports::Import as AstImport;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -8,20 +8,14 @@ use std::fmt;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct Import {
|
||||
pub path_string: String,
|
||||
pub symbols: Vec<ImportSymbol>,
|
||||
pub package: Package,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<AstImport<'ast>> for Import {
|
||||
fn from(import: AstImport<'ast>) -> Self {
|
||||
Import {
|
||||
path_string: import.source.value,
|
||||
symbols: import
|
||||
.symbols
|
||||
.into_iter()
|
||||
.map(|symbol| ImportSymbol::from(symbol))
|
||||
.collect(),
|
||||
package: Package::from(import.package),
|
||||
span: Span::from(import.span),
|
||||
}
|
||||
}
|
||||
@ -29,28 +23,17 @@ impl<'ast> From<AstImport<'ast>> for Import {
|
||||
|
||||
impl Import {
|
||||
pub fn path_string_full(&self) -> String {
|
||||
format!("{}.leo", self.path_string)
|
||||
format!("{}.leo", self.package.name)
|
||||
}
|
||||
|
||||
// from "./import" import *;
|
||||
pub fn is_star(&self) -> bool {
|
||||
self.symbols.is_empty()
|
||||
// self.symbols.is_empty()
|
||||
false
|
||||
}
|
||||
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "from {} import ", self.path_string)?;
|
||||
if self.symbols.is_empty() {
|
||||
write!(f, "*")
|
||||
} else {
|
||||
write!(f, "{{\n")?;
|
||||
for (i, symbol) in self.symbols.iter().enumerate() {
|
||||
write!(f, "{}", symbol)?;
|
||||
if i < self.symbols.len() - 1 {
|
||||
write!(f, ",\n")?;
|
||||
}
|
||||
}
|
||||
write!(f, "\n}}")
|
||||
}
|
||||
write!(f, "import {};", self.package)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,3 +3,9 @@ pub use import::*;
|
||||
|
||||
pub mod import_symbol;
|
||||
pub use import_symbol::*;
|
||||
|
||||
pub mod package;
|
||||
pub use package::*;
|
||||
|
||||
pub mod package_access;
|
||||
pub use package_access::*;
|
||||
|
40
types/src/imports/package.rs
Normal file
40
types/src/imports/package.rs
Normal file
@ -0,0 +1,40 @@
|
||||
use crate::{common::Identifier, PackageAccess, Span};
|
||||
use leo_ast::imports::Package as AstPackage;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct Package {
|
||||
pub name: Identifier,
|
||||
pub access: PackageAccess,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<AstPackage<'ast>> for Package {
|
||||
fn from(package: AstPackage<'ast>) -> Self {
|
||||
Package {
|
||||
name: Identifier::from(package.name),
|
||||
access: PackageAccess::from(package.access),
|
||||
span: Span::from(package.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Package {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}.{}", self.name, self.access)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Package {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.format(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Package {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.format(f)
|
||||
}
|
||||
}
|
58
types/src/imports/package_access.rs
Normal file
58
types/src/imports/package_access.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use crate::{ImportSymbol, Package};
|
||||
use leo_ast::imports::PackageAccess as AstPackageAccess;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub enum PackageAccess {
|
||||
Star,
|
||||
SubPackage(Box<Package>),
|
||||
Multiple(Vec<Package>),
|
||||
Symbol(ImportSymbol),
|
||||
}
|
||||
|
||||
impl<'ast> From<AstPackageAccess<'ast>> for PackageAccess {
|
||||
fn from(access: AstPackageAccess<'ast>) -> Self {
|
||||
match access {
|
||||
AstPackageAccess::Star(_) => PackageAccess::Star,
|
||||
AstPackageAccess::SubPackage(package) => PackageAccess::SubPackage(Box::new(Package::from(*package))),
|
||||
AstPackageAccess::Multiple(packages) => {
|
||||
PackageAccess::Multiple(packages.into_iter().map(|package| Package::from(package)).collect())
|
||||
}
|
||||
AstPackageAccess::Symbol(symbol) => PackageAccess::Symbol(ImportSymbol::from(symbol)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PackageAccess {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
PackageAccess::Star => write!(f, ".*"),
|
||||
PackageAccess::SubPackage(ref package) => write!(f, ".{}", package),
|
||||
PackageAccess::Multiple(ref packages) => {
|
||||
write!(f, ".(")?;
|
||||
for (i, package) in packages.iter().enumerate() {
|
||||
write!(f, "{}", package)?;
|
||||
if i < packages.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
PackageAccess::Symbol(ref symbol) => write!(f, ".{}", symbol),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for PackageAccess {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.format(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PackageAccess {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.format(f)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user