impl import package syntax for ast and types

This commit is contained in:
collin 2020-06-26 14:18:05 -07:00
parent d9b5c15d73
commit b5d90b857b
12 changed files with 261 additions and 127 deletions

View File

@ -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>,

View File

@ -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>,
}

View File

@ -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::*;

View 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>,
}

View 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
View 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 {}

View File

@ -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

View File

@ -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!()
}
}

View File

@ -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)
}
}

View File

@ -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::*;

View 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)
}
}

View 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)
}
}