Make VMNumber and LuaNumber into structs

This commit is contained in:
Sofia 2026-03-17 20:19:58 +02:00
parent 4c8f52de1a
commit 3b18b6c71e
4 changed files with 67 additions and 42 deletions

View File

@ -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<T: Clone + Debug> {
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))

View File

@ -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()),
}),
));

View File

@ -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]),
}

View File

@ -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<Value, RuntimeError> {
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<Value, RuntimeError> {
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<Value, RuntimeError> {
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<Value, RuntimeError> {
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<Value, RuntimeError> {
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 {