From c37e95e445e1234ef05b536123df2aed479cf486 Mon Sep 17 00:00:00 2001 From: Sofia Date: Tue, 17 Mar 2026 20:43:57 +0200 Subject: [PATCH] Add operators for int as well --- src/ast.rs | 2 +- src/main.rs | 5 +-- src/vm.rs | 119 ++++++++++++++++++++++++++++++++++------------------ 3 files changed, 81 insertions(+), 45 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index aa0c4e4..f4b05b9 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -466,7 +466,7 @@ impl Parse for PrimaryExpression { } else if let Some(Token::DecimalValue(value)) = peeked { stream.next(); // Consume decimal value Expression::Literal(Literal::Integer(LuaInteger( - u64::from_str_radix(&value, 10).unwrap(), + i64::from_str_radix(&value, 10).unwrap(), ))) } else if let Some(Token::StringLit(value)) = peeked { stream.next(); // Consume string-literal diff --git a/src/main.rs b/src/main.rs index 7b853a1..849b71b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,10 +23,7 @@ impl RustFunction for Max { let lhs = parameters.get(0).cloned().unwrap_or(vm::Value::Nil); let rhs = parameters.get(1).cloned().unwrap_or(vm::Value::Nil); match lhs.lt(&rhs)? { - vm::Value::Float(value) => { - let res = value.lua_number(); - Ok(vec![if res.0 > 0. { rhs } else { lhs }]) - } + vm::Value::Integer(value) => Ok(vec![if value.0 > 0 { rhs } else { lhs }]), _ => Ok(vec![vm::Value::Nil]), } } diff --git a/src/vm.rs b/src/vm.rs index f853d1a..9f0b295 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -44,7 +44,7 @@ impl Debug for LuaFloat { } #[derive(Clone, Copy, Hash, PartialEq, Eq)] -pub struct LuaInteger(pub u64); +pub struct LuaInteger(pub i64); impl Debug for LuaInteger { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -52,6 +52,18 @@ impl Debug for LuaInteger { } } +impl From for LuaFloat { + fn from(value: LuaInteger) -> Self { + LuaFloat(value.0 as f64) + } +} + +impl From<&LuaInteger> for LuaFloat { + fn from(value: &LuaInteger) -> Self { + LuaFloat(value.0 as f64) + } +} + #[derive(Clone, Hash, PartialEq, Eq)] pub enum Constant { String(String), @@ -170,6 +182,8 @@ pub enum RuntimeError { InvalidTableIndex(Value), #[error("Value is not a table: {0:?}")] NotTable(Value), + #[error("Value is not coercable to a float: {0:?}")] + NotFloatable(Value), #[error("{0}")] Custom(String), } @@ -235,6 +249,14 @@ impl Value { Value::Table(_) => Err(RuntimeError::InvalidTableIndex(self)), } } + + pub fn as_float(&self) -> Result { + match self { + Value::Float(vmfloat) => Ok(vmfloat.lua_number()), + Value::Integer(lua_integer) => Ok(lua_integer.into()), + _ => Err(RuntimeError::NotFloatable(self.clone())), + } + } } #[derive(Debug, PartialEq, Eq, Hash, Clone)] @@ -249,8 +271,12 @@ pub enum IndexableValue { impl Value { pub fn add(&self, other: &Value) -> Result { match (self, other) { - (Value::Float(lhs), Value::Float(rhs)) => { - let res = LuaFloat(lhs.lua_number().0 + rhs.lua_number().0); + (Value::Integer(lhs), Value::Integer(rhs)) => { + let res = LuaInteger(lhs.0 + rhs.0); + Ok(Value::Integer(res)) + } + (Value::Float(_) | Value::Integer(_), Value::Float(_) | Value::Integer(_)) => { + let res = LuaFloat(self.as_float()?.0 + other.as_float()?.0); Ok(Value::Float(res.vm_number())) } _ => Err(RuntimeError::InvalidOperands( @@ -263,9 +289,13 @@ impl Value { pub fn eq(&self, other: &Value) -> Result { match (self, other) { - (Value::Float(lhs), Value::Float(rhs)) => { - let res = LuaFloat((lhs == rhs) as u64 as f64); - Ok(Value::Float(res.vm_number())) + (Value::Integer(lhs), Value::Integer(rhs)) => { + let res = LuaInteger((lhs.0 == rhs.0) as i64); + Ok(Value::Integer(res)) + } + (Value::Float(_) | Value::Integer(_), Value::Float(_) | Value::Integer(_)) => { + let res = LuaInteger((self.as_float()?.0 == other.as_float()?.0) as i64); + Ok(Value::Integer(res)) } _ => Err(RuntimeError::InvalidOperands( BinaryOperator::Equal, @@ -277,9 +307,13 @@ impl Value { pub fn lt(&self, other: &Value) -> Result { match (self, other) { - (Value::Float(lhs), Value::Float(rhs)) => { - let res = LuaFloat((lhs.lua_number().0 < rhs.lua_number().0) as u64 as f64); - Ok(Value::Float(res.vm_number())) + (Value::Integer(lhs), Value::Integer(rhs)) => { + let res = LuaInteger((lhs.0 < rhs.0) as i64); + Ok(Value::Integer(res)) + } + (Value::Float(_) | Value::Integer(_), Value::Float(_) | Value::Integer(_)) => { + let res = LuaInteger((self.as_float()?.0 < other.as_float()?.0) as i64); + Ok(Value::Integer(res)) } _ => Err(RuntimeError::InvalidOperands( BinaryOperator::LessThan, @@ -291,9 +325,13 @@ impl Value { pub fn lte(&self, other: &Value) -> Result { match (self, other) { - (Value::Float(lhs), Value::Float(rhs)) => { - let res = LuaFloat((lhs.lua_number().0 <= rhs.lua_number().0) as u64 as f64); - Ok(Value::Float(res.vm_number())) + (Value::Integer(lhs), Value::Integer(rhs)) => { + let res = LuaInteger((lhs.0 <= rhs.0) as i64); + Ok(Value::Integer(res)) + } + (Value::Float(_) | Value::Integer(_), Value::Float(_) | Value::Integer(_)) => { + let res = LuaInteger((self.as_float()?.0 <= other.as_float()?.0) as i64); + Ok(Value::Integer(res)) } _ => Err(RuntimeError::InvalidOperands( BinaryOperator::LessThanOrEqual, @@ -305,6 +343,10 @@ impl Value { pub fn unm(&self) -> Result { match self { + Value::Integer(lhs) => { + let res = LuaInteger(-lhs.0); + Ok(Value::Integer(res)) + } Value::Float(lhs) => { let res = LuaFloat(-lhs.lua_number().0); Ok(Value::Float(res.vm_number())) @@ -318,37 +360,37 @@ impl Value { pub fn and(&self, other: &Value) -> Result { match (self, other) { + (Value::Float(_) | Value::Integer(_), Value::Float(_) | Value::Integer(_)) => Ok( + Value::Integer(LuaInteger((self.is_truthy() && other.is_truthy()) as i64)), + ), + (Value::Float(_) | Value::Integer(_), _) => { + Ok(Value::Integer(LuaInteger(self.is_truthy() as i64))) + } + (_, Value::Float(_) | Value::Integer(_)) => { + Ok(Value::Integer(LuaInteger(other.is_truthy() as i64))) + } (Value::Nil, _) | (_, Value::Nil) => Ok(Value::Nil), - (Value::Float(lhs), Value::Float(rhs)) => { - let res = - LuaFloat((lhs.lua_number().0 > 0. && rhs.lua_number().0 > 0.) as u64 as f64); - Ok(Value::Float(res.vm_number())) - } - (Value::Float(value), _) | (_, Value::Float(value)) => { - let res = LuaFloat((value.lua_number().0 > 0.) as u64 as f64); - Ok(Value::Float(res.vm_number())) - } _ => Ok(Value::Nil), } } pub fn or(&self, other: &Value) -> Result { - match (self, other) { - (Value::Nil, value) | (value, Value::Nil) => Ok(value.clone()), - (Value::Float(lhs), Value::Float(rhs)) => { - let res = - LuaFloat((lhs.lua_number().0 > 0. || rhs.lua_number().0 > 0.) as u64 as f64); - Ok(Value::Float(res.vm_number())) - } - (Value::Float(value), other) => { - if value.lua_number().0 > 0. { - Ok(Value::Float(*value)) - } else { - Ok(other.clone()) - } - } - (value, _) => Ok(value.clone()), - _ => Ok(Value::Nil), + if self.is_truthy() { + Ok(self.clone()) + } else { + Ok(other.clone()) + } + } + + pub fn is_truthy(&self) -> bool { + match self { + Value::String(value) => value.len() > 0, + Value::Float(vmfloat) => vmfloat.lua_number().0 > 0., + Value::Integer(lua_integer) => lua_integer.0 > 0, + Value::RustFunction(_) => true, + Value::Function(_) => true, + Value::Nil => false, + Value::Table(value) => value.borrow().len() > 0, } } } @@ -594,13 +636,10 @@ impl ClosureRunner { } Instruction::SetGlobal(reg, global) => { let value = self.get_stack(*reg); - dbg!(&value); self.closure .environment .borrow_mut() .set_global(constants.get(*global as usize).unwrap().clone(), value); - - dbg!(&self.closure.environment); } Instruction::GetGlobal(reg, global) => { let glob = self