From 1365a387000f286c357d3ccd04a9ce1a4ce5c19b Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Mon, 26 Nov 2018 20:22:37 -0600 Subject: [PATCH] FEATURE: Check bindings against the reserved word list for imports and let bindings. --- example_errors/errors_test.ucg | 12 +++++++----- integration_tests/modules_test.ucg | 4 ++-- src/build/mod.rs | 27 +++++++++++++++++++++++++++ src/error.rs | 2 ++ 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/example_errors/errors_test.ucg b/example_errors/errors_test.ucg index 4510eb7..0cde743 100644 --- a/example_errors/errors_test.ucg +++ b/example_errors/errors_test.ucg @@ -8,8 +8,10 @@ assert |=|; assert |let |; assert |let foo |; assert |let foo =|; -//assert |import |; -//assert |import foo |; -//assert |out |; -//assert |out "|; -//assert |out json|; +assert |import |; +assert |import foo |; +assert |out |; +assert |out "|; +assert |out json|; + +assert |let env = 1;|; \ No newline at end of file diff --git a/integration_tests/modules_test.ucg b/integration_tests/modules_test.ucg index 3493a37..0db7906 100644 --- a/integration_tests/modules_test.ucg +++ b/integration_tests/modules_test.ucg @@ -24,7 +24,7 @@ let embedded_mod = module { deep_value = "None", env = "None", } => { - let env = select mod.env, "qa", { + let env_name = select mod.env, "qa", { None = "qa", prod = "prod", qa = "qa", @@ -46,7 +46,7 @@ assert | |; assert | - embedded_default_params.env == "qa"; + embedded_default_params.env_name == "qa"; |; let embedded_with_params = embedded_mod{deep_value = "Some"}; diff --git a/src/build/mod.rs b/src/build/mod.rs index 83aeac8..8be105b 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -303,8 +303,27 @@ impl<'a> Builder<'a> { } } + fn check_reserved_word(name: &str) -> bool { + match name { + "self" | "assert" | "true" | "false" | "let" | "import" | "as" | "select" | "macro" + | "module" | "env" | "map" | "filter" | "NULL" | "out" => true, + _ => false, + } + } + fn build_import(&mut self, def: &ImportDef) -> Result, Box> { let sym = &def.name; + // TODO(jwall): Enforce reserved word restriction here. + if Self::check_reserved_word(&sym.fragment) { + return Err(Box::new(error::BuildError::new( + format!( + "Import {} binding collides with reserved word", + sym.fragment + ), + error::ErrorType::ReservedWordError, + sym.pos.clone(), + ))); + } let mut normalized = self.file.clone(); let import_path = PathBuf::from(&def.path.fragment); if import_path.is_relative() { @@ -344,6 +363,14 @@ impl<'a> Builder<'a> { fn build_let(&mut self, def: &LetDef) -> Result, Box> { let val = try!(self.eval_expr(&def.value)); let name = &def.name; + // TODO(jwall): Enforce the reserved words list here. + if Self::check_reserved_word(&name.fragment) { + return Err(Box::new(error::BuildError::new( + format!("Let {} binding collides with reserved word", name.fragment), + error::ErrorType::ReservedWordError, + name.pos.clone(), + ))); + } match self.build_output.entry(name.into()) { Entry::Occupied(e) => { return Err(Box::new(error::BuildError::new( diff --git a/src/error.rs b/src/error.rs index 8e06d7e..9198135 100644 --- a/src/error.rs +++ b/src/error.rs @@ -31,6 +31,7 @@ pub enum ErrorType { NoSuchSymbol, BadArgLen, FormatError, + ReservedWordError, // Parsing Errors ParseError, AssertError, @@ -45,6 +46,7 @@ impl fmt::Display for ErrorType { &ErrorType::NoSuchSymbol => "NoSuchSymbol", &ErrorType::BadArgLen => "BadArgLen", &ErrorType::FormatError => "FormatError", + &ErrorType::ReservedWordError => "ReservedWordError", &ErrorType::ParseError => "ParseError", &ErrorType::AssertError => "AssertError", };