♻️ refactor: extract value module
parent
693efa47bd
commit
e12d749c7c
|
@ -1,5 +1,6 @@
|
|||
mod loader;
|
||||
mod state;
|
||||
mod value;
|
||||
|
||||
#[cfg (test)]
|
||||
mod tests;
|
||||
|
|
108
src/state.rs
108
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 <Value>,
|
||||
}
|
||||
|
||||
#[derive (Clone, Debug, PartialEq)]
|
||||
pub enum Value {
|
||||
Nil,
|
||||
Boolean (bool),
|
||||
Float (f64),
|
||||
Integer (i64),
|
||||
String (Rc <String>),
|
||||
|
||||
// These are all bogus, I haven't figured out how to implement
|
||||
// tables and function pointers yet
|
||||
|
||||
BogusArg (Rc <Vec <String>>),
|
||||
BogusClosure (Rc <BogusClosure>),
|
||||
BogusEnv (Rc <BTreeMap <String, Value>>),
|
||||
BogusPrint,
|
||||
}
|
||||
|
||||
impl Default for Value {
|
||||
fn default () -> Self {
|
||||
Self::Nil
|
||||
}
|
||||
}
|
||||
|
||||
impl From <String> 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 <i32> for Value {
|
||||
fn from (x: i32) -> Self {
|
||||
Self::Integer (i64::try_from (x).unwrap ())
|
||||
}
|
||||
}
|
||||
|
||||
impl From <f64> for Value {
|
||||
fn from (x: f64) -> Self {
|
||||
Self::Float (x)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::hash::Hash for Value {
|
||||
fn hash <H: std::hash::Hasher> (&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 <f64> {
|
||||
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 <Instruction>,
|
||||
pub constants: Vec <Value>,
|
||||
|
|
|
@ -222,7 +222,7 @@ fn value_size () {
|
|||
let expected = 16;
|
||||
assert! (sz <= expected, "{sz} > {expected}");
|
||||
|
||||
let sz = size_of::<crate::state::Value> ();
|
||||
let sz = size_of::<crate::value::Value> ();
|
||||
let expected = 16;
|
||||
assert! (sz <= expected, "{sz} > {expected}");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
use std::{
|
||||
collections::BTreeMap,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
#[derive (Clone, Debug, Hash, PartialEq)]
|
||||
pub struct BogusClosure {
|
||||
pub idx: usize,
|
||||
pub upvalues: Vec <Value>,
|
||||
}
|
||||
|
||||
#[derive (Clone, Debug, PartialEq)]
|
||||
pub enum Value {
|
||||
Nil,
|
||||
Boolean (bool),
|
||||
Float (f64),
|
||||
Integer (i64),
|
||||
String (Rc <String>),
|
||||
|
||||
// These are all bogus, I haven't figured out how to implement
|
||||
// tables and function pointers yet
|
||||
|
||||
BogusArg (Rc <Vec <String>>),
|
||||
BogusClosure (Rc <BogusClosure>),
|
||||
BogusEnv (Rc <BTreeMap <String, Value>>),
|
||||
BogusPrint,
|
||||
}
|
||||
|
||||
impl Default for Value {
|
||||
fn default () -> Self {
|
||||
Self::Nil
|
||||
}
|
||||
}
|
||||
|
||||
impl From <String> 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 <i32> for Value {
|
||||
fn from (x: i32) -> Self {
|
||||
Self::Integer (i64::try_from (x).unwrap ())
|
||||
}
|
||||
}
|
||||
|
||||
impl From <f64> for Value {
|
||||
fn from (x: f64) -> Self {
|
||||
Self::Float (x)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::hash::Hash for Value {
|
||||
fn hash <H: std::hash::Hasher> (&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 <f64> {
|
||||
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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue