fibonacci is running because I put Rc<RefCell<Values>> on the stack (iso Values). Not sure If I'm happy about that
This commit is contained in:
parent
cd409c0897
commit
45d2d6f322
5 changed files with 120 additions and 114 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::cell::{Ref, RefMut};
|
||||||
use crate::builtins::{FunctionMap, Signature, add};
|
use crate::builtins::{FunctionMap, Signature, add};
|
||||||
use crate::compiler::tokens::TokenType::{DateTime, StringType, Void};
|
use crate::compiler::tokens::TokenType::{DateTime, StringType, Void};
|
||||||
use crate::errors::RuntimeError;
|
use crate::errors::RuntimeError;
|
||||||
|
|
@ -16,20 +17,20 @@ pub(crate) static GLOBAL_FUNCTIONS: LazyLock<FunctionMap> = LazyLock::new(|| {
|
||||||
global_functions
|
global_functions
|
||||||
});
|
});
|
||||||
|
|
||||||
fn println(_self_val: Value, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn println(_self_val: RefMut<Value>, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
print(_self_val, args)?;
|
print(_self_val, args)?;
|
||||||
println!();
|
println!();
|
||||||
Ok(Value::Void)
|
Ok(Value::Void)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print(_self_val: Value, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn print(_self_val: RefMut<Value>, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
print!("{}", arg);
|
print!("{}", arg);
|
||||||
}
|
}
|
||||||
Ok(Value::Void)
|
Ok(Value::Void)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn now(_self_val: Value, _args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn now(_self_val: RefMut<Value>, _args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
Ok(Value::DateTime(Box::new(chrono::DateTime::from(
|
Ok(Value::DateTime(Box::new(chrono::DateTime::from(
|
||||||
chrono::Utc::now(),
|
chrono::Utc::now(),
|
||||||
))))
|
))))
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
use crate::compiler::ast_pass::Parameter;
|
|
||||||
use crate::builtins::{FunctionMap, Signature, add, expected};
|
use crate::builtins::{FunctionMap, Signature, add, expected};
|
||||||
use crate::errors::RuntimeError;
|
use crate::compiler::ast_pass::Parameter;
|
||||||
use crate::compiler::tokens::TokenType;
|
use crate::compiler::tokens::TokenType;
|
||||||
use crate::compiler::tokens::TokenType::U64;
|
use crate::compiler::tokens::TokenType::U64;
|
||||||
|
use crate::errors::RuntimeError;
|
||||||
use crate::value::{Value, u64};
|
use crate::value::{Value, u64};
|
||||||
|
use std::cell::RefMut;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
macro_rules! mut_list_fn {
|
macro_rules! mut_list_fn {
|
||||||
(mut $list:ident, mut $args:ident => $body:expr) => {
|
(mut $list:ident, mut $args:ident => $body:expr) => {
|
||||||
|self_val: Value, mut $args: Vec<Value>| -> Result<Value, RuntimeError> {
|
|self_val: RefMut<Value>, mut $args: Vec<Value>| -> Result<Value, RuntimeError> {
|
||||||
match self_val {
|
match self_val {
|
||||||
Value::List(mut $list) => $body,
|
Value::List(mut $list) => $body,
|
||||||
_ => Err(expected_a_list()),
|
_ => Err(expected_a_list()),
|
||||||
|
|
@ -19,7 +21,7 @@ macro_rules! mut_list_fn {
|
||||||
|
|
||||||
macro_rules! list_fn {
|
macro_rules! list_fn {
|
||||||
($list:ident, $args:ident => $body:expr) => {
|
($list:ident, $args:ident => $body:expr) => {
|
||||||
|self_val: Value, $args: Vec<Value>| -> Result<Value, RuntimeError> {
|
|self_val: Ref<Value>, $args: Vec<Value>| -> Result<Value, RuntimeError> {
|
||||||
match self_val {
|
match self_val {
|
||||||
Value::List($list) => $body,
|
Value::List($list) => $body,
|
||||||
_ => Err(expected_a_list()),
|
_ => Err(expected_a_list()),
|
||||||
|
|
@ -31,46 +33,46 @@ macro_rules! list_fn {
|
||||||
pub(crate) fn list_functions() -> FunctionMap {
|
pub(crate) fn list_functions() -> FunctionMap {
|
||||||
let mut list_functions: FunctionMap = HashMap::new();
|
let mut list_functions: FunctionMap = HashMap::new();
|
||||||
let functions = &mut list_functions;
|
let functions = &mut list_functions;
|
||||||
add(
|
add(functions, "len", Signature::new(vec![], U64, len));
|
||||||
functions,
|
|
||||||
"len",
|
|
||||||
Signature::new(
|
|
||||||
vec![],
|
|
||||||
U64,
|
|
||||||
list_fn!(self_val, _args => Ok(u64(self_val.len() as u64))),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
add(
|
add(
|
||||||
functions,
|
functions,
|
||||||
"push",
|
"push",
|
||||||
Signature::new(
|
Signature::new(vec![Parameter::new("element", TokenType::Any)], U64, push),
|
||||||
vec![Parameter::new("element", TokenType::Any)],
|
|
||||||
U64,
|
|
||||||
mut_list_fn!(mut list, mut args => {
|
|
||||||
list.push(args.remove(0));
|
|
||||||
Ok(Value::List(list))
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
add(
|
add(
|
||||||
functions,
|
functions,
|
||||||
"remove",
|
"remove",
|
||||||
Signature::new(
|
Signature::new(vec![Parameter::new("index", U64)], U64, remove),
|
||||||
vec![Parameter::new("index", U64)],
|
|
||||||
U64,
|
|
||||||
mut_list_fn!(mut list, mut args => {
|
|
||||||
let index = args.remove(0).cast_usize().unwrap();
|
|
||||||
if index >= list.len() {
|
|
||||||
return Err(RuntimeError::IndexOutOfBounds(index, list.len()))
|
|
||||||
}
|
|
||||||
list.remove(index);
|
|
||||||
Ok(Value::List(list))
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
list_functions
|
list_functions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn remove(mut self_val: RefMut<Value>, mut args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
|
if let Value::List(list) = self_val.deref_mut() {
|
||||||
|
list.remove(args.remove(0).cast_usize()?);
|
||||||
|
Ok(Value::Void)
|
||||||
|
} else {
|
||||||
|
Err(expected_a_list())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push(mut self_val: RefMut<Value>, mut args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
|
if let Value::List(list) = self_val.deref_mut() {
|
||||||
|
list.push(args.remove(0));
|
||||||
|
Ok(Value::Void)
|
||||||
|
} else {
|
||||||
|
Err(expected_a_list())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn len(self_val: RefMut<Value>, _args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
|
if let Value::List(list) = self_val.deref() {
|
||||||
|
Ok(u64(list.len() as u64))
|
||||||
|
} else {
|
||||||
|
Err(expected_a_list())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn expected_a_list() -> RuntimeError {
|
fn expected_a_list() -> RuntimeError {
|
||||||
expected("list")
|
expected("list")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@ mod string;
|
||||||
mod list;
|
mod list;
|
||||||
pub(crate) mod globals;
|
pub(crate) mod globals;
|
||||||
|
|
||||||
|
use std::cell::{Ref, RefCell, RefMut};
|
||||||
use crate::builtins::string::string_functions;
|
use crate::builtins::string::string_functions;
|
||||||
use crate::errors::{CompilerError, RuntimeError};
|
use crate::errors::{CompilerError, RuntimeError};
|
||||||
use crate::compiler::tokens::TokenType;
|
use crate::compiler::tokens::TokenType;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
use crate::compiler::ast_pass::Parameter;
|
use crate::compiler::ast_pass::Parameter;
|
||||||
use crate::builtins::list::list_functions;
|
use crate::builtins::list::list_functions;
|
||||||
|
|
@ -35,7 +37,7 @@ impl Signature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) type FunctionFn = fn(Value, Vec<Value>) -> Result<Value, RuntimeError>;
|
pub(crate) type FunctionFn = fn(RefMut<Value>, Vec<Value>) -> Result<Value, RuntimeError>;
|
||||||
/// maps function names to the signature
|
/// maps function names to the signature
|
||||||
pub(crate) type FunctionMap = HashMap<String, Signature>;
|
pub(crate) type FunctionMap = HashMap<String, Signature>;
|
||||||
/// maps receiver type name to a function map
|
/// maps receiver type name to a function map
|
||||||
|
|
@ -63,10 +65,10 @@ pub(crate) fn lookup(type_name: &str, method_name: &str) -> Result<&'static Sign
|
||||||
pub(crate) fn call(
|
pub(crate) fn call(
|
||||||
type_name: &str,
|
type_name: &str,
|
||||||
method_name: &str,
|
method_name: &str,
|
||||||
self_val: Value,
|
self_val: Rc<RefCell<Value>>,
|
||||||
args: Vec<Value>,
|
args: Vec<Value>,
|
||||||
) -> Result<Value, RuntimeError> {
|
) -> Result<Value, RuntimeError> {
|
||||||
(lookup(type_name,method_name).map_err(|e|RuntimeError::FunctionNotFound(e.to_string()))?.function)(self_val, args)
|
(lookup(type_name,method_name).map_err(|e|RuntimeError::FunctionNotFound(e.to_string()))?.function)(self_val.borrow_mut(), args)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn expected(expected_type: &str) -> RuntimeError {
|
pub(crate) fn expected(expected_type: &str) -> RuntimeError {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::cell::{Ref, RefMut};
|
||||||
use crate::builtins::{FunctionMap, Parameter, Signature, add, expected};
|
use crate::builtins::{FunctionMap, Parameter, Signature, add, expected};
|
||||||
use crate::errors::RuntimeError;
|
use crate::errors::RuntimeError;
|
||||||
use crate::compiler::tokens::TokenType::{StringType, U64};
|
use crate::compiler::tokens::TokenType::{StringType, U64};
|
||||||
|
|
@ -43,62 +44,62 @@ pub(crate) fn string_functions() -> FunctionMap {
|
||||||
string_functions
|
string_functions
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_len(self_val: Value, _args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn string_len(self_val: RefMut<Value>, _args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
match self_val {
|
match self_val.clone() {
|
||||||
Value::String(s) => Ok(u64(s.len() as u64)),
|
Value::String(s) => Ok(u64(s.len() as u64)),
|
||||||
_ => Err(expected_a_string()),
|
_ => Err(expected_a_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_to_uppercase(self_val: Value, _args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn string_to_uppercase(self_val: RefMut<Value>, _args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
match self_val {
|
match self_val.clone() {
|
||||||
Value::String(s) => Ok(string(s.to_uppercase())),
|
Value::String(s) => Ok(string(s.to_uppercase())),
|
||||||
_ => Err(expected_a_string()),
|
_ => Err(expected_a_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_to_lowercase(self_val: Value, _args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn string_to_lowercase(self_val: RefMut<Value>, _args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
match self_val {
|
match self_val.clone() {
|
||||||
Value::String(s) => Ok(string(s.to_lowercase())),
|
Value::String(s) => Ok(string(s.to_lowercase())),
|
||||||
_ => Err(expected_a_string()),
|
_ => Err(expected_a_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_contains(self_val: Value, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn string_contains(self_val: RefMut<Value>, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
match (self_val, args.first()) {
|
match (self_val.clone(), args.first()) {
|
||||||
(Value::String(s), Some(Value::String(pat))) => Ok(bool(s.contains(pat.as_str()))),
|
(Value::String(s), Some(Value::String(pat))) => Ok(bool(s.contains(pat.as_str()))),
|
||||||
_ => Err(expected_a_string()),
|
_ => Err(expected_a_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_reverse(self_val: Value, _: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn string_reverse(self_val: RefMut<Value>, _: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
match self_val {
|
match self_val.clone() {
|
||||||
Value::String(s) => Ok(s.chars().rev().collect::<String>().into()),
|
Value::String(s) => Ok(s.chars().rev().collect::<String>().into()),
|
||||||
_ => Err(expected_a_string()),
|
_ => Err(expected_a_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_trim(self_val: Value, _: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn string_trim(self_val: RefMut<Value>, _: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
match self_val {
|
match self_val.clone() {
|
||||||
Value::String(s) => Ok(string(s.trim())),
|
Value::String(s) => Ok(string(s.trim())),
|
||||||
_ => Err(expected_a_string()),
|
_ => Err(expected_a_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_trim_start(self_val: Value, _: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn string_trim_start(self_val: RefMut<Value>, _: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
match self_val {
|
match self_val.clone() {
|
||||||
Value::String(s) => Ok(string(s.trim_start())),
|
Value::String(s) => Ok(string(s.trim_start())),
|
||||||
_ => Err(expected_a_string()),
|
_ => Err(expected_a_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_trim_end(self_val: Value, _: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn string_trim_end(self_val: RefMut<Value>, _: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
match self_val {
|
match self_val.clone() {
|
||||||
Value::String(s) => Ok(string(s.trim_end())),
|
Value::String(s) => Ok(string(s.trim_end())),
|
||||||
_ => Err(expected_a_string()),
|
_ => Err(expected_a_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn string_replace_all(receiver: Value, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn string_replace_all(receiver: RefMut<Value>, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
let pattern = if let Value::String(s) = &args[0] {
|
let pattern = if let Value::String(s) = &args[0] {
|
||||||
Regex::new(s).map_err(|_| RuntimeError::IllegalArgumentException("Invalid regex".into()))?
|
Regex::new(s).map_err(|_| RuntimeError::IllegalArgumentException("Invalid regex".into()))?
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -116,7 +117,7 @@ fn string_replace_all(receiver: Value, args: Vec<Value>) -> Result<Value, Runtim
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
match receiver {
|
match receiver.clone() {
|
||||||
Value::String(ref str) => Ok(string(pattern.replace_all(str, replacement))),
|
Value::String(ref str) => Ok(string(pattern.replace_all(str, replacement))),
|
||||||
_ => Err(expected_a_string()),
|
_ => Err(expected_a_string()),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
112
src/vm.rs
112
src/vm.rs
|
|
@ -5,7 +5,9 @@ use crate::compiler::tokens::TokenType;
|
||||||
use crate::errors::{RuntimeError, ValueError};
|
use crate::errors::{RuntimeError, ValueError};
|
||||||
use crate::value::{Object, Value};
|
use crate::value::{Object, Value};
|
||||||
use arc_swap::Guard;
|
use arc_swap::Guard;
|
||||||
|
use std::cell::{RefCell, RefMut};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
|
|
@ -19,12 +21,18 @@ pub async fn interpret_async(
|
||||||
let chunk = registry.get(function);
|
let chunk = registry.get(function);
|
||||||
if let Some(chunk) = chunk {
|
if let Some(chunk) = chunk {
|
||||||
let mut vm = Vm::new(®istry);
|
let mut vm = Vm::new(®istry);
|
||||||
vm.local_vars
|
vm.local_vars.insert(
|
||||||
.insert("path".to_string(), Value::String(uri.into()));
|
"path".to_string(),
|
||||||
vm.local_vars
|
Rc::new(RefCell::new(Value::String(uri.into()))),
|
||||||
.insert("query".to_string(), Value::Map(value_map(query_params)));
|
);
|
||||||
vm.local_vars
|
vm.local_vars.insert(
|
||||||
.insert("headers".to_string(), Value::Map(value_map(headers)));
|
"query".to_string(),
|
||||||
|
Rc::new(RefCell::new(Value::Map(value_map(query_params)))),
|
||||||
|
);
|
||||||
|
vm.local_vars.insert(
|
||||||
|
"headers".to_string(),
|
||||||
|
Rc::new(RefCell::new(Value::Map(value_map(headers)))),
|
||||||
|
);
|
||||||
vm.run(&get_context(function), chunk)
|
vm.run(&get_context(function), chunk)
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::FunctionNotFound(function.to_string()))
|
Err(RuntimeError::FunctionNotFound(function.to_string()))
|
||||||
|
|
@ -44,8 +52,8 @@ pub fn interpret_function(chunk: &AsmChunk, args: Vec<Value>) -> Result<Value, R
|
||||||
|
|
||||||
pub(crate) struct Vm {
|
pub(crate) struct Vm {
|
||||||
ip: usize,
|
ip: usize,
|
||||||
stack: Vec<Value>,
|
stack: Vec<Rc<RefCell<Value>>>,
|
||||||
local_vars: HashMap<String, Value>,
|
local_vars: HashMap<String, Rc<RefCell<Value>>>,
|
||||||
error_occurred: bool,
|
error_occurred: bool,
|
||||||
pub(crate) registry: Arc<AsmRegistry>,
|
pub(crate) registry: Arc<AsmRegistry>,
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +76,8 @@ impl Vm {
|
||||||
) -> Result<Value, RuntimeError> {
|
) -> Result<Value, RuntimeError> {
|
||||||
// arguments -> locals
|
// arguments -> locals
|
||||||
for (_, name) in chunk.vars.iter() {
|
for (_, name) in chunk.vars.iter() {
|
||||||
self.local_vars.insert(name.clone(), args.remove(0));
|
self.local_vars
|
||||||
|
.insert(name.clone(), Rc::new(RefCell::new(args.remove(0))));
|
||||||
}
|
}
|
||||||
self.run("", chunk)
|
self.run("", chunk)
|
||||||
}
|
}
|
||||||
|
|
@ -81,7 +90,7 @@ impl Vm {
|
||||||
match opcode {
|
match opcode {
|
||||||
Op::Constant(c) => {
|
Op::Constant(c) => {
|
||||||
let value = &chunk.constants[*c];
|
let value = &chunk.constants[*c];
|
||||||
self.push(value.clone());
|
self.push(Rc::new(RefCell::new(value.clone())));
|
||||||
}
|
}
|
||||||
Op::Add => binary_op(self, |a, b| a + b),
|
Op::Add => binary_op(self, |a, b| a + b),
|
||||||
Op::Subtract => binary_op(self, |a, b| a - b),
|
Op::Subtract => binary_op(self, |a, b| a - b),
|
||||||
|
|
@ -110,7 +119,7 @@ impl Vm {
|
||||||
return if self.stack.is_empty() {
|
return if self.stack.is_empty() {
|
||||||
Ok(Value::Void)
|
Ok(Value::Void)
|
||||||
} else {
|
} else {
|
||||||
Ok(self.pop())
|
Ok(self.pop().borrow().clone())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Op::Shl => binary_op(self, |a, b| a << b),
|
Op::Shl => binary_op(self, |a, b| a << b),
|
||||||
|
|
@ -123,46 +132,52 @@ impl Vm {
|
||||||
Op::NotEqual => binary_op(self, |a, b| Ok(Value::Bool(a != b))),
|
Op::NotEqual => binary_op(self, |a, b| Ok(Value::Bool(a != b))),
|
||||||
Op::Print => {
|
Op::Print => {
|
||||||
debug!("print {:?}", self.stack);
|
debug!("print {:?}", self.stack);
|
||||||
let v = self.pop();
|
let v = self.pop().borrow().clone();
|
||||||
println!("{}", v);
|
println!("{}", v);
|
||||||
}
|
}
|
||||||
Op::DefList(len) => {
|
Op::DefList(len) => {
|
||||||
let mut list = vec![];
|
let mut list = vec![];
|
||||||
for _ in 0..*len {
|
for _ in 0..*len {
|
||||||
let value = self.pop();
|
let value = self.pop();
|
||||||
list.push(value);
|
list.push(value.borrow().clone());
|
||||||
}
|
}
|
||||||
list.reverse();
|
list.reverse();
|
||||||
self.push(Value::List(list));
|
self.push(Rc::new(RefCell::new(Value::List(list))));
|
||||||
}
|
}
|
||||||
Op::Assign(var_index) => {
|
Op::Assign(var_index) => {
|
||||||
let (var_type, name) = chunk.vars.get(*var_index).unwrap();
|
let (var_type, name) = chunk.vars.get(*var_index).unwrap();
|
||||||
let value = self.pop();
|
let mut value = self.pop().borrow().clone();
|
||||||
let value = number(var_type, value)?;
|
match var_type {
|
||||||
self.local_vars.insert(name.to_string(), value); //insert or update
|
TokenType::U32 => value = value.cast_u32()?,
|
||||||
|
TokenType::U64 => value = value.cast_u64()?,
|
||||||
|
TokenType::F32 => value = value.cast_f32()?,
|
||||||
|
TokenType::I32 => value = value.cast_i32()?,
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
self.local_vars.insert(name.to_string(), Rc::new(RefCell::new(value))); //insert or update
|
||||||
}
|
}
|
||||||
Op::DefMap(len) => {
|
Op::DefMap(len) => {
|
||||||
let mut map = HashMap::new();
|
let mut map = HashMap::new();
|
||||||
for _ in 0..*len {
|
for _ in 0..*len {
|
||||||
let value = self.pop();
|
let value = self.pop().borrow().clone();
|
||||||
let key = self.pop();
|
let key = self.pop().borrow().clone();
|
||||||
map.insert(key, value);
|
map.insert(key, value);
|
||||||
}
|
}
|
||||||
self.push(Value::Map(map));
|
self.push(Rc::new(RefCell::new(Value::Map(map))));
|
||||||
}
|
}
|
||||||
Op::Get(var_index) => {
|
Op::Get(var_index) => {
|
||||||
let (_, name_index) = chunk.vars.get(*var_index).unwrap();
|
let (_, name_index) = chunk.vars.get(*var_index).unwrap();
|
||||||
let value = self.local_vars.get(name_index).unwrap().clone();
|
let value = Rc::clone(self.local_vars.get(name_index).unwrap());
|
||||||
self.push(value);
|
self.push(value);
|
||||||
}
|
}
|
||||||
Op::ListGet => {
|
Op::ListGet => {
|
||||||
let index = self.pop().cast_usize()?;
|
let index = self.pop().borrow().clone().cast_usize()?;
|
||||||
let list = self.pop();
|
let list = self.pop();
|
||||||
if let Value::List(list) = list {
|
if let Value::List(list) = list.borrow().clone() {
|
||||||
if list.len() <= index {
|
if list.len() <= index {
|
||||||
return Err(RuntimeError::IndexOutOfBounds(list.len(), index));
|
return Err(RuntimeError::IndexOutOfBounds(list.len(), index));
|
||||||
} else {
|
} else {
|
||||||
self.push(list.get(index).cloned().unwrap())
|
self.push(Rc::new(RefCell::new(list.get(index).cloned().unwrap())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -173,13 +188,13 @@ impl Vm {
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
for _ in 0..*num_args {
|
for _ in 0..*num_args {
|
||||||
let arg = self.pop();
|
let arg = self.pop();
|
||||||
args.push(arg);
|
args.push(arg.borrow().clone());
|
||||||
}
|
}
|
||||||
args.reverse();
|
args.reverse();
|
||||||
let receiver = self.pop();
|
let receiver = self.pop();
|
||||||
let return_value =
|
let return_value =
|
||||||
crate::builtins::call(&receiver_type_name, &function_name, receiver, args)?;
|
crate::builtins::call(&receiver_type_name, &function_name, receiver, args)?;
|
||||||
self.push(return_value);
|
self.push(Rc::new(RefCell::new(return_value)));
|
||||||
}
|
}
|
||||||
Op::Pop => {
|
Op::Pop => {
|
||||||
self.pop();
|
self.pop();
|
||||||
|
|
@ -187,15 +202,15 @@ impl Vm {
|
||||||
Op::Call(function_name_index, num_args) => {
|
Op::Call(function_name_index, num_args) => {
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
for _ in 0..*num_args {
|
for _ in 0..*num_args {
|
||||||
let arg = self.pop();
|
let arg = self.pop().borrow().clone();
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
}
|
}
|
||||||
args.reverse();
|
args.reverse();
|
||||||
|
|
||||||
let function_name = chunk.constants[*function_name_index].to_string();
|
let function_name = chunk.constants[*function_name_index].to_string();
|
||||||
if let Some(fun) = GLOBAL_FUNCTIONS.get(&function_name) {
|
if let Some(fun) = GLOBAL_FUNCTIONS.get(&function_name) {
|
||||||
let return_value = (fun.function)(Value::Void, args)?;
|
let return_value = (fun.function)(Rc::new(RefCell::new(Value::Void)).borrow_mut(), args)?;
|
||||||
self.push(return_value);
|
self.push(Rc::new(RefCell::new(return_value)));
|
||||||
} else {
|
} else {
|
||||||
let function_chunk = self.registry.get(&function_name).or_else(|| {
|
let function_chunk = self.registry.get(&function_name).or_else(|| {
|
||||||
self.registry.get(&format!("{}/{}", context, function_name))
|
self.registry.get(&format!("{}/{}", context, function_name))
|
||||||
|
|
@ -215,31 +230,31 @@ impl Vm {
|
||||||
|
|
||||||
let mut fields = vec![];
|
let mut fields = vec![];
|
||||||
params.iter().zip(args).for_each(|(param, arg)| {
|
params.iter().zip(args).for_each(|(param, arg)| {
|
||||||
fields.push((param.name.lexeme.clone(), arg))
|
fields.push((param.name.lexeme.clone(), arg.clone()));
|
||||||
});
|
});
|
||||||
let new_instance = Value::ObjectType(Box::new(Object {
|
let new_instance = Value::ObjectType(Box::new(Object {
|
||||||
definition: function_name,
|
definition: function_name,
|
||||||
fields,
|
fields,
|
||||||
}));
|
}));
|
||||||
self.push(new_instance);
|
self.push(Rc::new(RefCell::new(new_instance)));
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::FunctionNotFound(function_name));
|
return Err(RuntimeError::FunctionNotFound(function_name));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let result = interpret_function(function_chunk.unwrap(), args)?;
|
let result = interpret_function(function_chunk.unwrap(), args)?;
|
||||||
self.push(result);
|
self.push(Rc::new(RefCell::new(result)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Op::GotoIfNot(goto_addr) => {
|
Op::GotoIfNot(goto_addr) => {
|
||||||
let b = self.pop();
|
let b = self.pop();
|
||||||
if b == Value::Bool(false) {
|
if *b.borrow() == Value::Bool(false) {
|
||||||
self.ip = *goto_addr;
|
self.ip = *goto_addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Op::GotoIf(goto_addr) => {
|
Op::GotoIf(goto_addr) => {
|
||||||
let b = self.pop();
|
let b = self.pop();
|
||||||
if b == Value::Bool(true) {
|
if *b.borrow() == Value::Bool(true) {
|
||||||
self.ip = *goto_addr;
|
self.ip = *goto_addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -255,16 +270,12 @@ impl Vm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, value: Value) {
|
fn push(&mut self, value: Rc<RefCell<Value>>) {
|
||||||
if value != Value::Void {
|
|
||||||
self.stack.push(value);
|
self.stack.push(value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn pop(&mut self) -> Value {
|
fn pop(&mut self) -> Rc<RefCell<Value>> {
|
||||||
self.stack
|
self.stack.pop().unwrap_or_else(|| panic!("underflow"))
|
||||||
.pop()
|
|
||||||
.unwrap_or_else(|| Value::Error("Stack underflow".to_string()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -272,9 +283,9 @@ fn binary_op(vm: &mut Vm, op: impl Fn(&Value, &Value) -> Result<Value, ValueErro
|
||||||
let b = vm.pop();
|
let b = vm.pop();
|
||||||
let a = vm.pop();
|
let a = vm.pop();
|
||||||
|
|
||||||
let result = op(&a, &b);
|
let result = op(&a.borrow(), &b.borrow());
|
||||||
match result {
|
match result {
|
||||||
Ok(result) => vm.push(result),
|
Ok(result) => vm.push(Rc::new(RefCell::new(result))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
vm.error_occurred = true;
|
vm.error_occurred = true;
|
||||||
println!("Error: {} {:?} and {:?}", e, a, b);
|
println!("Error: {} {:?} and {:?}", e, a, b);
|
||||||
|
|
@ -284,9 +295,9 @@ fn binary_op(vm: &mut Vm, op: impl Fn(&Value, &Value) -> Result<Value, ValueErro
|
||||||
|
|
||||||
fn unary_op(stack: &mut Vm, op: impl Fn(&Value) -> Result<Value, ValueError> + Copy) {
|
fn unary_op(stack: &mut Vm, op: impl Fn(&Value) -> Result<Value, ValueError> + Copy) {
|
||||||
let a = stack.pop();
|
let a = stack.pop();
|
||||||
let result = op(&a);
|
let result = op(&a.borrow());
|
||||||
match result {
|
match result {
|
||||||
Ok(result) => stack.push(result),
|
Ok(result) => stack.push(Rc::new(RefCell::new(result))),
|
||||||
Err(e) => panic!("Error: {:?} {:?}", e, a),
|
Err(e) => panic!("Error: {:?} {:?}", e, a),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -299,17 +310,6 @@ pub(crate) fn get_context(path: &str) -> String {
|
||||||
parts.join("/")
|
parts.join("/")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn number(var_type: &TokenType, value: Value) -> Result<Value, RuntimeError> {
|
|
||||||
let value = match var_type {
|
|
||||||
TokenType::U32 => value.cast_u32()?,
|
|
||||||
TokenType::U64 => value.cast_u64()?,
|
|
||||||
TokenType::F32 => value.cast_f32()?,
|
|
||||||
TokenType::I32 => value.cast_i32()?,
|
|
||||||
_ => value,
|
|
||||||
};
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn value_map(strings: HashMap<String, String>) -> HashMap<Value, Value> {
|
fn value_map(strings: HashMap<String, String>) -> HashMap<Value, Value> {
|
||||||
strings
|
strings
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue