diff --git a/src/ast.rs b/src/ast.rs index edc33bd..903c80a 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,12 +1,13 @@ use std::{fmt::Debug, hash::Hash, ops::Add, path::PathBuf}; -use crate::token_stream::{ - Parse, TokenRange, TokenStream, TokenStreamError, - lexer::{Keyword, Position, Token}, +use crate::{ + token_stream::{ + Parse, TokenRange, TokenStream, TokenStreamError, + lexer::{Keyword, Position, Token}, + }, + vm::LuaNumber, }; -pub type LuaNumber = f64; - #[derive(Debug, Clone)] pub struct Node { pub kind: T, @@ -464,9 +465,9 @@ impl Parse for PrimaryExpression { Expression::FunctionDefinition(function.kind.params, function.kind.block) } else if let Some(Token::DecimalValue(value)) = peeked { stream.next(); // Consume decimal value - Expression::Literal(Literal::Number( - u64::from_str_radix(&value, 10).unwrap() as f64 - )) + Expression::Literal(Literal::Number(LuaNumber( + u64::from_str_radix(&value, 10).unwrap() as f64, + ))) } else if let Some(Token::StringLit(value)) = peeked { stream.next(); // Consume string-literal Expression::Literal(Literal::String(value)) diff --git a/src/compile.rs b/src/compile.rs index 5cb371f..b06b674 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -373,7 +373,7 @@ impl Expression { Expression::Literal(literal) => match literal { Literal::Number(value) => { let mut constants = HashSet::new(); - constants.insert(Constant::Number(value.to_bits())); + constants.insert(Constant::Number(value.vm_number())); constants } Literal::String(value) => { @@ -596,7 +596,7 @@ impl Expression { instructions.push(Instruction::LoadK( reg, state.get_constant(&match literal { - Literal::Number(value) => Constant::Number(value.to_bits()), + Literal::Number(value) => Constant::Number(value.vm_number()), Literal::String(value) => Constant::String(value.clone()), }), )); diff --git a/src/main.rs b/src/main.rs index 58e372f..8dd9609 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,12 @@ use std::{cell::RefCell, path::PathBuf, rc::Rc}; use crate::{ - ast::{Block, Function, LuaNumber}, + ast::{Block, Function}, token_stream::{ TokenStream, lexer::{Token, tokenize}, }, - vm::{RuntimeError, RustFunction, VirtualMachine}, + vm::{LuaNumber, RuntimeError, RustFunction, VirtualMachine}, }; mod ast; @@ -24,8 +24,8 @@ impl RustFunction for Max { let rhs = parameters.get(1).cloned().unwrap_or(vm::Value::Nil); match lhs.lt(&rhs)? { vm::Value::Number(value) => { - let res = LuaNumber::from_bits(value); - Ok(vec![if res > 0. { rhs } else { lhs }]) + let res = value.lua_number(); + Ok(vec![if res.0 > 0. { rhs } else { lhs }]) } _ => Ok(vec![vm::Value::Nil]), } diff --git a/src/vm.rs b/src/vm.rs index 4d5a4a5..70384b3 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -9,11 +9,39 @@ use std::{ }; use crate::{ - ast::{BinaryOperator, LuaNumber, UnaryOperator}, + ast::{BinaryOperator, UnaryOperator}, compile, }; -pub type VMNumber = u64; +#[derive(Clone, Hash, PartialEq, Eq, Copy)] +pub struct VMNumber(u64); + +impl VMNumber { + pub fn lua_number(&self) -> LuaNumber { + LuaNumber(f64::from_bits(self.0)) + } +} + +#[derive(Clone, Copy)] +pub struct LuaNumber(pub f64); + +impl LuaNumber { + pub fn vm_number(&self) -> VMNumber { + VMNumber(f64::to_bits(self.0)) + } +} + +impl Debug for VMNumber { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.lua_number().fmt(f) + } +} + +impl Debug for LuaNumber { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} #[derive(Clone, Hash, PartialEq, Eq)] pub enum Constant { @@ -25,10 +53,7 @@ impl Debug for Constant { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::String(arg0) => f.debug_tuple("String").field(arg0).finish(), - Self::Number(arg0) => f - .debug_tuple("Number") - .field(&LuaNumber::from_bits(*arg0)) - .finish(), + Self::Number(arg0) => f.debug_tuple("Number").field(&arg0.lua_number()).finish(), } } } @@ -211,8 +236,8 @@ impl Value { pub fn add(&self, other: &Value) -> Result { match (self, other) { (Value::Number(lhs), Value::Number(rhs)) => { - let res = LuaNumber::from_bits(*lhs) + LuaNumber::from_bits(*rhs); - Ok(Value::Number(res.to_bits())) + let res = LuaNumber(lhs.lua_number().0 + rhs.lua_number().0); + Ok(Value::Number(res.vm_number())) } _ => Err(RuntimeError::InvalidOperands( BinaryOperator::Add, @@ -225,8 +250,8 @@ impl Value { pub fn eq(&self, other: &Value) -> Result { match (self, other) { (Value::Number(lhs), Value::Number(rhs)) => { - let res = lhs == rhs; - Ok(Value::Number((res as u64 as f64).to_bits())) + let res = LuaNumber((lhs == rhs) as u64 as f64); + Ok(Value::Number(res.vm_number())) } _ => Err(RuntimeError::InvalidOperands( BinaryOperator::Equal, @@ -239,8 +264,8 @@ impl Value { pub fn lt(&self, other: &Value) -> Result { match (self, other) { (Value::Number(lhs), Value::Number(rhs)) => { - let res = LuaNumber::from_bits(*lhs) < LuaNumber::from_bits(*rhs); - Ok(Value::Number((res as u64 as f64).to_bits())) + let res = LuaNumber((lhs.lua_number().0 < rhs.lua_number().0) as u64 as f64); + Ok(Value::Number(res.vm_number())) } _ => Err(RuntimeError::InvalidOperands( BinaryOperator::LessThan, @@ -253,8 +278,8 @@ impl Value { pub fn lte(&self, other: &Value) -> Result { match (self, other) { (Value::Number(lhs), Value::Number(rhs)) => { - let res = LuaNumber::from_bits(*lhs) <= LuaNumber::from_bits(*rhs); - Ok(Value::Number((res as u64 as f64).to_bits())) + let res = LuaNumber((lhs.lua_number().0 <= rhs.lua_number().0) as u64 as f64); + Ok(Value::Number(res.vm_number())) } _ => Err(RuntimeError::InvalidOperands( BinaryOperator::LessThanOrEqual, @@ -267,8 +292,8 @@ impl Value { pub fn unm(&self) -> Result { match self { Value::Number(lhs) => { - let res = -LuaNumber::from_bits(*lhs); - Ok(Value::Number(res.to_bits())) + let res = LuaNumber(-lhs.lua_number().0); + Ok(Value::Number(res.vm_number())) } _ => Err(RuntimeError::InvalidOperand( UnaryOperator::Negation, @@ -281,12 +306,13 @@ impl Value { match (self, other) { (Value::Nil, _) | (_, Value::Nil) => Ok(Value::Nil), (Value::Number(lhs), Value::Number(rhs)) => { - let res = LuaNumber::from_bits(*lhs) > 0. && LuaNumber::from_bits(*rhs) > 0.; - Ok(Value::Number((res as u64 as f64).to_bits())) + let res = + LuaNumber((lhs.lua_number().0 > 0. && rhs.lua_number().0 > 0.) as u64 as f64); + Ok(Value::Number(res.vm_number())) } (Value::Number(value), _) | (_, Value::Number(value)) => { - let res = LuaNumber::from_bits(*value) > 0.; - Ok(Value::Number((res as u64 as f64).to_bits())) + let res = LuaNumber((value.lua_number().0 > 0.) as u64 as f64); + Ok(Value::Number(res.vm_number())) } _ => Ok(Value::Nil), } @@ -296,11 +322,12 @@ impl Value { match (self, other) { (Value::Nil, value) | (value, Value::Nil) => Ok(value.clone()), (Value::Number(lhs), Value::Number(rhs)) => { - let res = LuaNumber::from_bits(*lhs) > 0. || LuaNumber::from_bits(*rhs) > 0.; - Ok(Value::Number((res as u64 as f64).to_bits())) + let res = + LuaNumber((lhs.lua_number().0 > 0. || rhs.lua_number().0 > 0.) as u64 as f64); + Ok(Value::Number(res.vm_number())) } (Value::Number(value), other) => { - if LuaNumber::from_bits(*value) > 0. { + if value.lua_number().0 > 0. { Ok(Value::Number(*value)) } else { Ok(other.clone()) @@ -315,10 +342,7 @@ impl Value { impl Debug for Value { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Value::Number(arg0) => f - .debug_tuple("Number") - .field(&LuaNumber::from_bits(*arg0)) - .finish(), + Value::Number(arg0) => f.debug_tuple("Number").field(&arg0.lua_number()).finish(), Value::String(value) => f.debug_tuple("String").field(value).finish(), Value::RustFunction(arg0) => f.debug_tuple("RustFunction").field(arg0).finish(), Value::Function(closure) => f @@ -663,7 +687,7 @@ impl ClosureRunner { .map(|v| v.borrow().clone()) .unwrap_or(Value::Nil) { - Value::Number(val) => (LuaNumber::from_bits(val) as u16) == *c, + Value::Number(val) => (val.lua_number().0 as u16) == *c, _ => false, }; if is_true {