Add integers and floats separately

This commit is contained in:
Sofia 2026-03-17 20:26:13 +02:00
parent 3b18b6c71e
commit 0795957d0d
4 changed files with 82 additions and 59 deletions

View File

@ -5,7 +5,7 @@ use crate::{
Parse, TokenRange, TokenStream, TokenStreamError, Parse, TokenRange, TokenStream, TokenStreamError,
lexer::{Keyword, Position, Token}, lexer::{Keyword, Position, Token},
}, },
vm::LuaNumber, vm::{LuaFloat, LuaInteger},
}; };
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -465,8 +465,8 @@ impl Parse for PrimaryExpression {
Expression::FunctionDefinition(function.kind.params, function.kind.block) Expression::FunctionDefinition(function.kind.params, function.kind.block)
} else if let Some(Token::DecimalValue(value)) = peeked { } else if let Some(Token::DecimalValue(value)) = peeked {
stream.next(); // Consume decimal value stream.next(); // Consume decimal value
Expression::Literal(Literal::Number(LuaNumber( Expression::Literal(Literal::Integer(LuaInteger(
u64::from_str_radix(&value, 10).unwrap() as f64, u64::from_str_radix(&value, 10).unwrap(),
))) )))
} else if let Some(Token::StringLit(value)) = peeked { } else if let Some(Token::StringLit(value)) = peeked {
stream.next(); // Consume string-literal stream.next(); // Consume string-literal
@ -553,6 +553,7 @@ fn parse_binop_rhs(
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Literal { pub enum Literal {
Number(LuaNumber), Float(LuaFloat),
Integer(LuaInteger),
String(String), String(String),
} }

View File

@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet};
use crate::{ use crate::{
ast::{AccessModifier, BinaryOperator, Block, Expression, Literal, Statement, UnaryOperator}, ast::{AccessModifier, BinaryOperator, Block, Expression, Literal, Statement, UnaryOperator},
vm::{Constant, Instruction, VMNumber}, vm::{Constant, Instruction, VMFloat},
}; };
pub struct State { pub struct State {
@ -371,9 +371,14 @@ impl Expression {
constants constants
} }
Expression::Literal(literal) => match literal { Expression::Literal(literal) => match literal {
Literal::Number(value) => { Literal::Float(value) => {
let mut constants = HashSet::new(); let mut constants = HashSet::new();
constants.insert(Constant::Number(value.vm_number())); constants.insert(Constant::Float(value.vm_number()));
constants
}
Literal::Integer(value) => {
let mut constants = HashSet::new();
constants.insert(Constant::Integer(*value));
constants constants
} }
Literal::String(value) => { Literal::String(value) => {
@ -596,8 +601,9 @@ impl Expression {
instructions.push(Instruction::LoadK( instructions.push(Instruction::LoadK(
reg, reg,
state.get_constant(&match literal { state.get_constant(&match literal {
Literal::Number(value) => Constant::Number(value.vm_number()), Literal::Float(value) => Constant::Float(value.vm_number()),
Literal::String(value) => Constant::String(value.clone()), Literal::String(value) => Constant::String(value.clone()),
Literal::Integer(lua_integer) => Constant::Integer(*lua_integer),
}), }),
)); ));
(instructions, vec![reg]) (instructions, vec![reg])

View File

@ -6,7 +6,7 @@ use crate::{
TokenStream, TokenStream,
lexer::{Token, tokenize}, lexer::{Token, tokenize},
}, },
vm::{LuaNumber, RuntimeError, RustFunction, VirtualMachine}, vm::{LuaFloat, RuntimeError, RustFunction, VirtualMachine},
}; };
mod ast; mod ast;
@ -23,7 +23,7 @@ impl RustFunction for Max {
let lhs = parameters.get(0).cloned().unwrap_or(vm::Value::Nil); let lhs = parameters.get(0).cloned().unwrap_or(vm::Value::Nil);
let rhs = parameters.get(1).cloned().unwrap_or(vm::Value::Nil); let rhs = parameters.get(1).cloned().unwrap_or(vm::Value::Nil);
match lhs.lt(&rhs)? { match lhs.lt(&rhs)? {
vm::Value::Number(value) => { vm::Value::Float(value) => {
let res = value.lua_number(); let res = value.lua_number();
Ok(vec![if res.0 > 0. { rhs } else { lhs }]) Ok(vec![if res.0 > 0. { rhs } else { lhs }])
} }

114
src/vm.rs
View File

@ -14,30 +14,39 @@ use crate::{
}; };
#[derive(Clone, Hash, PartialEq, Eq, Copy)] #[derive(Clone, Hash, PartialEq, Eq, Copy)]
pub struct VMNumber(u64); pub struct VMFloat(u64);
impl VMNumber { impl VMFloat {
pub fn lua_number(&self) -> LuaNumber { pub fn lua_number(&self) -> LuaFloat {
LuaNumber(f64::from_bits(self.0)) LuaFloat(f64::from_bits(self.0))
} }
} }
#[derive(Clone, Copy)] impl Debug for VMFloat {
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 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.lua_number().fmt(f) self.lua_number().fmt(f)
} }
} }
impl Debug for LuaNumber { #[derive(Clone, Copy)]
pub struct LuaFloat(pub f64);
impl LuaFloat {
pub fn vm_number(&self) -> VMFloat {
VMFloat(f64::to_bits(self.0))
}
}
impl Debug for LuaFloat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
pub struct LuaInteger(pub u64);
impl Debug for LuaInteger {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f) self.0.fmt(f)
} }
@ -46,14 +55,16 @@ impl Debug for LuaNumber {
#[derive(Clone, Hash, PartialEq, Eq)] #[derive(Clone, Hash, PartialEq, Eq)]
pub enum Constant { pub enum Constant {
String(String), String(String),
Number(VMNumber), Float(VMFloat),
Integer(LuaInteger),
} }
impl Debug for Constant { impl Debug for Constant {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Self::String(arg0) => f.debug_tuple("String").field(arg0).finish(), Self::String(arg0) => f.debug_tuple("String").field(arg0).finish(),
Self::Number(arg0) => f.debug_tuple("Number").field(&arg0.lua_number()).finish(), Self::Float(arg0) => f.debug_tuple("Number").field(&arg0.lua_number()).finish(),
Self::Integer(arg0) => f.debug_tuple("Integer").field(arg0).finish(),
} }
} }
} }
@ -202,7 +213,8 @@ impl Environment {
#[derive(Clone)] #[derive(Clone)]
pub enum Value { pub enum Value {
String(String), String(String),
Number(VMNumber), Float(VMFloat),
Integer(LuaInteger),
RustFunction(Rc<RefCell<dyn RustFunction>>), RustFunction(Rc<RefCell<dyn RustFunction>>),
Function(Closure), Function(Closure),
Nil, Nil,
@ -213,7 +225,8 @@ impl Value {
pub fn as_indexable(self) -> Result<IndexableValue, RuntimeError> { pub fn as_indexable(self) -> Result<IndexableValue, RuntimeError> {
match self { match self {
Value::String(value) => Ok(IndexableValue::String(value)), Value::String(value) => Ok(IndexableValue::String(value)),
Value::Number(value) => Ok(IndexableValue::Number(value)), Value::Float(value) => Ok(IndexableValue::Number(value)),
Value::Integer(value) => Ok(IndexableValue::Integer(value)),
Value::RustFunction(value) => { Value::RustFunction(value) => {
Ok(IndexableValue::RustFunction(value.borrow().as_indexable())) Ok(IndexableValue::RustFunction(value.borrow().as_indexable()))
} }
@ -227,7 +240,8 @@ impl Value {
#[derive(Debug, PartialEq, Eq, Hash, Clone)] #[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub enum IndexableValue { pub enum IndexableValue {
String(String), String(String),
Number(VMNumber), Number(VMFloat),
Integer(LuaInteger),
RustFunction(String), RustFunction(String),
Function(u32), Function(u32),
} }
@ -235,9 +249,9 @@ pub enum IndexableValue {
impl Value { impl Value {
pub fn add(&self, other: &Value) -> Result<Value, RuntimeError> { pub fn add(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) { match (self, other) {
(Value::Number(lhs), Value::Number(rhs)) => { (Value::Float(lhs), Value::Float(rhs)) => {
let res = LuaNumber(lhs.lua_number().0 + rhs.lua_number().0); let res = LuaFloat(lhs.lua_number().0 + rhs.lua_number().0);
Ok(Value::Number(res.vm_number())) Ok(Value::Float(res.vm_number()))
} }
_ => Err(RuntimeError::InvalidOperands( _ => Err(RuntimeError::InvalidOperands(
BinaryOperator::Add, BinaryOperator::Add,
@ -249,9 +263,9 @@ impl Value {
pub fn eq(&self, other: &Value) -> Result<Value, RuntimeError> { pub fn eq(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) { match (self, other) {
(Value::Number(lhs), Value::Number(rhs)) => { (Value::Float(lhs), Value::Float(rhs)) => {
let res = LuaNumber((lhs == rhs) as u64 as f64); let res = LuaFloat((lhs == rhs) as u64 as f64);
Ok(Value::Number(res.vm_number())) Ok(Value::Float(res.vm_number()))
} }
_ => Err(RuntimeError::InvalidOperands( _ => Err(RuntimeError::InvalidOperands(
BinaryOperator::Equal, BinaryOperator::Equal,
@ -263,9 +277,9 @@ impl Value {
pub fn lt(&self, other: &Value) -> Result<Value, RuntimeError> { pub fn lt(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) { match (self, other) {
(Value::Number(lhs), Value::Number(rhs)) => { (Value::Float(lhs), Value::Float(rhs)) => {
let res = LuaNumber((lhs.lua_number().0 < rhs.lua_number().0) as u64 as f64); let res = LuaFloat((lhs.lua_number().0 < rhs.lua_number().0) as u64 as f64);
Ok(Value::Number(res.vm_number())) Ok(Value::Float(res.vm_number()))
} }
_ => Err(RuntimeError::InvalidOperands( _ => Err(RuntimeError::InvalidOperands(
BinaryOperator::LessThan, BinaryOperator::LessThan,
@ -277,9 +291,9 @@ impl Value {
pub fn lte(&self, other: &Value) -> Result<Value, RuntimeError> { pub fn lte(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) { match (self, other) {
(Value::Number(lhs), Value::Number(rhs)) => { (Value::Float(lhs), Value::Float(rhs)) => {
let res = LuaNumber((lhs.lua_number().0 <= rhs.lua_number().0) as u64 as f64); let res = LuaFloat((lhs.lua_number().0 <= rhs.lua_number().0) as u64 as f64);
Ok(Value::Number(res.vm_number())) Ok(Value::Float(res.vm_number()))
} }
_ => Err(RuntimeError::InvalidOperands( _ => Err(RuntimeError::InvalidOperands(
BinaryOperator::LessThanOrEqual, BinaryOperator::LessThanOrEqual,
@ -291,9 +305,9 @@ impl Value {
pub fn unm(&self) -> Result<Value, RuntimeError> { pub fn unm(&self) -> Result<Value, RuntimeError> {
match self { match self {
Value::Number(lhs) => { Value::Float(lhs) => {
let res = LuaNumber(-lhs.lua_number().0); let res = LuaFloat(-lhs.lua_number().0);
Ok(Value::Number(res.vm_number())) Ok(Value::Float(res.vm_number()))
} }
_ => Err(RuntimeError::InvalidOperand( _ => Err(RuntimeError::InvalidOperand(
UnaryOperator::Negation, UnaryOperator::Negation,
@ -305,14 +319,14 @@ impl Value {
pub fn and(&self, other: &Value) -> Result<Value, RuntimeError> { pub fn and(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) { match (self, other) {
(Value::Nil, _) | (_, Value::Nil) => Ok(Value::Nil), (Value::Nil, _) | (_, Value::Nil) => Ok(Value::Nil),
(Value::Number(lhs), Value::Number(rhs)) => { (Value::Float(lhs), Value::Float(rhs)) => {
let res = let res =
LuaNumber((lhs.lua_number().0 > 0. && rhs.lua_number().0 > 0.) as u64 as f64); LuaFloat((lhs.lua_number().0 > 0. && rhs.lua_number().0 > 0.) as u64 as f64);
Ok(Value::Number(res.vm_number())) Ok(Value::Float(res.vm_number()))
} }
(Value::Number(value), _) | (_, Value::Number(value)) => { (Value::Float(value), _) | (_, Value::Float(value)) => {
let res = LuaNumber((value.lua_number().0 > 0.) as u64 as f64); let res = LuaFloat((value.lua_number().0 > 0.) as u64 as f64);
Ok(Value::Number(res.vm_number())) Ok(Value::Float(res.vm_number()))
} }
_ => Ok(Value::Nil), _ => Ok(Value::Nil),
} }
@ -321,14 +335,14 @@ impl Value {
pub fn or(&self, other: &Value) -> Result<Value, RuntimeError> { pub fn or(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) { match (self, other) {
(Value::Nil, value) | (value, Value::Nil) => Ok(value.clone()), (Value::Nil, value) | (value, Value::Nil) => Ok(value.clone()),
(Value::Number(lhs), Value::Number(rhs)) => { (Value::Float(lhs), Value::Float(rhs)) => {
let res = let res =
LuaNumber((lhs.lua_number().0 > 0. || rhs.lua_number().0 > 0.) as u64 as f64); LuaFloat((lhs.lua_number().0 > 0. || rhs.lua_number().0 > 0.) as u64 as f64);
Ok(Value::Number(res.vm_number())) Ok(Value::Float(res.vm_number()))
} }
(Value::Number(value), other) => { (Value::Float(value), other) => {
if value.lua_number().0 > 0. { if value.lua_number().0 > 0. {
Ok(Value::Number(*value)) Ok(Value::Float(*value))
} else { } else {
Ok(other.clone()) Ok(other.clone())
} }
@ -342,7 +356,8 @@ impl Value {
impl Debug for Value { impl Debug for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Value::Number(arg0) => f.debug_tuple("Number").field(&arg0.lua_number()).finish(), Value::Float(arg0) => f.debug_tuple("Number").field(&arg0.lua_number()).finish(),
Value::Integer(arg0) => f.debug_tuple("Integer").field(arg0).finish(),
Value::String(value) => f.debug_tuple("String").field(value).finish(), Value::String(value) => f.debug_tuple("String").field(value).finish(),
Value::RustFunction(arg0) => f.debug_tuple("RustFunction").field(arg0).finish(), Value::RustFunction(arg0) => f.debug_tuple("RustFunction").field(arg0).finish(),
Value::Function(closure) => f Value::Function(closure) => f
@ -567,7 +582,8 @@ impl ClosureRunner {
*reg, *reg,
StackValue::Value(match constants.get(*constant as usize).unwrap() { StackValue::Value(match constants.get(*constant as usize).unwrap() {
Constant::String(value) => Value::String(value.clone()), Constant::String(value) => Value::String(value.clone()),
Constant::Number(value) => Value::Number(*value), Constant::Float(value) => Value::Float(*value),
Constant::Integer(value) => Value::Integer(*value),
}), }),
); );
} }
@ -687,7 +703,7 @@ impl ClosureRunner {
.map(|v| v.borrow().clone()) .map(|v| v.borrow().clone())
.unwrap_or(Value::Nil) .unwrap_or(Value::Nil)
{ {
Value::Number(val) => (val.lua_number().0 as u16) == *c, Value::Float(val) => (val.lua_number().0 as u16) == *c,
_ => false, _ => false,
}; };
if is_true { if is_true {