fix reassignment bugs
This commit is contained in:
parent
44f063fb6b
commit
0bce2ae9eb
12 changed files with 226 additions and 63 deletions
|
|
@ -68,7 +68,6 @@ impl AstCompiler {
|
|||
&mut self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
) -> Result<Vec<Statement>, CompilerErrorAtLine> {
|
||||
self.current_line();
|
||||
if !self.had_error {
|
||||
let mut statements = vec![];
|
||||
while !self.is_at_end() {
|
||||
|
|
@ -365,10 +364,19 @@ impl AstCompiler {
|
|||
}
|
||||
|
||||
fn bit_xor(&mut self, symbol_table: &mut SymbolTable) -> Expr {
|
||||
let expr = self.equality(symbol_table)?;
|
||||
let expr = self.assignment(symbol_table)?;
|
||||
self.binary(&[TokenType::BitXor], expr, symbol_table)
|
||||
}
|
||||
|
||||
fn assignment(&mut self, symbol_table: &mut SymbolTable) -> Expr {
|
||||
let expr = self.equality(symbol_table)?;
|
||||
self.binary(
|
||||
&[TokenType::Equal],
|
||||
expr,
|
||||
symbol_table,
|
||||
)
|
||||
}
|
||||
|
||||
fn equality(&mut self, symbol_table: &mut SymbolTable) -> Expr {
|
||||
let expr = self.comparison(symbol_table)?;
|
||||
self.binary(
|
||||
|
|
|
|||
65
src/builtins/list.rs
Normal file
65
src/builtins/list.rs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
use crate::ast_compiler::Parameter;
|
||||
use crate::builtins::{FunctionMap, Signature, add, expected};
|
||||
use crate::errors::RuntimeError;
|
||||
use crate::tokens::TokenType;
|
||||
use crate::tokens::TokenType::U64;
|
||||
use crate::value::{Value, u64};
|
||||
use std::collections::HashMap;
|
||||
|
||||
macro_rules! mut_list_fn {
|
||||
(mut $list:ident, mut $args:ident => $body:expr) => {
|
||||
|self_val: Value, mut $args: Vec<Value>| -> Result<Value, RuntimeError> {
|
||||
match self_val {
|
||||
Value::List(mut $list) => $body,
|
||||
_ => Err(expected_a_list()),
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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,
|
||||
mut_list_fn!(mut self_val, mut _args => Ok(u64(self_val.len() as u64))),
|
||||
),
|
||||
);
|
||||
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))
|
||||
}),
|
||||
),
|
||||
);
|
||||
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))
|
||||
}),
|
||||
),
|
||||
);
|
||||
list_functions
|
||||
}
|
||||
|
||||
fn expected_a_list() -> RuntimeError {
|
||||
expected("list")
|
||||
}
|
||||
|
|
@ -1,24 +1,26 @@
|
|||
mod string;
|
||||
mod list;
|
||||
|
||||
use crate::builtins::string::string_methods;
|
||||
use crate::builtins::string::string_functions;
|
||||
use crate::errors::{CompilerError, RuntimeError};
|
||||
use crate::tokens::TokenType;
|
||||
use crate::value::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::LazyLock;
|
||||
use crate::ast_compiler::Parameter;
|
||||
use crate::builtins::list::list_functions;
|
||||
|
||||
pub(crate) struct Signature {
|
||||
pub(crate) parameters: Vec<Parameter>,
|
||||
pub(crate) return_type: TokenType,
|
||||
pub(crate) function: MethodFn,
|
||||
pub(crate) function: FunctionFn,
|
||||
}
|
||||
|
||||
impl Signature {
|
||||
pub(crate) fn new(
|
||||
parameters: Vec<Parameter>,
|
||||
return_type: TokenType,
|
||||
function: MethodFn,
|
||||
function: FunctionFn,
|
||||
) -> Self {
|
||||
Self {
|
||||
parameters,
|
||||
|
|
@ -32,17 +34,19 @@ impl Signature {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) type MethodFn = fn(Value, Vec<Value>) -> Result<Value, RuntimeError>;
|
||||
pub(crate) type MethodMap = HashMap<String, Signature>;
|
||||
pub(crate) type MethodTable = HashMap<String, MethodMap>;
|
||||
pub(crate) type FunctionFn = fn(Value, Vec<Value>) -> Result<Value, RuntimeError>;
|
||||
pub(crate) type FunctionMap = HashMap<String, Signature>;
|
||||
pub(crate) type FunctionTable = HashMap<String, FunctionMap>;
|
||||
|
||||
static METHODS: LazyLock<FunctionTable> = LazyLock::new(|| {
|
||||
let mut table: FunctionTable = HashMap::new();
|
||||
table.insert("string".to_string(), string_functions());
|
||||
table.insert("list".to_string(), list_functions());
|
||||
|
||||
static METHODS: LazyLock<MethodTable> = LazyLock::new(|| {
|
||||
let mut table: MethodTable = HashMap::new();
|
||||
table.insert("string".to_string(), string_methods());
|
||||
table
|
||||
});
|
||||
|
||||
pub(crate) fn add(m: &mut MethodMap, name: &str, method: Signature) {
|
||||
pub(crate) fn add(m: &mut FunctionMap, name: &str, method: Signature) {
|
||||
m.insert(name.to_string(), method);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,35 +1,35 @@
|
|||
use crate::builtins::{MethodMap, Parameter, Signature, add, expected};
|
||||
use crate::builtins::{FunctionMap, Parameter, Signature, add, expected};
|
||||
use crate::errors::RuntimeError;
|
||||
use crate::tokens::TokenType::{StringType, U64};
|
||||
use crate::value::{Value, bool, i64, string};
|
||||
use crate::value::{Value, bool, i64, string, u64};
|
||||
use regex::Regex;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub(crate) fn string_methods() -> MethodMap {
|
||||
let mut string_methods: MethodMap = HashMap::new();
|
||||
let m = &mut string_methods;
|
||||
add(m, "len", Signature::new(vec![], U64, string_len));
|
||||
pub(crate) fn string_functions() -> FunctionMap {
|
||||
let mut string_functions: FunctionMap = HashMap::new();
|
||||
let functions = &mut string_functions;
|
||||
add(functions, "len", Signature::new(vec![], U64, string_len));
|
||||
add(
|
||||
m,
|
||||
functions,
|
||||
"to_uppercase",
|
||||
Signature::new(vec![], StringType, string_to_uppercase),
|
||||
);
|
||||
add(
|
||||
m,
|
||||
functions,
|
||||
"to_lowercase",
|
||||
Signature::new(vec![], StringType, string_to_lowercase),
|
||||
);
|
||||
add(m, "contains", Signature::new(vec![], StringType, string_contains));
|
||||
add(m, "reverse", Signature::new(vec![], StringType, string_reverse));
|
||||
add(m, "trim", Signature::new(vec![], StringType, string_trim));
|
||||
add(functions, "contains", Signature::new(vec![Parameter::new("key", StringType)], StringType, string_contains));
|
||||
add(functions, "reverse", Signature::new(vec![], StringType, string_reverse));
|
||||
add(functions, "trim", Signature::new(vec![], StringType, string_trim));
|
||||
add(
|
||||
m,
|
||||
functions,
|
||||
"trim_start",
|
||||
Signature::new(vec![], StringType, string_trim_start),
|
||||
);
|
||||
add(m, "trim_end", Signature::new(vec![], StringType, string_trim_end));
|
||||
add(functions, "trim_end", Signature::new(vec![], StringType, string_trim_end));
|
||||
add(
|
||||
m,
|
||||
functions,
|
||||
"replace_all",
|
||||
Signature::new(
|
||||
vec![
|
||||
|
|
@ -40,12 +40,12 @@ pub(crate) fn string_methods() -> MethodMap {
|
|||
string_replace_all,
|
||||
),
|
||||
);
|
||||
string_methods
|
||||
string_functions
|
||||
}
|
||||
|
||||
fn string_len(self_val: Value, _args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
match self_val {
|
||||
Value::String(s) => Ok(i64(s.len() as i64)),
|
||||
Value::String(s) => Ok(u64(s.len() as u64)),
|
||||
_ => Err(expected_a_string()),
|
||||
}
|
||||
}
|
||||
|
|
@ -98,7 +98,6 @@ fn string_trim_end(self_val: Value, _: Vec<Value>) -> Result<Value, RuntimeError
|
|||
_ => Err(expected_a_string()),
|
||||
}
|
||||
}
|
||||
//TODO check arity in compiler (generically)
|
||||
fn string_replace_all(receiver: Value, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
let pattern = if let Value::String(s) = &args[0] {
|
||||
Regex::new(s).map_err(|_| RuntimeError::IllegalArgumentException("Invalid regex".into()))?
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use crate::ast_compiler::{Expression, Function, Parameter, Statement};
|
|||
use crate::builtins::lookup;
|
||||
use crate::chunk::Chunk;
|
||||
use crate::errors::CompilerError::{IncompatibleTypes, UndeclaredVariable};
|
||||
use crate::errors::RuntimeError::IllegalArgumentsException;
|
||||
use crate::errors::{CompilerError, CompilerErrorAtLine};
|
||||
use crate::symbol_builder::{Symbol, calculate_type, infer_type};
|
||||
use crate::tokens::TokenType;
|
||||
|
|
@ -12,11 +13,12 @@ use crate::vm::{
|
|||
OP_ADD, OP_AND, OP_ASSIGN, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CALL, OP_CALL_BUILTIN,
|
||||
OP_CONSTANT, OP_DEF_LIST, OP_DEF_MAP, OP_DIVIDE, OP_EQUAL, OP_GET, OP_GREATER,
|
||||
OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_LIST_GET, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_OR,
|
||||
OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT,
|
||||
OP_POP, OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT,
|
||||
};
|
||||
use crate::{Registry, SymbolTable};
|
||||
use clap::arg;
|
||||
use std::collections::HashMap;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
|
||||
pub fn compile(
|
||||
qualified_name: Option<&str>,
|
||||
|
|
@ -216,7 +218,13 @@ impl Compiler {
|
|||
.add_constant(Value::String(method_name.to_string()))
|
||||
});
|
||||
let signature = lookup(&receiver_type, method_name).map_err(|e| self.raise(e))?;
|
||||
|
||||
if signature.parameters.len() != arguments.len() {
|
||||
return Err(self.raise(CompilerError::IllegalArgumentsException(
|
||||
format!("{}.{}", receiver_type, method_name),
|
||||
signature.parameters.len(),
|
||||
arguments.len(),
|
||||
)));
|
||||
}
|
||||
self.get_arguments_in_order(
|
||||
namespace,
|
||||
symbols,
|
||||
|
|
@ -279,22 +287,31 @@ impl Compiler {
|
|||
self.compile_expression(namespace, left, symbols, registry)?;
|
||||
self.compile_expression(namespace, right, symbols, registry)?;
|
||||
match operator.token_type {
|
||||
TokenType::Plus => self.emit_byte(OP_ADD),
|
||||
TokenType::Minus => self.emit_byte(OP_SUBTRACT),
|
||||
TokenType::Star => self.emit_byte(OP_MULTIPLY),
|
||||
TokenType::Slash => self.emit_byte(OP_DIVIDE),
|
||||
TokenType::BitAnd => self.emit_byte(OP_BITAND),
|
||||
TokenType::Pipe => self.emit_byte(OP_BITOR),
|
||||
TokenType::BitXor => self.emit_byte(OP_BITXOR),
|
||||
TokenType::GreaterGreater => self.emit_byte(OP_SHR),
|
||||
TokenType::LessLess => self.emit_byte(OP_SHL),
|
||||
TokenType::Equal => {
|
||||
if let Expression::Variable { name, .. } = left.deref() {
|
||||
let index = self.vars.get(name).unwrap();
|
||||
self.emit_bytes(OP_ASSIGN, *index as u16);
|
||||
self.emit_byte(OP_POP);
|
||||
} else {
|
||||
return Err(self.raise(UndeclaredVariable("".to_string())));
|
||||
}
|
||||
}
|
||||
TokenType::EqualEqual => self.emit_byte(OP_EQUAL),
|
||||
TokenType::Greater => self.emit_byte(OP_GREATER),
|
||||
TokenType::GreaterEqual => self.emit_byte(OP_GREATER_EQUAL),
|
||||
TokenType::GreaterGreater => self.emit_byte(OP_SHR),
|
||||
TokenType::Less => self.emit_byte(OP_LESS),
|
||||
TokenType::LessEqual => self.emit_byte(OP_LESS_EQUAL),
|
||||
TokenType::LessLess => self.emit_byte(OP_SHL),
|
||||
TokenType::LogicalAnd => self.emit_byte(OP_AND),
|
||||
TokenType::LogicalOr => self.emit_byte(OP_OR),
|
||||
TokenType::Minus => self.emit_byte(OP_SUBTRACT),
|
||||
TokenType::Pipe => self.emit_byte(OP_BITOR),
|
||||
TokenType::Plus => self.emit_byte(OP_ADD),
|
||||
TokenType::Slash => self.emit_byte(OP_DIVIDE),
|
||||
TokenType::Star => self.emit_byte(OP_MULTIPLY),
|
||||
_ => unimplemented!("binary other than plus, minus, star, slash"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::errors::CompilerError::IllegalArgumentsException;
|
||||
use crate::errors::CompilerErrorAtLine;
|
||||
use crate::errors::CrudLangError::{Compiler, Runtime};
|
||||
use crate::value::{Value, string};
|
||||
use crate::{compile, run};
|
||||
use chrono::DateTime;
|
||||
use crate::errors::RuntimeError::{IllegalArgumentException, IndexOutOfBounds};
|
||||
|
||||
#[test]
|
||||
fn literal_int() {
|
||||
|
|
@ -165,14 +169,8 @@ p"#);
|
|||
assert!(result.is_ok());
|
||||
let result = result.unwrap();
|
||||
if let Value::Map(map) = result {
|
||||
assert_eq!(
|
||||
map.get(&string("name")).unwrap(),
|
||||
&string("Dent")
|
||||
);
|
||||
assert_eq!(
|
||||
map.get(&string("age")).unwrap(),
|
||||
&Value::I64(40)
|
||||
);
|
||||
assert_eq!(map.get(&string("name")).unwrap(), &string("Dent"));
|
||||
assert_eq!(map.get(&string("age")).unwrap(), &Value::I64(40));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -183,10 +181,7 @@ m"#);
|
|||
|
||||
let result = result.unwrap();
|
||||
if let Value::Map(map) = result {
|
||||
assert_eq!(
|
||||
map.get(&string("name")).unwrap(),
|
||||
&string("Dent")
|
||||
);
|
||||
assert_eq!(map.get(&string("name")).unwrap(), &string("Dent"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -267,7 +262,7 @@ date"#),
|
|||
|
||||
#[test]
|
||||
fn string_len() {
|
||||
assert_eq!(run(r#""abc".len()"#), Ok(Value::I64(3)));
|
||||
assert_eq!(run(r#""abc".len()"#), Ok(Value::U64(3)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -275,6 +270,56 @@ date"#),
|
|||
assert_eq!(run(r#""Hello".replace_all("l","p")"#), Ok(string("Heppo")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_replace_wrong_nr_of_args() {
|
||||
assert_eq!(
|
||||
run(r#""Hello".replace_all("l")"#),
|
||||
Err(Compiler(CompilerErrorAtLine {
|
||||
error: IllegalArgumentsException("string.replace_all".to_string(), 2, 1),
|
||||
line: 1
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_replace_wrong_type_of_args() {
|
||||
assert_eq!(
|
||||
run(r#""Hello".replace_all("l", 1)"#),
|
||||
Err(Runtime(IllegalArgumentException("Illegal replacement. Expected a string but got 1".to_string())))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_contains() {
|
||||
assert_eq!(run(r#""Hello".contains("l")"#), Ok(Value::Bool(true)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_length(){
|
||||
assert_eq!(run(r#"[1,2,3].len()"#), Ok(Value::U64(3)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_push(){
|
||||
assert_eq!(run(r#"[1,2].push(3)"#), Ok(Value::List(vec![Value::I64(1), Value::I64(2), Value::I64(3)])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_remove(){
|
||||
assert_eq!(run(r#"[1,2,3].remove(0)"#), Ok(Value::List(vec![Value::I64(2), Value::I64(3)])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_remove_out_of_bounds(){
|
||||
assert_eq!(run(r#"[1,2,3].remove(4)"#), Err(Runtime(IndexOutOfBounds(4, 3))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reassign(){
|
||||
assert_eq!(run(r#"let a=1
|
||||
a=2"#), Ok(Value::Void));
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn package() {
|
||||
// assert_eq!(run(r#"a.b.c()"#), Ok(Value::U32(48)));
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ pub enum CompilerError {
|
|||
IllegalIndexArgument(TokenType),
|
||||
#[error("Illegal argument: '{0}' cannot be indexed")]
|
||||
IllegalTypeToIndex(String),
|
||||
#[error("The number of of arguments for {0} is not correct. Should be {1}, got {2}")]
|
||||
IllegalArgumentsException(String,usize,usize),
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, PartialEq)]
|
||||
|
|
@ -87,6 +89,8 @@ pub enum RuntimeError {
|
|||
IllegalArgumentException(String),
|
||||
#[error("Expected {0}")]
|
||||
ExpectedType(String),
|
||||
#[error("Index out of bounds: {0} > {1}")]
|
||||
IndexOutOfBounds(usize, usize),
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, PartialEq)]
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ async fn main() -> Result<(), CrudLangError> {
|
|||
);
|
||||
|
||||
if args.repl {
|
||||
std::thread::spawn(move || tipi_lang::repl::start(swap.clone()).unwrap());
|
||||
let _ = std::thread::spawn(move || tipi_lang::repl::start(swap.clone()));
|
||||
}
|
||||
|
||||
axum::serve(listener, app).await.map_err(map_underlying())?;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,13 @@ pub fn start(registry: Arc<ArcSwap<HashMap<String, Chunk>>>) -> Result<(), CrudL
|
|||
|
||||
let tokens = scan(input)?;
|
||||
|
||||
let ast = ast_compiler::compile(None, tokens, &mut symbol_table)?;
|
||||
let ast = match ast_compiler::compile(None, tokens, &mut symbol_table){
|
||||
Ok(ast) => ast,
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
symbol_builder::build("", &ast, &mut symbol_table);
|
||||
|
||||
match bytecode_compiler.compile(&ast, &symbol_table, &mut registry_copy, "") {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ impl Token {
|
|||
|
||||
#[derive(Debug, PartialEq, Clone, Hash)]
|
||||
pub enum TokenType {
|
||||
Any,
|
||||
Bang,
|
||||
BangEqual,
|
||||
BitAnd,
|
||||
|
|
@ -93,6 +94,7 @@ pub enum TokenType {
|
|||
impl fmt::Display for TokenType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
TokenType::Any => write!(f, "any"),
|
||||
TokenType::StringType => write!(f, "string"),
|
||||
TokenType::DateTime => write!(f, "datetime"),
|
||||
TokenType::Char => write!(f, "char"),
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ pub(crate) fn i64(v: impl Into<i64>) -> Value {
|
|||
Value::I64(v.into())
|
||||
}
|
||||
|
||||
pub(crate) fn u64(v: impl Into<u64>) -> Value {
|
||||
Value::U64(v.into())
|
||||
}
|
||||
|
||||
pub(crate) fn bool(v: impl Into<bool>) -> Value {
|
||||
Value::Bool(v.into())
|
||||
}
|
||||
|
|
@ -419,6 +423,7 @@ impl PartialEq for Value {
|
|||
equal
|
||||
}
|
||||
// TODO objects
|
||||
(Value::Void, Value::Void) => true,
|
||||
_ => false, //?
|
||||
}
|
||||
}
|
||||
|
|
|
|||
26
src/vm.rs
26
src/vm.rs
|
|
@ -156,13 +156,7 @@ impl Vm {
|
|||
let index = self.read(chunk);
|
||||
let (var_type, name) = chunk.vars.get(index).unwrap();
|
||||
let value = self.pop();
|
||||
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,
|
||||
};
|
||||
let value = Self::number(var_type, value)?;
|
||||
self.local_vars.insert(name.to_string(), value);
|
||||
}
|
||||
OP_DEF_MAP => {
|
||||
|
|
@ -178,8 +172,8 @@ impl Vm {
|
|||
OP_GET => {
|
||||
let var_index = self.read(chunk);
|
||||
let (_, name_index) = chunk.vars.get(var_index).unwrap();
|
||||
let value = self.local_vars.get(name_index).unwrap();
|
||||
self.push(value.clone()); // not happy , take ownership, no clone
|
||||
let value = self.local_vars.remove(name_index).unwrap();
|
||||
self.push(value);
|
||||
}
|
||||
OP_LIST_GET => {
|
||||
let index = self.pop();
|
||||
|
|
@ -205,6 +199,9 @@ impl Vm {
|
|||
let return_value = crate::builtins::call(&receiver_type_name, &function_name, receiver, args)?;
|
||||
self.push(return_value);
|
||||
}
|
||||
OP_POP =>{
|
||||
self.pop(); // discards the value
|
||||
}
|
||||
OP_CALL => {
|
||||
let function_name_index = self.read(chunk);
|
||||
let num_args = self.read(chunk);
|
||||
|
|
@ -259,6 +256,17 @@ impl Vm {
|
|||
}
|
||||
}
|
||||
|
||||
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 read(&mut self, chunk: &Chunk) -> usize {
|
||||
self.ip += 1;
|
||||
chunk.code[self.ip - 1] as usize
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue