From 029104722698773f4bd87229503b875e4e3fef66 Mon Sep 17 00:00:00 2001 From: thesayyn Date: Sat, 17 Feb 2024 13:45:25 -0800 Subject: [PATCH] feat: evaluation logic --- program/src/context.rs | 2 +- program/src/eval.rs | 64 ++++++++++++++++++++++++++++++++++++++++ program/src/lib.rs | 3 +- program/src/program.rs | 10 +++---- program/src/value.rs | 66 +++++++++++++++++++----------------------- web/index.html | 12 +++++--- 6 files changed, 110 insertions(+), 47 deletions(-) create mode 100644 program/src/eval.rs diff --git a/program/src/context.rs b/program/src/context.rs index 0618b4f..e44457b 100644 --- a/program/src/context.rs +++ b/program/src/context.rs @@ -1,5 +1,5 @@ pub struct Context { - + } impl Default for Context { diff --git a/program/src/eval.rs b/program/src/eval.rs new file mode 100644 index 0000000..e634695 --- /dev/null +++ b/program/src/eval.rs @@ -0,0 +1,64 @@ +use crate::{value::Value, Context}; +use parser::{ArithmeticOp, Atom, Expression, RelationOp}; + +impl From for Value { + fn from(atom: Atom) -> Self { + match atom { + Atom::Int(i) => Value::Int(i), + Atom::UInt(ui) => Value::UInt(ui), + Atom::Float(f) => Value::Float(f), + Atom::Bool(b) => Value::Bool(b), + Atom::Null => Value::Null, + Atom::Bytes(b) => Value::Bytes(b), + Atom::String(s) => Value::String(s), + } + } +} + +pub struct Eval { + ctx: Context, +} + +impl Eval { + pub fn new(ctx: Context) -> Self { + Eval { ctx } + } + pub fn eval(&self, expr: Expression) -> Value { + match expr { + Expression::Atom(atom) => atom.into(), + Expression::Relation(left, op, right) => { + let left = self.eval(*left); + let right = self.eval(*right); + let result = match op { + RelationOp::Equals => left.eq(&right), + RelationOp::LessThan => todo!("lt"), + RelationOp::LessThanEq => todo!("lte"), + RelationOp::GreaterThan => todo!("gt"), + RelationOp::GreaterThanEq => todo!("gte"), + RelationOp::NotEquals => todo!("ne"), + RelationOp::In => todo!("in"), + }; + Value::Bool(result) + } + Expression::Arithmetic(left, op, right) => { + let left = self.eval(*left); + let right = self.eval(*right); + match op { + ArithmeticOp::Add => left + right, + ArithmeticOp::Subtract => left - right, + ArithmeticOp::Divide => left / right, + ArithmeticOp::Multiply => left * right, + ArithmeticOp::Modulus => todo!("modulus"), + } + } + Expression::Ternary(_, _, _) => todo!(), + Expression::Or(_, _) => todo!(), + Expression::And(_, _) => todo!(), + Expression::Unary(_, _) => todo!(), + Expression::Member(_, _) => todo!(), + Expression::List(_) => todo!(), + Expression::Map(_) => todo!(), + Expression::Ident(_) => todo!(), + } + } +} diff --git a/program/src/lib.rs b/program/src/lib.rs index 94096cc..04195a3 100644 --- a/program/src/lib.rs +++ b/program/src/lib.rs @@ -2,4 +2,5 @@ pub mod context; pub mod program; pub use crate::program::Program; pub use crate::context::Context; -mod value; \ No newline at end of file +mod value; +mod eval; \ No newline at end of file diff --git a/program/src/program.rs b/program/src/program.rs index 0f49fba..da97fe7 100644 --- a/program/src/program.rs +++ b/program/src/program.rs @@ -1,11 +1,10 @@ -use parser::{Expression}; +use parser::Expression; use parser::parser::ExpressionParser; - use std::fmt; - use std::result::Result; use crate::context::Context; use crate::value::Value; +use crate::eval::Eval; pub struct Program { expr: Expression @@ -31,8 +30,9 @@ impl Program { } } - pub fn execute(&self, context: Context) -> bool { - match Value::from(&self.expr) { + pub fn execute(self, context: Context) -> bool { + let e = Eval::new(context); + match e.eval(self.expr) { Value::Bool(b) => b, _ => panic!("this was not supposed to happen!") } diff --git a/program/src/value.rs b/program/src/value.rs index 6ff70af..c77e8ff 100644 --- a/program/src/value.rs +++ b/program/src/value.rs @@ -1,4 +1,3 @@ -use parser::{ArithmeticOp, Atom, Expression, RelationOp}; use std::rc::Rc; #[derive(PartialEq)] @@ -12,43 +11,38 @@ pub enum Value { String(Rc), } -impl From<&Atom> for Value { - fn from(atom: &Atom) -> Self { - match atom { - Atom::Int(i) => Value::Int(*i), - Atom::UInt(ui) => Value::UInt(*ui), - Atom::Float(f) => Value::Float(*f), - Atom::Bool(b) => Value::Bool(*b), - Atom::Bytes(b) => Value::Bytes(b.clone()), - Atom::Null => Value::Null, - Atom::String(s) => Value::String(s.clone()), +impl std::fmt::Display for Value { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Value::Int(v) => write!(f, "int({})", v), + Value::UInt(v) => write!(f, "uint({})", v), + Value::Float(v) => write!(f, "float({})", v), + Value::Null => write!(f, "null"), + Self::Bool(v) => write!(f, "bool({})", v), + Value::Bytes(v) => write!(f, "bytes(len = {})", v.len()), + Value::String(v) => write!(f, "string({})", v), } } } -impl<'a> Value { - pub fn from(expr: &'a Expression) -> Value { - match expr { - Expression::Atom(atom) => atom.into(), - Expression::Relation(left, op, right) => { - let left = Value::from(left); - let right = Value::from(right); - let result = match op { - RelationOp::Equals => left.eq(&right), - _ => unimplemented!(), - }; - Value::Bool(result) - } - Expression::Arithmetic(left, op, right) => { - let left = Value::from(left); - let right = Value::from(right); - match op { - ArithmeticOp::Add => left + right, - ArithmeticOp::Subtract => left - right, - _ => todo!(), - } - } - _ => todo!(), +impl std::ops::Mul for Value { + type Output = Value; + + fn mul(self, rhs: Self) -> Self::Output { + match (self, rhs) { + (Value::Int(l), Value::Int(r)) => Value::Int(l * r), + (a, b) => todo!("mul {} {}", a, b), + } + } +} + +impl std::ops::Div for Value { + type Output = Value; + + fn div(self, rhs: Self) -> Self::Output { + match (self, rhs) { + (Value::Int(l), Value::Int(r)) => Value::Int(l / r), + (a, b) => todo!("div {} {}", a, b), } } } @@ -59,7 +53,7 @@ impl std::ops::Add for Value { fn add(self, o: Value) -> Self::Output { match (self, o) { (Value::Int(l), Value::Int(r)) => Value::Int(l + r), - _ => todo!("add"), + (a, b) => todo!("add {} {}", a, b), } } } @@ -69,7 +63,7 @@ impl std::ops::Sub for Value { fn sub(self, o: Value) -> Self::Output { match (self, o) { (Value::Int(l), Value::Int(r)) => Value::Int(l - r), - _ => todo!("sub"), + (a, b) => todo!("sub {} {}", a, b), } } } diff --git a/web/index.html b/web/index.html index f832c9b..5b0a390 100644 --- a/web/index.html +++ b/web/index.html @@ -19,14 +19,18 @@ const editor = document.querySelector("wc-codemirror"); - requestAnimationFrame(() => editor.setValue("5 == -5" + "\n".repeat(8))) + requestAnimationFrame(() => editor.setValue("(2000 / 2 == 1000) - 2 == 998")) const card = document.querySelector("sp-card"); window.run = function() { - const r = execute(editor.value); - card.subheading = `Result is: ${r}`; - console.log("here"); + try { + const r = execute(editor.value); + card.subheading = `Result is: ${r}`; + } catch (e) { + card.subheading = `Failed to evaluate: ${e.message}` + } + }