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};
|
use super::{AbstractTree, Identifier, Statement, Value};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct Assignment {
|
pub struct Assignment {
|
||||||
identifier: Identifier,
|
identifier: Identifier,
|
||||||
statement: Box<Statement>,
|
statement: Box<Statement>,
|
||||||
|
@ -2,7 +2,7 @@ use crate::{context::Context, error::RuntimeError};
|
|||||||
|
|
||||||
use super::{AbstractTree, Statement, Value};
|
use super::{AbstractTree, Statement, Value};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::{context::Context, error::RuntimeError};
|
|||||||
|
|
||||||
use super::{AbstractTree, Statement, Value};
|
use super::{AbstractTree, Statement, Value};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Logic {
|
pub enum Logic {
|
||||||
Equal(Statement, Statement),
|
Equal(Statement, Statement),
|
||||||
NotEqual(Statement, Statement),
|
NotEqual(Statement, Statement),
|
||||||
@ -16,7 +16,40 @@ pub enum Logic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Logic {
|
impl AbstractTree for Logic {
|
||||||
fn run(self, _: &Context) -> Result<Value, RuntimeError> {
|
fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
|
||||||
todo!()
|
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};
|
use super::{AbstractTree, Block, Value};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct Loop {
|
pub struct Loop {
|
||||||
block: Block,
|
block: Block,
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::{context::Context, error::RuntimeError};
|
|||||||
|
|
||||||
use super::{AbstractTree, Assignment, Block, Identifier, Logic, Loop, Value};
|
use super::{AbstractTree, Assignment, Block, Identifier, Logic, Loop, Value};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
Assignment(Assignment),
|
Assignment(Assignment),
|
||||||
Block(Block),
|
Block(Block),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
|
cmp::Ordering,
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
ops::Range,
|
ops::Range,
|
||||||
sync::{Arc, OnceLock},
|
sync::{Arc, OnceLock},
|
||||||
@ -59,6 +60,28 @@ impl Value {
|
|||||||
pub fn r#enum(r#enum: EnumInstance) -> Self {
|
pub fn r#enum(r#enum: EnumInstance) -> Self {
|
||||||
Value(Arc::new(ValueInner::Enum(r#enum)))
|
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)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
@ -73,7 +96,48 @@ pub enum ValueInner {
|
|||||||
Enum(EnumInstance),
|
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 {
|
pub struct EnumInstance {
|
||||||
type_name: Identifier,
|
type_name: Identifier,
|
||||||
variant: Identifier,
|
variant: Identifier,
|
||||||
|
@ -32,6 +32,7 @@ impl<'src> From<RuntimeError> for Error<'src> {
|
|||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum RuntimeError {
|
pub enum RuntimeError {
|
||||||
RwLockPoison(RwLockPoisonError),
|
RwLockPoison(RwLockPoisonError),
|
||||||
|
ExpectedBoolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<RwLockPoisonError> for RuntimeError {
|
impl From<RwLockPoisonError> for RuntimeError {
|
||||||
|
Loading…
Reference in New Issue
Block a user