all found issues fixed. got rid of some stupid mistakes

This commit is contained in:
Shautvast 2025-11-02 10:17:19 +01:00
parent c63cf3777f
commit 8234e9d50a
7 changed files with 156 additions and 135 deletions

View file

@ -228,6 +228,9 @@ impl AstCompiler {
} }
fn let_declaration(&mut self) -> Result<Statement, CompilerError> { fn let_declaration(&mut self) -> Result<Statement, CompilerError> {
if self.peek().token_type.is_type(){
return Err(CompilerError::KeywordNotAllowedAsIdentifier(self.peek().token_type))
}
let name_token = self.consume(Identifier, Expected("variable name."))?; let name_token = self.consume(Identifier, Expected("variable name."))?;
let declared_type = if self.check(Colon) { let declared_type = if self.check(Colon) {

View file

@ -1,16 +1,22 @@
use crate::ast_compiler::{Expression, Function, Statement}; use crate::ast_compiler::{Expression, Function, Statement};
use crate::chunk::Chunk; use crate::chunk::Chunk;
use crate::errors::CompilerError;
use crate::tokens::TokenType; use crate::tokens::TokenType;
use crate::value::Value; use crate::value::Value;
use crate::vm::{OP_ADD, OP_AND, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CALL, OP_CONSTANT, OP_DEF_BOOL, OP_DEF_CHAR, OP_DEF_DATE, OP_DEF_F32, OP_DEF_F64, OP_DEF_I32, OP_DEF_I64, OP_DEF_LIST, OP_DEF_MAP, OP_DEF_STRING, OP_DEF_STRUCT, OP_DEFINE, OP_DIVIDE, OP_EQUAL, OP_GET, OP_GREATER, OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_OR, OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT, OP_DEF_U32}; use crate::vm::{
OP_ADD, OP_AND, OP_ASSIGN, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CALL, OP_CONSTANT, OP_DEF_BOOL,
OP_DEF_CHAR, OP_DEF_DATE, OP_DEF_F32, OP_DEF_F64, OP_DEF_I32, OP_DEF_I64, OP_DEF_LIST,
OP_DEF_MAP, OP_DEF_STRING, OP_DEF_STRUCT, OP_DEF_U32, OP_DEFINE, OP_DIVIDE, OP_EQUAL, OP_GET,
OP_GREATER, OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_OR,
OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT,
};
use std::collections::HashMap; use std::collections::HashMap;
use crate::errors::CompilerError;
pub fn compile( pub fn compile(
namespace: Option<&str>, namespace: Option<&str>,
ast: &Vec<Statement>, ast: &Vec<Statement>,
registry: &mut HashMap<String, Chunk>, registry: &mut HashMap<String, Chunk>,
) -> Result<(),CompilerError> { ) -> Result<(), CompilerError> {
compile_name(ast, namespace, registry) compile_name(ast, namespace, registry)
} }
@ -22,9 +28,10 @@ pub(crate) fn compile_function(
let mut compiler = Compiler::new(&function.name.lexeme); let mut compiler = Compiler::new(&function.name.lexeme);
for parm in &function.parameters { for parm in &function.parameters {
let name = parm.name.lexeme.clone(); let name = parm.name.lexeme.clone();
let name_index = compiler.chunk.add_constant(Value::String(name.clone())); let var_index = compiler.chunk.add_var(&parm.var_type, &parm.name.lexeme);
compiler.vars.insert(name, name_index);
compiler.emit_bytes(OP_DEFINE, name_index as u16); compiler.vars.insert(name, var_index);
// compiler.emit_bytes(OP_DEFINE, name_index as u16);
} }
Ok(compiler.compile(&function.body, registry, namespace)?) Ok(compiler.compile(&function.body, registry, namespace)?)
@ -34,11 +41,11 @@ pub(crate) fn compile_name(
ast: &Vec<Statement>, ast: &Vec<Statement>,
namespace: Option<&str>, namespace: Option<&str>,
registry: &mut HashMap<String, Chunk>, registry: &mut HashMap<String, Chunk>,
) -> Result<(),CompilerError> { ) -> Result<(), CompilerError> {
let name=namespace.unwrap_or("main"); let name = namespace.unwrap_or("main");
let compiler = Compiler::new(name); let compiler = Compiler::new(name);
let chunk = compiler.compile(ast, registry, name)?; let chunk = compiler.compile(ast, registry, name)?;
let qname = if let Some(namespace) = namespace{ let qname = if let Some(namespace) = namespace {
format!("{}.{}", namespace, "main") format!("{}.{}", namespace, "main")
} else { } else {
"main".to_string() "main".to_string()
@ -70,17 +77,6 @@ impl Compiler {
registry: &mut HashMap<String, Chunk>, registry: &mut HashMap<String, Chunk>,
namespace: &str, namespace: &str,
) -> Result<Chunk, CompilerError> { ) -> Result<Chunk, CompilerError> {
//TODO can likely be removed
for statement in ast {
if let Statement::FunctionStmt { function } = statement {
self.emit_constant(Value::String(format!(
"{}.{}",
namespace,
function.name.lexeme.clone()
)));
}
}
for statement in ast { for statement in ast {
self.compile_statement(statement, registry, namespace)?; self.compile_statement(statement, registry, namespace)?;
} }
@ -102,10 +98,10 @@ impl Compiler {
var_type, var_type,
initializer, initializer,
} => { } => {
let name_index = self.chunk.add_constant(Value::String(name.lexeme.clone())); let name_index = self.chunk.add_var(var_type, &name.lexeme);
self.vars.insert(name.lexeme.clone(), name_index); self.vars.insert(name.lexeme.clone(), name_index);
self.compile_expression(namespace, initializer, registry)?; self.compile_expression(namespace, initializer, registry)?;
self.define_variable(var_type, name_index, &initializer)?; self.emit_bytes(OP_ASSIGN, name_index as u16);
} }
Statement::PrintStmt { value } => { Statement::PrintStmt { value } => {
self.compile_expression(namespace, value, registry)?; self.compile_expression(namespace, value, registry)?;
@ -116,7 +112,7 @@ impl Compiler {
} }
Statement::FunctionStmt { function } => { Statement::FunctionStmt { function } => {
let function_name = function.name.lexeme.clone(); let function_name = function.name.lexeme.clone();
self.emit_constant(Value::String(function_name.clone())); // self.emit_constant(Value::String(function_name.clone()));
let compiled_function = compile_function(function, registry, namespace)?; let compiled_function = compile_function(function, registry, namespace)?;
registry.insert( registry.insert(
format!("{}.{}", self.chunk.name, function_name), format!("{}.{}", self.chunk.name, function_name),
@ -140,7 +136,7 @@ impl Compiler {
Expression::FunctionCall { Expression::FunctionCall {
name, arguments, .. name, arguments, ..
} => { } => {
let qname=format!("{}.{}", namespace, name); let qname = format!("{}.{}", namespace, name);
let name_index = self let name_index = self
.chunk .chunk
.find_constant(&qname) .find_constant(&qname)
@ -163,12 +159,14 @@ impl Compiler {
for expr in values { for expr in values {
self.compile_expression(namespace, expr, registry)?; self.compile_expression(namespace, expr, registry)?;
} }
self.emit_bytes(OP_DEF_LIST, values.len() as u16);
} }
Expression::Map { entries, .. } => { Expression::Map { entries, .. } => {
for (key, value) in entries { for (key, value) in entries {
self.compile_expression(namespace, key, registry)?; self.compile_expression(namespace, key, registry)?;
self.compile_expression(namespace, value, registry)?; self.compile_expression(namespace, value, registry)?;
} }
self.emit_bytes(OP_DEF_MAP, entries.len() as u16);
} }
Expression::Grouping { expression, .. } => { Expression::Grouping { expression, .. } => {
self.compile_expression(namespace, expression, registry)? self.compile_expression(namespace, expression, registry)?
@ -219,42 +217,6 @@ impl Compiler {
Ok(()) Ok(())
} }
fn define_variable(
&mut self,
var_type: &TokenType,
name_index: usize,
initializer: &Expression,
) -> Result<(), CompilerError> {
let def_op = match var_type {
TokenType::I32 => OP_DEF_I32,
TokenType::I64 => OP_DEF_I64,
TokenType::U32 => OP_DEF_U32,
TokenType::U64 => OP_DEF_I64,
TokenType::F32 => OP_DEF_F32,
TokenType::F64 => OP_DEF_F64,
TokenType::Date => OP_DEF_DATE,
TokenType::StringType => OP_DEF_STRING,
TokenType::Char => OP_DEF_CHAR,
TokenType::Bool => OP_DEF_BOOL,
TokenType::ListType => OP_DEF_LIST,
TokenType::MapType => OP_DEF_MAP,
TokenType::Object => OP_DEF_STRUCT,
_ => unimplemented!("{}", var_type),
};
self.emit_bytes(def_op, name_index as u16);
match initializer {
Expression::List { values, .. } => {
self.emit_byte(values.len() as u16);
}
Expression::Map { entries, .. } => {
self.emit_byte(entries.len() as u16);
}
_ => {}
}
Ok(())
}
fn emit_byte(&mut self, byte: u16) { fn emit_byte(&mut self, byte: u16) {
self.chunk.add(byte, self.current_line); self.chunk.add(byte, self.current_line);
} }

View file

@ -1,5 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::ast_compiler::Parameter; use crate::ast_compiler::Parameter;
use crate::tokens::TokenType;
use crate::value::Value; use crate::value::Value;
use crate::vm::{ use crate::vm::{
OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CALL, OP_CONSTANT, OP_DEF_BOOL, OP_DEF_F32, OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CALL, OP_CONSTANT, OP_DEF_BOOL, OP_DEF_F32,
@ -14,7 +15,8 @@ pub struct Chunk {
pub code: Vec<u16>, pub code: Vec<u16>,
pub constants: Vec<Value>, pub constants: Vec<Value>,
lines: Vec<usize>, lines: Vec<usize>,
object_defs: HashMap<String, Vec<Parameter>> object_defs: HashMap<String, Vec<Parameter>>,
pub vars: Vec<(TokenType, String)>
} }
impl Chunk { impl Chunk {
@ -38,6 +40,7 @@ impl Chunk {
constants: vec![], constants: vec![],
lines: vec![], lines: vec![],
object_defs: HashMap::new(), object_defs: HashMap::new(),
vars: vec![]
} }
} }
@ -51,6 +54,11 @@ impl Chunk {
self.constants.len() - 1 self.constants.len() - 1
} }
pub(crate) fn add_var(&mut self, var_type: &TokenType, name: &str) -> usize {
self.vars.push((var_type.clone(), name.to_string()));
self.vars.len() - 1
}
pub (crate) fn add_object_def(&mut self, name: &str, fields: &[Parameter]){ pub (crate) fn add_object_def(&mut self, name: &str, fields: &[Parameter]){
self.object_defs.insert(name.to_string(), fields.to_vec()); self.object_defs.insert(name.to_string(), fields.to_vec());
} }

View file

@ -29,19 +29,19 @@ mod tests {
} }
#[test] #[test]
fn let_infer_type() { fn infer_type() {
assert_eq!(run(r#"let a=1 assert_eq!(run(r#"let a=1
a"#), Ok(Value::I64(1))); a"#), Ok(Value::I64(1)));
} }
#[test] #[test]
fn let_u32() { fn define_u32() {
assert_eq!(run(r#"let a:u32=1 assert_eq!(run(r#"let a:u32=1
a"#), Ok(Value::U32(1))); a"#), Ok(Value::U32(1)));
} }
#[test] #[test]
fn let_char() { fn define_char() {
assert_eq!( assert_eq!(
run(r#"let a:char='a' run(r#"let a:char='a'
a"#), a"#),
@ -50,7 +50,7 @@ a"#),
} }
#[test] #[test]
fn let_u32_invalid_value_negative() { fn define_u32_invalid_value_negative() {
let r = compile("let a:u32=-1"); let r = compile("let a:u32=-1");
assert!(r.is_err()); assert!(r.is_err());
if let Err(e) = &r { if let Err(e) = &r {
@ -62,7 +62,7 @@ a"#),
} }
#[test] #[test]
fn let_u64_invalid_value_negative() { fn define_u64_invalid_value_negative() {
let r = compile("let a:u64=-1"); let r = compile("let a:u64=-1");
assert!(r.is_err()); assert!(r.is_err());
if let Err(e) = &r { if let Err(e) = &r {
@ -97,7 +97,7 @@ add_hello("world")"#,),
} }
#[test] #[test]
fn object_definition() { fn define_object() {
let r = compile( let r = compile(
r#" r#"
object Person: object Person:
@ -120,7 +120,7 @@ object Person:
// } // }
#[test] #[test]
fn let_map() { fn literal_map() {
let result = run(r#"{"name": "Dent", "age": 40 }"#); let result = run(r#"{"name": "Dent", "age": 40 }"#);
assert!(result.is_ok()); assert!(result.is_ok());
let result = result.unwrap(); let result = result.unwrap();
@ -131,8 +131,29 @@ object Person:
); );
assert_eq!( assert_eq!(
map.get(&Value::String("age".to_string())).unwrap(), map.get(&Value::String("age".to_string())).unwrap(),
&Value::I32(40) &Value::I64(40)
); );
} }
} }
#[test]
fn define_map() {
let result = run(r#"let m = {"name": "Dent"}
m"#);
let result = result.unwrap();
if let Value::Map(map) = result {
assert_eq!(
map.get(&Value::String("name".to_string())).unwrap(),
&Value::String("Dent".to_string())
);
}
}
#[test]
fn keyword_error(){
let result = run(r#"let map = {"name": "Dent"}"#);
assert!(result.is_err());
assert_eq!("'map' is a keyword. You cannot use it as an identifier",result.unwrap_err().to_string());
}
} }

View file

@ -1,5 +1,5 @@
use thiserror::Error;
use crate::tokens::{Token, TokenType}; use crate::tokens::{Token, TokenType};
use thiserror::Error;
#[derive(Error, Debug, PartialEq)] #[derive(Error, Debug, PartialEq)]
pub enum Error { pub enum Error {
@ -11,7 +11,6 @@ pub enum Error {
Platform(String), Platform(String),
} }
#[derive(Error, Debug, PartialEq)] #[derive(Error, Debug, PartialEq)]
pub enum CompilerError { pub enum CompilerError {
#[error("Compilation failed")] #[error("Compilation failed")]
@ -21,7 +20,7 @@ pub enum CompilerError {
#[error("Expected {0}")] #[error("Expected {0}")]
Expected(&'static str), Expected(&'static str),
#[error("unexpected indent level {0} vs expected {1}")] #[error("unexpected indent level {0} vs expected {1}")]
UnexpectedIndent(usize,usize), UnexpectedIndent(usize, usize),
#[error("Type mismatch at line {0}: {1}")] #[error("Type mismatch at line {0}: {1}")]
TypeError(usize, Box<CompilerError>), TypeError(usize, Box<CompilerError>),
#[error("Uninitialized variables are not allowed.")] #[error("Uninitialized variables are not allowed.")]
@ -39,7 +38,9 @@ pub enum CompilerError {
#[error("Illegal char length for {0} at line {1}")] #[error("Illegal char length for {0} at line {1}")]
IllegalCharLength(String, usize), IllegalCharLength(String, usize),
#[error("Unexpected type {0}")] #[error("Unexpected type {0}")]
UnexpectedType(TokenType) UnexpectedType(TokenType),
#[error("'{0}' is a keyword. You cannot use it as an identifier")]
KeywordNotAllowedAsIdentifier(TokenType),
} }
#[derive(Error, Debug, PartialEq)] #[derive(Error, Debug, PartialEq)]
@ -58,4 +59,6 @@ pub enum ValueError {
CannotAnd(&'static str), CannotAnd(&'static str),
#[error("{0}")] #[error("{0}")]
Some(&'static str), Some(&'static str),
} #[error("Illegal cast")]
IllegalCast,
}

View file

@ -1,10 +1,10 @@
use crate::errors::ValueError;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Shl, Shr, Sub}; use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Shl, Shr, Sub};
use crate::errors::ValueError;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Object { pub struct Object {
@ -32,6 +32,56 @@ pub enum Value {
Void, Void,
} }
impl Value {
pub fn cast_u32(self) -> Result<Self, ValueError> {
match self {
Value::U32(v) => Ok(Value::U32(v)),
Value::U64(v) => Ok(Value::U32(v as u32)),
Value::I32(v) => Ok(Value::U32(v as u32)),
Value::I64(v) => Ok(Value::U32(v as u32)),
Value::F32(v) => Ok(Value::U32(v as u32)),
Value::F64(v) => Ok(Value::U32(v as u32)),
_ => Err(ValueError::IllegalCast),
}
}
pub fn cast_u64(self) -> Result<Self, ValueError> {
match self {
Value::U32(v) => Ok(Value::U64(v as u64)),
Value::U64(v) => Ok(Value::U64(v)),
Value::I32(v) => Ok(Value::U64(v as u64)),
Value::I64(v) => Ok(Value::U64(v as u64)),
Value::F32(v) => Ok(Value::U64(v as u64)),
Value::F64(v) => Ok(Value::U64(v as u64)),
_ => Err(ValueError::IllegalCast),
}
}
pub fn cast_i32(self) -> Result<Self, ValueError> {
match self {
Value::U32(v) => Ok(Value::I32(v as i32)),
Value::U64(v) => Ok(Value::I32(v as i32)),
Value::I32(v) => Ok(Value::I32(v)),
Value::I64(v) => Ok(Value::I32(v as i32)),
Value::F32(v) => Ok(Value::I32(v as i32)),
Value::F64(v) => Ok(Value::I32(v as i32)),
_ => Err(ValueError::IllegalCast),
}
}
pub fn cast_f32(self) -> Result<Self, ValueError> {
match self {
Value::U32(v) => Ok(Value::F32(v as f32)),
Value::U64(v) => Ok(Value::F32(v as f32)),
Value::I32(v) => Ok(Value::F32(v as f32)),
Value::I64(v) => Ok(Value::F32(v as f32)),
Value::F32(v) => Ok(Value::F32(v)),
Value::F64(v) => Ok(Value::F32(v as f32)),
_ => Err(ValueError::IllegalCast),
}
}
}
impl Into<Value> for i32 { impl Into<Value> for i32 {
fn into(self) -> Value { fn into(self) -> Value {
Value::I32(self) Value::I32(self)

View file

@ -4,6 +4,7 @@ use crate::errors::{RuntimeError, ValueError};
use crate::value::Value; use crate::value::Value;
use std::collections::HashMap; use std::collections::HashMap;
use tracing::debug; use tracing::debug;
use crate::tokens::TokenType;
macro_rules! define_var { macro_rules! define_var {
($self:ident, $variant:ident, $chunk:ident) => {{ ($self:ident, $variant:ident, $chunk:ident) => {{
@ -40,7 +41,7 @@ pub fn interpret(registry: &HashMap<String, Chunk>, function: &str) -> Result<Va
error_occurred: false, error_occurred: false,
registry, registry,
}; };
vm.run(&chunk, vec![]) vm.run(&chunk)
} }
pub async fn interpret_async(registry: &HashMap<String, Chunk>, function: &str) -> Result<Value, RuntimeError> { pub async fn interpret_async(registry: &HashMap<String, Chunk>, function: &str) -> Result<Value, RuntimeError> {
@ -52,7 +53,7 @@ pub async fn interpret_async(registry: &HashMap<String, Chunk>, function: &str)
error_occurred: false, error_occurred: false,
registry, registry,
}; };
vm.run(&chunk, vec![]) vm.run(&chunk)
} }
pub fn interpret_function(chunk: &Chunk, args: Vec<Value>) -> Result<Value, RuntimeError> { pub fn interpret_function(chunk: &Chunk, args: Vec<Value>) -> Result<Value, RuntimeError> {
@ -63,14 +64,20 @@ pub fn interpret_function(chunk: &Chunk, args: Vec<Value>) -> Result<Value, Runt
error_occurred: false, error_occurred: false,
registry: &HashMap::new(), registry: &HashMap::new(),
}; };
vm.run(chunk, args)
vm.run_function(chunk, args)
} }
impl<'a> Vm<'a> { impl<'a> Vm<'a> {
fn run(&mut self, chunk: &Chunk, args: Vec<Value>) -> Result<Value, RuntimeError> { fn run_function(&mut self, chunk: &Chunk, mut args: Vec<Value>) -> Result<Value, RuntimeError> {
for arg in args { // arguments -> locals
self.push(arg); for (_,name) in chunk.vars.iter() {
self.local_vars.insert(name.clone(), args.remove(0));
} }
self.run(&chunk)
}
fn run(&mut self, chunk: &Chunk) -> Result<Value, RuntimeError> {
loop { loop {
if self.error_occurred { if self.error_occurred {
return Err(Something); return Err(Something);
@ -131,64 +138,30 @@ impl<'a> Vm<'a> {
let value = self.pop(); let value = self.pop();
self.local_vars.insert(name, value); self.local_vars.insert(name, value);
} }
OP_DEF_I32 => {
let name = self.read_name(chunk);
let value = self.pop();
let value = match value{
Value::I32(v) => Value::I32(v),
Value::I64(v) => Value::I32(v as i32),
_ => unreachable!(),
};
self.local_vars.insert(name, value);
}
OP_DEF_I64 => define_var!(self, I64, chunk),
OP_DEF_U32 => {
let name = self.read_name(chunk);
let value = self.pop();
let value = match value{
Value::U32(v) => Value::U32(v),
Value::I64(v) => Value::U32(v as u32),
_ => unreachable!(),
};
self.local_vars.insert(name, value);
}
OP_DEF_U64 => {
let name = self.read_name(chunk);
let value = self.pop();
let value = match value{
Value::U64(v) => Value::U64(v),
Value::I64(v) => Value::U64(v as u64),
_ => unreachable!(),
};
self.local_vars.insert(name, value);
}
OP_DEF_F32 => {
let name = self.read_name(chunk);
let value = self.pop();
let value = match value{
Value::F32(v) => Value::F32(v),
Value::F64(v) => Value::F32(v as f32),
_ => unreachable!(),
};
self.local_vars.insert(name, value);
}
OP_DEF_F64 => define_var!(self, F64, chunk),
OP_DEF_STRING => define_var!(self, String, chunk),
OP_DEF_CHAR => define_var!(self, Char, chunk),
OP_DEF_BOOL => define_var!(self, Bool, chunk),
OP_DEF_DATE => define_var!(self, Date, chunk),
OP_DEF_LIST => { OP_DEF_LIST => {
let name = self.read_name(chunk);
let len = self.read(chunk); let len = self.read(chunk);
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);
} }
self.local_vars.insert(name, Value::List(list)); list.reverse();
self.push(Value::List(list));
}
OP_ASSIGN=>{
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,
};
self.local_vars.insert(name.to_string(), value);
} }
OP_DEF_MAP => { OP_DEF_MAP => {
let name = self.read_name(chunk);
let len = self.read(chunk); let len = self.read(chunk);
let mut map = HashMap::new(); let mut map = HashMap::new();
for _ in 0..len { for _ in 0..len {
@ -196,12 +169,13 @@ impl<'a> Vm<'a> {
let key = self.pop(); let key = self.pop();
map.insert(key, value); map.insert(key, value);
} }
self.local_vars.insert(name, Value::Map(map)); self.push(Value::Map(map));
} }
OP_GET => { OP_GET => {
let name = self.read_name(chunk); let var_index = self.read(chunk);
let value = self.local_vars.get(&name).unwrap(); let (_,name_index)= chunk.vars.get(var_index).unwrap();
self.push(value.clone()); // not happy let value = self.local_vars.get(name_index).unwrap();
self.push(value.clone()); // not happy , take ownership, no clone
debug!("after get {:?}", self.stack); debug!("after get {:?}", self.stack);
} }
OP_CALL => { OP_CALL => {
@ -309,4 +283,4 @@ pub const OP_DEF_MAP: u16 = 37;
pub const OP_DEF_STRUCT: u16 = 38; pub const OP_DEF_STRUCT: u16 = 38;
pub const OP_DEF_F32: u16 = 39; pub const OP_DEF_F32: u16 = 39;
pub const OP_DEF_F64: u16 = 40; pub const OP_DEF_F64: u16 = 40;
// pub const OP_NEW_LIST: u16 = 40; pub const OP_ASSIGN: u16 = 41;