From fb7675a782d9c9036a1065ba4a071be7b927bb89 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sun, 25 Feb 2024 14:26:22 -0500 Subject: [PATCH] Add plumbing and test --- src/abstract_tree/assignment.rs | 2 +- src/abstract_tree/block.rs | 2 +- src/abstract_tree/logic.rs | 39 +++++++++++++++++-- src/abstract_tree/loop.rs | 2 +- src/abstract_tree/statement.rs | 2 +- src/abstract_tree/value.rs | 66 ++++++++++++++++++++++++++++++++- src/error.rs | 1 + 7 files changed, 106 insertions(+), 8 deletions(-) diff --git a/src/abstract_tree/assignment.rs b/src/abstract_tree/assignment.rs index 9d7cdac..2fdcdfa 100644 --- a/src/abstract_tree/assignment.rs +++ b/src/abstract_tree/assignment.rs @@ -2,7 +2,7 @@ use crate::{error::RuntimeError, Context}; use super::{AbstractTree, Identifier, Statement, Value}; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Assignment { identifier: Identifier, statement: Box, diff --git a/src/abstract_tree/block.rs b/src/abstract_tree/block.rs index ff4c940..67215e1 100644 --- a/src/abstract_tree/block.rs +++ b/src/abstract_tree/block.rs @@ -2,7 +2,7 @@ use crate::{context::Context, error::RuntimeError}; use super::{AbstractTree, Statement, Value}; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Block { statements: Vec, } diff --git a/src/abstract_tree/logic.rs b/src/abstract_tree/logic.rs index 0fd7994..42c2102 100644 --- a/src/abstract_tree/logic.rs +++ b/src/abstract_tree/logic.rs @@ -2,7 +2,7 @@ use crate::{context::Context, error::RuntimeError}; use super::{AbstractTree, Statement, Value}; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Logic { Equal(Statement, Statement), NotEqual(Statement, Statement), @@ -16,7 +16,40 @@ pub enum Logic { } impl AbstractTree for Logic { - fn run(self, _: &Context) -> Result { - todo!() + fn run(self, _context: &Context) -> Result { + let boolean = match self { + Logic::Equal(left, right) => left.run(_context)? == right.run(_context)?, + Logic::NotEqual(left, right) => left.run(_context)? != right.run(_context)?, + Logic::Greater(left, right) => left.run(_context)? > right.run(_context)?, + Logic::Less(left, right) => left.run(_context)? < right.run(_context)?, + Logic::GreaterOrEqual(left, right) => left.run(_context)? >= right.run(_context)?, + Logic::LessOrEqual(left, right) => left.run(_context)? <= right.run(_context)?, + Logic::And(left, right) => { + left.run(_context)?.as_boolean()? && right.run(_context)?.as_boolean()? + } + Logic::Or(left, right) => { + left.run(_context)?.as_boolean()? || right.run(_context)?.as_boolean()? + } + Logic::Not(statement) => !statement.run(_context)?.as_boolean()?, + }; + + Ok(Value::boolean(boolean)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn equal() { + assert!(Logic::Equal( + Statement::Value(Value::integer(42)), + Statement::Value(Value::integer(42)), + ) + .run(&Context::new()) + .unwrap() + .as_boolean() + .unwrap()) } } diff --git a/src/abstract_tree/loop.rs b/src/abstract_tree/loop.rs index 0419ffe..3d3ce54 100644 --- a/src/abstract_tree/loop.rs +++ b/src/abstract_tree/loop.rs @@ -2,7 +2,7 @@ use crate::{context::Context, error::RuntimeError}; use super::{AbstractTree, Block, Value}; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Loop { block: Block, } diff --git a/src/abstract_tree/statement.rs b/src/abstract_tree/statement.rs index 8cb7ca5..47978a8 100644 --- a/src/abstract_tree/statement.rs +++ b/src/abstract_tree/statement.rs @@ -2,7 +2,7 @@ use crate::{context::Context, error::RuntimeError}; use super::{AbstractTree, Assignment, Block, Identifier, Logic, Loop, Value}; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Statement { Assignment(Assignment), Block(Block), diff --git a/src/abstract_tree/value.rs b/src/abstract_tree/value.rs index 3cc57ac..cb01337 100644 --- a/src/abstract_tree/value.rs +++ b/src/abstract_tree/value.rs @@ -1,4 +1,5 @@ use std::{ + cmp::Ordering, collections::BTreeMap, ops::Range, sync::{Arc, OnceLock}, @@ -59,6 +60,28 @@ impl Value { pub fn r#enum(r#enum: EnumInstance) -> Self { Value(Arc::new(ValueInner::Enum(r#enum))) } + + pub fn as_boolean(&self) -> Result { + if let ValueInner::Boolean(boolean) = self.0.as_ref() { + return Ok(*boolean); + } + + Err(RuntimeError::ExpectedBoolean) + } +} + +impl Eq for Value {} + +impl PartialOrd for Value { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Value { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.0.as_ref().cmp(other.0.as_ref()) + } } #[derive(Clone, Debug, PartialEq)] @@ -73,7 +96,48 @@ pub enum ValueInner { Enum(EnumInstance), } -#[derive(Clone, Debug, PartialEq)] +impl Eq for ValueInner {} + +impl PartialOrd for ValueInner { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for ValueInner { + fn cmp(&self, other: &Self) -> Ordering { + use ValueInner::*; + + match (self, other) { + (Boolean(left), Boolean(right)) => left.cmp(right), + (Boolean(_), _) => Ordering::Greater, + (Float(left), Float(right)) => left.total_cmp(right), + (Float(_), _) => Ordering::Greater, + (Integer(left), Integer(right)) => left.cmp(right), + (Integer(_), _) => Ordering::Greater, + (List(left), List(right)) => left.cmp(right), + (List(_), _) => Ordering::Greater, + (Map(left), Map(right)) => left.cmp(right), + (Map(_), _) => Ordering::Greater, + (Range(left), Range(right)) => { + let start_cmp = left.start.cmp(&right.start); + + if start_cmp.is_eq() { + left.end.cmp(&right.end) + } else { + start_cmp + } + } + (Range(_), _) => Ordering::Greater, + (String(left), String(right)) => left.cmp(right), + (String(_), _) => Ordering::Greater, + (Enum(left), Enum(right)) => left.cmp(right), + (Enum(_), _) => Ordering::Greater, + } + } +} + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct EnumInstance { type_name: Identifier, variant: Identifier, diff --git a/src/error.rs b/src/error.rs index 50b140e..2b324ca 100644 --- a/src/error.rs +++ b/src/error.rs @@ -32,6 +32,7 @@ impl<'src> From for Error<'src> { #[derive(Debug, PartialEq)] pub enum RuntimeError { RwLockPoison(RwLockPoisonError), + ExpectedBoolean, } impl From for RuntimeError {