Small tweaks
This commit is contained in:
parent
bfc418a55e
commit
93d6f6a886
4 changed files with 175 additions and 119 deletions
53
Cargo.lock
generated
53
Cargo.lock
generated
|
|
@ -5,6 +5,10 @@ version = 4
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deimos"
|
name = "deimos"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"macros",
|
||||||
|
"map",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glam"
|
name = "glam"
|
||||||
|
|
@ -12,6 +16,20 @@ version = "0.33.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7360bd2cd76e0cd9032d42cf2922155cecea2685b0cfa4630c3246df030bcfd6"
|
checksum = "7360bd2cd76e0cd9032d42cf2922155cecea2685b0cfa4630c3246df030bcfd6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "macros"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"map",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "map"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mars"
|
name = "mars"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
@ -19,3 +37,38 @@ dependencies = [
|
||||||
"deimos",
|
"deimos",
|
||||||
"glam",
|
"glam",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.107"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.47"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954"
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ mod tests {
|
||||||
let closure = match machine.load(include_str!("tests/script.lua")) {
|
let closure = match machine.load(include_str!("tests/script.lua")) {
|
||||||
Err(error) => panic!("{}", error),
|
Err(error) => panic!("{}", error),
|
||||||
Ok(closure) => closure,
|
Ok(closure) => closure,
|
||||||
_ => panic!(),
|
|
||||||
};
|
};
|
||||||
println!("{:?}", machine.freelist().get(&closure).prototype);
|
println!("{:?}", machine.freelist().get(&closure).prototype);
|
||||||
match machine.enter(closure) {
|
match machine.enter(closure) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::vm::{Callable, MarsAllocator, RunError, Value};
|
use crate::vm::{Callable, MarsAllocator, RunError, Value};
|
||||||
use deimos::gc::{Allocates, Id, MaybeId, Traverse};
|
use deimos::gc::{Id, MaybeId, Traverse};
|
||||||
use deimos::map::{DisplacementSet, Entry, Equivalent, Hashed, Hashes, Map, TableEntry};
|
use deimos::map::{DisplacementSet, Equivalent, Hashed, Hashes, TableEntry};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct KeyValue {
|
struct KeyValue {
|
||||||
|
|
@ -47,8 +47,8 @@ impl Hashes for Value {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::CachedString(cached) => cached.1,
|
Value::CachedString(hashed) => hashed.1,
|
||||||
Value::String(_string, hash) => *hash,
|
Value::String(hashed) => hashed.1,
|
||||||
Value::Function(callable) => match callable {
|
Value::Function(callable) => match callable {
|
||||||
Callable::Rust(native) => native.hashed(),
|
Callable::Rust(native) => native.hashed(),
|
||||||
Callable::Mars(closure) => closure.hashed(),
|
Callable::Mars(closure) => closure.hashed(),
|
||||||
|
|
|
||||||
232
src/vm.rs
232
src/vm.rs
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use crate::parser::{BinaryOp, Piece, UnaryOp, parse};
|
use crate::parser::{BinaryOp, Piece, UnaryOp, parse};
|
||||||
use deimos::gc::{Allocates, AnyId, FreeList, Id, MaybeId, Traverse};
|
use deimos::gc::{Allocates, AnyId, FreeList, Id, MaybeId, Traverse};
|
||||||
use deimos::map::{DisplacementSet, Equivalent, Hashed, Hashes, Map, TableEntry};
|
use deimos::map::{DisplacementSet, Equivalent, Hashed, Hashes, MapEntry, TableEntry};
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
@ -157,7 +157,7 @@ impl std::fmt::Debug for Callable {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RunError(pub(crate) String);
|
pub struct RunError(pub String);
|
||||||
|
|
||||||
impl RunError {
|
impl RunError {
|
||||||
pub fn new(string: &str) -> RunError {
|
pub fn new(string: &str) -> RunError {
|
||||||
|
|
@ -165,36 +165,50 @@ impl RunError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<String> for RunError {
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
RunError(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for RunError {
|
impl Display for RunError {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}", self.0)
|
write!(f, "{}", self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for RunError {}
|
||||||
|
|
||||||
use crate::compiler::compile;
|
use crate::compiler::compile;
|
||||||
use crate::core::load;
|
use crate::core::load;
|
||||||
use crate::table::Table;
|
use crate::table::Table;
|
||||||
#[cfg(feature = "vector3")]
|
#[cfg(feature = "vector3")]
|
||||||
use glam::Vec3;
|
use glam::Vec3;
|
||||||
|
|
||||||
// Any value in the language
|
|
||||||
const SHORT_STRING_LEN: usize = 40;
|
const SHORT_STRING_LEN: usize = 40;
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct CachedString(Rc<str>, pub(crate) Hashed);
|
pub struct HashedString(Rc<str>, pub(crate) Hashed);
|
||||||
|
|
||||||
impl Hashes for CachedString {
|
impl Hashes for HashedString {
|
||||||
fn hashed(&self) -> Hashed {
|
fn hashed(&self) -> Hashed {
|
||||||
self.1
|
self.1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for CachedString {
|
impl PartialEq for HashedString {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.1 == other.1 && self.0 == other.0
|
self.1 == other.1 && self.0 == other.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HashedString {
|
||||||
|
pub fn as_str(&self) -> &str {
|
||||||
|
self.0.deref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct CachedStringEntry(Option<CachedString>);
|
struct CachedStringEntry(Option<HashedString>);
|
||||||
impl Hashes for CachedStringEntry {
|
impl Hashes for CachedStringEntry {
|
||||||
fn hashed(&self) -> Hashed {
|
fn hashed(&self) -> Hashed {
|
||||||
self.0.as_ref().unwrap().0.deref().hashed()
|
self.0.as_ref().unwrap().0.deref().hashed()
|
||||||
|
|
@ -227,15 +241,14 @@ impl Equivalent<&str> for CachedStringEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const PHRASE_LEN: usize = 16;
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Nil, // Empty value
|
Nil, // Empty value
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Number(f64),
|
Number(f64),
|
||||||
Integer(u64), // 64 maybe we should use signed integers...
|
Integer(u64), // 64 maybe we should use signed integers...
|
||||||
CachedString(CachedString),
|
CachedString(HashedString),
|
||||||
String(Rc<str>, Hashed),
|
String(HashedString),
|
||||||
Table(Id<Table>),
|
Table(Id<Table>),
|
||||||
Object(AnyId, AnyId),
|
Object(AnyId, AnyId),
|
||||||
Function(Callable),
|
Function(Callable),
|
||||||
|
|
@ -257,7 +270,7 @@ impl Debug for Value {
|
||||||
Value::Number(number) => write!(f, "{}", number),
|
Value::Number(number) => write!(f, "{}", number),
|
||||||
Value::Integer(integer) => write!(f, "{}", integer),
|
Value::Integer(integer) => write!(f, "{}", integer),
|
||||||
Value::CachedString(string) => write!(f, "{}", string.0.deref()),
|
Value::CachedString(string) => write!(f, "{}", string.0.deref()),
|
||||||
Value::String(string, _hash) => write!(f, "{}", string.deref()),
|
Value::String(string) => write!(f, "{}", string.0.deref()),
|
||||||
Value::Table(it) => write!(f, "{:?}", it),
|
Value::Table(it) => write!(f, "{:?}", it),
|
||||||
Value::Object(it, meta) => write!(f, "{:?}:{:?}", it, meta),
|
Value::Object(it, meta) => write!(f, "{:?}:{:?}", it, meta),
|
||||||
Value::Function(it) => write!(f, "{:?}", it),
|
Value::Function(it) => write!(f, "{:?}", it),
|
||||||
|
|
@ -275,11 +288,18 @@ impl Value {
|
||||||
}
|
}
|
||||||
pub(crate) fn unwrap_str(&mut self) -> Rc<str> {
|
pub(crate) fn unwrap_str(&mut self) -> Rc<str> {
|
||||||
match self {
|
match self {
|
||||||
Value::CachedString(cached) => cached.0.clone(),
|
Value::CachedString(hashed) => hashed.0.clone(),
|
||||||
Value::String(string, _hash) => string.clone(),
|
Value::String(hashed) => hashed.0.clone(),
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn try_string(self) -> Option<HashedString> {
|
||||||
|
match self {
|
||||||
|
Value::CachedString(hashed) => Some(hashed),
|
||||||
|
Value::String(hashed) => Some(hashed),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
pub(crate) fn traverse<C>(&self, context: &mut C)
|
pub(crate) fn traverse<C>(&self, context: &mut C)
|
||||||
where
|
where
|
||||||
C: MarsAllocator,
|
C: MarsAllocator,
|
||||||
|
|
@ -313,17 +333,17 @@ impl PartialEq for Value {
|
||||||
Value::Integer(other) => this == other,
|
Value::Integer(other) => this == other,
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
Value::String(string, hash) => match other {
|
Value::String(string) => match other {
|
||||||
Value::CachedString(other) => {
|
Value::CachedString(other) => {
|
||||||
if *hash == other.1 {
|
if string.1 == other.1 {
|
||||||
other.0.deref() == string.deref()
|
other.0.deref() == string.0.deref()
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::String(other_string, other_hash) => {
|
Value::String(other) => {
|
||||||
if hash == other_hash {
|
if string.1 == other.1 {
|
||||||
string == other_string
|
string.0.deref() == other.0.deref()
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
@ -332,9 +352,9 @@ impl PartialEq for Value {
|
||||||
},
|
},
|
||||||
Value::CachedString(string) => match other {
|
Value::CachedString(string) => match other {
|
||||||
Value::CachedString(other) => other.0 == string.0, // pointer equality
|
Value::CachedString(other) => other.0 == string.0, // pointer equality
|
||||||
Value::String(other_string, other_hash) => {
|
Value::String(other) => {
|
||||||
if string.1 == *other_hash {
|
if string.1 == other.1 {
|
||||||
string.0.deref() == other_string.deref()
|
string.0.deref() == other.0.deref()
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
@ -366,43 +386,86 @@ pub struct Frame {
|
||||||
closure: Id<Closure>, // The function that was called on this frame
|
closure: Id<Closure>, // The function that was called on this frame
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! read_only {
|
impl<V> Equivalent<HashedString> for MapEntry<&str,V> { // For the constant maps
|
||||||
() => {
|
fn matches(&self, other: &HashedString) -> bool {
|
||||||
|machine, id, needle| Err(RunError(format!("Field {} is read only", needle.pop())))
|
self.0.as_ref().unwrap().0 == other.as_str()
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type MetaFieldSet<S> = fn(
|
#[macro_export]
|
||||||
&mut Machine<S>,
|
macro_rules! getter {
|
||||||
id: AnyId,
|
(@$state:ident,$index:literal=>$f:expr,$($x:literal=>$y:expr),*) => {
|
||||||
index: Value,
|
let temp: MetaOutFn<$state> = $f;
|
||||||
value: Value,
|
$crate::getter!(@$($x=>$y)*)
|
||||||
needle: Needle,
|
};
|
||||||
) -> Result<Value, RunError>;
|
(@$state:ident,$index:literal=>$f:expr) => {
|
||||||
type MetaFieldGet<S> = fn(&mut Machine<S>, id: AnyId, index: Value, needle: Needle) -> Result<(), RunError>;
|
let temp: MetaOutFn<$state> = $f;
|
||||||
pub struct MetaField<S> {
|
};
|
||||||
set: MetaFieldSet<S>,
|
(@) => {
|
||||||
get: MetaFieldGet<S>,
|
|
||||||
|
};
|
||||||
|
($ident:tt,$state:ident,{$($map:tt)*}) => {
|
||||||
|
|machine,id,index,needle| {
|
||||||
|
use $crate::deimos::map::Entry;
|
||||||
|
use $crate::deimos::map::MapEntry;
|
||||||
|
$crate::getter!(@$state,$($map)*);
|
||||||
|
static MAP: &[
|
||||||
|
$crate::deimos::map::Entry<
|
||||||
|
$crate::deimos::map::MapEntry<&'static str,$crate::MetaOutFn<$state>>
|
||||||
|
>] = &$crate::deimos::macros::map!{$($map)*};
|
||||||
|
if let Some(string) = index.clone().try_string() {
|
||||||
|
if let Some(func) = $crate::deimos::map::get(MAP,string) {
|
||||||
|
(func.0.unwrap().1)(machine,id,needle)
|
||||||
|
} else {
|
||||||
|
Err(RunError::from(format!("No field {:?} for {}",index,stringify!($ident))))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Err(RunError::from(format!("No field {:?} for {}",index,stringify!($ident))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! setter {
|
||||||
|
($ident:tt,$state:tt,$($map:tt)*) => {
|
||||||
|
|machine,id,index,value,needle| {
|
||||||
|
static MAP: &[Entry<MapEntry<&'static str,$crate::MetaInFn<$state>>>] = &$($map)*;
|
||||||
|
if let Some(string) = index.clone().try_string() {
|
||||||
|
if let Some(func) = $crate::deimos::map::get(MAP,string) {
|
||||||
|
(func.0.unwrap().1)(machine,id,value,needle)
|
||||||
|
} else {
|
||||||
|
Err(RunError::from(format!("No field {:?} for {}",index,stringify!($ident))))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(RunError::from(format!("No field {:?} for {}",index,stringify!($ident))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type MetaGetFn<S> = fn(&mut Machine<S>, AnyId, Value, Needle) -> Result<Value, RunError>;
|
||||||
|
pub type MetaSetFn<S> = fn(&mut Machine<S>, AnyId, Value, Value, Needle) -> Result<(), RunError>;
|
||||||
|
pub type MetaInFn<S> = fn(&mut Machine<S>, AnyId, Value, Needle) -> Result<(), RunError>;
|
||||||
|
pub type MetaOutFn<S> = fn(&mut Machine<S>, AnyId, Needle) -> Result<Value, RunError>;
|
||||||
|
pub type MetaTraverseFn<S> = fn(&mut Machine<S>, AnyId) -> Result<(), RunError>;
|
||||||
|
|
||||||
pub struct Meta<S> {
|
pub struct Meta<S> {
|
||||||
pub string: fn(&mut Machine<S>, id: AnyId, needle: Needle) -> Result<Value, RunError>,
|
pub string: MetaOutFn<S>,
|
||||||
pub number: fn(&mut Machine<S>, id: AnyId, needle: Needle) -> Result<Value, RunError>,
|
pub number: MetaOutFn<S>,
|
||||||
pub get: fn(&mut Machine<S>, id: AnyId, index: Value, needle: Needle) -> Result<Value, RunError>,
|
pub get: MetaGetFn<S>,
|
||||||
pub set: fn(&mut Machine<S>, id: AnyId, index: Value, value: Value, needle: Needle) -> Result<(), RunError>,
|
pub set: MetaSetFn<S>,
|
||||||
pub traverse: fn(&mut Machine<S>, id: AnyId) -> Result<(), RunError>,
|
pub traverse: MetaTraverseFn<S>,
|
||||||
pub fields: Map<Value, MetaField<S>>,
|
|
||||||
pub constants: Map<Value, Value>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Default for Meta<S> {
|
impl<S> Default for Meta<S> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Meta {
|
Meta {
|
||||||
string: |machine, id, needle| Err(RunError::new("Type does not implement to string.")),
|
string: |_machine, _id, _needle| Err(RunError::new("Type does not implement to string")),
|
||||||
number: |machine, id, needle| Err(RunError::new("Type does not implement to number.")),
|
number: |_machine, _id, _needle| Err(RunError::new("Type does not implement to number")),
|
||||||
get: |machine, id, index, needle|,
|
get: |_machine, _id, _index, _needle| Err(RunError::new("Type does not implement get")),
|
||||||
set: |machine, id, index, value, needle| (),
|
set: |_machine, _id, _index, _value, _needle| Err(RunError::new("Type does not implement set")),
|
||||||
traverse: |machine, id| (),
|
traverse: |_machine, _id| Err(RunError::new("Type did not subscribe to traversal")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -411,7 +474,7 @@ pub type ForeignFunction<S> = fn(&mut Machine<S>, needle: Needle) -> Result<(),
|
||||||
|
|
||||||
// Machine for executing functions
|
// Machine for executing functions
|
||||||
pub struct Machine<S> {
|
pub struct Machine<S> {
|
||||||
state: S,
|
pub state: S,
|
||||||
global: Id<Table>,
|
global: Id<Table>,
|
||||||
tables: FreeList<Table>,
|
tables: FreeList<Table>,
|
||||||
closures: FreeList<Closure>,
|
closures: FreeList<Closure>,
|
||||||
|
|
@ -637,13 +700,13 @@ impl<S> Machine<S> {
|
||||||
match self.cache.get(string) {
|
match self.cache.get(string) {
|
||||||
Some(ref entry) => Ok(Value::CachedString(entry.0.as_ref().unwrap().clone())),
|
Some(ref entry) => Ok(Value::CachedString(entry.0.as_ref().unwrap().clone())),
|
||||||
None => {
|
None => {
|
||||||
let cached = CachedString(Rc::from(string), string.hashed());
|
let cached = HashedString(Rc::from(string), string.hashed());
|
||||||
self.cache.set(CachedStringEntry(Some(cached.clone())));
|
self.cache.set(CachedStringEntry(Some(cached.clone())));
|
||||||
Ok(Value::CachedString(cached))
|
Ok(Value::CachedString(cached))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::String(Rc::from(string), string.hashed()))
|
Ok(Value::String(HashedString(Rc::from(string), string.hashed())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn meta_call(
|
fn meta_call(
|
||||||
|
|
@ -831,68 +894,9 @@ impl<S> Machine<S> {
|
||||||
// todo: object-table equality
|
// todo: object-table equality
|
||||||
fn meta_equal(&mut self, lhs: &mut Value, rhs: &mut Value) -> Result<bool, RunError> {
|
fn meta_equal(&mut self, lhs: &mut Value, rhs: &mut Value) -> Result<bool, RunError> {
|
||||||
// with respect to metamethods
|
// with respect to metamethods
|
||||||
Ok(match lhs {
|
Ok(false)
|
||||||
Value::Nil => match rhs {
|
|
||||||
Value::Nil => true,
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
Value::Bool(this) => match rhs {
|
|
||||||
Value::Bool(other) => this == other,
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
Value::Number(this) => match rhs {
|
|
||||||
Value::Number(other) => this == other,
|
|
||||||
Value::Integer(other) => *this == *other as f64,
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
Value::Integer(this) => match rhs {
|
|
||||||
Value::Number(other) => *this as f64 == *other, // are these conversions ok?
|
|
||||||
Value::Integer(other) => this == other,
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
Value::String(string, hash) => match rhs {
|
|
||||||
Value::CachedString(other) => {
|
|
||||||
if *hash == other.1 {
|
|
||||||
other.0.deref() == (*string).deref()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
pub fn load(&mut self, source: &str) -> Result<Id<Closure>, MarsError> {
|
||||||
Value::String(other_string, other_hash) => {
|
|
||||||
if hash == other_hash {
|
|
||||||
string == other_string
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
Value::CachedString(string) => match rhs {
|
|
||||||
Value::CachedString(other) => other.0 == string.0, // pointer equality
|
|
||||||
Value::String(other_string, other_hash) => {
|
|
||||||
if string.1 == *other_hash {
|
|
||||||
string.0.deref() == (*other_string).deref()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
Value::Table(this) => match rhs {
|
|
||||||
Value::Table(other) => other == this,
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
Value::Object(this, meta) => match rhs {
|
|
||||||
Value::Object(other, meta) => other == this,
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
Value::Function(this) => match rhs {
|
|
||||||
Value::Function(other) => other == this,
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
pub(crate) fn load(&mut self, source: &str) -> Result<Id<Closure>, MarsError> {
|
|
||||||
let chunk = match parse(source) {
|
let chunk = match parse(source) {
|
||||||
Ok(parsed) => parsed,
|
Ok(parsed) => parsed,
|
||||||
Err(error) => return Err(MarsError(error.msg(source))),
|
Err(error) => return Err(MarsError(error.msg(source))),
|
||||||
|
|
@ -1286,7 +1290,7 @@ impl<S> Machine<S> {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub(crate) fn enter(&mut self, closure: Id<Closure>) -> Result<(), RunError> {
|
pub fn enter(&mut self, closure: Id<Closure>) -> Result<(), RunError> {
|
||||||
let mut needle = Dispatch {
|
let mut needle = Dispatch {
|
||||||
frames: vec![Frame {
|
frames: vec![Frame {
|
||||||
vararg: 0,
|
vararg: 0,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue