Add operators for int as well
This commit is contained in:
parent
0795957d0d
commit
c37e95e445
@ -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
|
||||
|
||||
@ -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]),
|
||||
}
|
||||
}
|
||||
|
||||
119
src/vm.rs
119
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<LuaInteger> 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<LuaFloat, RuntimeError> {
|
||||
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<Value, RuntimeError> {
|
||||
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<Value, RuntimeError> {
|
||||
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<Value, RuntimeError> {
|
||||
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<Value, RuntimeError> {
|
||||
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<Value, RuntimeError> {
|
||||
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<Value, RuntimeError> {
|
||||
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<Value, RuntimeError> {
|
||||
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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user