Add UserData generic everywhere
This commit is contained in:
parent
d717718a9c
commit
641aa878bb
@ -1,14 +1,22 @@
|
|||||||
use ferrite_lua::{
|
use ferrite_lua::{
|
||||||
compile,
|
compile,
|
||||||
vm::{RuntimeError, VirtualMachine, value},
|
vm::{
|
||||||
|
RuntimeError, VirtualMachine,
|
||||||
|
value::{self, AsValue},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static TEST: &str = include_str!("../examples/test.lua");
|
static TEST: &str = include_str!("../examples/test.lua");
|
||||||
|
|
||||||
|
type UserData = ();
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct Max;
|
pub struct Max;
|
||||||
impl value::RustFunction for Max {
|
impl value::RustFunction<UserData> for Max {
|
||||||
fn execute(&self, parameters: Vec<value::Value>) -> Result<Vec<value::Value>, RuntimeError> {
|
fn execute(
|
||||||
|
&self,
|
||||||
|
parameters: Vec<value::Value<UserData>>,
|
||||||
|
) -> Result<Vec<value::Value<UserData>>, RuntimeError<UserData>> {
|
||||||
let lhs = parameters.get(0).cloned().unwrap_or(value::Value::Nil);
|
let lhs = parameters.get(0).cloned().unwrap_or(value::Value::Nil);
|
||||||
let rhs = parameters.get(1).cloned().unwrap_or(value::Value::Nil);
|
let rhs = parameters.get(1).cloned().unwrap_or(value::Value::Nil);
|
||||||
match lhs.lt(&rhs)? {
|
match lhs.lt(&rhs)? {
|
||||||
@ -23,8 +31,11 @@ impl value::RustFunction for Max {
|
|||||||
}
|
}
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct Print;
|
pub struct Print;
|
||||||
impl value::RustFunction for Print {
|
impl value::RustFunction<UserData> for Print {
|
||||||
fn execute(&self, parameters: Vec<value::Value>) -> Result<Vec<value::Value>, RuntimeError> {
|
fn execute(
|
||||||
|
&self,
|
||||||
|
parameters: Vec<value::Value<UserData>>,
|
||||||
|
) -> Result<Vec<value::Value<UserData>>, RuntimeError<UserData>> {
|
||||||
println!(
|
println!(
|
||||||
"{}",
|
"{}",
|
||||||
parameters
|
parameters
|
||||||
@ -46,8 +57,8 @@ fn main() {
|
|||||||
|
|
||||||
let mut vm = VirtualMachine::default();
|
let mut vm = VirtualMachine::default();
|
||||||
|
|
||||||
vm.set_global("max".into(), Max.into()).unwrap();
|
vm.set_global("max".into(), Max.as_value()).unwrap();
|
||||||
vm.set_global("print".into(), Print.into()).unwrap();
|
vm.set_global("print".into(), Print.as_value()).unwrap();
|
||||||
|
|
||||||
dbg!(&compilation_unit);
|
dbg!(&compilation_unit);
|
||||||
|
|
||||||
|
|||||||
23
src/lib.rs
23
src/lib.rs
@ -1,11 +1,13 @@
|
|||||||
//! Usage example:
|
//! Usage example:
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use ferrite_lua::{compile, vm::{self, value}};
|
//! use ferrite_lua::{compile, vm::{self, value::{self, AsValue}}};
|
||||||
|
//!
|
||||||
|
//! type UserData = ();
|
||||||
//!
|
//!
|
||||||
//! #[derive(Debug, PartialEq, Eq)]
|
//! #[derive(Debug, PartialEq, Eq)]
|
||||||
//! pub struct Print;
|
//! pub struct Print;
|
||||||
//! impl value::RustFunction for Print {
|
//! impl value::RustFunction<UserData> for Print {
|
||||||
//! fn execute(&self, parameters: Vec<value::Value>) -> Result<Vec<value::Value>, vm::RuntimeError> {
|
//! fn execute(&self, parameters: Vec<value::Value<UserData>>) -> Result<Vec<value::Value<UserData>>, vm::RuntimeError<UserData>> {
|
||||||
//! println!("{:?}", parameters);
|
//! println!("{:?}", parameters);
|
||||||
//! Ok(Vec::new())
|
//! Ok(Vec::new())
|
||||||
//! }
|
//! }
|
||||||
@ -18,7 +20,7 @@
|
|||||||
//! let compilation_unit = compile("print(\"hello\")", None).unwrap();
|
//! let compilation_unit = compile("print(\"hello\")", None).unwrap();
|
||||||
//!
|
//!
|
||||||
//! let mut vm = vm::VirtualMachine::default();
|
//! let mut vm = vm::VirtualMachine::default();
|
||||||
//! vm.set_global("print".into(), Print.into()).unwrap();
|
//! vm.set_global("print".into(), Print.as_value()).unwrap();
|
||||||
//!
|
//!
|
||||||
//! let mut runner = compilation_unit.with_virtual_machine(&mut vm).execute();
|
//! let mut runner = compilation_unit.with_virtual_machine(&mut vm).execute();
|
||||||
//!
|
//!
|
||||||
@ -70,7 +72,10 @@ impl Debug for CompilationUnit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CompilationUnit {
|
impl CompilationUnit {
|
||||||
pub fn with_virtual_machine<'a>(&self, vm: &'a mut VirtualMachine) -> ExecutionUnit<'a> {
|
pub fn with_virtual_machine<'a, UserData: Clone>(
|
||||||
|
&self,
|
||||||
|
vm: &'a mut VirtualMachine<UserData>,
|
||||||
|
) -> ExecutionUnit<'a, UserData> {
|
||||||
let chunk_id = vm.new_prototype(vm::Prototype {
|
let chunk_id = vm.new_prototype(vm::Prototype {
|
||||||
instructions: self.instructions.clone(),
|
instructions: self.instructions.clone(),
|
||||||
parameters: 0,
|
parameters: 0,
|
||||||
@ -85,13 +90,13 @@ impl CompilationUnit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ExecutionUnit<'a> {
|
pub struct ExecutionUnit<'a, UserData: Clone> {
|
||||||
chunk_id: u32,
|
chunk_id: u32,
|
||||||
vm: &'a mut VirtualMachine,
|
vm: &'a mut VirtualMachine<UserData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ExecutionUnit<'a> {
|
impl<'a, UserData: Clone> ExecutionUnit<'a, UserData> {
|
||||||
pub fn execute(self) -> ClosureRunner {
|
pub fn execute(self) -> ClosureRunner<UserData> {
|
||||||
let closure = self.vm.create_closure(self.chunk_id);
|
let closure = self.vm.create_closure(self.chunk_id);
|
||||||
closure.run(Vec::new())
|
closure.run(Vec::new())
|
||||||
}
|
}
|
||||||
|
|||||||
127
src/vm/mod.rs
127
src/vm/mod.rs
@ -12,8 +12,11 @@ pub mod value;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SetMetatable;
|
pub struct SetMetatable;
|
||||||
impl RustFunction for SetMetatable {
|
impl<UserData: Clone> RustFunction<UserData> for SetMetatable {
|
||||||
fn execute(&self, parameters: Vec<Value>) -> Result<Vec<Value>, RuntimeError> {
|
fn execute(
|
||||||
|
&self,
|
||||||
|
parameters: Vec<Value<UserData>>,
|
||||||
|
) -> Result<Vec<Value<UserData>>, RuntimeError<UserData>> {
|
||||||
let table = parameters
|
let table = parameters
|
||||||
.get(0)
|
.get(0)
|
||||||
.ok_or(RuntimeError::NotTable(Value::Nil))?;
|
.ok_or(RuntimeError::NotTable(Value::Nil))?;
|
||||||
@ -215,35 +218,35 @@ impl Debug for Instruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum RuntimeError {
|
pub enum RuntimeError<UserData: Clone> {
|
||||||
#[error("Unable to perform {0:?} operator between {1:?} and {2:?}")]
|
#[error("Unable to perform {0:?} operator between {1:?} and {2:?}")]
|
||||||
InvalidOperands(BinaryOperator, Value, Value),
|
InvalidOperands(BinaryOperator, Value<UserData>, Value<UserData>),
|
||||||
#[error("Unable to call metamethod {0} for values {1:?} and {2:?}")]
|
#[error("Unable to call metamethod {0} for values {1:?} and {2:?}")]
|
||||||
InvalidBinop(String, Value, Value),
|
InvalidBinop(String, Value<UserData>, Value<UserData>),
|
||||||
#[error("Unable to call metamethod {0} for value {1:?}")]
|
#[error("Unable to call metamethod {0} for value {1:?}")]
|
||||||
InvalidUnop(String, Value),
|
InvalidUnop(String, Value<UserData>),
|
||||||
#[error("Metatable is not a table: {0:?}")]
|
#[error("Metatable is not a table: {0:?}")]
|
||||||
MetatableNotTable(Value),
|
MetatableNotTable(Value<UserData>),
|
||||||
#[error("Metafunction not found: {0} for {1:?}")]
|
#[error("Metafunction not found: {0} for {1:?}")]
|
||||||
MetafunctionNotFound(String, Value),
|
MetafunctionNotFound(String, Value<UserData>),
|
||||||
#[error("Metafunction is not callable: {0:?}")]
|
#[error("Metafunction is not callable: {0:?}")]
|
||||||
MetafunctionNotCallable(Value),
|
MetafunctionNotCallable(Value<UserData>),
|
||||||
#[error("Unable to perform {0:?} operator to {1:?}")]
|
#[error("Unable to perform {0:?} operator to {1:?}")]
|
||||||
InvalidOperand(UnaryOperator, Value),
|
InvalidOperand(UnaryOperator, Value<UserData>),
|
||||||
#[error("Tried calling a non-function: {0:?}")]
|
#[error("Tried calling a non-function: {0:?}")]
|
||||||
TriedCallingNonFunction(Value),
|
TriedCallingNonFunction(Value<UserData>),
|
||||||
#[error("Global not found: {0:?}")]
|
#[error("Global not found: {0:?}")]
|
||||||
GlobalNotFound(Option<Constant>),
|
GlobalNotFound(Option<Constant>),
|
||||||
#[error("Unable to index tables with {0:?}")]
|
#[error("Unable to index tables with {0:?}")]
|
||||||
InvalidTableIndex(Value),
|
InvalidTableIndex(Value<UserData>),
|
||||||
#[error("Value is not a table: {0:?}")]
|
#[error("Value is not a table: {0:?}")]
|
||||||
NotTable(Value),
|
NotTable(Value<UserData>),
|
||||||
#[error("Value is not coercable to a float: {0:?}")]
|
#[error("Value is not coercable to a float: {0:?}")]
|
||||||
NotFloatable(Value),
|
NotFloatable(Value<UserData>),
|
||||||
#[error("Value is not coercable to bits: {0:?}")]
|
#[error("Value is not coercable to bits: {0:?}")]
|
||||||
NotBittable(Value),
|
NotBittable(Value<UserData>),
|
||||||
#[error("Value does not have a length: {0:?}")]
|
#[error("Value does not have a length: {0:?}")]
|
||||||
NotLengthable(Value),
|
NotLengthable(Value<UserData>),
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Custom(String),
|
Custom(String),
|
||||||
}
|
}
|
||||||
@ -255,19 +258,19 @@ pub struct Prototype {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct VirtualMachine {
|
pub struct VirtualMachine<UserData: Clone> {
|
||||||
pub(super) environment: Table,
|
pub(super) environment: Table<UserData>,
|
||||||
pub(super) constants: Vec<Constant>,
|
pub(super) constants: Vec<Constant>,
|
||||||
pub(super) prototypes: HashMap<u32, Prototype>,
|
pub(super) prototypes: HashMap<u32, Prototype>,
|
||||||
pub(super) proto_counter: u32,
|
pub(super) proto_counter: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for VirtualMachine {
|
impl<UserData: Clone> Default for VirtualMachine<UserData> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let environment: Table = Default::default();
|
let environment: Table<UserData> = Default::default();
|
||||||
environment.borrow_mut().insert(
|
environment.borrow_mut().insert(
|
||||||
IndexableValue::String("SETMETATABLE".into()),
|
IndexableValue::String("SETMETATABLE".into()),
|
||||||
SetMetatable.into(),
|
Value::RustFunction(Rc::new(RefCell::new(SetMetatable))),
|
||||||
);
|
);
|
||||||
Self {
|
Self {
|
||||||
environment,
|
environment,
|
||||||
@ -278,7 +281,7 @@ impl Default for VirtualMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualMachine {
|
impl<UserData: Clone> VirtualMachine<UserData> {
|
||||||
pub fn new_prototype(&mut self, instructions: Prototype) -> u32 {
|
pub fn new_prototype(&mut self, instructions: Prototype) -> u32 {
|
||||||
let proto_id = self.proto_counter;
|
let proto_id = self.proto_counter;
|
||||||
self.proto_counter += 1;
|
self.proto_counter += 1;
|
||||||
@ -286,7 +289,7 @@ impl VirtualMachine {
|
|||||||
proto_id
|
proto_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn create_closure(&self, prototype: u32) -> Closure {
|
pub(crate) fn create_closure(&self, prototype: u32) -> Closure<UserData> {
|
||||||
Closure {
|
Closure {
|
||||||
vm: self.clone(),
|
vm: self.clone(),
|
||||||
prototype,
|
prototype,
|
||||||
@ -295,14 +298,18 @@ impl VirtualMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_global(&mut self, key: Value, value: Value) -> Result<(), RuntimeError> {
|
pub fn set_global(
|
||||||
|
&mut self,
|
||||||
|
key: Value<UserData>,
|
||||||
|
value: Value<UserData>,
|
||||||
|
) -> Result<(), RuntimeError<UserData>> {
|
||||||
self.environment
|
self.environment
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.insert(key.as_indexable()?, value);
|
.insert(key.as_indexable()?, value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_globals(&self) -> HashMap<IndexableValue, Value> {
|
pub fn get_globals(&self) -> HashMap<IndexableValue, Value<UserData>> {
|
||||||
let mut values = HashMap::new();
|
let mut values = HashMap::new();
|
||||||
for (key, value) in self.environment.borrow().iter() {
|
for (key, value) in self.environment.borrow().iter() {
|
||||||
values.insert(key.clone(), value.clone());
|
values.insert(key.clone(), value.clone());
|
||||||
@ -313,15 +320,15 @@ impl VirtualMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Closure {
|
pub struct Closure<UserData: Clone> {
|
||||||
vm: VirtualMachine,
|
vm: VirtualMachine<UserData>,
|
||||||
pub(crate) prototype: u32,
|
pub(crate) prototype: u32,
|
||||||
environment: Table,
|
environment: Table<UserData>,
|
||||||
upvalues: HashMap<u16, Rc<RefCell<Value>>>,
|
upvalues: HashMap<u16, Rc<RefCell<Value<UserData>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Closure {
|
impl<UserData: Clone> Closure<UserData> {
|
||||||
pub fn run(&self, params: Vec<Value>) -> ClosureRunner {
|
pub fn run(&self, params: Vec<Value<UserData>>) -> ClosureRunner<UserData> {
|
||||||
let mut stack = HashMap::new();
|
let mut stack = HashMap::new();
|
||||||
for (i, param) in params.iter().enumerate() {
|
for (i, param) in params.iter().enumerate() {
|
||||||
stack.insert(i as u16, Rc::new(RefCell::new(param.clone())));
|
stack.insert(i as u16, Rc::new(RefCell::new(param.clone())));
|
||||||
@ -340,7 +347,7 @@ impl Closure {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_upvalue(&mut self, idx: u16) -> StackValue {
|
fn get_upvalue(&mut self, idx: u16) -> StackValue<UserData> {
|
||||||
let value = self.upvalues.get(&idx);
|
let value = self.upvalues.get(&idx);
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
match &*value.borrow() {
|
match &*value.borrow() {
|
||||||
@ -352,25 +359,25 @@ impl Closure {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ClosureRunner {
|
pub struct ClosureRunner<UserData: Clone> {
|
||||||
closure: Closure,
|
closure: Closure<UserData>,
|
||||||
program_counter: usize,
|
program_counter: usize,
|
||||||
stack: HashMap<u16, Rc<RefCell<Value>>>,
|
stack: HashMap<u16, Rc<RefCell<Value<UserData>>>>,
|
||||||
inner: Option<Box<ClosureRunner>>,
|
inner: Option<Box<ClosureRunner<UserData>>>,
|
||||||
function_register: u16,
|
function_register: u16,
|
||||||
return_registers: Vec<u16>,
|
return_registers: Vec<u16>,
|
||||||
top: u16,
|
top: u16,
|
||||||
parameters: Vec<Value>,
|
parameters: Vec<Value<UserData>>,
|
||||||
to_close_upvalues: u16,
|
to_close_upvalues: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
enum StackValue {
|
enum StackValue<UserData: Clone> {
|
||||||
Value(Value),
|
Value(Value<UserData>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClosureRunner {
|
impl<UserData: Clone> ClosureRunner<UserData> {
|
||||||
fn set_stack(&mut self, idx: u16, value: StackValue) {
|
fn set_stack(&mut self, idx: u16, value: StackValue<UserData>) {
|
||||||
if let Some(stack_slot) = self.stack.get_mut(&idx) {
|
if let Some(stack_slot) = self.stack.get_mut(&idx) {
|
||||||
match value {
|
match value {
|
||||||
StackValue::Value(value) => {
|
StackValue::Value(value) => {
|
||||||
@ -386,7 +393,7 @@ impl ClosureRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_stack(&mut self, idx: u16) -> StackValue {
|
fn get_stack(&mut self, idx: u16) -> StackValue<UserData> {
|
||||||
let value = self.stack.get(&idx);
|
let value = self.stack.get(&idx);
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
match &*value.borrow() {
|
match &*value.borrow() {
|
||||||
@ -397,7 +404,7 @@ impl ClosureRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close_upvalues(&self) -> HashMap<u16, Rc<RefCell<Value>>> {
|
fn close_upvalues(&self) -> HashMap<u16, Rc<RefCell<Value<UserData>>>> {
|
||||||
let highest_upvalue = self
|
let highest_upvalue = self
|
||||||
.closure
|
.closure
|
||||||
.upvalues
|
.upvalues
|
||||||
@ -417,7 +424,7 @@ impl ClosureRunner {
|
|||||||
upvalues
|
upvalues
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(&mut self, unit: &CompilationUnit) -> ClosureRunner {
|
pub fn execute(&mut self, unit: &CompilationUnit) -> ClosureRunner<UserData> {
|
||||||
let mut vm = self.closure.vm.clone();
|
let mut vm = self.closure.vm.clone();
|
||||||
vm.constants = unit.constants.clone();
|
vm.constants = unit.constants.clone();
|
||||||
let proto_id = vm.new_prototype(Prototype {
|
let proto_id = vm.new_prototype(Prototype {
|
||||||
@ -437,7 +444,7 @@ impl ClosureRunner {
|
|||||||
closure.run(Vec::new())
|
closure.run(Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(&mut self) -> Result<Option<Vec<Value>>, RuntimeError> {
|
pub fn next(&mut self) -> Result<Option<Vec<Value<UserData>>>, RuntimeError<UserData>> {
|
||||||
if let Some(inner) = &mut self.inner {
|
if let Some(inner) = &mut self.inner {
|
||||||
match inner.next() {
|
match inner.next() {
|
||||||
Ok(ret_values) => {
|
Ok(ret_values) => {
|
||||||
@ -815,7 +822,7 @@ impl ClosureRunner {
|
|||||||
Value::Table { metatable, .. } => {
|
Value::Table { metatable, .. } => {
|
||||||
let mut metamethod_params = vec![value.clone()];
|
let mut metamethod_params = vec![value.clone()];
|
||||||
metamethod_params.extend(params);
|
metamethod_params.extend(params);
|
||||||
let ret_values =
|
let ret_values: Vec<Value<UserData>> =
|
||||||
self.call_metamethod(&metatable, "__call", metamethod_params)??;
|
self.call_metamethod(&metatable, "__call", metamethod_params)??;
|
||||||
|
|
||||||
if *ret_len != 0 {
|
if *ret_len != 0 {
|
||||||
@ -1195,10 +1202,10 @@ impl ClosureRunner {
|
|||||||
|
|
||||||
fn result_or_metamethod_unop(
|
fn result_or_metamethod_unop(
|
||||||
&self,
|
&self,
|
||||||
value: Result<Value, RuntimeError>,
|
value: Result<Value<UserData>, RuntimeError<UserData>>,
|
||||||
metamethod: &str,
|
metamethod: &str,
|
||||||
param: Value,
|
param: Value<UserData>,
|
||||||
) -> Result<Value, RuntimeError> {
|
) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
let metatable = extract_metatable(¶m);
|
let metatable = extract_metatable(¶m);
|
||||||
|
|
||||||
if let Some(metatable) = metatable {
|
if let Some(metatable) = metatable {
|
||||||
@ -1213,11 +1220,11 @@ impl ClosureRunner {
|
|||||||
|
|
||||||
fn result_or_metamethod_binop(
|
fn result_or_metamethod_binop(
|
||||||
&self,
|
&self,
|
||||||
value: Result<Value, RuntimeError>,
|
value: Result<Value<UserData>, RuntimeError<UserData>>,
|
||||||
metamethod: &str,
|
metamethod: &str,
|
||||||
lhs: Value,
|
lhs: Value<UserData>,
|
||||||
rhs: Value,
|
rhs: Value<UserData>,
|
||||||
) -> Result<Value, RuntimeError> {
|
) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
let metatable = extract_metatable(&lhs).or(extract_metatable(&rhs));
|
let metatable = extract_metatable(&lhs).or(extract_metatable(&rhs));
|
||||||
|
|
||||||
if let Some(metatable) = metatable {
|
if let Some(metatable) = metatable {
|
||||||
@ -1232,10 +1239,10 @@ impl ClosureRunner {
|
|||||||
|
|
||||||
fn call_metamethod(
|
fn call_metamethod(
|
||||||
&self,
|
&self,
|
||||||
metatable: &Table,
|
metatable: &Table<UserData>,
|
||||||
metamethod: &str,
|
metamethod: &str,
|
||||||
params: Vec<Value>,
|
params: Vec<Value<UserData>>,
|
||||||
) -> Result<Result<Vec<Value>, RuntimeError>, RuntimeError> {
|
) -> Result<Result<Vec<Value<UserData>>, RuntimeError<UserData>>, RuntimeError<UserData>> {
|
||||||
if let Some(value) = metatable
|
if let Some(value) = metatable
|
||||||
.borrow()
|
.borrow()
|
||||||
.get(&IndexableValue::String(metamethod.to_owned()))
|
.get(&IndexableValue::String(metamethod.to_owned()))
|
||||||
@ -1268,7 +1275,7 @@ impl ClosureRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lhs_and_rhs(&self, lhs: &u16, rhs: &u16) -> (Value, Value) {
|
fn lhs_and_rhs(&self, lhs: &u16, rhs: &u16) -> (Value<UserData>, Value<UserData>) {
|
||||||
(
|
(
|
||||||
self.stack
|
self.stack
|
||||||
.get(lhs)
|
.get(lhs)
|
||||||
@ -1282,13 +1289,15 @@ impl ClosureRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_metatable(value: &Value) -> Option<&Table> {
|
fn extract_metatable<UserData: Clone>(value: &Value<UserData>) -> Option<&Table<UserData>> {
|
||||||
match value {
|
match value {
|
||||||
Value::Table { metatable, .. } => Some(metatable),
|
Value::Table { metatable, .. } => Some(metatable),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_ret_value(values: Result<Vec<Value>, RuntimeError>) -> Result<Value, RuntimeError> {
|
fn extract_ret_value<UserData: Clone>(
|
||||||
|
values: Result<Vec<Value<UserData>>, RuntimeError<UserData>>,
|
||||||
|
) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
values.map(|v| v.into_iter().next().unwrap())
|
values.map(|v| v.into_iter().next().unwrap())
|
||||||
}
|
}
|
||||||
|
|||||||
111
src/vm/value.rs
111
src/vm/value.rs
@ -82,16 +82,24 @@ impl From<&LuaBool> for LuaInteger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RustFunction: Debug {
|
pub trait RustFunction<UserData: Clone>: Debug {
|
||||||
fn execute(&self, parameters: Vec<Value>) -> Result<Vec<Value>, RuntimeError>;
|
fn execute(
|
||||||
|
&self,
|
||||||
|
parameters: Vec<Value<UserData>>,
|
||||||
|
) -> Result<Vec<Value<UserData>>, RuntimeError<UserData>>;
|
||||||
fn as_indexable(&self) -> String;
|
fn as_indexable(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RustFunction + 'static> From<T> for Value {
|
pub trait AsValue<UserData: Clone> {
|
||||||
fn from(value: T) -> Self {
|
fn as_value(self) -> Value<UserData>;
|
||||||
Self::RustFunction(Rc::new(RefCell::new(value)))
|
}
|
||||||
|
|
||||||
|
impl<UserData: Clone, T: RustFunction<UserData> + 'static> AsValue<UserData> for T {
|
||||||
|
fn as_value(self) -> Value<UserData> {
|
||||||
|
Value::RustFunction(Rc::new(RefCell::new(self)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Hash, PartialEq, Eq)]
|
#[derive(Clone, Hash, PartialEq, Eq)]
|
||||||
pub enum Constant {
|
pub enum Constant {
|
||||||
String(String),
|
String(String),
|
||||||
@ -102,7 +110,7 @@ pub enum Constant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Constant {
|
impl Constant {
|
||||||
pub fn as_value(self) -> Value {
|
pub fn as_value<UserData: Clone>(self) -> Value<UserData> {
|
||||||
match self {
|
match self {
|
||||||
Constant::String(value) => Value::String(value),
|
Constant::String(value) => Value::String(value),
|
||||||
Constant::Float(vmfloat) => Value::Float(vmfloat),
|
Constant::Float(vmfloat) => Value::Float(vmfloat),
|
||||||
@ -125,23 +133,26 @@ impl Debug for Constant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Table = Rc<RefCell<TableMap>>;
|
pub type Table<UserData: Clone> = Rc<RefCell<TableMap<UserData>>>;
|
||||||
pub type TableMap = HashMap<IndexableValue, Value>;
|
pub type TableMap<UserData: Clone> = HashMap<IndexableValue, Value<UserData>>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Value {
|
pub enum Value<UserData: Clone> {
|
||||||
String(String),
|
String(String),
|
||||||
Float(VMFloat),
|
Float(VMFloat),
|
||||||
Integer(LuaInteger),
|
Integer(LuaInteger),
|
||||||
Boolean(LuaBool),
|
Boolean(LuaBool),
|
||||||
RustFunction(Rc<RefCell<dyn RustFunction>>),
|
RustFunction(Rc<RefCell<dyn RustFunction<UserData>>>),
|
||||||
Function(Closure),
|
Function(Closure<UserData>),
|
||||||
Nil,
|
Nil,
|
||||||
Table { contents: Table, metatable: Table },
|
Table {
|
||||||
|
contents: Table<UserData>,
|
||||||
|
metatable: Table<UserData>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl<UserData: Clone> Value<UserData> {
|
||||||
pub fn as_indexable(self) -> Result<IndexableValue, RuntimeError> {
|
pub fn as_indexable(self) -> Result<IndexableValue, RuntimeError<UserData>> {
|
||||||
match self {
|
match self {
|
||||||
Value::String(value) => Ok(IndexableValue::String(value)),
|
Value::String(value) => Ok(IndexableValue::String(value)),
|
||||||
Value::Float(value) => Ok(IndexableValue::Float(value)),
|
Value::Float(value) => Ok(IndexableValue::Float(value)),
|
||||||
@ -152,11 +163,11 @@ impl Value {
|
|||||||
}
|
}
|
||||||
Value::Function(closure) => Ok(IndexableValue::Function(closure.prototype)),
|
Value::Function(closure) => Ok(IndexableValue::Function(closure.prototype)),
|
||||||
Value::Nil => Err(RuntimeError::InvalidTableIndex(self)),
|
Value::Nil => Err(RuntimeError::InvalidTableIndex(self)),
|
||||||
Value::Table { contents, .. } => Ok(IndexableValue::Table(contents.as_ptr())),
|
Value::Table { contents, .. } => Ok(IndexableValue::Table(contents.as_ptr() as u64)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_float(&self) -> Result<LuaFloat, RuntimeError> {
|
pub fn as_float(&self) -> Result<LuaFloat, RuntimeError<UserData>> {
|
||||||
match self {
|
match self {
|
||||||
Value::Float(vmfloat) => Ok(vmfloat.lua_number()),
|
Value::Float(vmfloat) => Ok(vmfloat.lua_number()),
|
||||||
Value::Integer(lua_integer) => Ok(lua_integer.into()),
|
Value::Integer(lua_integer) => Ok(lua_integer.into()),
|
||||||
@ -165,7 +176,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_integer(&self) -> Result<LuaInteger, RuntimeError> {
|
pub fn as_integer(&self) -> Result<LuaInteger, RuntimeError<UserData>> {
|
||||||
match self {
|
match self {
|
||||||
Value::Integer(lua_integer) => Ok(*lua_integer),
|
Value::Integer(lua_integer) => Ok(*lua_integer),
|
||||||
Value::Boolean(lua_boolean) => Ok(LuaInteger(lua_boolean.0 as i64)),
|
Value::Boolean(lua_boolean) => Ok(LuaInteger(lua_boolean.0 as i64)),
|
||||||
@ -173,7 +184,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_bits(&self) -> Result<LuaInteger, RuntimeError> {
|
pub fn as_bits(&self) -> Result<LuaInteger, RuntimeError<UserData>> {
|
||||||
match self {
|
match self {
|
||||||
Value::Float(vmfloat) => Ok(LuaInteger(vmfloat.lua_number().0 as i64)),
|
Value::Float(vmfloat) => Ok(LuaInteger(vmfloat.lua_number().0 as i64)),
|
||||||
Value::Integer(lua_integer) => Ok(LuaInteger(lua_integer.0 as i64)),
|
Value::Integer(lua_integer) => Ok(LuaInteger(lua_integer.0 as i64)),
|
||||||
@ -184,13 +195,13 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for Value {
|
impl<UserData: Clone> From<&str> for Value<UserData> {
|
||||||
fn from(value: &str) -> Self {
|
fn from(value: &str) -> Self {
|
||||||
Value::String(value.to_owned())
|
Value::String(value.to_owned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Value {
|
impl<UserData: Clone> Display for Value<UserData> {
|
||||||
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::String(value) => Display::fmt(value, f),
|
Value::String(value) => Display::fmt(value, f),
|
||||||
@ -207,8 +218,11 @@ impl Display for Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl<UserData: Clone> Value<UserData> {
|
||||||
pub fn concat(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn concat(
|
||||||
|
&self,
|
||||||
|
other: &Value<UserData>,
|
||||||
|
) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(
|
(
|
||||||
Value::String(_) | Value::Integer(_) | Value::Boolean(_),
|
Value::String(_) | Value::Integer(_) | Value::Boolean(_),
|
||||||
@ -229,7 +243,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn add(&self, other: &Value<UserData>) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
|
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
|
||||||
let res = LuaInteger(self.as_integer()?.0 + other.as_integer()?.0);
|
let res = LuaInteger(self.as_integer()?.0 + other.as_integer()?.0);
|
||||||
@ -250,7 +264,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mult(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn mult(&self, other: &Value<UserData>) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
|
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
|
||||||
let res = LuaInteger(self.as_integer()?.0 * other.as_integer()?.0);
|
let res = LuaInteger(self.as_integer()?.0 * other.as_integer()?.0);
|
||||||
@ -271,7 +285,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn div(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn div(&self, other: &Value<UserData>) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
|
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
|
||||||
let res = LuaFloat(self.as_integer()?.0 as f64 / other.as_integer()?.0 as f64);
|
let res = LuaFloat(self.as_integer()?.0 as f64 / other.as_integer()?.0 as f64);
|
||||||
@ -292,7 +306,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn idiv(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn idiv(&self, other: &Value<UserData>) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
|
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
|
||||||
let res = LuaInteger(self.as_integer()?.0 / other.as_integer()?.0);
|
let res = LuaInteger(self.as_integer()?.0 / other.as_integer()?.0);
|
||||||
@ -313,7 +327,10 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn r#mod(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn r#mod(
|
||||||
|
&self,
|
||||||
|
other: &Value<UserData>,
|
||||||
|
) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
|
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
|
||||||
let res = LuaInteger(self.as_integer()?.0 % other.as_integer()?.0);
|
let res = LuaInteger(self.as_integer()?.0 % other.as_integer()?.0);
|
||||||
@ -334,7 +351,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exp(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn exp(&self, other: &Value<UserData>) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
|
(Value::Integer(_) | Value::Boolean(_), Value::Integer(_) | Value::Boolean(_)) => {
|
||||||
let res = LuaInteger(self.as_integer()?.0.pow(other.as_integer()?.0 as u32));
|
let res = LuaInteger(self.as_integer()?.0.pow(other.as_integer()?.0 as u32));
|
||||||
@ -355,7 +372,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn band(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn band(&self, other: &Value<UserData>) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(
|
(
|
||||||
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
|
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
|
||||||
@ -372,7 +389,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bor(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn bor(&self, other: &Value<UserData>) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(
|
(
|
||||||
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
|
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
|
||||||
@ -389,7 +406,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bxor(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn bxor(&self, other: &Value<UserData>) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(
|
(
|
||||||
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
|
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
|
||||||
@ -406,7 +423,10 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bsleft(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn bsleft(
|
||||||
|
&self,
|
||||||
|
other: &Value<UserData>,
|
||||||
|
) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(
|
(
|
||||||
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
|
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
|
||||||
@ -423,7 +443,10 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bsright(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn bsright(
|
||||||
|
&self,
|
||||||
|
other: &Value<UserData>,
|
||||||
|
) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(
|
(
|
||||||
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
|
Value::Float(_) | Value::Integer(_) | Value::Boolean(_) | Value::Nil,
|
||||||
@ -440,7 +463,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eq(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn eq(&self, other: &Value<UserData>) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::Integer(lhs), Value::Integer(rhs)) => {
|
(Value::Integer(lhs), Value::Integer(rhs)) => {
|
||||||
Ok(Value::Boolean(LuaBool(lhs.0 == rhs.0)))
|
Ok(Value::Boolean(LuaBool(lhs.0 == rhs.0)))
|
||||||
@ -457,7 +480,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lt(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn lt(&self, other: &Value<UserData>) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::Integer(lhs), Value::Integer(rhs)) => {
|
(Value::Integer(lhs), Value::Integer(rhs)) => {
|
||||||
Ok(Value::Boolean(LuaBool(lhs.0 < rhs.0)))
|
Ok(Value::Boolean(LuaBool(lhs.0 < rhs.0)))
|
||||||
@ -474,7 +497,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lte(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn lte(&self, other: &Value<UserData>) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Value::Integer(lhs), Value::Integer(rhs)) => {
|
(Value::Integer(lhs), Value::Integer(rhs)) => {
|
||||||
Ok(Value::Boolean(LuaBool(lhs.0 <= rhs.0)))
|
Ok(Value::Boolean(LuaBool(lhs.0 <= rhs.0)))
|
||||||
@ -491,7 +514,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unm(&self) -> Result<Value, RuntimeError> {
|
pub fn unm(&self) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match self {
|
match self {
|
||||||
Value::Integer(lhs) => {
|
Value::Integer(lhs) => {
|
||||||
let res = LuaInteger(-lhs.0);
|
let res = LuaInteger(-lhs.0);
|
||||||
@ -512,7 +535,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> Result<Value, RuntimeError> {
|
pub fn len(&self) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
match self {
|
match self {
|
||||||
Value::String(value) => Ok(Self::Integer(LuaInteger(value.len() as i64))),
|
Value::String(value) => Ok(Self::Integer(LuaInteger(value.len() as i64))),
|
||||||
Value::Table { contents, .. } => {
|
Value::Table { contents, .. } => {
|
||||||
@ -553,7 +576,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn and(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn and(&self, other: &Value<UserData>) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
if self.is_truthy() {
|
if self.is_truthy() {
|
||||||
Ok(self.clone())
|
Ok(self.clone())
|
||||||
} else {
|
} else {
|
||||||
@ -561,7 +584,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn or(&self, other: &Value) -> Result<Value, RuntimeError> {
|
pub fn or(&self, other: &Value<UserData>) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
if self.is_truthy() {
|
if self.is_truthy() {
|
||||||
Ok(self.clone())
|
Ok(self.clone())
|
||||||
} else {
|
} else {
|
||||||
@ -569,7 +592,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn not(&self) -> Result<Value, RuntimeError> {
|
pub fn not(&self) -> Result<Value<UserData>, RuntimeError<UserData>> {
|
||||||
if self.is_truthy() {
|
if self.is_truthy() {
|
||||||
Ok(Value::Boolean(LuaBool(false)))
|
Ok(Value::Boolean(LuaBool(false)))
|
||||||
} else {
|
} else {
|
||||||
@ -591,7 +614,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Value {
|
impl<UserData: Clone> Debug for Value<UserData> {
|
||||||
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::Float(arg0) => f.debug_tuple("Float").field(&arg0.lua_number()).finish(),
|
Value::Float(arg0) => f.debug_tuple("Float").field(&arg0.lua_number()).finish(),
|
||||||
@ -622,11 +645,11 @@ pub enum IndexableValue {
|
|||||||
Bool(LuaBool),
|
Bool(LuaBool),
|
||||||
RustFunction(String),
|
RustFunction(String),
|
||||||
Function(u32),
|
Function(u32),
|
||||||
Table(*mut TableMap),
|
Table(u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for IndexableValue {
|
impl From<&str> for IndexableValue {
|
||||||
fn from(value: &str) -> Self {
|
fn from(value: &str) -> Self {
|
||||||
Value::from(value).as_indexable().unwrap()
|
Value::<()>::from(value).as_indexable().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user