Compare commits
3 Commits
21300b71cf
...
71c11e87e5
| Author | SHA1 | Date | |
|---|---|---|---|
| 71c11e87e5 | |||
| 875cfc1220 | |||
| 90c3b90065 |
145
src/vm/mod.rs
145
src/vm/mod.rs
@ -566,28 +566,60 @@ impl ClosureRunner {
|
|||||||
.unwrap_or(Value::Nil);
|
.unwrap_or(Value::Nil);
|
||||||
}
|
}
|
||||||
Instruction::SetTable(tablereg, indexreg, valuereg) => {
|
Instruction::SetTable(tablereg, indexreg, valuereg) => {
|
||||||
let table = self.stack.get(tablereg);
|
let table_value = self.stack.get(tablereg);
|
||||||
match table {
|
match table_value {
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
let mut table = value.borrow_mut();
|
let mut table = value.borrow_mut();
|
||||||
if let Value::Table { contents, .. } = &mut *table {
|
if let Value::Table {
|
||||||
|
contents,
|
||||||
|
metatable,
|
||||||
|
} = &mut *table
|
||||||
|
{
|
||||||
let index_value = self
|
let index_value = self
|
||||||
.stack
|
.stack
|
||||||
.get(indexreg)
|
.get(indexreg)
|
||||||
.map(|v| v.borrow().clone())
|
.map(|v| v.borrow().clone())
|
||||||
.unwrap_or(Value::Nil)
|
.unwrap_or(Value::Nil);
|
||||||
.as_indexable()?;
|
|
||||||
let value = self
|
let value = self
|
||||||
.stack
|
.stack
|
||||||
.get(valuereg)
|
.get(valuereg)
|
||||||
.map(|v| v.borrow().clone())
|
.map(|v| v.borrow().clone())
|
||||||
.unwrap_or(Value::Nil);
|
.unwrap_or(Value::Nil);
|
||||||
|
if contents
|
||||||
|
.borrow()
|
||||||
|
.contains_key(&index_value.clone().as_indexable()?)
|
||||||
|
{
|
||||||
match value {
|
match value {
|
||||||
Value::Nil => {
|
Value::Nil => {
|
||||||
contents.borrow_mut().remove(&index_value);
|
contents
|
||||||
|
.borrow_mut()
|
||||||
|
.remove(&index_value.as_indexable()?);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
contents.borrow_mut().insert(index_value, value);
|
contents
|
||||||
|
.borrow_mut()
|
||||||
|
.insert(index_value.as_indexable()?, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match self.call_metamethod(
|
||||||
|
metatable,
|
||||||
|
"__newindex",
|
||||||
|
vec![table_value.unwrap().borrow().clone()],
|
||||||
|
) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(_) => match value {
|
||||||
|
Value::Nil => {
|
||||||
|
contents
|
||||||
|
.borrow_mut()
|
||||||
|
.remove(&index_value.as_indexable()?);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
contents
|
||||||
|
.borrow_mut()
|
||||||
|
.insert(index_value.as_indexable()?, value);
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -599,20 +631,34 @@ impl ClosureRunner {
|
|||||||
}
|
}
|
||||||
Instruction::GetTable(res, tablereg, indexreg) => {
|
Instruction::GetTable(res, tablereg, indexreg) => {
|
||||||
let value = match self.stack.get(tablereg).cloned() {
|
let value = match self.stack.get(tablereg).cloned() {
|
||||||
Some(value) => {
|
Some(table_value) => {
|
||||||
let table = value.borrow();
|
let table = table_value.borrow();
|
||||||
if let Value::Table { contents, .. } = &*table {
|
if let Value::Table {
|
||||||
|
contents,
|
||||||
|
metatable,
|
||||||
|
} = &*table
|
||||||
|
{
|
||||||
let table = contents.borrow();
|
let table = contents.borrow();
|
||||||
let index_value = self
|
let index_value = self
|
||||||
.stack
|
.stack
|
||||||
.get(indexreg)
|
.get(indexreg)
|
||||||
.map(|v| v.borrow().clone())
|
.map(|v| v.borrow().clone())
|
||||||
.unwrap_or(Value::Nil)
|
.unwrap_or(Value::Nil);
|
||||||
.as_indexable()?;
|
let value = table.get(&index_value.clone().as_indexable()?);
|
||||||
let value = table.get(&index_value);
|
|
||||||
match value {
|
match value {
|
||||||
Some(value) => StackValue::Value(value.clone()),
|
Some(value) => StackValue::Value(value.clone()),
|
||||||
None => StackValue::Value(Value::Nil),
|
None => {
|
||||||
|
match self.call_metamethod(
|
||||||
|
metatable,
|
||||||
|
"__index",
|
||||||
|
vec![value.unwrap().clone(), index_value.clone()],
|
||||||
|
) {
|
||||||
|
Ok(value) => {
|
||||||
|
StackValue::Value(value.first().unwrap().clone())
|
||||||
|
}
|
||||||
|
Err(_) => StackValue::Value(Value::Nil),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::NotTable(table.clone()));
|
return Err(RuntimeError::NotTable(table.clone()));
|
||||||
@ -729,7 +775,7 @@ impl ClosureRunner {
|
|||||||
.get(func_reg)
|
.get(func_reg)
|
||||||
.map(|v| v.borrow().clone())
|
.map(|v| v.borrow().clone())
|
||||||
.unwrap_or(Value::Nil);
|
.unwrap_or(Value::Nil);
|
||||||
match value {
|
match &value {
|
||||||
Value::RustFunction(func) => {
|
Value::RustFunction(func) => {
|
||||||
let ret_values = func.borrow_mut().execute(params)?;
|
let ret_values = func.borrow_mut().execute(params)?;
|
||||||
if *ret_len != 0 {
|
if *ret_len != 0 {
|
||||||
@ -763,6 +809,34 @@ impl ClosureRunner {
|
|||||||
}
|
}
|
||||||
self.inner = Some(Box::new(closure.run(params)));
|
self.inner = Some(Box::new(closure.run(params)));
|
||||||
}
|
}
|
||||||
|
Value::Table { metatable, .. } => {
|
||||||
|
let mut metamethod_params = vec![value.clone()];
|
||||||
|
metamethod_params.extend(params);
|
||||||
|
let ret_values =
|
||||||
|
self.call_metamethod(&metatable, "__call", metamethod_params)?;
|
||||||
|
|
||||||
|
if *ret_len != 0 {
|
||||||
|
for i in 0..=(*ret_len - 2) {
|
||||||
|
self.set_stack(
|
||||||
|
*func_reg + i,
|
||||||
|
StackValue::Value(
|
||||||
|
ret_values
|
||||||
|
.get(i as usize)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(Value::Nil),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i, value) in ret_values.iter().enumerate() {
|
||||||
|
self.set_stack(
|
||||||
|
*func_reg + i as u16 + 1,
|
||||||
|
StackValue::Value(value.clone()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
self.top = *func_reg + ret_values.len() as u16;
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => return Err(RuntimeError::TriedCallingNonFunction(value.clone())),
|
_ => return Err(RuntimeError::TriedCallingNonFunction(value.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -975,6 +1049,8 @@ impl ClosureRunner {
|
|||||||
"__eq",
|
"__eq",
|
||||||
vec![lhs.clone(), rhs.clone()],
|
vec![lhs.clone(), rhs.clone()],
|
||||||
)?
|
)?
|
||||||
|
.first()
|
||||||
|
.unwrap()
|
||||||
.is_truthy(),
|
.is_truthy(),
|
||||||
))),
|
))),
|
||||||
);
|
);
|
||||||
@ -1049,7 +1125,10 @@ impl ClosureRunner {
|
|||||||
Value::Table { metatable, .. } => {
|
Value::Table { metatable, .. } => {
|
||||||
match self.call_metamethod(&metatable, "__len", vec![value.clone()]) {
|
match self.call_metamethod(&metatable, "__len", vec![value.clone()]) {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
self.set_stack(*res, StackValue::Value(result));
|
self.set_stack(
|
||||||
|
*res,
|
||||||
|
StackValue::Value(result.first().unwrap().clone()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
self.set_stack(*res, StackValue::Value(value.len()?));
|
self.set_stack(*res, StackValue::Value(value.len()?));
|
||||||
@ -1143,7 +1222,11 @@ impl ClosureRunner {
|
|||||||
.borrow()
|
.borrow()
|
||||||
.contains_key(&IndexableValue::String(metamethod.to_owned()))
|
.contains_key(&IndexableValue::String(metamethod.to_owned()))
|
||||||
{
|
{
|
||||||
self.call_metamethod(metatable, metamethod, vec![param.clone()])
|
Ok(self
|
||||||
|
.call_metamethod(metatable, metamethod, vec![param.clone()])?
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.unwrap())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::InvalidUnop(
|
Err(RuntimeError::InvalidUnop(
|
||||||
metamethod.to_owned(),
|
metamethod.to_owned(),
|
||||||
@ -1174,14 +1257,26 @@ impl ClosureRunner {
|
|||||||
.borrow()
|
.borrow()
|
||||||
.contains_key(&IndexableValue::String(metamethod.to_owned()))
|
.contains_key(&IndexableValue::String(metamethod.to_owned()))
|
||||||
{
|
{
|
||||||
self.call_metamethod(&metatable, metamethod, vec![lhs.clone(), rhs])
|
Ok(self
|
||||||
|
.call_metamethod(&metatable, metamethod, vec![lhs.clone(), rhs])?
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.unwrap())
|
||||||
} else {
|
} else {
|
||||||
if let Value::Table { metatable, .. } = &rhs {
|
if let Value::Table { metatable, .. } = &rhs {
|
||||||
if metatable
|
if metatable
|
||||||
.borrow()
|
.borrow()
|
||||||
.contains_key(&IndexableValue::String(metamethod.to_owned()))
|
.contains_key(&IndexableValue::String(metamethod.to_owned()))
|
||||||
{
|
{
|
||||||
self.call_metamethod(&metatable, metamethod, vec![lhs, rhs.clone()])
|
Ok(self
|
||||||
|
.call_metamethod(
|
||||||
|
&metatable,
|
||||||
|
metamethod,
|
||||||
|
vec![lhs, rhs.clone()],
|
||||||
|
)?
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.unwrap())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::InvalidBinop(
|
Err(RuntimeError::InvalidBinop(
|
||||||
metamethod.to_owned(),
|
metamethod.to_owned(),
|
||||||
@ -1202,7 +1297,11 @@ impl ClosureRunner {
|
|||||||
.borrow()
|
.borrow()
|
||||||
.contains_key(&IndexableValue::String(metamethod.to_owned()))
|
.contains_key(&IndexableValue::String(metamethod.to_owned()))
|
||||||
{
|
{
|
||||||
self.call_metamethod(&metatable, metamethod, vec![lhs, rhs.clone()])
|
Ok(self
|
||||||
|
.call_metamethod(&metatable, metamethod, vec![lhs, rhs.clone()])?
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.unwrap())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::InvalidBinop(
|
Err(RuntimeError::InvalidBinop(
|
||||||
metamethod.to_owned(),
|
metamethod.to_owned(),
|
||||||
@ -1226,7 +1325,7 @@ impl ClosureRunner {
|
|||||||
metatable: &Table,
|
metatable: &Table,
|
||||||
metamethod: &str,
|
metamethod: &str,
|
||||||
params: Vec<Value>,
|
params: Vec<Value>,
|
||||||
) -> Result<Value, RuntimeError> {
|
) -> Result<Vec<Value>, RuntimeError> {
|
||||||
if let Some(value) = metatable
|
if let Some(value) = metatable
|
||||||
.borrow()
|
.borrow()
|
||||||
.get(&IndexableValue::String(metamethod.to_owned()))
|
.get(&IndexableValue::String(metamethod.to_owned()))
|
||||||
@ -1234,7 +1333,7 @@ impl ClosureRunner {
|
|||||||
match value {
|
match value {
|
||||||
Value::RustFunction(function) => {
|
Value::RustFunction(function) => {
|
||||||
let result = function.borrow_mut().execute(params)?;
|
let result = function.borrow_mut().execute(params)?;
|
||||||
Ok(result.into_iter().next().unwrap())
|
Ok(result)
|
||||||
}
|
}
|
||||||
Value::Function(closure) => {
|
Value::Function(closure) => {
|
||||||
let mut runnable = closure.run(params);
|
let mut runnable = closure.run(params);
|
||||||
@ -1244,7 +1343,7 @@ impl ClosureRunner {
|
|||||||
return_value = runnable.next()?;
|
return_value = runnable.next()?;
|
||||||
return_value.is_none()
|
return_value.is_none()
|
||||||
} {}
|
} {}
|
||||||
Ok(return_value.unwrap().into_iter().next().unwrap())
|
Ok(return_value.unwrap())
|
||||||
}
|
}
|
||||||
_ => Err(RuntimeError::MetafunctionNotCallable(value.clone())),
|
_ => Err(RuntimeError::MetafunctionNotCallable(value.clone())),
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user