From e12d749c7c6256d445f36824db37441ad200e4d2 Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Tue, 26 Sep 2023 14:41:10 -0500 Subject: [PATCH] :recycle: refactor: extract value module --- src/main.rs | 1 + src/state.rs | 108 +++------------------------------------------------ src/tests.rs | 2 +- src/value.rs | 104 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 104 deletions(-) create mode 100644 src/value.rs diff --git a/src/main.rs b/src/main.rs index 703664d..0aee6ef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod loader; mod state; +mod value; #[cfg (test)] mod tests; diff --git a/src/state.rs b/src/state.rs index 92c7008..034f511 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,6 +1,8 @@ -use std::{ - collections::BTreeMap, - rc::Rc, +use std::collections::BTreeMap; + +use crate::value::{ + BogusClosure, + Value, }; #[derive (Debug, PartialEq)] @@ -65,106 +67,6 @@ pub enum Instruction { VarArgPrep (i32), } -#[derive (Clone, Debug, Hash, PartialEq)] -pub struct BogusClosure { - idx: usize, - upvalues: Vec , -} - -#[derive (Clone, Debug, PartialEq)] -pub enum Value { - Nil, - Boolean (bool), - Float (f64), - Integer (i64), - String (Rc ), - - // These are all bogus, I haven't figured out how to implement - // tables and function pointers yet - - BogusArg (Rc >), - BogusClosure (Rc ), - BogusEnv (Rc >), - BogusPrint, -} - -impl Default for Value { - fn default () -> Self { - Self::Nil - } -} - -impl From for Value { - fn from (x: String) -> Self { - Self::String (x.into ()) - } -} - -impl From <&str> for Value { - fn from (x: &str) -> Self { - Self::from (String::from (x)) - } -} - -impl From for Value { - fn from (x: i32) -> Self { - Self::Integer (i64::try_from (x).unwrap ()) - } -} - -impl From for Value { - fn from (x: f64) -> Self { - Self::Float (x) - } -} - -impl std::hash::Hash for Value { - fn hash (&self, state: &mut H) { - // Per https://doc.rust-lang.org/std/hash/trait.Hash.html#prefix-collisions - [0xff].hash (state); - - match self { - // TODO: Weaken to a Lua error - Self::Nil => panic! ("can't hash a nil value"), - Self::Boolean (x) => x.hash (state), - Self::Float (x) => x.to_ne_bytes ().hash (state), - Self::Integer (x) => x.hash (state), - Self::String (x) => x.as_ptr ().hash (state), - Self::BogusArg (_) => panic! ("can't hash Bogus values"), - Self::BogusClosure (_) => panic! ("can't hash Bogus values"), - Self::BogusEnv (_) => panic! ("can't hash Bogus values"), - Self::BogusPrint => panic! ("can't hash Bogus values"), - } - } -} - -impl Value { - fn as_float (&self) -> Option { - match self { - Self::Float (x) => Some (*x), - // FloatToInt isn't stable yet, so only ints in i32 space can practically be used for now - Self::Integer (x) => f64::try_from (i32::try_from (*x).ok ()?).ok (), - _ => None, - } - } - - fn is_truthy (&self) -> bool { - // And this is something Lua does better than JS and Python. - - match self { - Value::Nil => false, - Value::Boolean (false) => false, - _ => true, - } - } - - fn take (&mut self) -> Self { - let mut x = Value::Nil; - std::mem::swap (self, &mut x); - x - } -} - pub struct Block { pub instructions: Vec , pub constants: Vec , diff --git a/src/tests.rs b/src/tests.rs index 604a57f..b27198c 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -222,7 +222,7 @@ fn value_size () { let expected = 16; assert! (sz <= expected, "{sz} > {expected}"); - let sz = size_of:: (); + let sz = size_of:: (); let expected = 16; assert! (sz <= expected, "{sz} > {expected}"); } diff --git a/src/value.rs b/src/value.rs new file mode 100644 index 0000000..db60274 --- /dev/null +++ b/src/value.rs @@ -0,0 +1,104 @@ +use std::{ + collections::BTreeMap, + rc::Rc, +}; + +#[derive (Clone, Debug, Hash, PartialEq)] +pub struct BogusClosure { + pub idx: usize, + pub upvalues: Vec , +} + +#[derive (Clone, Debug, PartialEq)] +pub enum Value { + Nil, + Boolean (bool), + Float (f64), + Integer (i64), + String (Rc ), + + // These are all bogus, I haven't figured out how to implement + // tables and function pointers yet + + BogusArg (Rc >), + BogusClosure (Rc ), + BogusEnv (Rc >), + BogusPrint, +} + +impl Default for Value { + fn default () -> Self { + Self::Nil + } +} + +impl From for Value { + fn from (x: String) -> Self { + Self::String (x.into ()) + } +} + +impl From <&str> for Value { + fn from (x: &str) -> Self { + Self::from (String::from (x)) + } +} + +impl From for Value { + fn from (x: i32) -> Self { + Self::Integer (i64::try_from (x).unwrap ()) + } +} + +impl From for Value { + fn from (x: f64) -> Self { + Self::Float (x) + } +} + +impl std::hash::Hash for Value { + fn hash (&self, state: &mut H) { + // Per https://doc.rust-lang.org/std/hash/trait.Hash.html#prefix-collisions + [0xff].hash (state); + + match self { + // TODO: Weaken to a Lua error + Self::Nil => panic! ("can't hash a nil value"), + Self::Boolean (x) => x.hash (state), + Self::Float (x) => x.to_ne_bytes ().hash (state), + Self::Integer (x) => x.hash (state), + Self::String (x) => x.as_ptr ().hash (state), + Self::BogusArg (_) => panic! ("can't hash Bogus values"), + Self::BogusClosure (_) => panic! ("can't hash Bogus values"), + Self::BogusEnv (_) => panic! ("can't hash Bogus values"), + Self::BogusPrint => panic! ("can't hash Bogus values"), + } + } +} + +impl Value { + pub fn as_float (&self) -> Option { + match self { + Self::Float (x) => Some (*x), + // FloatToInt isn't stable yet, so only ints in i32 space can practically be used for now + Self::Integer (x) => f64::try_from (i32::try_from (*x).ok ()?).ok (), + _ => None, + } + } + + pub fn is_truthy (&self) -> bool { + // And this is something Lua does better than JS and Python. + + match self { + Value::Nil => false, + Value::Boolean (false) => false, + _ => true, + } + } + + pub fn take (&mut self) -> Self { + let mut x = Value::Nil; + std::mem::swap (self, &mut x); + x + } +}