diff --git a/Cargo.lock b/Cargo.lock index 6640c86..d05b232 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -184,6 +184,11 @@ dependencies = [ "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "simple-error" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "strsim" version = "0.6.0" @@ -228,6 +233,7 @@ dependencies = [ "nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nom_locate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "simple-error 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -295,6 +301,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649" "checksum serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "e9a2d9a9ac5120e0f768801ca2b58ad6eec929dc9d1d616c162f208869c2ce95" "checksum serde_json 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "eb40600c756f02d7ea34943626cefa85732fdae5f95b90b31f9797b3c526d1e6" +"checksum simple-error 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "7779d1977a9e1e50bebb430a57114acc64bc4c40d6d8efb3e57893531d5fd895" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" diff --git a/Cargo.toml b/Cargo.toml index 7276581..7e74e29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,9 +13,10 @@ license = "Apache-2.0" version = "^3.2" [dependencies] -nom_locate = "^0.1.1" -clap = "~2.26.0" -serde_json = "~1.0.9" +nom_locate = "^0.1.1" +clap = "~2.26.0" +serde_json = "~1.0.9" +simple-error = "0.1" [dev-dependencies] bencher = "~0.1.5" diff --git a/src/build/mod.rs b/src/build/mod.rs index b20a69d..49b75c1 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -488,16 +488,25 @@ impl Builder { eprintln!("processing import for {}", normalized.to_string_lossy()); // Only parse the file once on import. let mut shared_assets = self.assets.borrow_mut(); - if try!(shared_assets.get(&normalized)).is_some() { - return Ok(try!(shared_assets.get(&normalized)).unwrap().clone()); + let result = match try!(shared_assets.get(&normalized)) { + Some(v) => v.clone(), + None => { + let mut b = Self::new(normalized.clone(), self.assets.clone()); + let filepath = normalized.to_str().unwrap().clone(); + try!(b.build_file(filepath)); + let fields: Vec<(Positioned, Rc)> = b.build_output.drain().collect(); + Rc::new(Val::Tuple(fields)) + } + }; + let key = sym.into(); + if self.build_output.contains_key(&key) { + return Err(Box::new(error::Error::new( + format!("Binding for import name {} already exists", sym.fragment), + error::ErrorType::DuplicateBinding, + def.path.pos.clone(), + ))); } - let mut b = Self::new(normalized.clone(), self.assets.clone()); - let filepath = normalized.to_str().unwrap().clone(); - try!(b.build_file(filepath)); - let fields: Vec<(Positioned, Rc)> = b.build_output.drain().collect(); - let result = Rc::new(Val::Tuple(fields)); - //eprintln!("storing sym {:?} results {:?} ", sym, result) - self.build_output.insert(sym.into(), result.clone()); + self.build_output.insert(key, result.clone()); try!(shared_assets.stash(normalized.clone(), result.clone())); return Ok(result); } diff --git a/src/lib.rs b/src/lib.rs index 64d5dea..006b0f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -423,6 +423,7 @@ extern crate nom; #[macro_use] extern crate nom_locate; extern crate serde_json; +extern crate simple_error; #[macro_use] pub mod ast; diff --git a/src/main.rs b/src/main.rs index dd9b457..732e34e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,16 +59,19 @@ fn run_converter(c: ConverterRunner, v: Rc, f: Option<&str>) -> traits::Res fn main() { let app = do_flags(); + let cache = Rc::new(RefCell::new(MemoryCache::new())); if let Some(matches) = app.subcommand_matches("build") { let file = matches.value_of("INPUT").unwrap(); let out = matches.value_of("out"); let sym = matches.value_of("sym"); let target = matches.value_of("target").unwrap(); let root = PathBuf::from(file); - let cache = Rc::new(RefCell::new(MemoryCache::new())); let mut builder = build::Builder::new(root.parent().unwrap(), cache); match ConverterRunner::new(target) { Ok(converter) => { + // FIXME(jwall): What should happen if they requested we build a _test.ucg file. + // 1. We could automatically go into validate mode. + // 2. We could warn that this is a test file. let result = builder.build_file(file); if !result.is_ok() { eprintln!("{:?}", result.err().unwrap()); @@ -97,7 +100,6 @@ fn main() { } } else if let Some(matches) = app.subcommand_matches("validate") { let file = matches.value_of("INPUT").unwrap(); - let cache = Rc::new(RefCell::new(MemoryCache::new())); let mut builder = build::Builder::new(std::env::current_dir().unwrap(), cache); builder.enable_validate_mode(); builder.build_file(file).unwrap();