impl importing from package lib, file, directory, and star

This commit is contained in:
collin 2020-06-29 17:47:23 -07:00
parent 24cf5a0181
commit d905ffd569
16 changed files with 139 additions and 19 deletions

View File

@ -299,7 +299,7 @@ package_access = {
| import_symbol
}
multiple_package_access = _{ "(" ~ NEWLINE* ~ package_access ~ ("," ~ NEWLINE* ~ package_access)* ~ NEWLINE* ~ ")"}
multiple_package_access = _{ "(" ~ NEWLINE* ~ package_access ~ ("," ~ NEWLINE* ~ package_access)* ~ ","? ~ NEWLINE* ~ ")"}
// Declared in imports/star.rs
star = {"*"}

View File

@ -8,7 +8,10 @@ use leo_ast::LeoParser;
use leo_types::{ImportSymbol, Program, Span};
use snarkos_models::curves::{Field, PrimeField};
use std::fs::DirEntry;
use std::{
ffi::OsString,
fs::{read_dir, DirEntry},
};
static LIBRARY_FILE: &str = "src/lib.leo";
@ -27,7 +30,10 @@ fn parse_import_file(entry: &DirEntry, span: &Span) -> Result<Program, ImportErr
file_path.push(LIBRARY_FILE);
if !file_path.exists() {
return Err(ImportError::expected_file(file_name, span.clone()));
return Err(ImportError::expected_lib_file(
format!("{:?}", file_path.as_path()),
span.clone(),
));
}
}
@ -41,13 +47,35 @@ fn parse_import_file(entry: &DirEntry, span: &Span) -> Result<Program, ImportErr
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn enforce_import_star(&mut self, scope: String, entry: &DirEntry, span: Span) -> Result<(), ImportError> {
let mut program = parse_import_file(entry, &span)?;
// import star from a file
if entry.path().is_file() {
// only parse `.leo` files
if let Some(extension) = entry.path().extension() {
if extension.eq(&OsString::from("leo")) {
let mut program = parse_import_file(entry, &span)?;
// Use same namespace as calling function for imported symbols
program = program.name(scope);
// Use same namespace as calling function for imported symbols
program = program.name(scope);
// * -> import all imports, circuits, functions in the current scope
self.resolve_definitions(program)
// * -> import all imports, circuits, functions in the current scope
self.resolve_definitions(program)
} else {
Ok(())
}
} else {
Ok(())
}
} else {
// import star for every file in the directory
for entry in read_dir(entry.path()).map_err(|error| ImportError::directory_error(error, span.clone()))? {
match entry {
Ok(entry) => self.enforce_import_star(scope.clone(), &entry, span.clone())?,
Err(error) => return Err(ImportError::directory_error(error, span.clone())),
}
}
Ok(())
}
}
pub fn enforce_import_symbol(

View File

@ -31,14 +31,23 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
}
}
pub fn enforce_package(&mut self, scope: String, path: PathBuf, package: Package) -> Result<(), ImportError> {
pub fn enforce_package(&mut self, scope: String, mut path: PathBuf, package: Package) -> Result<(), ImportError> {
let package_name = package.name;
// search for package name in local src directory
// search for package name in local directory
let mut source_directory = path.clone();
source_directory.push(SOURCE_DIRECTORY_NAME);
let entries = fs::read_dir(source_directory)
// search for package name in `imports` directory
let mut imports_directory = path.clone();
imports_directory.push(IMPORTS_DIRECTORY_NAME);
// read from local `src` directory or the current path
if source_directory.exists() {
path = source_directory
}
let entries = fs::read_dir(path)
.map_err(|error| ImportError::directory_error(error, package_name.span.clone()))?
.into_iter()
.collect::<Result<Vec<_>, std::io::Error>>()
@ -53,10 +62,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
.eq(&package_name.name)
});
// search for package name in imports directory
let mut imports_directory = path.clone();
imports_directory.push(IMPORTS_DIRECTORY_NAME);
if imports_directory.exists() {
let entries = fs::read_dir(imports_directory)
.map_err(|error| ImportError::directory_error(error, package_name.span.clone()))?

View File

@ -35,8 +35,11 @@ impl ImportError {
Self::new_from_span(message, span)
}
pub fn expected_file(entry: String, span: Span) -> Self {
let message = format!("cannot import symbol `{}` from directory `{}`", span.text, entry);
pub fn expected_lib_file(entry: String, span: Span) -> Self {
let message = format!(
"expected library file`{}` when looking for symbol `{}`",
entry, span.text
);
Self::new_from_span(message, span)
}

View File

@ -0,0 +1 @@
outputs/

View File

@ -0,0 +1,3 @@
[package]
name = "bar"
version = "0.1.0"

View File

@ -0,0 +1,3 @@
circuit Bat {
t: u32
}

View File

@ -0,0 +1,3 @@
circuit Baz {
z: u32
}

View File

@ -0,0 +1,3 @@
circuit Bar {
r: u32
}

View File

@ -0,0 +1 @@
outputs/

View File

@ -0,0 +1,3 @@
[package]
name = "car"
version = "0.1.0"

View File

@ -0,0 +1,3 @@
circuit Car {
c: u32
}

View File

@ -0,0 +1,25 @@
import test_import.( // local import
Point,
foo,
);
import bar.( // imports directory import
Bar,
baz.Baz,
bat.bat.Bat,
);
import car.Car; // imports directory import
function main() -> u32 {
// const point = Point { x: 1u32, y: 1u32 };
// const foo = foo();
const bar = Bar { r: 1u32 };
const bat = Bat { t: 1u32 };
const baz = Baz { z: 1u32 };
const car = Car { c: 1u32 };
return car.c
}

View File

@ -0,0 +1,16 @@
import test_import.*; // local import
import bar.*; // imports directory import
import car.*; // imports directory import
function main() -> u32 {
const point = Point { x: 1u32, y: 1u32 };
const foo = foo();
const bar = Bar { r: 1u32 };
const bat = Bat { t: 1u32 };
const baz = Baz { z: 1u32 };
const car = Car { c: 1u32 };
return car.c
}

View File

@ -56,3 +56,26 @@ fn test_alias() {
output_one(program);
}
// more complex tests
#[test]
#[ignore]
fn test_many_import() {
let bytes = include_bytes!("many_import.leo");
let program = parse_program(bytes).unwrap();
set_local_dir();
output_one(program);
}
#[test]
#[ignore]
fn test_many_import_star() {
let bytes = include_bytes!("many_import_star.leo");
let program = parse_program(bytes).unwrap();
set_local_dir();
output_one(program);
}

View File

@ -46,8 +46,8 @@ impl LibFile {
fn template(&self) -> String {
format!(
r#"// The '{}' lib function.
circuit Circ {{
c: field
circuit Foo {{
a: field
}}
"#,
self.package_name