From f6a6a3ac32bb80481bfcb857eaef5f8ac6da7bd9 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Tue, 20 Aug 2019 21:30:17 -0500 Subject: [PATCH] DEV: Reserved word enforcement for bindings. --- src/build/opcode/scope.rs | 2 +- src/build/opcode/translate.rs | 17 +++++++++-------- src/build/opcode/vm.rs | 30 ++++++++++++++++++++++++++---- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/build/opcode/scope.rs b/src/build/opcode/scope.rs index 5b83f67..58b8a47 100644 --- a/src/build/opcode/scope.rs +++ b/src/build/opcode/scope.rs @@ -14,8 +14,8 @@ use std::collections::BTreeMap; use std::rc::Rc; -use crate::ast::Position; use super::Value; +use crate::ast::Position; #[derive(Clone, PartialEq, Debug)] pub struct Stack { diff --git a/src/build/opcode/translate.rs b/src/build/opcode/translate.rs index 05d13eb..3c96839 100644 --- a/src/build/opcode/translate.rs +++ b/src/build/opcode/translate.rs @@ -13,7 +13,7 @@ // limitations under the License. use std::path::Path; -use crate::ast::{Token, BinaryExprType, Expression, FormatArgs, Position, Statement, Value}; +use crate::ast::{BinaryExprType, Expression, FormatArgs, Position, Statement, Token, Value}; use crate::ast::{FuncOpDef, TemplatePart}; use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser}; use crate::build::opcode::Primitive; @@ -212,9 +212,7 @@ impl AST { Value::Int(sym) => { ops.push(Op::Val(Primitive::Int(sym.val)), sym.pos); } - _ => { - unreachable!() - } + _ => unreachable!(), } ops.push(Op::Index, copy_def.pos.clone()); Self::translate_copy(ops, copy_def.fields, copy_def.pos, root); @@ -234,9 +232,7 @@ impl AST { Value::Int(sym) => { ops.push(Op::Val(Primitive::Int(sym.val)), sym.pos); } - _ => { - unreachable!() - } + _ => unreachable!(), } ops.push(Op::FCall, func_pos); return; @@ -529,7 +525,12 @@ impl AST { } } - fn translate_copy(mut ops: &mut PositionMap, flds: Vec<(Token, Expression)>, pos: Position, root: &Path) { + fn translate_copy( + mut ops: &mut PositionMap, + flds: Vec<(Token, Expression)>, + pos: Position, + root: &Path, + ) { ops.push(Op::PushSelf, pos.clone()); ops.push(Op::InitTuple, pos.clone()); for (t, e) in flds { diff --git a/src/build/opcode/vm.rs b/src/build/opcode/vm.rs index 37fcfd0..13d0be4 100644 --- a/src/build/opcode/vm.rs +++ b/src/build/opcode/vm.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. use std::cell::RefCell; +use std::collections::BTreeSet; use std::rc::Rc; use crate::ast::Position; @@ -28,6 +29,17 @@ use super::Value::{C, F, M, P, S, T}; use super::{Error, Op, Primitive, Value}; use super::{Func, Module}; +fn construct_reserved_word_set() -> BTreeSet<&'static str> { + let mut words = BTreeSet::new(); + for word in vec![ + "let", "module", "func", "out", "assert", "self", "import", "include", "as", "map", + "filter", "convert", "fail", "NULL", "in", "is", "TRACE", + ] { + words.insert(word); + } + words +} + pub struct VM where O: std::io::Write, @@ -40,6 +52,7 @@ where pub env: Rc>>, pub last: Option<(Rc, Position)>, self_stack: Vec<(Rc, Position)>, + reserved_words: BTreeSet<&'static str>, } impl<'a, O, E> VM @@ -60,6 +73,7 @@ where env: env, last: None, self_stack: Vec::new(), + reserved_words: construct_reserved_word_set(), } } @@ -72,6 +86,7 @@ where env: self.env.clone(), last: self.last, self_stack: self.self_stack, + reserved_words: self.reserved_words, } } @@ -389,7 +404,7 @@ where // TODO(jwall): This should do a better error if there is // nothing on the stack. let (val, pos) = stack.pop().unwrap(); - vm.binding_push(nm.clone(), val, false, &pos)?; + vm.binding_push(nm.clone(), val, false, &pos, &pos)?; } // proceed to the function body vm.run()?; @@ -597,9 +612,10 @@ where // pop val off stack. let (val, val_pos) = self.pop()?; // pop name off stack. - let (name, _) = self.pop()?; + let (name, name_pos) = self.pop()?; + // TODO(jwall): We need to restrict against our reserved word list. if let &S(ref name) = name.as_ref() { - self.binding_push(name.clone(), val, strict, &val_pos)?; + self.binding_push(name.clone(), val, strict, &val_pos, &name_pos)?; } else { unreachable!(); } @@ -785,7 +801,14 @@ where val: Rc, strict: bool, pos: &Position, + name_pos: &Position, ) -> Result<(), Error> { + if self.reserved_words.contains(name.as_str()) { + return Err(dbg!(Error::new( + format!("{} is a reserved word.", name), + name_pos.clone(), + ))); + } if self.symbols.is_bound(&name) && strict { return Err(dbg!(Error::new( format!("Binding {} already exists", name), @@ -813,7 +836,6 @@ where match self.symbols.get(name) { Some((ref v, ref pos)) => Ok((v.clone(), pos.clone())), None => { - // TODO(jwall): Look in the last item? return Err(dbg!(Error::new( format!("No such binding {}", name), pos.clone()