From fe5c27e890959e77d11af4db67d6e5a302f9c9b4 Mon Sep 17 00:00:00 2001 From: mars Date: Sat, 23 Jul 2022 02:03:37 -0600 Subject: [PATCH] Add initial replicant crate --- Cargo.toml | 3 +- replicant/Cargo.toml | 8 +++ replicant/src/lib.rs | 148 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 replicant/Cargo.toml create mode 100644 replicant/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 7ef1119..f487016 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ - "editor" + "editor", + "replicant" ] [package] diff --git a/replicant/Cargo.toml b/replicant/Cargo.toml new file mode 100644 index 0000000..d0b56db --- /dev/null +++ b/replicant/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "replicant" +version = "0.1.0" +edition = "2021" + +[dependencies] +glam = "0.21" +termtree = "0.4" diff --git a/replicant/src/lib.rs b/replicant/src/lib.rs new file mode 100644 index 0000000..1e5329c --- /dev/null +++ b/replicant/src/lib.rs @@ -0,0 +1,148 @@ +use std::fmt; +use termtree; + +#[non_exhaustive] +#[derive(Copy, Clone, Debug)] +pub enum FieldOp { + Add, + Sub, + Mul, + Div, +} + +impl fmt::Display for FieldOp { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let name = match self { + FieldOp::Add => "+", + FieldOp::Sub => "-", + FieldOp::Mul => "*", + FieldOp::Div => "/", + }; + + write!(f, "{}", name) + } +} + +pub trait Field: fmt::Debug + Clone { + fn op(&self, other: Self, op: FieldOp) -> Self; +} + +#[derive(Debug)] +pub struct FieldNode { + field: T, + op: FieldOp, + children: Vec>, +} + +impl FieldNode { + pub fn evaluate(&self) -> T { + let mut result = self.field.clone(); + + for child in self.children.iter() { + let child_result = child.evaluate(); + result = result.op(child_result, child.op); + } + + result + } + + pub fn to_termtree(&self) -> termtree::Tree { + let desc = format!("{} {:?} ({:?})", self.op, self.field, self.evaluate()); + let mut tree = termtree::Tree::new(desc); + + for child in self.children.iter() { + tree.push(child.to_termtree()); + } + + tree + } +} + +impl fmt::Display for FieldNode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.to_termtree()) + } +} + +impl Field for f32 { + fn op(&self, other: Self, op: FieldOp) -> Self { + match op { + FieldOp::Add => self + other, + FieldOp::Sub => self - other, + FieldOp::Mul => self * other, + FieldOp::Div => self / other, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_nodes() { + use FieldOp::*; + + let nodes: FieldNode = FieldNode { + field: 10.0, + op: Add, + children: vec![ + FieldNode { + field: 4.0, + op: Add, + children: Vec::new(), + }, + FieldNode { + field: 2.0, + op: Sub, + children: vec![ + FieldNode { + field: 0.0, + op: Add, + children: vec![ + FieldNode { + field: 0.6, + op: Add, + children: Vec::new(), + }, + FieldNode { + field: 0.2, + op: Sub, + children: Vec::new(), + }, + ], + }, + FieldNode { + field: 3.0, + op: Div, + children: Vec::new(), + }, + ], + }, + FieldNode { + field: 7.0, + op: Mul, + children: vec![ + FieldNode { + field: 0.75, + op: Add, + children: Vec::new(), + }, + FieldNode { + field: 0.5, + op: Sub, + children: Vec::new(), + }, + FieldNode { + field: 2.0, + op: Div, + children: Vec::new(), + }, + ], + }, + ], + }; + + println!("{}", nodes); + } +}