From a36322461e249107ff3d971f346000fde1a06a76 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Thu, 1 Aug 2019 19:04:58 -0500 Subject: [PATCH] DEV: And and Or operators work --- src/build/opcode/mod.rs | 5 +- src/build/opcode/pointer.rs | 2 +- src/build/opcode/runtime.rs | 38 ++++++++-------- src/build/opcode/test.rs | 12 ++++- src/build/opcode/translate.rs | 52 +++++++++++++++++---- src/build/opcode/vm.rs | 86 +++++++++++++++++++++++------------ 6 files changed, 133 insertions(+), 62 deletions(-) diff --git a/src/build/opcode/mod.rs b/src/build/opcode/mod.rs index b925f9e..31858b3 100644 --- a/src/build/opcode/mod.rs +++ b/src/build/opcode/mod.rs @@ -130,9 +130,8 @@ pub enum Op { JumpIfTrue(i32), JumpIfFalse(i32), SelectJump(i32), - // FIXME(jwall): Short circuiting operations - // - And(usize) - // - Or(usize) + And(i32), + Or(i32), // Spacer operation, Does nothing. Index, // indexing operation Noop, diff --git a/src/build/opcode/pointer.rs b/src/build/opcode/pointer.rs index f6f6683..79abb90 100644 --- a/src/build/opcode/pointer.rs +++ b/src/build/opcode/pointer.rs @@ -49,7 +49,7 @@ impl OpPointer { self.ptr = Some(ptr); return Ok(()); } - Err(Error {}) + Err(dbg!(Error {})) } pub fn op(&self) -> Option<&Op> { diff --git a/src/build/opcode/runtime.rs b/src/build/opcode/runtime.rs index e55cc16..42b8507 100644 --- a/src/build/opcode/runtime.rs +++ b/src/build/opcode/runtime.rs @@ -145,7 +145,7 @@ impl Builtins { return Ok(()); } } - return Err(Error {}); + return Err(dbg!(Error {})); } fn include(&self, stack: &mut Vec>) -> Result<(), Error> { @@ -156,19 +156,19 @@ impl Builtins { if let &Value::P(Str(ref path)) = val.as_ref() { path.clone() } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error {})); } } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error {})); }; let typ = if let Some(val) = typ.as_ref() { if let &Value::P(Str(ref typ)) = val.as_ref() { typ.clone() } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error {})); } } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error {})); }; if typ == "str" { stack.push(Rc::new(P(Str(self.get_file_as_string(&path)?)))); @@ -182,14 +182,14 @@ impl Builtins { } else { match importer.import(contents.as_bytes()) { Ok(v) => v.try_into()?, - Err(_e) => return dbg!(Err(Error {})), + Err(_e) => return Err(dbg!(Error {})), } } } - None => return dbg!(Err(Error {})), + None => return Err(dbg!(Error {})), })); } - return Err(Error {}); + return Err(dbg!(Error {})); } fn assert(&mut self, stack: &mut Vec>) -> Result<(), Error> { @@ -237,14 +237,14 @@ impl Builtins { Ok(_) => { // noop } - Err(_e) => return Err(Error {}), + Err(_e) => return Err(dbg!(Error {})), } return Ok(()); } } } } - return Err(Error {}); + return Err(dbg!(Error {})); } fn convert(&self, stack: &mut Vec>) -> Result<(), Error> { @@ -262,14 +262,14 @@ impl Builtins { String::from_utf8_lossy(buf.as_slice()).to_string() )))); } - Err(_e) => return Err(Error {}), + Err(_e) => return Err(dbg!(Error {})), } return Ok(()); } } } } - return Err(Error {}); + return Err(dbg!(Error {})); } fn map>(&self, path: P, stack: &mut Vec>) -> Result<(), Error> { @@ -277,25 +277,25 @@ impl Builtins { let list = if let Some(list) = stack.pop() { list } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error {})); }; let elems = if let &C(List(ref elems)) = list.as_ref() { elems } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error {})); }; // get the func ptr from the stack let fptr = if let Some(ptr) = stack.pop() { ptr } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error {})); }; let f = if let &F(ref f) = fptr.as_ref() { f } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error {})); }; let mut result_elems = Vec::new(); @@ -314,19 +314,19 @@ impl Builtins { let list = if let Some(list) = stack.pop() { list } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error {})); }; let elems = if let &C(List(ref elems)) = list.as_ref() { elems } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error {})); }; // get the func ptr from the stack let fptr = if let Some(ptr) = stack.pop() { ptr } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error {})); }; let f = if let &F(ref f) = fptr.as_ref() { diff --git a/src/build/opcode/test.rs b/src/build/opcode/test.rs index 93fd9b7..1c528ea 100644 --- a/src/build/opcode/test.rs +++ b/src/build/opcode/test.rs @@ -551,7 +551,7 @@ use crate::parse::parse; macro_rules! assert_parse_cases { (__impl__ $cases:expr) => { for case in $cases.drain(0..) { - let stmts = parse(OffsetStrIter::from(case.0), None).unwrap(); + let stmts = parse(OffsetStrIter::from(dbg!(case.0)), None).unwrap(); let ops = Rc::new(translate::AST::translate(stmts)); assert!(ops.len() > 0); let mut vm = VM::new("foo.ucg", ops.clone()); @@ -597,8 +597,16 @@ fn simple_binary_expr() { "2<1;" => P(Bool(false)), "1!=1;" => P(Bool(false)), "\"foo\" ~ \"bar\";" => P(Bool(false)), + "\"foo\" !~ \"bar\";" => P(Bool(true)), "\"foo\" is \"str\";" => P(Bool(true)), - //"true && false;" => P(Bool(false)), + "true && true;" => P(Bool(true)), + "true && false;" => P(Bool(false)), + "false && false;" => P(Bool(false)), + "false && true;" => P(Bool(false)), + "false || false;" => P(Bool(false)), + "true || false;" => P(Bool(true)), + "false || true;" => P(Bool(true)), + "true || true;" => P(Bool(true)), ) } diff --git a/src/build/opcode/translate.rs b/src/build/opcode/translate.rs index 44c6679..ea6a878 100644 --- a/src/build/opcode/translate.rs +++ b/src/build/opcode/translate.rs @@ -40,33 +40,45 @@ impl AST { } fn translate_expr(expr: Expression, mut ops: &mut Vec) { - match dbg!(expr) { + match expr { Expression::Simple(v) => { Self::translate_value(v, &mut ops); } Expression::Binary(def) => { - Self::translate_expr(*def.right, &mut ops); - Self::translate_expr(*def.left, &mut ops); match def.kind { BinaryExprType::Add => { + Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.left, &mut ops); ops.push(Op::Add); } BinaryExprType::Sub => { + Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.left, &mut ops); ops.push(Op::Sub); } BinaryExprType::Div => { + Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.left, &mut ops); ops.push(Op::Div); } BinaryExprType::Mul => { + Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.left, &mut ops); ops.push(Op::Mul); } BinaryExprType::Equal => { + Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.left, &mut ops); ops.push(Op::Equal); } BinaryExprType::GT => { + Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.left, &mut ops); ops.push(Op::Gt); } BinaryExprType::LT => { + Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.left, &mut ops); ops.push(Op::Lt); } BinaryExprType::GTEqual => { @@ -79,25 +91,47 @@ impl AST { unimplemented!("Binary expressions are not implmented yet") } BinaryExprType::NotEqual => { + Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.left, &mut ops); ops.push(Op::Equal); ops.push(Op::Not); } BinaryExprType::REMatch => { + Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.left, &mut ops); ops.push(Op::Runtime(Hook::Regex)); } BinaryExprType::NotREMatch => { + Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.left, &mut ops); ops.push(Op::Runtime(Hook::Regex)); ops.push(Op::Not); } BinaryExprType::IS => { + Self::translate_expr(*def.right, &mut ops); + Self::translate_expr(*def.left, &mut ops); ops.push(Op::Typ); ops.push(Op::Equal); } - BinaryExprType::IN - | BinaryExprType::Mod - | BinaryExprType::OR - | BinaryExprType::AND - | BinaryExprType::DOT => { + BinaryExprType::AND => { + Self::translate_expr(*def.left, &mut ops); + ops.push(Op::Noop); + let idx = ops.len() - 1; + Self::translate_expr(*def.right, &mut ops); + let jptr = (ops.len() - 1 - idx) as i32; + ops[idx] = Op::And(dbg!(jptr)); + dbg!(ops); + } + BinaryExprType::OR => { + // FIXME(jwall): This needs to be handled very differently + Self::translate_expr(*def.left, &mut ops); + ops.push(Op::Noop); // Placeholder used for + let idx = ops.len() - 1; + Self::translate_expr(*def.right, &mut ops); + let jptr = (ops.len() - 1 - idx) as i32; + ops[idx] = Op::Or(jptr); + } + BinaryExprType::IN | BinaryExprType::Mod | BinaryExprType::DOT => { unimplemented!("Binary expressions are not implmented yet") // TODO } @@ -126,7 +160,7 @@ impl AST { } fn translate_value(value: Value, ops: &mut Vec) { - match dbg!(value) { + match value { Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val))), Value::Float(f) => ops.push(Op::Val(Primitive::Float(f.val))), Value::Str(s) => ops.push(Op::Val(Primitive::Str(s.val))), diff --git a/src/build/opcode/vm.rs b/src/build/opcode/vm.rs index fe9b09c..9867f39 100644 --- a/src/build/opcode/vm.rs +++ b/src/build/opcode/vm.rs @@ -72,15 +72,15 @@ impl<'a> VM { pub fn run(&mut self) -> Result<(), Error> { loop { - let op = if let Some(op) = dbg!(self.ops.next()) { + let op = if let Some(op) = self.ops.next() { op.clone() } else { break; }; let idx = self.ops.idx()?; match op { - Op::Val(p) => self.push(Rc::new(dbg!(P(p.clone()))))?, - Op::Sym(s) => self.push(Rc::new(dbg!(S(s.clone()))))?, + Op::Val(p) => self.push(Rc::new(P(p.clone())))?, + Op::Sym(s) => self.push(Rc::new(S(s.clone())))?, Op::DeRef(s) => self.op_deref(s.clone())?, Op::Add => self.op_add()?, Op::Sub => self.op_sub()?, @@ -111,6 +111,8 @@ impl<'a> VM { Op::JumpIfTrue(jp) => self.op_jump_if_true(jp)?, Op::JumpIfFalse(jp) => self.op_jump_if_false(jp)?, Op::SelectJump(jp) => self.op_select_jump(jp)?, + Op::And(jp) => self.op_and(jp)?, + Op::Or(jp) => self.op_or(jp)?, Op::Module(mptr) => self.op_module(idx, mptr)?, Op::Func(jptr) => self.op_func(idx, jptr)?, Op::FCall => self.op_fcall()?, @@ -126,7 +128,7 @@ impl<'a> VM { } fn op_typ(&mut self) -> Result<(), Error> { - let val = dbg!(self.pop())?; + let val = self.pop()?; let typ_name = match val.as_ref() { P(Int(_)) => "int", P(Float(_)) => "float", @@ -147,7 +149,7 @@ impl<'a> VM { } fn op_deref(&mut self, name: String) -> Result<(), Error> { - let val = dbg!(self.get_binding(&name)?.clone()); + let val = self.get_binding(&name)?.clone(); self.push(val) } @@ -161,12 +163,40 @@ impl<'a> VM { Ok(()) } + fn op_and(&mut self, jp: i32) -> Result<(), Error> { + let cond = self.pop()?; + let cc = cond.clone(); + if let &P(Bool(cond)) = cond.as_ref() { + if !cond { + self.push(cc)?; + self.op_jump(jp)?; + } + } else { + return Err(dbg!(Error {})); + } + Ok(()) + } + + fn op_or(&mut self, jp: i32) -> Result<(), Error> { + let cond = self.pop()?; + let cc = cond.clone(); + if let &P(Bool(cond)) = cond.as_ref() { + if cond { + self.push(cc)?; + self.op_jump(jp)?; + } + } + Ok(()) + } + fn op_jump_if_true(&mut self, jp: i32) -> Result<(), Error> { let cond = self.pop()?; if let &P(Bool(cond)) = cond.as_ref() { if cond { self.op_jump(jp)?; } + } else { + return Err(dbg!(Error {})); } Ok(()) } @@ -175,7 +205,7 @@ impl<'a> VM { let cond = self.pop()?; if let &P(Bool(cond)) = cond.as_ref() { if !cond { - self.op_jump(jp)?; + self.op_jump(dbg!(jp))?; } } Ok(()) @@ -318,7 +348,7 @@ impl<'a> VM { (&P(Float(f)), &P(Float(ff))) => { self.push(Rc::new(P(Bool(f > ff))))?; } - _ => return Err(Error {}), + _ => return Err(dbg!(Error {})), } Ok(()) } @@ -333,7 +363,7 @@ impl<'a> VM { (&P(Float(f)), &P(Float(ff))) => { self.push(Rc::new(P(Bool(f < ff))))?; } - _ => return Err(Error {}), + _ => return Err(dbg!(Error {})), } Ok(()) } @@ -348,7 +378,7 @@ impl<'a> VM { (&P(Float(f)), &P(Float(ff))) => { self.push(Rc::new(P(Bool(f <= ff))))?; } - _ => return Err(Error {}), + _ => return Err(dbg!(Error {})), } Ok(()) } @@ -363,7 +393,7 @@ impl<'a> VM { (&P(Float(f)), &P(Float(ff))) => { self.push(Rc::new(P(Bool(f >= ff))))?; } - _ => return Err(Error {}), + _ => return Err(dbg!(Error {})), } Ok(()) } @@ -412,7 +442,7 @@ impl<'a> VM { if let &S(ref name) = name.as_ref() { self.binding_push(name.clone(), val)?; } else { - return Err(Error {}); + return Err(dbg!(Error {})); } Ok(()) } @@ -426,7 +456,7 @@ impl<'a> VM { let name = if let &S(ref s) | &P(Str(ref s)) = name_val.as_ref() { s } else { - return Err(Error {}); + return Err(dbg!(Error {})); }; // get composite tuple from stack let tpl = self.pop()?; @@ -439,7 +469,7 @@ impl<'a> VM { // place composite tuple back on stack self.push(Rc::new(C(Tuple(flds))))?; } else { - return Err(Error {}); + return Err(dbg!(Error {})); }; Ok(()) } @@ -458,7 +488,7 @@ impl<'a> VM { // Add that value to the list and put list back on stack. self.push(Rc::new(C(List(elems))))?; } else { - return Err(Error {}); + return Err(dbg!(Error {})); }; Ok(()) } @@ -470,7 +500,7 @@ impl<'a> VM { }; match elems.get(idx as usize) { Some(v) => Ok(v.clone()), - None => Err(Error {}), + None => Err(dbg!(Error {})), } } @@ -489,14 +519,14 @@ impl<'a> VM { return Ok(f.1.clone()); } } - Err(Error {}) + Err(dbg!(Error {})) } fn find_in_value(&self, index: &Value, target: &Value) -> Result, Error> { match target { C(Tuple(flds)) => self.find_in_flds(index, flds), C(List(elements)) => self.find_in_list(index, elements), - _ => return Err(Error {}), + _ => return Err(dbg!(Error {})), } } @@ -505,11 +535,11 @@ impl<'a> VM { let path = if let &C(List(ref elems)) = path_val.as_ref() { elems.clone() } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error {})); }; let target_val = self.pop()?; match target_val.as_ref() { - &P(_) | &S(_) | &T(_) | &F(_) | &M(_) => return dbg!(Err(Error {})), + &P(_) | &S(_) | &T(_) | &F(_) | &M(_) => return Err(dbg!(Error {})), _ => { let mut out = target_val.clone(); for p in path { @@ -531,7 +561,7 @@ impl<'a> VM { let overrides = if let &C(Tuple(ref oflds)) = override_val.as_ref() { oflds.clone() } else { - return dbg!(Err(Error {})); + return Err(dbg!(Error {})); }; match tgt.as_ref() { &C(Tuple(ref flds)) => { @@ -571,7 +601,7 @@ impl<'a> VM { } } _ => { - return Err(Error {}); + return Err(dbg!(Error {})); } } Ok(()) @@ -600,7 +630,7 @@ impl<'a> VM { pub fn binding_push(&mut self, name: String, val: Rc) -> Result<(), Error> { if self.symbols.is_bound(&name) { - return Err(Error {}); + return Err(dbg!(Error {})); } self.symbols.add(name, val); Ok(()) @@ -609,14 +639,14 @@ impl<'a> VM { pub fn get_binding(&'a self, name: &str) -> Result, Error> { match self.symbols.get(name) { Some(v) => Ok(v), - None => Err(Error {}), + None => Err(dbg!(Error {})), } } pub fn pop(&mut self) -> Result, Error> { match self.stack.pop() { Some(v) => Ok(v), - None => Err(Error {}), + None => Err(dbg!(Error {})), } } @@ -624,7 +654,7 @@ impl<'a> VM { Ok(match (left, right) { (P(Int(i)), P(Int(ii))) => Int(i * ii), (P(Float(f)), P(Float(ff))) => Float(f * ff), - _ => return Err(Error {}), + _ => return Err(dbg!(Error {})), }) } @@ -632,7 +662,7 @@ impl<'a> VM { Ok(match (left, right) { (P(Int(i)), P(Int(ii))) => Int(i / ii), (P(Float(f)), P(Float(ff))) => Float(f / ff), - _ => return Err(Error {}), + _ => return Err(dbg!(Error {})), }) } @@ -640,7 +670,7 @@ impl<'a> VM { Ok(match (left, right) { (P(Int(i)), Value::P(Int(ii))) => Int(i - ii), (P(Float(f)), Value::P(Float(ff))) => Float(f - ff), - _ => return Err(Error {}), + _ => return Err(dbg!(Error {})), }) } @@ -654,7 +684,7 @@ impl<'a> VM { ns.push_str(&ss); Str(ns) } - _ => return Err(Error {}), + _ => return Err(dbg!(Error {})), }) }