Compare commits

..

No commits in common. "8fe3ffc8e054f487e96cabc693bb3c93e3f20d2b" and "56943d612a4ba546330798917cfd7e99033fd27c" have entirely different histories.

8 changed files with 82 additions and 734 deletions

View File

@ -93,5 +93,3 @@ end
for k, v in (ipairs(table)) do
print(k, v)
end
print("hello " .. "there")

View File

@ -39,8 +39,8 @@ fn main() {
let mut vm = VirtualMachine::default();
vm.set_global("max".into(), Max.into()).unwrap();
vm.set_global("print".into(), Print.into()).unwrap();
vm.set_global("max".into(), Max.into());
vm.set_global("print".into(), Print.into());
dbg!(&compilation_unit);

View File

@ -480,11 +480,6 @@ impl Parse for IndexedAccess {
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
let mut expressions = Vec::new();
while let Some(Token::Symbol('[') | Token::Symbol('.')) = stream.peek() {
if let (Some(Token::Symbol('.')), Some(Token::Symbol('.'))) =
(stream.peek(), stream.peek2())
{
break;
}
match stream.next().unwrap() {
Token::Symbol('[') => {
let expression = stream.parse()?;
@ -563,10 +558,8 @@ pub struct PrimaryExpression(Node<Expression>);
#[derive(Debug, Clone, Copy)]
pub enum UnaryOperator {
Not,
Negation,
Length,
BitNot,
}
impl Parse for UnaryOperator {
@ -575,8 +568,6 @@ impl Parse for UnaryOperator {
match token {
Token::Symbol('-') => Ok(UnaryOperator::Negation),
Token::Symbol('#') => Ok(UnaryOperator::Length),
Token::Keyword(Keyword::Not) => Ok(UnaryOperator::Not),
Token::Symbol('~') => Ok(UnaryOperator::BitNot),
_ => Err(stream.expected_err("unop")),
}
} else {
@ -589,28 +580,13 @@ impl Parse for UnaryOperator {
pub enum BinaryOperator {
And,
Or,
Concat,
LessThan,
LessThanOrEqual,
GreaterThan,
GreaterThanOrEqual,
Equal,
NotEqual,
Add,
Sub,
Mult,
Div,
IDiv,
Mod,
Exp,
BitAnd,
BitOr,
BitXOr,
BitSRight,
BitSLeft,
}
impl BinaryOperator {
@ -618,32 +594,13 @@ impl BinaryOperator {
match self {
BinaryOperator::Or => 0,
BinaryOperator::And => 1,
BinaryOperator::LessThan => 10,
BinaryOperator::LessThanOrEqual => 10,
BinaryOperator::GreaterThan => 10,
BinaryOperator::GreaterThanOrEqual => 10,
BinaryOperator::Equal => 10,
BinaryOperator::NotEqual => 10,
BinaryOperator::BitOr => 20,
BinaryOperator::BitXOr => 21,
BinaryOperator::BitAnd => 22,
BinaryOperator::BitSLeft => 25,
BinaryOperator::BitSRight => 25,
BinaryOperator::Concat => 30,
BinaryOperator::Add => 40,
BinaryOperator::Sub => 40,
BinaryOperator::Mult => 50,
BinaryOperator::Div => 50,
BinaryOperator::IDiv => 50,
BinaryOperator::Mod => 50,
BinaryOperator::Exp => 60,
BinaryOperator::Add => 20,
BinaryOperator::Sub => 20,
}
}
}
@ -669,42 +626,10 @@ impl Parse for BinaryOperator {
stream.next();
Ok(BinaryOperator::Equal)
}
(Token::Symbol('~'), Some(Token::Symbol('='))) => {
stream.next();
Ok(BinaryOperator::NotEqual)
}
(Token::Symbol('.'), Some(Token::Symbol('.'))) => {
stream.next();
Ok(BinaryOperator::Concat)
}
(Token::Symbol('>'), Some(Token::Symbol('>'))) => {
stream.next();
Ok(BinaryOperator::BitSRight)
}
(Token::Symbol('<'), Some(Token::Symbol('<'))) => {
stream.next();
Ok(BinaryOperator::BitSLeft)
}
(Token::Symbol('/'), Some(Token::Symbol('/'))) => {
stream.next();
Ok(BinaryOperator::IDiv)
}
(Token::Symbol('<'), _) => Ok(BinaryOperator::LessThan),
(Token::Symbol('>'), _) => Ok(BinaryOperator::GreaterThan),
(Token::Symbol('+'), _) => Ok(BinaryOperator::Add),
(Token::Symbol('-'), _) => Ok(BinaryOperator::Sub),
(Token::Symbol('*'), _) => Ok(BinaryOperator::Mult),
(Token::Symbol('/'), _) => Ok(BinaryOperator::Div),
(Token::Symbol('%'), _) => Ok(BinaryOperator::Mod),
(Token::Symbol('^'), _) => Ok(BinaryOperator::Exp),
(Token::Symbol('&'), _) => Ok(BinaryOperator::BitAnd),
(Token::Symbol('|'), _) => Ok(BinaryOperator::BitOr),
(Token::Symbol('~'), _) => Ok(BinaryOperator::BitXOr),
_ => Err(stream.expected_err("binop")),
}
} else {
@ -799,9 +724,6 @@ impl Parse for PrimaryExpression {
);
}
Token::Symbol('[') | Token::Symbol('.') => {
if stream.peek2() == Some(Token::Symbol('.')) {
break;
}
let meta = Metadata::produce(&mut stream, pre.clone());
let IndexedAccess(accesses) = stream.parse()?;
for access in accesses {

View File

@ -1,4 +1,7 @@
use std::collections::{HashMap, HashSet};
use std::{
collections::{HashMap, HashSet},
num::IntErrorKind,
};
use crate::{
ast::{
@ -858,91 +861,6 @@ impl Expression {
*rhs.get(0).unwrap(),
)));
}
BinaryOperator::Concat => {
instructions.push(PreInstr::Instr(Instruction::Concat(
reg,
*lhs.get(0).unwrap(),
*rhs.get(0).unwrap(),
)));
}
BinaryOperator::NotEqual => {
instructions.push(PreInstr::Instr(Instruction::Equal(
reg,
*lhs.get(0).unwrap(),
*rhs.get(0).unwrap(),
)));
instructions.push(PreInstr::Instr(Instruction::Not(reg, reg)));
}
BinaryOperator::Mult => {
instructions.push(PreInstr::Instr(Instruction::Mult(
reg,
*lhs.get(0).unwrap(),
*rhs.get(0).unwrap(),
)));
}
BinaryOperator::Div => {
instructions.push(PreInstr::Instr(Instruction::Div(
reg,
*lhs.get(0).unwrap(),
*rhs.get(0).unwrap(),
)));
}
BinaryOperator::IDiv => {
instructions.push(PreInstr::Instr(Instruction::IDiv(
reg,
*lhs.get(0).unwrap(),
*rhs.get(0).unwrap(),
)));
}
BinaryOperator::Mod => {
instructions.push(PreInstr::Instr(Instruction::Mod(
reg,
*lhs.get(0).unwrap(),
*rhs.get(0).unwrap(),
)));
}
BinaryOperator::Exp => {
instructions.push(PreInstr::Instr(Instruction::Exp(
reg,
*lhs.get(0).unwrap(),
*rhs.get(0).unwrap(),
)));
}
BinaryOperator::BitAnd => {
instructions.push(PreInstr::Instr(Instruction::BitAnd(
reg,
*lhs.get(0).unwrap(),
*rhs.get(0).unwrap(),
)));
}
BinaryOperator::BitOr => {
instructions.push(PreInstr::Instr(Instruction::BitOr(
reg,
*lhs.get(0).unwrap(),
*rhs.get(0).unwrap(),
)));
}
BinaryOperator::BitXOr => {
instructions.push(PreInstr::Instr(Instruction::BitXOr(
reg,
*lhs.get(0).unwrap(),
*rhs.get(0).unwrap(),
)));
}
BinaryOperator::BitSRight => {
instructions.push(PreInstr::Instr(Instruction::BitSRight(
reg,
*lhs.get(0).unwrap(),
*rhs.get(0).unwrap(),
)));
}
BinaryOperator::BitSLeft => {
instructions.push(PreInstr::Instr(Instruction::BitSLeft(
reg,
*lhs.get(0).unwrap(),
*rhs.get(0).unwrap(),
)));
}
};
(instructions, vec![reg])
}
@ -958,12 +876,6 @@ impl Expression {
UnaryOperator::Length => {
instructions.push(PreInstr::Instr(Instruction::Len(*reg, *reg)))
}
UnaryOperator::Not => {
instructions.push(PreInstr::Instr(Instruction::Not(*reg, *reg)))
}
UnaryOperator::BitNot => {
instructions.push(PreInstr::Instr(Instruction::BitNot(*reg, *reg)))
}
}
}
(instructions, registers)
@ -1185,6 +1097,8 @@ fn compile_function_call(
instructions.push(PreInstr::Instr(Instruction::MoveRetValues(last_reg)));
}
let last_param_reg = param_regs.last().unwrap_or(&function_reg);
let mut return_regs = Vec::new();
if let Some(expected_values) = expected_values {
for i in 0..expected_values {

View File

@ -18,7 +18,7 @@
//! let compilation_unit = compile("print(\"hello\")", None).unwrap();
//!
//! let mut vm = vm::VirtualMachine::default();
//! vm.set_global("print".into(), Print.into()).unwrap();
//! vm.set_global("print".into(), Print.into());
//!
//! let mut runner = compilation_unit.with_virtual_machine(&mut vm).execute();
//!

View File

@ -286,7 +286,7 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
}
}
// "words"
c if c.is_alphabetic() || *c == '_' => {
c if c.is_alphabetic() => {
let mut value = character.to_string();
while let Some(c) = cursor.first() {
if !(c.is_ascii_alphanumeric() || c == '_') {

View File

@ -1,11 +1,11 @@
use thiserror::Error;
use std::{cell::RefCell, collections::HashMap, fmt::Debug, i64, rc::Rc};
use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};
use crate::{
CompilationUnit,
ast::{BinaryOperator, UnaryOperator},
vm::value::{Constant, IndexableValue, LuaInteger, Table, Value},
vm::value::{Constant, IndexableValue, LuaInteger, Value},
};
pub mod value;
@ -16,7 +16,6 @@ pub enum Instruction {
Move(u16, u16),
/// R(A) ... R(A + func_register - top) := previous function return values
MoveRetValues(u16),
/// R(A) := K(Bx)
LoadK(u16, u32),
/// R(A), ..., R(B) := nil
@ -35,58 +34,24 @@ pub enum Instruction {
SetList(u16, u32),
/// R(A) := R(B)[R(C)]
GetTable(u16, u16, u16),
/// R(A) := {}
NewTable(u16),
/// R(A) := R(B) .. R(C)
Concat(u16, u16, u16),
/// R(A) := R(B) + R(C)
Add(u16, u16, u16),
/// R(A) := R(B) * R(C)
Mult(u16, u16, u16),
/// R(A) := R(B) / R(C)
Div(u16, u16, u16),
/// R(A) := R(B) // R(C)
IDiv(u16, u16, u16),
/// R(A) := R(B) % R(C)
Mod(u16, u16, u16),
/// R(A) := R(B) ^ R(C)
Exp(u16, u16, u16),
/// R(A) := R(B) & R(C)
BitAnd(u16, u16, u16),
/// R(A) := R(B) | R(C)
BitOr(u16, u16, u16),
/// R(A) := R(B) ~ R(C)
BitXOr(u16, u16, u16),
/// R(A) := R(B) >> R(C)
BitSRight(u16, u16, u16),
/// R(A) := R(B) << R(C)
BitSLeft(u16, u16, u16),
/// R(A) := -R(B)
Unm(u16, u16),
/// R(A) := #R(B) (length operator)
Len(u16, u16),
/// R(A) := not R(B)
Not(u16, u16),
/// R(A) := ~R(B)
BitNot(u16, u16),
/// R(A) := R(B) == R(C)
Equal(u16, u16, u16),
/// R(A) := R(B) < R(C)
LessThan(u16, u16, u16),
/// R(A) := R(B) <= R(C)
LessThanOrEqual(u16, u16, u16),
/// R(A) := R(B) or R(C)
Or(u16, u16, u16),
/// R(A) := R(B) and R(C)
And(u16, u16, u16),
/// PC += sAx
Jmp(i32),
/// PC = Ax
@ -104,12 +69,10 @@ pub enum Instruction {
Call(u16, u16, u16),
/// return R(A), ... , R(B)
Return(u16, u16),
/// close stack variables up to R(A)
Close(u16),
/// R(A) := closure(KPROTO[Bx], R(A), ..., R(A+n))
Closure(u16, u32),
/// R(A), ... , R(A+B-2) := varargs
Vararg(u16, u16),
}
@ -142,35 +105,15 @@ impl Debug for Instruction {
Instruction::Close(arg0) => write!(f, "CLOSE {}", arg0),
Instruction::Closure(arg0, arg1) => write!(f, "CLOSURE {} {}", arg0, arg1),
Instruction::Return(arg0, arg1) => write!(f, "RETURN {} {}", arg0, arg1),
Instruction::Concat(arg0, arg1, arg2) => write!(f, "CONCAT {} {} {}", arg0, arg1, arg2),
Instruction::Equal(arg0, arg1, arg2) => write!(f, "EQ {} {} {}", arg0, arg1, arg2),
Instruction::LessThan(arg0, arg1, arg2) => write!(f, "LT {} {} {}", arg0, arg1, arg2),
Instruction::LessThanOrEqual(arg0, arg1, arg2) => {
write!(f, "LE {} {} {}", arg0, arg1, arg2)
}
Instruction::Add(arg0, arg1, arg2) => write!(f, "ADD {} {} {}", arg0, arg1, arg2),
Instruction::Mult(arg0, arg1, arg2) => write!(f, "MUL {} {} {}", arg0, arg1, arg2),
Instruction::Div(arg0, arg1, arg2) => write!(f, "DIV {} {} {}", arg0, arg1, arg2),
Instruction::IDiv(arg0, arg1, arg2) => write!(f, "IDIV {} {} {}", arg0, arg1, arg2),
Instruction::Mod(arg0, arg1, arg2) => write!(f, "MOD {} {} {}", arg0, arg1, arg2),
Instruction::Exp(arg0, arg1, arg2) => write!(f, "EXP {} {} {}", arg0, arg1, arg2),
Instruction::BitAnd(arg0, arg1, arg2) => write!(f, "BAND {} {} {}", arg0, arg1, arg2),
Instruction::BitOr(arg0, arg1, arg2) => write!(f, "BOR {} {} {}", arg0, arg1, arg2),
Instruction::BitXOr(arg0, arg1, arg2) => write!(f, "BXOR {} {} {}", arg0, arg1, arg2),
Instruction::BitSRight(arg0, arg1, arg2) => write!(f, "BSR {} {} {}", arg0, arg1, arg2),
Instruction::BitSLeft(arg0, arg1, arg2) => write!(f, "BSL {} {} {}", arg0, arg1, arg2),
Instruction::LoadNil(arg0, arg1) => write!(f, "LOADNIL {} {}", arg0, arg1),
Instruction::Unm(arg0, arg1) => write!(f, "UNM {} {}", arg0, arg1),
Instruction::Len(arg0, arg1) => write!(f, "LEN {} {}", arg0, arg1),
Instruction::Not(arg0, arg1) => write!(f, "NOT {} {}", arg0, arg1),
Instruction::BitNot(arg0, arg1) => write!(f, "BNOT {} {}", arg0, arg1),
Instruction::Or(arg0, arg1, arg2) => write!(f, "OR {} {} {}", arg0, arg1, arg2),
Instruction::And(arg0, arg1, arg2) => write!(f, "AND {} {} {}", arg0, arg1, arg2),
Instruction::Vararg(arg0, arg1) => write!(f, "VARARG {} {}", arg0, arg1),
@ -194,14 +137,42 @@ pub enum RuntimeError {
NotTable(Value),
#[error("Value is not coercable to a float: {0:?}")]
NotFloatable(Value),
#[error("Value is not coercable to bits: {0:?}")]
NotBittable(Value),
#[error("Value does not have a length: {0:?}")]
NotLengthable(Value),
#[error("{0}")]
Custom(String),
}
#[derive(Debug, Clone, Default)]
pub(crate) struct Environment {
pub globals: HashMap<Constant, Rc<RefCell<Value>>>,
}
impl Environment {
fn get_global(&mut self, key: &Constant) -> Option<StackValue> {
let value = self.globals.get_mut(key)?;
Some(match &*value.borrow() {
_ => StackValue::Value(value.borrow().clone()),
})
}
fn set_global(&mut self, key: Constant, value: StackValue) {
if let Some(existing) = self.globals.get_mut(&key) {
match value {
StackValue::Value(value) => {
*existing.borrow_mut() = value;
}
}
} else {
match value {
StackValue::Value(value) => {
self.globals.insert(key, Rc::new(RefCell::new(value)));
}
}
}
}
}
#[derive(Debug, Clone, Default)]
pub struct Prototype {
pub instructions: Vec<Instruction>,
@ -210,7 +181,7 @@ pub struct Prototype {
#[derive(Debug, Clone, Default)]
pub struct VirtualMachine {
pub(super) environment: Table,
pub(super) environment: Rc<RefCell<Environment>>,
pub(super) constants: Vec<Constant>,
pub(super) prototypes: HashMap<u32, Prototype>,
pub(super) proto_counter: u32,
@ -235,17 +206,16 @@ impl VirtualMachine {
}
}
pub fn set_global(&mut self, key: Value, value: Value) -> Result<(), RuntimeError> {
pub fn set_global(&mut self, key: Constant, value: Value) {
self.environment
.borrow_mut()
.insert(key.as_indexable()?, value);
Ok(())
.set_global(key, StackValue::Value(value));
}
pub fn get_globals(&self) -> HashMap<IndexableValue, Value> {
pub fn get_globals(&self) -> HashMap<Constant, Value> {
let mut values = HashMap::new();
for (key, value) in self.environment.borrow().iter() {
values.insert(key.clone(), value.clone());
for (key, value) in &self.environment.borrow().globals {
values.insert(key.clone(), value.borrow().clone());
}
values
@ -256,7 +226,7 @@ impl VirtualMachine {
pub struct Closure {
vm: VirtualMachine,
pub(crate) prototype: u32,
environment: Table,
environment: Rc<RefCell<Environment>>,
upvalues: HashMap<u16, Rc<RefCell<Value>>>,
}
@ -454,41 +424,23 @@ impl ClosureRunner {
}
Instruction::SetGlobal(reg, global) => {
let value = self.get_stack(*reg);
self.closure.environment.borrow_mut().insert(
constants
.get(*global as usize)
.unwrap()
.clone()
.as_value()
.as_indexable()?,
match value {
StackValue::Value(value) => value,
},
);
self.closure
.environment
.borrow_mut()
.set_global(constants.get(*global as usize).unwrap().clone(), value);
}
Instruction::GetGlobal(reg, global) => {
let constant = constants.get(*global as usize).unwrap().clone();
if let Constant::String(name) = &constant
&& name.clone() == "_ENV".to_owned()
{
self.set_stack(
*reg,
StackValue::Value(Value::Table(self.closure.environment.clone())),
);
let glob = self
.closure
.environment
.borrow_mut()
.get_global(constants.get(*global as usize).unwrap());
if let Some(global) = glob {
self.set_stack(*reg, global);
} else {
let environment = self.closure.environment.borrow_mut().clone();
let glob = environment
.get(&constant.as_value().as_indexable()?)
.cloned();
if let Some(global) = glob {
self.set_stack(*reg, StackValue::Value(global));
} else {
return Err(RuntimeError::GlobalNotFound(
constants.get(*global as usize).cloned(),
));
}
return Err(RuntimeError::GlobalNotFound(
constants.get(*global as usize).cloned(),
));
}
}
Instruction::GetUpVal(reg, upvalreg) => {
@ -737,21 +689,6 @@ impl ClosureRunner {
}
return Ok(Some(ret_values));
}
Instruction::Concat(res, lhs, rhs) => {
let lhs = self
.stack
.get(lhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
let rhs = self
.stack
.get(rhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.concat(&rhs)?));
}
Instruction::Add(res, lhs, rhs) => {
let lhs = self
.stack
@ -765,138 +702,6 @@ impl ClosureRunner {
.unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.add(&rhs)?));
}
Instruction::Mult(res, lhs, rhs) => {
let lhs = self
.stack
.get(lhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
let rhs = self
.stack
.get(rhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.mult(&rhs)?));
}
Instruction::Div(res, lhs, rhs) => {
let lhs = self
.stack
.get(lhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
let rhs = self
.stack
.get(rhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.div(&rhs)?));
}
Instruction::IDiv(res, lhs, rhs) => {
let lhs = self
.stack
.get(lhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
let rhs = self
.stack
.get(rhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.idiv(&rhs)?));
}
Instruction::Mod(res, lhs, rhs) => {
let lhs = self
.stack
.get(lhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
let rhs = self
.stack
.get(rhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.r#mod(&rhs)?));
}
Instruction::Exp(res, lhs, rhs) => {
let lhs = self
.stack
.get(lhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
let rhs = self
.stack
.get(rhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.exp(&rhs)?));
}
Instruction::BitAnd(res, lhs, rhs) => {
let lhs = self
.stack
.get(lhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
let rhs = self
.stack
.get(rhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.band(&rhs)?));
}
Instruction::BitOr(res, lhs, rhs) => {
let lhs = self
.stack
.get(lhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
let rhs = self
.stack
.get(rhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.bor(&rhs)?));
}
Instruction::BitXOr(res, lhs, rhs) => {
let lhs = self
.stack
.get(lhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
let rhs = self
.stack
.get(rhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.bxor(&rhs)?));
}
Instruction::BitSRight(res, lhs, rhs) => {
let lhs = self
.stack
.get(lhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
let rhs = self
.stack
.get(rhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.bsright(&rhs)?));
}
Instruction::BitSLeft(res, lhs, rhs) => {
let lhs = self
.stack
.get(lhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
let rhs = self
.stack
.get(rhs)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.bsleft(&rhs)?));
}
Instruction::Equal(res, lhs, rhs) => {
let lhs = self
.stack
@ -936,7 +741,6 @@ impl ClosureRunner {
.unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.lte(&rhs)?));
}
Instruction::Unm(res, reg) => {
self.set_stack(
*res,
@ -961,31 +765,6 @@ impl ClosureRunner {
),
);
}
Instruction::Not(res, reg) => {
self.set_stack(
*res,
StackValue::Value(
self.stack
.get(reg)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil)
.not()?,
),
);
}
Instruction::BitNot(res, reg) => {
self.set_stack(
*res,
StackValue::Value(
self.stack
.get(reg)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil)
.bxor(&Value::Integer(LuaInteger(u64::MAX as i64)))?,
),
);
}
Instruction::Or(res, lhs, rhs) => {
let lhs = self
.stack

View File

@ -1,9 +1,4 @@
use std::{
cell::RefCell,
collections::HashMap,
fmt::{Debug, Display},
rc::Rc,
};
use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};
use crate::{
ast::{BinaryOperator, UnaryOperator},
@ -36,7 +31,7 @@ impl LuaFloat {
impl Debug for LuaFloat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&self.0, f)
self.0.fmt(f)
}
}
@ -45,7 +40,7 @@ pub struct LuaInteger(pub i64);
impl Debug for LuaInteger {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&self.0, f)
self.0.fmt(f)
}
}
@ -66,7 +61,7 @@ pub struct LuaBool(pub bool);
impl Debug for LuaBool {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&self.0, f)
self.0.fmt(f)
}
}
@ -101,15 +96,9 @@ pub enum Constant {
Nil,
}
impl Constant {
pub fn as_value(self) -> Value {
match self {
Constant::String(value) => Value::String(value),
Constant::Float(vmfloat) => Value::Float(vmfloat),
Constant::Integer(lua_integer) => Value::Integer(lua_integer),
Constant::Bool(lua_bool) => Value::Boolean(lua_bool),
Constant::Nil => Value::Nil,
}
impl From<&str> for Constant {
fn from(value: &str) -> Self {
Constant::String(value.to_owned())
}
}
@ -125,8 +114,6 @@ impl Debug for Constant {
}
}
pub type Table = Rc<RefCell<HashMap<IndexableValue, Value>>>;
#[derive(Clone)]
pub enum Value {
String(String),
@ -136,7 +123,7 @@ pub enum Value {
RustFunction(Rc<RefCell<dyn RustFunction>>),
Function(Closure),
Nil,
Table(Table),
Table(Rc<RefCell<HashMap<IndexableValue, Value>>>),
}
impl Value {
@ -171,63 +158,19 @@ impl Value {
_ => Err(RuntimeError::NotFloatable(self.clone())),
}
}
pub fn as_bits(&self) -> Result<LuaInteger, RuntimeError> {
match self {
Value::Float(vmfloat) => Ok(LuaInteger(vmfloat.lua_number().0 as i64)),
Value::Integer(lua_integer) => Ok(LuaInteger(lua_integer.0 as i64)),
Value::Boolean(lua_bool) => Ok(LuaInteger(lua_bool.0 as i64)),
Value::Nil => Ok(LuaInteger(0)),
_ => Err(RuntimeError::NotFloatable(self.clone())),
}
}
}
impl From<&str> for Value {
fn from(value: &str) -> Self {
Value::String(value.to_owned())
}
}
impl Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Value::String(value) => Display::fmt(value, f),
Value::Float(vmfloat) => Display::fmt(&vmfloat.lua_number().0, f),
Value::Integer(lua_integer) => Display::fmt(&lua_integer.0, f),
Value::Boolean(lua_bool) => Display::fmt(&lua_bool.0, f),
Value::RustFunction(ref_cell) => {
write!(f, "<RustFunction({})>", ref_cell.borrow().as_indexable())
}
Value::Function(closure) => write!(f, "<function({})>", closure.prototype),
Value::Nil => write!(f, "nil"),
Value::Table(_) => write!(f, "<table>"),
}
}
#[derive(Debug, PartialEq, Eq, Hash, Clone, Ord, PartialOrd)]
pub enum IndexableValue {
String(String),
Float(VMFloat),
Integer(LuaInteger),
Bool(LuaBool),
RustFunction(String),
Function(u32),
}
impl Value {
pub fn concat(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) {
(
Value::String(_) | Value::Integer(_) | Value::Boolean(_),
Value::String(_) | Value::Integer(_) | Value::Boolean(_),
) => Ok(Value::String(format!("{}{}", self, other))),
(
Value::Float(_) | Value::Integer(_) | Value::Boolean(_),
Value::Float(_) | Value::Integer(_) | Value::Boolean(_),
) => {
let res = LuaFloat(self.as_float()?.0 * other.as_float()?.0);
Ok(Value::Float(res.vm_number()))
}
_ => Err(RuntimeError::InvalidOperands(
BinaryOperator::Concat,
self.clone(),
other.clone(),
)),
}
}
pub fn add(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) {
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
@ -249,196 +192,6 @@ impl Value {
}
}
pub fn mult(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) {
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
let res = LuaInteger(self.as_integer()?.0 * other.as_integer()?.0);
Ok(Value::Integer(res))
}
(
Value::Float(_) | Value::Integer(_) | Value::Boolean(_),
Value::Float(_) | Value::Integer(_) | Value::Boolean(_),
) => {
let res = LuaFloat(self.as_float()?.0 * other.as_float()?.0);
Ok(Value::Float(res.vm_number()))
}
_ => Err(RuntimeError::InvalidOperands(
BinaryOperator::Mult,
self.clone(),
other.clone(),
)),
}
}
pub fn div(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) {
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
let res = LuaFloat(self.as_integer()?.0 as f64 / other.as_integer()?.0 as f64);
Ok(Value::Float(res.vm_number()))
}
(
Value::Float(_) | Value::Integer(_) | Value::Boolean(_),
Value::Float(_) | Value::Integer(_) | Value::Boolean(_),
) => {
let res = LuaFloat(self.as_float()?.0 / other.as_float()?.0);
Ok(Value::Float(res.vm_number()))
}
_ => Err(RuntimeError::InvalidOperands(
BinaryOperator::Div,
self.clone(),
other.clone(),
)),
}
}
pub fn idiv(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) {
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
let res = LuaInteger(self.as_integer()?.0 / other.as_integer()?.0);
Ok(Value::Integer(res))
}
(
Value::Float(_) | Value::Integer(_) | Value::Boolean(_),
Value::Float(_) | Value::Integer(_) | Value::Boolean(_),
) => {
let res = LuaInteger((self.as_float()?.0 / other.as_float()?.0).floor() as i64);
Ok(Value::Integer(res))
}
_ => Err(RuntimeError::InvalidOperands(
BinaryOperator::IDiv,
self.clone(),
other.clone(),
)),
}
}
pub fn r#mod(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) {
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
let res = LuaInteger(self.as_integer()?.0 % other.as_integer()?.0);
Ok(Value::Integer(res))
}
(
Value::Float(_) | Value::Integer(_) | Value::Boolean(_),
Value::Float(_) | Value::Integer(_) | Value::Boolean(_),
) => {
let res = LuaFloat(self.as_float()?.0 % other.as_float()?.0);
Ok(Value::Float(res.vm_number()))
}
_ => Err(RuntimeError::InvalidOperands(
BinaryOperator::Mod,
self.clone(),
other.clone(),
)),
}
}
pub fn exp(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) {
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
let res = LuaInteger(self.as_integer()?.0.pow(other.as_integer()?.0 as u32));
Ok(Value::Integer(res))
}
(
Value::Float(_) | Value::Integer(_) | Value::Boolean(_),
Value::Float(_) | Value::Integer(_) | Value::Boolean(_),
) => {
let res = LuaFloat(self.as_float()?.0.powf(other.as_float()?.0));
Ok(Value::Float(res.vm_number()))
}
_ => Err(RuntimeError::InvalidOperands(
BinaryOperator::Exp,
self.clone(),
other.clone(),
)),
}
}
pub fn band(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) {
(
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
) => {
let res = LuaInteger(self.as_bits()?.0 & other.as_bits()?.0);
Ok(Value::Integer(res))
}
_ => Err(RuntimeError::InvalidOperands(
BinaryOperator::BitAnd,
self.clone(),
other.clone(),
)),
}
}
pub fn bor(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) {
(
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
) => {
let res = LuaInteger(self.as_bits()?.0 | other.as_bits()?.0);
Ok(Value::Integer(res))
}
_ => Err(RuntimeError::InvalidOperands(
BinaryOperator::BitOr,
self.clone(),
other.clone(),
)),
}
}
pub fn bxor(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) {
(
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
) => {
let res = LuaInteger(self.as_bits()?.0 ^ other.as_bits()?.0);
Ok(Value::Integer(res))
}
_ => Err(RuntimeError::InvalidOperands(
BinaryOperator::BitXOr,
self.clone(),
other.clone(),
)),
}
}
pub fn bsleft(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) {
(
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
) => {
let res = LuaInteger(self.as_bits()?.0 << other.as_bits()?.0);
Ok(Value::Integer(res))
}
_ => Err(RuntimeError::InvalidOperands(
BinaryOperator::BitSLeft,
self.clone(),
other.clone(),
)),
}
}
pub fn bsright(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) {
(
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
) => {
let res = LuaInteger(self.as_bits()?.0 >> other.as_bits()?.0);
Ok(Value::Integer(res))
}
_ => Err(RuntimeError::InvalidOperands(
BinaryOperator::BitSRight,
self.clone(),
other.clone(),
)),
}
}
pub fn eq(&self, other: &Value) -> Result<Value, RuntimeError> {
match (self, other) {
(Value::Integer(lhs), Value::Integer(rhs)) => {
@ -568,14 +321,6 @@ impl Value {
}
}
pub fn not(&self) -> Result<Value, RuntimeError> {
if self.is_truthy() {
Ok(Value::Boolean(LuaBool(false)))
} else {
Ok(Value::Boolean(LuaBool(true)))
}
}
pub fn is_truthy(&self) -> bool {
match self {
Value::String(_) => true,
@ -612,13 +357,3 @@ impl Debug for Value {
}
}
}
#[derive(Debug, PartialEq, Eq, Hash, Clone, Ord, PartialOrd)]
pub enum IndexableValue {
String(String),
Float(VMFloat),
Integer(LuaInteger),
Bool(LuaBool),
RustFunction(String),
Function(u32),
}