From 9d5b7b660675f671539cdb4cb07ef5312af44bc8 Mon Sep 17 00:00:00 2001 From: Jeff Date: Wed, 28 Feb 2024 18:36:47 -0500 Subject: [PATCH] Add logic tests --- src/abstract_tree/logic.rs | 111 ++++++++++++++++++++++++++++++++ src/abstract_tree/value_node.rs | 36 ++++++++--- src/lexer.rs | 6 +- src/value.rs | 49 ++++++-------- 4 files changed, 161 insertions(+), 41 deletions(-) diff --git a/src/abstract_tree/logic.rs b/src/abstract_tree/logic.rs index be32c1b..75a40e4 100644 --- a/src/abstract_tree/logic.rs +++ b/src/abstract_tree/logic.rs @@ -54,4 +54,115 @@ mod tests { .as_boolean() .unwrap()) } + + #[test] + fn not_equal() { + assert!(Logic::NotEqual( + Expression::Value(ValueNode::Integer(42)), + Expression::Value(ValueNode::Integer(43)), + ) + .run(&Context::new()) + .unwrap() + .as_boolean() + .unwrap()) + } + + #[test] + fn greater() { + assert!(Logic::Greater( + Expression::Value(ValueNode::Integer(43)), + Expression::Value(ValueNode::Integer(42)), + ) + .run(&Context::new()) + .unwrap() + .as_boolean() + .unwrap()) + } + + #[test] + fn less() { + assert!(Logic::Less( + Expression::Value(ValueNode::Integer(42)), + Expression::Value(ValueNode::Integer(43)), + ) + .run(&Context::new()) + .unwrap() + .as_boolean() + .unwrap()) + } + + #[test] + fn greater_or_equal() { + assert!(Logic::GreaterOrEqual( + Expression::Value(ValueNode::Integer(42)), + Expression::Value(ValueNode::Integer(41)), + ) + .run(&Context::new()) + .unwrap() + .as_boolean() + .unwrap()); + + assert!(Logic::GreaterOrEqual( + Expression::Value(ValueNode::Integer(42)), + Expression::Value(ValueNode::Integer(42)), + ) + .run(&Context::new()) + .unwrap() + .as_boolean() + .unwrap()) + } + + #[test] + fn less_or_equal() { + assert!(Logic::LessOrEqual( + Expression::Value(ValueNode::Integer(42)), + Expression::Value(ValueNode::Integer(43)), + ) + .run(&Context::new()) + .unwrap() + .as_boolean() + .unwrap()); + + assert!(Logic::LessOrEqual( + Expression::Value(ValueNode::Integer(42)), + Expression::Value(ValueNode::Integer(42)), + ) + .run(&Context::new()) + .unwrap() + .as_boolean() + .unwrap()) + } + + #[test] + fn and() { + assert!(Logic::And( + Expression::Value(ValueNode::Boolean(true)), + Expression::Value(ValueNode::Boolean(true)), + ) + .run(&Context::new()) + .unwrap() + .as_boolean() + .unwrap()) + } + + #[test] + fn or() { + assert!(Logic::Or( + Expression::Value(ValueNode::Boolean(true)), + Expression::Value(ValueNode::Boolean(false)), + ) + .run(&Context::new()) + .unwrap() + .as_boolean() + .unwrap()) + } + + #[test] + fn not() { + assert!(Logic::Not(Expression::Value(ValueNode::Boolean(false))) + .run(&Context::new()) + .unwrap() + .as_boolean() + .unwrap()) + } } diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index 030f96f..a20929e 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -10,7 +10,7 @@ pub enum ValueNode<'src> { Float(f64), Integer(i64), List(Vec>), - Map(BTreeMap>), + Map(Vec<(Identifier, Expression<'src>)>), Range(Range), String(&'src str), Enum(Identifier, Identifier), @@ -20,13 +20,33 @@ impl<'src> AbstractTree for ValueNode<'src> { fn run(self, _context: &Context) -> Result { let value = match self { ValueNode::Boolean(boolean) => Value::boolean(boolean), - ValueNode::Float(float) => todo!(), - ValueNode::Integer(integer) => todo!(), - ValueNode::List(expression_list) => todo!(), - ValueNode::Map(property_list) => todo!(), - ValueNode::Range(range) => todo!(), - ValueNode::String(string) => todo!(), - ValueNode::Enum(name, variant) => todo!(), + ValueNode::Float(float) => Value::float(float), + ValueNode::Integer(integer) => Value::integer(integer), + ValueNode::List(expression_list) => { + let mut value_list = Vec::with_capacity(expression_list.len()); + + for expression in expression_list { + let value = expression.run(_context)?; + + value_list.push(value); + } + + Value::list(value_list) + } + ValueNode::Map(property_list) => { + let mut property_map = BTreeMap::new(); + + for (identifier, expression) in property_list { + let value = expression.run(_context)?; + + property_map.insert(identifier, value); + } + + Value::map(property_map) + } + ValueNode::Range(range) => Value::range(range), + ValueNode::String(string) => Value::string(string), + ValueNode::Enum(name, variant) => Value::r#enum(name, variant), }; Ok(value) diff --git a/src/lexer.rs b/src/lexer.rs index 2da5496..9d081e3 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -47,11 +47,7 @@ pub fn lexer<'src>() -> impl Parser< .then(text::int(10)) .to_slice() .map(|text: &str| { - let integer = if let Ok(integer) = text.parse::() { - integer - } else { - panic!("Failed to parse {text} as integer."); - }; + let integer = text.parse::().unwrap(); Token::Integer(integer) }); diff --git a/src/value.rs b/src/value.rs index 043d611..9f57646 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,10 +1,11 @@ use std::{ cmp::Ordering, + collections::BTreeMap, ops::Range, sync::{Arc, OnceLock}, }; -use crate::error::RuntimeError; +use crate::{abstract_tree::Identifier, error::RuntimeError}; pub static NONE: OnceLock = OnceLock::new(); @@ -16,16 +17,6 @@ impl Value { &self.0 } - pub fn none() -> Self { - NONE.get_or_init(|| { - Value::r#enum(EnumInstance { - type_name: "Option".to_string(), - variant: "None".to_string(), - }) - }) - .clone() - } - pub fn boolean(boolean: bool) -> Self { Value(Arc::new(ValueInner::Boolean(boolean))) } @@ -42,9 +33,9 @@ impl Value { Value(Arc::new(ValueInner::List(list))) } - // pub fn map(map: BTreeMap) -> Self { - // Value(Arc::new(ValueInner::Map(map))) - // } + pub fn map(map: BTreeMap) -> Self { + Value(Arc::new(ValueInner::Map(map))) + } pub fn range(range: Range) -> Self { Value(Arc::new(ValueInner::Range(range))) @@ -54,8 +45,8 @@ impl Value { Value(Arc::new(ValueInner::String(string.to_string()))) } - pub fn r#enum(r#enum: EnumInstance) -> Self { - Value(Arc::new(ValueInner::Enum(r#enum))) + pub fn r#enum(name: Identifier, variant: Identifier) -> Self { + Value(Arc::new(ValueInner::Enum(name, variant))) } pub fn as_boolean(&self) -> Result { @@ -87,10 +78,10 @@ pub enum ValueInner { Float(f64), Integer(i64), List(Vec), - // Map(BTreeMap), + Map(BTreeMap), Range(Range), String(String), - Enum(EnumInstance), + Enum(Identifier, Identifier), } impl Eq for ValueInner {} @@ -114,8 +105,8 @@ impl Ord for ValueInner { (Integer(_), _) => Ordering::Greater, (List(left), List(right)) => left.cmp(right), (List(_), _) => Ordering::Greater, - // (Map(left), Map(right)) => left.cmp(right), - // (Map(_), _) => Ordering::Greater, + (Map(left), Map(right)) => left.cmp(right), + (Map(_), _) => Ordering::Greater, (Range(left), Range(right)) => { let start_cmp = left.start.cmp(&right.start); @@ -128,14 +119,16 @@ impl Ord for ValueInner { (Range(_), _) => Ordering::Greater, (String(left), String(right)) => left.cmp(right), (String(_), _) => Ordering::Greater, - (Enum(left), Enum(right)) => left.cmp(right), - (Enum(_), _) => Ordering::Greater, + (Enum(name_left, variant_left), Enum(name_right, variant_right)) => { + let name_cmp = name_left.cmp(name_right); + + if name_cmp.is_eq() { + variant_left.cmp(variant_right) + } else { + name_cmp + } + } + (Enum(..), _) => Ordering::Greater, } } } - -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub struct EnumInstance { - type_name: String, - variant: String, -}