Add plumbing and test
This commit is contained in:
parent
8ff4b4ba82
commit
fb7675a782
@ -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<Statement>,
|
||||
|
@ -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<Statement>,
|
||||
}
|
||||
|
@ -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<Value, RuntimeError> {
|
||||
todo!()
|
||||
fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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<bool, RuntimeError> {
|
||||
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<std::cmp::Ordering> {
|
||||
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<Ordering> {
|
||||
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,
|
||||
|
@ -32,6 +32,7 @@ impl<'src> From<RuntimeError> for Error<'src> {
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum RuntimeError {
|
||||
RwLockPoison(RwLockPoisonError),
|
||||
ExpectedBoolean,
|
||||
}
|
||||
|
||||
impl From<RwLockPoisonError> for RuntimeError {
|
||||
|
Loading…
Reference in New Issue
Block a user