diff --git a/src/build/opcode/mod.rs b/src/build/opcode/mod.rs index 0d76bd0..d37d051 100644 --- a/src/build/opcode/mod.rs +++ b/src/build/opcode/mod.rs @@ -108,6 +108,8 @@ pub enum Op { Lt, GtEq, LtEq, + // Not, + Not, // Primitive Types ops Val(Primitive), // A bareword for use in bindings or lookups diff --git a/src/build/opcode/test.rs b/src/build/opcode/test.rs index 86a21a3..e81ee3f 100644 --- a/src/build/opcode/test.rs +++ b/src/build/opcode/test.rs @@ -20,7 +20,7 @@ use super::Op::{ InitThunk, InitTuple, Jump, JumpIfFalse, JumpIfTrue, Module, Mul, Noop, Pop, Return, SelectJump, Sub, Sym, Val, }; -use super::Primitive::{Bool, Float, Int, Str, Empty}; +use super::Primitive::{Bool, Empty, Float, Int, Str}; use super::Value::{C, P}; use super::VM; @@ -503,10 +503,10 @@ fn scope_stacks() { assert_eq!(val.as_ref(), &P(Int(1))); } -use crate::ast::{Expression, Statement, Value as ASTValue, PositionedItem, Position}; use super::translate; -use crate::parse::parse; +use crate::ast::{Expression, Position, PositionedItem, Statement, Value as ASTValue}; use crate::iter::OffsetStrIter; +use crate::parse::parse; macro_rules! assert_parse_cases { (__impl__ $cases:expr) => { @@ -538,4 +538,17 @@ fn simple_expr_scalar_value() { "NULL;" => P(Empty), "\"foo\";" => P(Str("foo".to_owned())), ) -} \ No newline at end of file +} + +#[test] +fn simple_binary_expr() { + assert_parse_cases!( + "1+1;" => P(Int(2)), + "2-1;" => P(Int(1)), + "2*2;" => P(Int(4)), + "6/2;" => P(Int(3)), + "1.0+1.0;" => P(Float(2.0)), + "\"foo\"+\"bar\";" => P(Str("foobar".to_owned())), + //"true && false;" => P(Bool(false)), + ) +} diff --git a/src/build/opcode/translate.rs b/src/build/opcode/translate.rs index e0285ba..061c0da 100644 --- a/src/build/opcode/translate.rs +++ b/src/build/opcode/translate.rs @@ -11,7 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -use crate::ast::{Expression, Statement, Value}; +use crate::ast::{BinaryExprType, Expression, Statement, Value}; use crate::build::opcode::Op; use crate::build::opcode::Primitive; use crate::build::opcode::Value::{C, F, M, P, T}; @@ -40,10 +40,61 @@ impl AST { } fn translate_expr(expr: Expression, mut ops: &mut Vec) { - match expr { + match dbg!(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 => { + ops.push(Op::Add); + } + BinaryExprType::Sub => { + ops.push(Op::Sub); + } + BinaryExprType::Div => { + ops.push(Op::Div); + } + BinaryExprType::Mul => { + ops.push(Op::Mul); + } + BinaryExprType::Equal => { + ops.push(Op::Equal); + } + BinaryExprType::GT => { + ops.push(Op::Gt); + } + BinaryExprType::LT => { + ops.push(Op::Lt); + } + BinaryExprType::GTEqual => { + // An Equal and an And + //ops.push(Op::GtEqual); + unimplemented!("Binary expressions are not implmented yet") + } + BinaryExprType::LTEqual => { + //ops.push(Op::LtEqual); + unimplemented!("Binary expressions are not implmented yet") + } + BinaryExprType::NotEqual => { + ops.push(Op::Not); + ops.push(Op::Equal); + } + BinaryExprType::REMatch + | BinaryExprType::NotREMatch + | BinaryExprType::IN + | BinaryExprType::IS + | BinaryExprType::Mod + | BinaryExprType::OR + | BinaryExprType::AND + | BinaryExprType::DOT => { + unimplemented!("Binary expressions are not implmented yet") + // TODO + } + }; + } Expression::Fail(_) => unimplemented!("Fail expressions are not implmented yet"), Expression::Format(_) => unimplemented!("Format expressions are not implmented yet"), Expression::Func(_) => unimplemented!("Func expressions are not implmented yet"), @@ -57,7 +108,6 @@ impl AST { Expression::Not(_) => unimplemented!("Not expressions are not implmented yet"), Expression::Range(_) => unimplemented!("Range expressions are not implmented yet"), Expression::Select(_) => unimplemented!("Select expressions are not implmented yet"), - Expression::Binary(_) => unimplemented!("Binary expressions are not implmented yet"), Expression::Call(_) => unimplemented!("Call expressions are not implmented yet"), Expression::Copy(_) => unimplemented!("Copy expressions are not implmented yet"), Expression::Debug(_) => unimplemented!("Debug expressions are not implmented yet"), @@ -65,7 +115,7 @@ impl AST { } fn translate_value(value: Value, ops: &mut Vec) { - match value { + match dbg!(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 0c228d6..0e0cc82 100644 --- a/src/build/opcode/vm.rs +++ b/src/build/opcode/vm.rs @@ -88,6 +88,7 @@ impl<'a> VM { Op::Div => self.op_div()?, Op::Bind => self.op_bind()?, Op::Equal => self.op_equal()?, + Op::Not => self.op_not()?, Op::Gt => self.op_gt()?, Op::Lt => self.op_lt()?, Op::GtEq => self.op_gteq()?, @@ -269,6 +270,15 @@ impl<'a> VM { self.op_jump(jp) } + fn op_not(&mut self) -> Result<(), Error> { + let operand = self.pop()?; + if let P(Bool(val)) = operand.as_ref() { + self.push(Rc::new(P(Bool(!val))))?; + return Ok(()); + } + return Err(dbg!(Error {})); + } + fn op_equal(&mut self) -> Result<(), Error> { let left = self.pop()?; let right = self.pop()?;