refactor import * for packages and leo files only

This commit is contained in:
collin 2020-06-30 13:31:27 -07:00
parent 26890ff097
commit 330bfe46c8
5 changed files with 48 additions and 33 deletions

View File

@ -8,12 +8,10 @@ use leo_ast::LeoParser;
use leo_types::{ImportSymbol, Program, Span};
use snarkos_models::curves::{Field, PrimeField};
use std::{
ffi::OsString,
fs::{read_dir, DirEntry},
};
use std::{ffi::OsString, fs::DirEntry};
static LIBRARY_FILE: &str = "src/lib.leo";
static FILE_EXTENSION: &str = "leo";
fn parse_import_file(entry: &DirEntry, span: &Span) -> Result<Program, ImportError> {
// make sure the given entry is file
@ -47,34 +45,28 @@ 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> {
// 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)?;
let mut path = entry.path();
let is_dir = path.is_dir();
let is_leo_file = path
.extension()
.map_or(false, |ext| ext.eq(&OsString::from(FILE_EXTENSION)));
// Use same namespace as calling function for imported symbols
program = program.name(scope);
path.push(LIBRARY_FILE);
// * -> import all imports, circuits, functions in the current scope
self.resolve_definitions(program)
} else {
Ok(())
}
} else {
Ok(())
}
let is_package = is_dir && path.exists();
// import * can only be invoked on a package with a library file or a leo file
if is_package || is_leo_file {
let mut program = parse_import_file(entry, &span)?;
// use the 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)
} 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(())
// importing * from a directory or non-leo file in `package/src/` is illegal
Err(ImportError::star(entry.path(), span))
}
}

View File

@ -35,6 +35,12 @@ impl ImportError {
Self::new_from_span(message, span)
}
pub fn star(path: PathBuf, span: Span) -> Self {
let message = format!("cannot import `*` from path `{:?}`", path);
Self::new_from_span(message, span)
}
pub fn expected_lib_file(entry: String, span: Span) -> Self {
let message = format!(
"expected library file`{}` when looking for symbol `{}`",

View File

@ -1,6 +1,9 @@
import test_import.*; // local import
import bar.*; // imports directory import
import car.*; // imports directory import
import bar.*; // imports directory import
import bar.baz.*; // imports directory import
import bar.bat.bat.*; // imports directory import
import car.*; // imports directory import
function main() -> u32 {
const point = Point { x: 1u32, y: 1u32 };

View File

@ -1,4 +1,4 @@
use crate::{integers::u32::output_one, parse_program};
use crate::{get_error, integers::u32::output_one, parse_program};
use std::env::{current_dir, set_current_dir};
@ -46,6 +46,17 @@ fn test_star() {
output_one(program);
}
#[test]
#[ignore]
fn test_star_fail() {
let bytes = include_bytes!("star_fail.leo");
let program = parse_program(bytes).unwrap();
set_local_dir();
let _err = get_error(program);
}
#[test]
#[ignore]
fn test_alias() {
@ -70,7 +81,6 @@ fn test_many_import() {
}
#[test]
#[ignore]
fn test_many_import_star() {
let bytes = include_bytes!("many_import_star.leo");
let program = parse_program(bytes).unwrap();

View File

@ -0,0 +1,4 @@
// importing `*` from a directory is illegal
import bar.bat.*;
function main() {}