DEV: And and Or operators work

This commit is contained in:
Jeremy Wall 2019-08-01 19:04:58 -05:00
parent 48ea8b30ef
commit a36322461e
6 changed files with 133 additions and 62 deletions

View File

@ -130,9 +130,8 @@ pub enum Op {
JumpIfTrue(i32), JumpIfTrue(i32),
JumpIfFalse(i32), JumpIfFalse(i32),
SelectJump(i32), SelectJump(i32),
// FIXME(jwall): Short circuiting operations And(i32),
// - And(usize) Or(i32),
// - Or(usize)
// Spacer operation, Does nothing. // Spacer operation, Does nothing.
Index, // indexing operation Index, // indexing operation
Noop, Noop,

View File

@ -49,7 +49,7 @@ impl OpPointer {
self.ptr = Some(ptr); self.ptr = Some(ptr);
return Ok(()); return Ok(());
} }
Err(Error {}) Err(dbg!(Error {}))
} }
pub fn op(&self) -> Option<&Op> { pub fn op(&self) -> Option<&Op> {

View File

@ -145,7 +145,7 @@ impl Builtins {
return Ok(()); return Ok(());
} }
} }
return Err(Error {}); return Err(dbg!(Error {}));
} }
fn include(&self, stack: &mut Vec<Rc<Value>>) -> Result<(), Error> { fn include(&self, stack: &mut Vec<Rc<Value>>) -> Result<(), Error> {
@ -156,19 +156,19 @@ impl Builtins {
if let &Value::P(Str(ref path)) = val.as_ref() { if let &Value::P(Str(ref path)) = val.as_ref() {
path.clone() path.clone()
} else { } else {
return dbg!(Err(Error {})); return Err(dbg!(Error {}));
} }
} else { } else {
return dbg!(Err(Error {})); return Err(dbg!(Error {}));
}; };
let typ = if let Some(val) = typ.as_ref() { let typ = if let Some(val) = typ.as_ref() {
if let &Value::P(Str(ref typ)) = val.as_ref() { if let &Value::P(Str(ref typ)) = val.as_ref() {
typ.clone() typ.clone()
} else { } else {
return dbg!(Err(Error {})); return Err(dbg!(Error {}));
} }
} else { } else {
return dbg!(Err(Error {})); return Err(dbg!(Error {}));
}; };
if typ == "str" { if typ == "str" {
stack.push(Rc::new(P(Str(self.get_file_as_string(&path)?)))); stack.push(Rc::new(P(Str(self.get_file_as_string(&path)?))));
@ -182,14 +182,14 @@ impl Builtins {
} else { } else {
match importer.import(contents.as_bytes()) { match importer.import(contents.as_bytes()) {
Ok(v) => v.try_into()?, 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<Rc<Value>>) -> Result<(), Error> { fn assert(&mut self, stack: &mut Vec<Rc<Value>>) -> Result<(), Error> {
@ -237,14 +237,14 @@ impl Builtins {
Ok(_) => { Ok(_) => {
// noop // noop
} }
Err(_e) => return Err(Error {}), Err(_e) => return Err(dbg!(Error {})),
} }
return Ok(()); return Ok(());
} }
} }
} }
} }
return Err(Error {}); return Err(dbg!(Error {}));
} }
fn convert(&self, stack: &mut Vec<Rc<Value>>) -> Result<(), Error> { fn convert(&self, stack: &mut Vec<Rc<Value>>) -> Result<(), Error> {
@ -262,14 +262,14 @@ impl Builtins {
String::from_utf8_lossy(buf.as_slice()).to_string() String::from_utf8_lossy(buf.as_slice()).to_string()
)))); ))));
} }
Err(_e) => return Err(Error {}), Err(_e) => return Err(dbg!(Error {})),
} }
return Ok(()); return Ok(());
} }
} }
} }
} }
return Err(Error {}); return Err(dbg!(Error {}));
} }
fn map<P: AsRef<Path>>(&self, path: P, stack: &mut Vec<Rc<Value>>) -> Result<(), Error> { fn map<P: AsRef<Path>>(&self, path: P, stack: &mut Vec<Rc<Value>>) -> Result<(), Error> {
@ -277,25 +277,25 @@ impl Builtins {
let list = if let Some(list) = stack.pop() { let list = if let Some(list) = stack.pop() {
list list
} else { } else {
return dbg!(Err(Error {})); return Err(dbg!(Error {}));
}; };
let elems = if let &C(List(ref elems)) = list.as_ref() { let elems = if let &C(List(ref elems)) = list.as_ref() {
elems elems
} else { } else {
return dbg!(Err(Error {})); return Err(dbg!(Error {}));
}; };
// get the func ptr from the stack // get the func ptr from the stack
let fptr = if let Some(ptr) = stack.pop() { let fptr = if let Some(ptr) = stack.pop() {
ptr ptr
} else { } else {
return dbg!(Err(Error {})); return Err(dbg!(Error {}));
}; };
let f = if let &F(ref f) = fptr.as_ref() { let f = if let &F(ref f) = fptr.as_ref() {
f f
} else { } else {
return dbg!(Err(Error {})); return Err(dbg!(Error {}));
}; };
let mut result_elems = Vec::new(); let mut result_elems = Vec::new();
@ -314,19 +314,19 @@ impl Builtins {
let list = if let Some(list) = stack.pop() { let list = if let Some(list) = stack.pop() {
list list
} else { } else {
return dbg!(Err(Error {})); return Err(dbg!(Error {}));
}; };
let elems = if let &C(List(ref elems)) = list.as_ref() { let elems = if let &C(List(ref elems)) = list.as_ref() {
elems elems
} else { } else {
return dbg!(Err(Error {})); return Err(dbg!(Error {}));
}; };
// get the func ptr from the stack // get the func ptr from the stack
let fptr = if let Some(ptr) = stack.pop() { let fptr = if let Some(ptr) = stack.pop() {
ptr ptr
} else { } else {
return dbg!(Err(Error {})); return Err(dbg!(Error {}));
}; };
let f = if let &F(ref f) = fptr.as_ref() { let f = if let &F(ref f) = fptr.as_ref() {

View File

@ -551,7 +551,7 @@ use crate::parse::parse;
macro_rules! assert_parse_cases { macro_rules! assert_parse_cases {
(__impl__ $cases:expr) => { (__impl__ $cases:expr) => {
for case in $cases.drain(0..) { 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)); let ops = Rc::new(translate::AST::translate(stmts));
assert!(ops.len() > 0); assert!(ops.len() > 0);
let mut vm = VM::new("foo.ucg", ops.clone()); let mut vm = VM::new("foo.ucg", ops.clone());
@ -597,8 +597,16 @@ fn simple_binary_expr() {
"2<1;" => P(Bool(false)), "2<1;" => P(Bool(false)),
"1!=1;" => P(Bool(false)), "1!=1;" => P(Bool(false)),
"\"foo\" ~ \"bar\";" => P(Bool(false)), "\"foo\" ~ \"bar\";" => P(Bool(false)),
"\"foo\" !~ \"bar\";" => P(Bool(true)),
"\"foo\" is \"str\";" => 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)),
) )
} }

View File

@ -40,33 +40,45 @@ impl AST {
} }
fn translate_expr(expr: Expression, mut ops: &mut Vec<Op>) { fn translate_expr(expr: Expression, mut ops: &mut Vec<Op>) {
match dbg!(expr) { match expr {
Expression::Simple(v) => { Expression::Simple(v) => {
Self::translate_value(v, &mut ops); Self::translate_value(v, &mut ops);
} }
Expression::Binary(def) => { Expression::Binary(def) => {
Self::translate_expr(*def.right, &mut ops);
Self::translate_expr(*def.left, &mut ops);
match def.kind { match def.kind {
BinaryExprType::Add => { BinaryExprType::Add => {
Self::translate_expr(*def.right, &mut ops);
Self::translate_expr(*def.left, &mut ops);
ops.push(Op::Add); ops.push(Op::Add);
} }
BinaryExprType::Sub => { BinaryExprType::Sub => {
Self::translate_expr(*def.right, &mut ops);
Self::translate_expr(*def.left, &mut ops);
ops.push(Op::Sub); ops.push(Op::Sub);
} }
BinaryExprType::Div => { BinaryExprType::Div => {
Self::translate_expr(*def.right, &mut ops);
Self::translate_expr(*def.left, &mut ops);
ops.push(Op::Div); ops.push(Op::Div);
} }
BinaryExprType::Mul => { BinaryExprType::Mul => {
Self::translate_expr(*def.right, &mut ops);
Self::translate_expr(*def.left, &mut ops);
ops.push(Op::Mul); ops.push(Op::Mul);
} }
BinaryExprType::Equal => { BinaryExprType::Equal => {
Self::translate_expr(*def.right, &mut ops);
Self::translate_expr(*def.left, &mut ops);
ops.push(Op::Equal); ops.push(Op::Equal);
} }
BinaryExprType::GT => { BinaryExprType::GT => {
Self::translate_expr(*def.right, &mut ops);
Self::translate_expr(*def.left, &mut ops);
ops.push(Op::Gt); ops.push(Op::Gt);
} }
BinaryExprType::LT => { BinaryExprType::LT => {
Self::translate_expr(*def.right, &mut ops);
Self::translate_expr(*def.left, &mut ops);
ops.push(Op::Lt); ops.push(Op::Lt);
} }
BinaryExprType::GTEqual => { BinaryExprType::GTEqual => {
@ -79,25 +91,47 @@ impl AST {
unimplemented!("Binary expressions are not implmented yet") unimplemented!("Binary expressions are not implmented yet")
} }
BinaryExprType::NotEqual => { BinaryExprType::NotEqual => {
Self::translate_expr(*def.right, &mut ops);
Self::translate_expr(*def.left, &mut ops);
ops.push(Op::Equal); ops.push(Op::Equal);
ops.push(Op::Not); ops.push(Op::Not);
} }
BinaryExprType::REMatch => { BinaryExprType::REMatch => {
Self::translate_expr(*def.right, &mut ops);
Self::translate_expr(*def.left, &mut ops);
ops.push(Op::Runtime(Hook::Regex)); ops.push(Op::Runtime(Hook::Regex));
} }
BinaryExprType::NotREMatch => { 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::Runtime(Hook::Regex));
ops.push(Op::Not); ops.push(Op::Not);
} }
BinaryExprType::IS => { BinaryExprType::IS => {
Self::translate_expr(*def.right, &mut ops);
Self::translate_expr(*def.left, &mut ops);
ops.push(Op::Typ); ops.push(Op::Typ);
ops.push(Op::Equal); ops.push(Op::Equal);
} }
BinaryExprType::IN BinaryExprType::AND => {
| BinaryExprType::Mod Self::translate_expr(*def.left, &mut ops);
| BinaryExprType::OR ops.push(Op::Noop);
| BinaryExprType::AND let idx = ops.len() - 1;
| BinaryExprType::DOT => { 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") unimplemented!("Binary expressions are not implmented yet")
// TODO // TODO
} }
@ -126,7 +160,7 @@ impl AST {
} }
fn translate_value(value: Value, ops: &mut Vec<Op>) { fn translate_value(value: Value, ops: &mut Vec<Op>) {
match dbg!(value) { match value {
Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val))), Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val))),
Value::Float(f) => ops.push(Op::Val(Primitive::Float(f.val))), Value::Float(f) => ops.push(Op::Val(Primitive::Float(f.val))),
Value::Str(s) => ops.push(Op::Val(Primitive::Str(s.val))), Value::Str(s) => ops.push(Op::Val(Primitive::Str(s.val))),

View File

@ -72,15 +72,15 @@ impl<'a> VM {
pub fn run(&mut self) -> Result<(), Error> { pub fn run(&mut self) -> Result<(), Error> {
loop { loop {
let op = if let Some(op) = dbg!(self.ops.next()) { let op = if let Some(op) = self.ops.next() {
op.clone() op.clone()
} else { } else {
break; break;
}; };
let idx = self.ops.idx()?; let idx = self.ops.idx()?;
match op { match op {
Op::Val(p) => self.push(Rc::new(dbg!(P(p.clone()))))?, Op::Val(p) => self.push(Rc::new(P(p.clone())))?,
Op::Sym(s) => self.push(Rc::new(dbg!(S(s.clone()))))?, Op::Sym(s) => self.push(Rc::new(S(s.clone())))?,
Op::DeRef(s) => self.op_deref(s.clone())?, Op::DeRef(s) => self.op_deref(s.clone())?,
Op::Add => self.op_add()?, Op::Add => self.op_add()?,
Op::Sub => self.op_sub()?, Op::Sub => self.op_sub()?,
@ -111,6 +111,8 @@ impl<'a> VM {
Op::JumpIfTrue(jp) => self.op_jump_if_true(jp)?, Op::JumpIfTrue(jp) => self.op_jump_if_true(jp)?,
Op::JumpIfFalse(jp) => self.op_jump_if_false(jp)?, Op::JumpIfFalse(jp) => self.op_jump_if_false(jp)?,
Op::SelectJump(jp) => self.op_select_jump(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::Module(mptr) => self.op_module(idx, mptr)?,
Op::Func(jptr) => self.op_func(idx, jptr)?, Op::Func(jptr) => self.op_func(idx, jptr)?,
Op::FCall => self.op_fcall()?, Op::FCall => self.op_fcall()?,
@ -126,7 +128,7 @@ impl<'a> VM {
} }
fn op_typ(&mut self) -> Result<(), Error> { fn op_typ(&mut self) -> Result<(), Error> {
let val = dbg!(self.pop())?; let val = self.pop()?;
let typ_name = match val.as_ref() { let typ_name = match val.as_ref() {
P(Int(_)) => "int", P(Int(_)) => "int",
P(Float(_)) => "float", P(Float(_)) => "float",
@ -147,7 +149,7 @@ impl<'a> VM {
} }
fn op_deref(&mut self, name: String) -> Result<(), Error> { 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) self.push(val)
} }
@ -161,12 +163,40 @@ impl<'a> VM {
Ok(()) 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> { fn op_jump_if_true(&mut self, jp: i32) -> Result<(), Error> {
let cond = self.pop()?; let cond = self.pop()?;
if let &P(Bool(cond)) = cond.as_ref() { if let &P(Bool(cond)) = cond.as_ref() {
if cond { if cond {
self.op_jump(jp)?; self.op_jump(jp)?;
} }
} else {
return Err(dbg!(Error {}));
} }
Ok(()) Ok(())
} }
@ -175,7 +205,7 @@ impl<'a> VM {
let cond = self.pop()?; let cond = self.pop()?;
if let &P(Bool(cond)) = cond.as_ref() { if let &P(Bool(cond)) = cond.as_ref() {
if !cond { if !cond {
self.op_jump(jp)?; self.op_jump(dbg!(jp))?;
} }
} }
Ok(()) Ok(())
@ -318,7 +348,7 @@ impl<'a> VM {
(&P(Float(f)), &P(Float(ff))) => { (&P(Float(f)), &P(Float(ff))) => {
self.push(Rc::new(P(Bool(f > ff))))?; self.push(Rc::new(P(Bool(f > ff))))?;
} }
_ => return Err(Error {}), _ => return Err(dbg!(Error {})),
} }
Ok(()) Ok(())
} }
@ -333,7 +363,7 @@ impl<'a> VM {
(&P(Float(f)), &P(Float(ff))) => { (&P(Float(f)), &P(Float(ff))) => {
self.push(Rc::new(P(Bool(f < ff))))?; self.push(Rc::new(P(Bool(f < ff))))?;
} }
_ => return Err(Error {}), _ => return Err(dbg!(Error {})),
} }
Ok(()) Ok(())
} }
@ -348,7 +378,7 @@ impl<'a> VM {
(&P(Float(f)), &P(Float(ff))) => { (&P(Float(f)), &P(Float(ff))) => {
self.push(Rc::new(P(Bool(f <= ff))))?; self.push(Rc::new(P(Bool(f <= ff))))?;
} }
_ => return Err(Error {}), _ => return Err(dbg!(Error {})),
} }
Ok(()) Ok(())
} }
@ -363,7 +393,7 @@ impl<'a> VM {
(&P(Float(f)), &P(Float(ff))) => { (&P(Float(f)), &P(Float(ff))) => {
self.push(Rc::new(P(Bool(f >= ff))))?; self.push(Rc::new(P(Bool(f >= ff))))?;
} }
_ => return Err(Error {}), _ => return Err(dbg!(Error {})),
} }
Ok(()) Ok(())
} }
@ -412,7 +442,7 @@ impl<'a> VM {
if let &S(ref name) = name.as_ref() { if let &S(ref name) = name.as_ref() {
self.binding_push(name.clone(), val)?; self.binding_push(name.clone(), val)?;
} else { } else {
return Err(Error {}); return Err(dbg!(Error {}));
} }
Ok(()) Ok(())
} }
@ -426,7 +456,7 @@ impl<'a> VM {
let name = if let &S(ref s) | &P(Str(ref s)) = name_val.as_ref() { let name = if let &S(ref s) | &P(Str(ref s)) = name_val.as_ref() {
s s
} else { } else {
return Err(Error {}); return Err(dbg!(Error {}));
}; };
// get composite tuple from stack // get composite tuple from stack
let tpl = self.pop()?; let tpl = self.pop()?;
@ -439,7 +469,7 @@ impl<'a> VM {
// place composite tuple back on stack // place composite tuple back on stack
self.push(Rc::new(C(Tuple(flds))))?; self.push(Rc::new(C(Tuple(flds))))?;
} else { } else {
return Err(Error {}); return Err(dbg!(Error {}));
}; };
Ok(()) Ok(())
} }
@ -458,7 +488,7 @@ impl<'a> VM {
// Add that value to the list and put list back on stack. // Add that value to the list and put list back on stack.
self.push(Rc::new(C(List(elems))))?; self.push(Rc::new(C(List(elems))))?;
} else { } else {
return Err(Error {}); return Err(dbg!(Error {}));
}; };
Ok(()) Ok(())
} }
@ -470,7 +500,7 @@ impl<'a> VM {
}; };
match elems.get(idx as usize) { match elems.get(idx as usize) {
Some(v) => Ok(v.clone()), Some(v) => Ok(v.clone()),
None => Err(Error {}), None => Err(dbg!(Error {})),
} }
} }
@ -489,14 +519,14 @@ impl<'a> VM {
return Ok(f.1.clone()); return Ok(f.1.clone());
} }
} }
Err(Error {}) Err(dbg!(Error {}))
} }
fn find_in_value(&self, index: &Value, target: &Value) -> Result<Rc<Value>, Error> { fn find_in_value(&self, index: &Value, target: &Value) -> Result<Rc<Value>, Error> {
match target { match target {
C(Tuple(flds)) => self.find_in_flds(index, flds), C(Tuple(flds)) => self.find_in_flds(index, flds),
C(List(elements)) => self.find_in_list(index, elements), 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() { let path = if let &C(List(ref elems)) = path_val.as_ref() {
elems.clone() elems.clone()
} else { } else {
return dbg!(Err(Error {})); return Err(dbg!(Error {}));
}; };
let target_val = self.pop()?; let target_val = self.pop()?;
match target_val.as_ref() { 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(); let mut out = target_val.clone();
for p in path { for p in path {
@ -531,7 +561,7 @@ impl<'a> VM {
let overrides = if let &C(Tuple(ref oflds)) = override_val.as_ref() { let overrides = if let &C(Tuple(ref oflds)) = override_val.as_ref() {
oflds.clone() oflds.clone()
} else { } else {
return dbg!(Err(Error {})); return Err(dbg!(Error {}));
}; };
match tgt.as_ref() { match tgt.as_ref() {
&C(Tuple(ref flds)) => { &C(Tuple(ref flds)) => {
@ -571,7 +601,7 @@ impl<'a> VM {
} }
} }
_ => { _ => {
return Err(Error {}); return Err(dbg!(Error {}));
} }
} }
Ok(()) Ok(())
@ -600,7 +630,7 @@ impl<'a> VM {
pub fn binding_push(&mut self, name: String, val: Rc<Value>) -> Result<(), Error> { pub fn binding_push(&mut self, name: String, val: Rc<Value>) -> Result<(), Error> {
if self.symbols.is_bound(&name) { if self.symbols.is_bound(&name) {
return Err(Error {}); return Err(dbg!(Error {}));
} }
self.symbols.add(name, val); self.symbols.add(name, val);
Ok(()) Ok(())
@ -609,14 +639,14 @@ impl<'a> VM {
pub fn get_binding(&'a self, name: &str) -> Result<Rc<Value>, Error> { pub fn get_binding(&'a self, name: &str) -> Result<Rc<Value>, Error> {
match self.symbols.get(name) { match self.symbols.get(name) {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(Error {}), None => Err(dbg!(Error {})),
} }
} }
pub fn pop(&mut self) -> Result<Rc<Value>, Error> { pub fn pop(&mut self) -> Result<Rc<Value>, Error> {
match self.stack.pop() { match self.stack.pop() {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(Error {}), None => Err(dbg!(Error {})),
} }
} }
@ -624,7 +654,7 @@ impl<'a> VM {
Ok(match (left, right) { Ok(match (left, right) {
(P(Int(i)), P(Int(ii))) => Int(i * ii), (P(Int(i)), P(Int(ii))) => Int(i * ii),
(P(Float(f)), P(Float(ff))) => Float(f * ff), (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) { Ok(match (left, right) {
(P(Int(i)), P(Int(ii))) => Int(i / ii), (P(Int(i)), P(Int(ii))) => Int(i / ii),
(P(Float(f)), P(Float(ff))) => Float(f / ff), (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) { Ok(match (left, right) {
(P(Int(i)), Value::P(Int(ii))) => Int(i - ii), (P(Int(i)), Value::P(Int(ii))) => Int(i - ii),
(P(Float(f)), Value::P(Float(ff))) => Float(f - ff), (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); ns.push_str(&ss);
Str(ns) Str(ns)
} }
_ => return Err(Error {}), _ => return Err(dbg!(Error {})),
}) })
} }