From 45d2d6f3221754fcbbd4c88a76df31746c27b785 Mon Sep 17 00:00:00 2001 From: Shautvast Date: Fri, 5 Dec 2025 20:30:14 +0100 Subject: [PATCH] fibonacci is running because I put Rc> on the stack (iso Values). Not sure If I'm happy about that --- src/builtins/globals.rs | 7 +-- src/builtins/list.rs | 68 ++++++++++++------------ src/builtins/mod.rs | 8 +-- src/builtins/string.rs | 37 ++++++------- src/vm.rs | 114 ++++++++++++++++++++-------------------- 5 files changed, 120 insertions(+), 114 deletions(-) diff --git a/src/builtins/globals.rs b/src/builtins/globals.rs index 85e3b98..a000b6f 100644 --- a/src/builtins/globals.rs +++ b/src/builtins/globals.rs @@ -1,3 +1,4 @@ +use std::cell::{Ref, RefMut}; use crate::builtins::{FunctionMap, Signature, add}; use crate::compiler::tokens::TokenType::{DateTime, StringType, Void}; use crate::errors::RuntimeError; @@ -16,20 +17,20 @@ pub(crate) static GLOBAL_FUNCTIONS: LazyLock = LazyLock::new(|| { global_functions }); -fn println(_self_val: Value, args: Vec) -> Result { +fn println(_self_val: RefMut, args: Vec) -> Result { print(_self_val, args)?; println!(); Ok(Value::Void) } -fn print(_self_val: Value, args: Vec) -> Result { +fn print(_self_val: RefMut, args: Vec) -> Result { for arg in args { print!("{}", arg); } Ok(Value::Void) } -fn now(_self_val: Value, _args: Vec) -> Result { +fn now(_self_val: RefMut, _args: Vec) -> Result { Ok(Value::DateTime(Box::new(chrono::DateTime::from( chrono::Utc::now(), )))) diff --git a/src/builtins/list.rs b/src/builtins/list.rs index 474d2c3..d2d430f 100644 --- a/src/builtins/list.rs +++ b/src/builtins/list.rs @@ -1,14 +1,16 @@ -use crate::compiler::ast_pass::Parameter; 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::U64; +use crate::errors::RuntimeError; use crate::value::{Value, u64}; +use std::cell::RefMut; use std::collections::HashMap; +use std::ops::{Deref, DerefMut}; macro_rules! mut_list_fn { (mut $list:ident, mut $args:ident => $body:expr) => { - |self_val: Value, mut $args: Vec| -> Result { + |self_val: RefMut, mut $args: Vec| -> Result { match self_val { Value::List(mut $list) => $body, _ => Err(expected_a_list()), @@ -19,7 +21,7 @@ macro_rules! mut_list_fn { macro_rules! list_fn { ($list:ident, $args:ident => $body:expr) => { - |self_val: Value, $args: Vec| -> Result { + |self_val: Ref, $args: Vec| -> Result { match self_val { Value::List($list) => $body, _ => Err(expected_a_list()), @@ -31,46 +33,46 @@ macro_rules! list_fn { pub(crate) fn list_functions() -> FunctionMap { let mut list_functions: FunctionMap = HashMap::new(); let functions = &mut list_functions; - add( - functions, - "len", - Signature::new( - vec![], - U64, - list_fn!(self_val, _args => Ok(u64(self_val.len() as u64))), - ), - ); + add(functions, "len", Signature::new(vec![], U64, len)); add( functions, "push", - Signature::new( - vec![Parameter::new("element", TokenType::Any)], - U64, - mut_list_fn!(mut list, mut args => { - list.push(args.remove(0)); - Ok(Value::List(list)) - }), - ), + Signature::new(vec![Parameter::new("element", TokenType::Any)], U64, push), ); add( functions, "remove", - Signature::new( - 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)) - }), - ), + Signature::new(vec![Parameter::new("index", U64)], U64, remove), ); list_functions } +fn remove(mut self_val: RefMut, mut args: Vec) -> Result { + 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, mut args: Vec) -> Result { + 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, _args: Vec) -> Result { + if let Value::List(list) = self_val.deref() { + Ok(u64(list.len() as u64)) + } else { + Err(expected_a_list()) + } +} + fn expected_a_list() -> RuntimeError { expected("list") } diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index 03dd602..0800959 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -2,11 +2,13 @@ mod string; mod list; pub(crate) mod globals; +use std::cell::{Ref, RefCell, RefMut}; use crate::builtins::string::string_functions; use crate::errors::{CompilerError, RuntimeError}; use crate::compiler::tokens::TokenType; use crate::value::Value; use std::collections::HashMap; +use std::rc::Rc; use std::sync::LazyLock; use crate::compiler::ast_pass::Parameter; use crate::builtins::list::list_functions; @@ -35,7 +37,7 @@ impl Signature { } } -pub(crate) type FunctionFn = fn(Value, Vec) -> Result; +pub(crate) type FunctionFn = fn(RefMut, Vec) -> Result; /// maps function names to the signature pub(crate) type FunctionMap = HashMap; /// 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( type_name: &str, method_name: &str, - self_val: Value, + self_val: Rc>, args: Vec, ) -> Result { - (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 { diff --git a/src/builtins/string.rs b/src/builtins/string.rs index 289252f..ea2bc08 100644 --- a/src/builtins/string.rs +++ b/src/builtins/string.rs @@ -1,3 +1,4 @@ +use std::cell::{Ref, RefMut}; use crate::builtins::{FunctionMap, Parameter, Signature, add, expected}; use crate::errors::RuntimeError; use crate::compiler::tokens::TokenType::{StringType, U64}; @@ -43,62 +44,62 @@ pub(crate) fn string_functions() -> FunctionMap { string_functions } -fn string_len(self_val: Value, _args: Vec) -> Result { - match self_val { +fn string_len(self_val: RefMut, _args: Vec) -> Result { + match self_val.clone() { Value::String(s) => Ok(u64(s.len() as u64)), _ => Err(expected_a_string()), } } -fn string_to_uppercase(self_val: Value, _args: Vec) -> Result { - match self_val { +fn string_to_uppercase(self_val: RefMut, _args: Vec) -> Result { + match self_val.clone() { Value::String(s) => Ok(string(s.to_uppercase())), _ => Err(expected_a_string()), } } -fn string_to_lowercase(self_val: Value, _args: Vec) -> Result { - match self_val { +fn string_to_lowercase(self_val: RefMut, _args: Vec) -> Result { + match self_val.clone() { Value::String(s) => Ok(string(s.to_lowercase())), _ => Err(expected_a_string()), } } -fn string_contains(self_val: Value, args: Vec) -> Result { - match (self_val, args.first()) { +fn string_contains(self_val: RefMut, args: Vec) -> Result { + match (self_val.clone(), args.first()) { (Value::String(s), Some(Value::String(pat))) => Ok(bool(s.contains(pat.as_str()))), _ => Err(expected_a_string()), } } -fn string_reverse(self_val: Value, _: Vec) -> Result { - match self_val { +fn string_reverse(self_val: RefMut, _: Vec) -> Result { + match self_val.clone() { Value::String(s) => Ok(s.chars().rev().collect::().into()), _ => Err(expected_a_string()), } } -fn string_trim(self_val: Value, _: Vec) -> Result { - match self_val { +fn string_trim(self_val: RefMut, _: Vec) -> Result { + match self_val.clone() { Value::String(s) => Ok(string(s.trim())), _ => Err(expected_a_string()), } } -fn string_trim_start(self_val: Value, _: Vec) -> Result { - match self_val { +fn string_trim_start(self_val: RefMut, _: Vec) -> Result { + match self_val.clone() { Value::String(s) => Ok(string(s.trim_start())), _ => Err(expected_a_string()), } } -fn string_trim_end(self_val: Value, _: Vec) -> Result { - match self_val { +fn string_trim_end(self_val: RefMut, _: Vec) -> Result { + match self_val.clone() { Value::String(s) => Ok(string(s.trim_end())), _ => Err(expected_a_string()), } } -fn string_replace_all(receiver: Value, args: Vec) -> Result { +fn string_replace_all(receiver: RefMut, args: Vec) -> Result { let pattern = if let Value::String(s) = &args[0] { Regex::new(s).map_err(|_| RuntimeError::IllegalArgumentException("Invalid regex".into()))? } else { @@ -116,7 +117,7 @@ fn string_replace_all(receiver: Value, args: Vec) -> Result Ok(string(pattern.replace_all(str, replacement))), _ => Err(expected_a_string()), } diff --git a/src/vm.rs b/src/vm.rs index de4b553..45bfcbb 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -5,7 +5,9 @@ use crate::compiler::tokens::TokenType; use crate::errors::{RuntimeError, ValueError}; use crate::value::{Object, Value}; use arc_swap::Guard; +use std::cell::{RefCell, RefMut}; use std::collections::HashMap; +use std::rc::Rc; use std::sync::Arc; use tracing::debug; @@ -19,12 +21,18 @@ pub async fn interpret_async( let chunk = registry.get(function); if let Some(chunk) = chunk { let mut vm = Vm::new(®istry); - vm.local_vars - .insert("path".to_string(), Value::String(uri.into())); - vm.local_vars - .insert("query".to_string(), Value::Map(value_map(query_params))); - vm.local_vars - .insert("headers".to_string(), Value::Map(value_map(headers))); + vm.local_vars.insert( + "path".to_string(), + Rc::new(RefCell::new(Value::String(uri.into()))), + ); + vm.local_vars.insert( + "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) } else { Err(RuntimeError::FunctionNotFound(function.to_string())) @@ -44,8 +52,8 @@ pub fn interpret_function(chunk: &AsmChunk, args: Vec) -> Result, - local_vars: HashMap, + stack: Vec>>, + local_vars: HashMap>>, error_occurred: bool, pub(crate) registry: Arc, } @@ -68,7 +76,8 @@ impl Vm { ) -> Result { // arguments -> locals 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) } @@ -81,7 +90,7 @@ impl Vm { match opcode { Op::Constant(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::Subtract => binary_op(self, |a, b| a - b), @@ -110,7 +119,7 @@ impl Vm { return if self.stack.is_empty() { Ok(Value::Void) } else { - Ok(self.pop()) + Ok(self.pop().borrow().clone()) }; } 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::Print => { debug!("print {:?}", self.stack); - let v = self.pop(); + let v = self.pop().borrow().clone(); println!("{}", v); } Op::DefList(len) => { let mut list = vec![]; for _ in 0..*len { let value = self.pop(); - list.push(value); + list.push(value.borrow().clone()); } list.reverse(); - self.push(Value::List(list)); + self.push(Rc::new(RefCell::new(Value::List(list)))); } Op::Assign(var_index) => { let (var_type, name) = chunk.vars.get(*var_index).unwrap(); - let value = self.pop(); - let value = number(var_type, value)?; - self.local_vars.insert(name.to_string(), value); //insert or update + let mut value = self.pop().borrow().clone(); + match var_type { + 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) => { let mut map = HashMap::new(); for _ in 0..*len { - let value = self.pop(); - let key = self.pop(); + let value = self.pop().borrow().clone(); + let key = self.pop().borrow().clone(); map.insert(key, value); } - self.push(Value::Map(map)); + self.push(Rc::new(RefCell::new(Value::Map(map)))); } Op::Get(var_index) => { 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); } Op::ListGet => { - let index = self.pop().cast_usize()?; + let index = self.pop().borrow().clone().cast_usize()?; let list = self.pop(); - if let Value::List(list) = list { + if let Value::List(list) = list.borrow().clone() { if list.len() <= index { return Err(RuntimeError::IndexOutOfBounds(list.len(), index)); } 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![]; for _ in 0..*num_args { let arg = self.pop(); - args.push(arg); + args.push(arg.borrow().clone()); } args.reverse(); let receiver = self.pop(); let return_value = crate::builtins::call(&receiver_type_name, &function_name, receiver, args)?; - self.push(return_value); + self.push(Rc::new(RefCell::new(return_value))); } Op::Pop => { self.pop(); @@ -187,15 +202,15 @@ impl Vm { Op::Call(function_name_index, num_args) => { let mut args = vec![]; for _ in 0..*num_args { - let arg = self.pop(); + let arg = self.pop().borrow().clone(); args.push(arg); } args.reverse(); let function_name = chunk.constants[*function_name_index].to_string(); if let Some(fun) = GLOBAL_FUNCTIONS.get(&function_name) { - let return_value = (fun.function)(Value::Void, args)?; - self.push(return_value); + let return_value = (fun.function)(Rc::new(RefCell::new(Value::Void)).borrow_mut(), args)?; + self.push(Rc::new(RefCell::new(return_value))); } else { let function_chunk = self.registry.get(&function_name).or_else(|| { self.registry.get(&format!("{}/{}", context, function_name)) @@ -215,31 +230,31 @@ impl Vm { let mut fields = vec![]; 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 { definition: function_name, fields, })); - self.push(new_instance); + self.push(Rc::new(RefCell::new(new_instance))); } else { return Err(RuntimeError::FunctionNotFound(function_name)); } } else { let result = interpret_function(function_chunk.unwrap(), args)?; - self.push(result); + self.push(Rc::new(RefCell::new(result))); } } } Op::GotoIfNot(goto_addr) => { let b = self.pop(); - if b == Value::Bool(false) { + if *b.borrow() == Value::Bool(false) { self.ip = *goto_addr; } } Op::GotoIf(goto_addr) => { let b = self.pop(); - if b == Value::Bool(true) { + if *b.borrow() == Value::Bool(true) { self.ip = *goto_addr; } } @@ -255,16 +270,12 @@ impl Vm { } } - fn push(&mut self, value: Value) { - if value != Value::Void { - self.stack.push(value); - } + fn push(&mut self, value: Rc>) { + self.stack.push(value); } - fn pop(&mut self) -> Value { - self.stack - .pop() - .unwrap_or_else(|| Value::Error("Stack underflow".to_string())) + fn pop(&mut self) -> Rc> { + self.stack.pop().unwrap_or_else(|| panic!("underflow")) } } @@ -272,9 +283,9 @@ fn binary_op(vm: &mut Vm, op: impl Fn(&Value, &Value) -> Result vm.push(result), + Ok(result) => vm.push(Rc::new(RefCell::new(result))), Err(e) => { vm.error_occurred = true; println!("Error: {} {:?} and {:?}", e, a, b); @@ -284,9 +295,9 @@ fn binary_op(vm: &mut Vm, op: impl Fn(&Value, &Value) -> Result Result + Copy) { let a = stack.pop(); - let result = op(&a); + let result = op(&a.borrow()); match result { - Ok(result) => stack.push(result), + Ok(result) => stack.push(Rc::new(RefCell::new(result))), Err(e) => panic!("Error: {:?} {:?}", e, a), } } @@ -299,17 +310,6 @@ pub(crate) fn get_context(path: &str) -> String { parts.join("/") } -fn number(var_type: &TokenType, value: Value) -> Result { - 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) -> HashMap { strings .into_iter()