From c407349bf0c3102b6f292742db23f3e5be1aa696 Mon Sep 17 00:00:00 2001 From: ghostly_zsh Date: Wed, 2 Oct 2024 21:35:03 -0500 Subject: [PATCH] move variables to a separate list, assign to array subscript works --- kabel/opcodes.txt | 57 ++++++++--------- kabel/src/codegen.rs | 15 ++++- kabel/src/debug.rs | 9 +++ kabel/src/extension.rs | 2 +- kabel/src/opcodes.rs | 135 +++++++++++++++++++++-------------------- kabel/src/vm.rs | 96 +++++++++++++++++------------ kabel/tmp.kab | 3 - 7 files changed, 179 insertions(+), 138 deletions(-) diff --git a/kabel/opcodes.txt b/kabel/opcodes.txt index 2fe9fb52c4bab60c84ce1822750cd3bb1915bd46..4e403d3590b9f73ad2808f9987d0df2ecfa9cb22 100644 --- a/kabel/opcodes.txt +++ b/kabel/opcodes.txt @@ -1,37 +1,38 @@ LOAD VAL ; 0x00 VAR STACKPTR ; 0x01 -ASN PTR ; 0x02 -ASNARR ; 0x03 -DECL ; 0x04 +REF PTR ; 0x02 +ASN PTR ; 0x03 +ASNARR ; 0x04 +DECL ; 0x05 -ADD ; 0x05 -SUB ; 0x06 -MUL ; 0x07 -DIV ; 0x08 -MOD ; 0x09 -BITAND ; 0x0a -BITXOR ; 0x0b -BITOR ; 0x0c -EQ ; 0x0D -NE ; 0x0E -GR ; 0x0F -GE ; 0x10 -LS ; 0x11 -LE ; 0x12 -OR ; 0x13 -AND ; 0x14 -NOT ; 0x15 -NEG ; 0x16 +ADD ; 0x06 +SUB ; 0x07 +MUL ; 0x08 +DIV ; 0x09 +MOD ; 0x0A +BITAND ; 0x0b +BITXOR ; 0x0c +BITOR ; 0x0d +EQ ; 0x0E +NE ; 0x0F +GR ; 0x10 +GE ; 0x11 +LS ; 0x12 +LE ; 0x13 +OR ; 0x14 +AND ; 0x15 +NOT ; 0x16 +NEG ; 0x17 -JMP LOC ; 0x17 -JMP_UP LOC ; 0x18 -JNE ELSE ; 0x19 +JMP LOC ; 0x18 +JMP_UP LOC ; 0x19 +JNE ELSE ; 0x1A -CALL ARITY ; 0x1A -RET ; 0x1B +CALL ARITY ; 0x1B +RET ; 0x1C -LIST LEN ; 0x1C -SCR ; 0x1D +LIST LEN ; 0x1D +SCR ; 0x1E POP COUNT ; 0xFD PRINT ; 0xFE diff --git a/kabel/src/codegen.rs b/kabel/src/codegen.rs index 464b1fd2053d78ab5accd79a477875b11aa2bd33..18c9ae393b435425c713d6a4b83cae4db85b19de 100644 --- a/kabel/src/codegen.rs +++ b/kabel/src/codegen.rs @@ -456,7 +456,20 @@ impl Codegen { } LhsAssignType::Subscript(name, index) => { self.visit(*index); - self.visit(*name); + + #[allow(irrefutable_let_patterns)] + if let Extension::Resolution(_scope, ptr) = name.extensions[0] { + self.vm.units[self.vm.unit_ptr].code.push(OpCode::REF.into()); + self.vm.units[self.vm.unit_ptr].code.push(ptr as u8); + if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line { + self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2)); + } else { + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2; + } + } else { + panic!("Subscript assignment should always have a Resolution"); + } + self.vm.units[self.vm.unit_ptr].code.push(OpCode::ASNARR.into()); if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line { diff --git a/kabel/src/debug.rs b/kabel/src/debug.rs index 4ac58000abfb4047541d8a50a5947ad00966d31c..246588e83aec78ffbc9a30d14f604b0e8d5f25c5 100644 --- a/kabel/src/debug.rs +++ b/kabel/src/debug.rs @@ -261,6 +261,15 @@ pub fn debug_bytecode(vm: &VM) -> String { output += &vm.units[vm.unit_ptr].code[vm.ip].to_string(); output += "\n"; } + REF => { + output += &vm.ip.to_string(); + output += " "; + output += &vm.find_line().to_string(); + output += " REF "; + vm.ip += 1; + output += &vm.units[vm.unit_ptr].code[vm.ip].to_string(); + output += "\n"; + } ASN => { output += &vm.ip.to_string(); output += " "; diff --git a/kabel/src/extension.rs b/kabel/src/extension.rs index 6efbee9033bc4d537401c98cd0bba86202f7588f..bc7af02c852b2188c125c898cb200e43f4fc7d98 100644 --- a/kabel/src/extension.rs +++ b/kabel/src/extension.rs @@ -1,4 +1,4 @@ #[derive(Debug, Clone)] pub enum Extension { - Resolution(usize, usize), // scope, pointer to local table + Resolution(usize, usize), // scope, pointer to variable } diff --git a/kabel/src/opcodes.rs b/kabel/src/opcodes.rs index be9945f9a37f69c77992bb7ae6b415faaa80c9c2..8584e0c6d9059db5d64e0a62640167678e5d2516 100644 --- a/kabel/src/opcodes.rs +++ b/kabel/src/opcodes.rs @@ -4,6 +4,7 @@ pub enum OpCode { LOAD, VAR, + REF, ASN, ASNARR, DECL, @@ -49,39 +50,40 @@ impl From for u8 { match value { LOAD => 0x00, VAR => 0x01, - ASN => 0x02, - ASNARR => 0x03, - DECL => 0x04, - - ADD => 0x05, - SUB => 0x06, - MUL => 0x07, - DIV => 0x08, - MOD => 0x09, - BITAND => 0x0a, - BITXOR => 0x0b, - BITOR => 0x0c, - EQ => 0x0D, - NE => 0x0E, - GR => 0x0F, - GE => 0x10, - LS => 0x11, - LE => 0x12, - OR => 0x13, - AND => 0x14, - - NOT => 0x15, - NEG => 0x16, - - JMP => 0x17, - JMP_UP => 0x18, - JNE => 0x19, - - CALL => 0x1A, - RET => 0x1B, - - LIST => 0x1C, - SCR => 0x1D, + REF => 0x02, + ASN => 0x03, + ASNARR => 0x04, + DECL => 0x05, + + ADD => 0x06, + SUB => 0x07, + MUL => 0x08, + DIV => 0x09, + MOD => 0x0A, + BITAND => 0x0B, + BITXOR => 0x0C, + BITOR => 0x0D, + EQ => 0x0E, + NE => 0x0F, + GR => 0x10, + GE => 0x11, + LS => 0x12, + LE => 0x13, + OR => 0x14, + AND => 0x15, + + NOT => 0x16, + NEG => 0x17, + + JMP => 0x18, + JMP_UP => 0x19, + JNE => 0x1A, + + CALL => 0x1B, + RET => 0x1C, + + LIST => 0x1D, + SCR => 0x1E, POP => 0xFD, PRINT => 0xFE, @@ -94,39 +96,40 @@ impl From for OpCode { use OpCode::*; match value { 0x00 => LOAD, 0x01 => VAR, - 0x02 => ASN, - 0x03 => ASNARR, - 0x04 => DECL, - - 0x05 => ADD, - 0x06 => SUB, - 0x07 => MUL, - 0x08 => DIV, - 0x09 => MOD, - 0x0A => BITAND, - 0x0b => BITXOR, - 0x0c => BITOR, - 0x0D => EQ, - 0x0E => NE, - 0x0F => GR, - 0x10 => GE, - 0x11 => LS, - 0x12 => LE, - 0x13 => OR, - 0x14 => AND, - - 0x15 => NOT, - 0x16 => NEG, - - 0x17 => JMP, - 0x18 => JMP_UP, - 0x19 => JNE, - - 0x1A => CALL, - 0x1b => RET, - - 0x1C => LIST, - 0x1D => SCR, + 0x02 => REF, + 0x03 => ASN, + 0x04 => ASNARR, + 0x05 => DECL, + + 0x06 => ADD, + 0x07 => SUB, + 0x08 => MUL, + 0x09 => DIV, + 0x0A => MOD, + 0x0B => BITAND, + 0x0c => BITXOR, + 0x0d => BITOR, + 0x0E => EQ, + 0x0F => NE, + 0x10 => GR, + 0x11 => GE, + 0x12 => LS, + 0x13 => LE, + 0x14 => OR, + 0x15 => AND, + + 0x16 => NOT, + 0x17 => NEG, + + 0x18 => JMP, + 0x19 => JMP_UP, + 0x1A => JNE, + + 0x1B => CALL, + 0x1c => RET, + + 0x1D => LIST, + 0x1E => SCR, 0xFD => POP, 0xFE => PRINT, diff --git a/kabel/src/vm.rs b/kabel/src/vm.rs index eaf69bb912550a38aae923604cbf07e8e283060a..84c54ef42d4162bdd32a49478488066f6a7380d5 100644 --- a/kabel/src/vm.rs +++ b/kabel/src/vm.rs @@ -1,6 +1,4 @@ -use std::rc::Rc; - use crate::{runtime_error::{KabelRuntimeError, RuntimeErrorKind}, vm_boolean_comparison, vm_boolean_equality}; use crate::vm_error; @@ -59,6 +57,7 @@ impl VM { match self.read() { 0x00 => { // LOAD let byte = self.read() as usize; + println!("ip: {}", self.ip); let value = self.units[self.unit_ptr].pool[byte].clone(); self.stack.push(value); } @@ -67,15 +66,19 @@ impl VM { let value = self.variables[ptr+self.variables_offset].clone(); self.stack.push(value); } - 0x02 => { // ASN + 0x02 => { // REF + let ptr = self.read() as usize; + self.stack.push(Ref(ptr)); + } + 0x03 => { // ASN let value = self.stack.pop().unwrap(); let ptr = self.read(); let offset = self.call_stack.last().expect("var call stack last").2; self.variables[ptr as usize + offset] = value.clone(); self.stack.push(value); } - 0x03 => { // ASNARR - let mut list = self.stack.pop().unwrap(); + 0x04 => { // ASNARR + let listref = self.stack.pop().unwrap(); let index = self.stack.pop().unwrap(); let value = self.stack.pop().unwrap(); if let Value::Num(index) = index { @@ -83,26 +86,32 @@ impl VM { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Subscript index must be an integer but found {}", index)) } let index = index as usize; - if let Value::List(ref mut list) = list { - let len = list.len(); - if index > len { - return Err(vm_error!(self, RuntimeErrorKind::ArrayOutOfBounds, "List length is {} but found index {}", len, index)) + if let Value::Ref(listref) = listref { + let list = &mut self.variables[listref]; + if let Value::List(ref mut list) = list { + let len = list.len(); + if index > len { + return Err(vm_error!(self, RuntimeErrorKind::ArrayOutOfBounds, "List length is {} but found index {}", len, index)) + } + println!("index: {}", index); + list[index] = value.clone(); + self.stack.push(value); + } else { + let type_str = list.type_str(); + return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to subscript non-list type {}", type_str)) } - println!("index: {}", index); - list[index] = value.clone(); - self.stack.push(value); } else { - return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to subscript non-list type {}", list.type_str())) + panic!("Something went wrong in kabel, listref was not a Ref"); } } else { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to use non-integer type {} to subscript list", index.type_str())) } } - 0x04 => { // DECL + 0x05 => { // DECL let value = self.stack.pop().unwrap(); self.variables.push(value); } - 0x05 => { // ADD + 0x06 => { // ADD match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(v1), Num(v2)) => self.stack.push(Num(v1 + v2)), (Str(v1), Str(v2)) => { @@ -116,7 +125,7 @@ impl VM { } } } - 0x06 => { // SUB + 0x07 => { // SUB match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(v1), Num(v2)) => self.stack.push(Num(v1 - v2)), (Str(_v1), Str(_v2)) => { @@ -130,7 +139,7 @@ impl VM { } } } - 0x07 => { // MUL + 0x08 => { // MUL match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(v1), Num(v2)) => self.stack.push(Num(v1 * v2)), (Str(v1), Num(v2)) => { @@ -151,7 +160,7 @@ impl VM { } } } - 0x08 => { // DIV + 0x09 => { // DIV match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(v1), Num(v2)) => self.stack.push(Num(v1 / v2)), (Str(_v1), Str(_v2)) => { @@ -165,7 +174,7 @@ impl VM { } } } - 0x09 => { // MOD + 0x0A => { // MOD match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(v1), Num(v2)) => self.stack.push(Num(v1 % v2)), (Str(_v1), Str(_v2)) => { @@ -179,7 +188,7 @@ impl VM { } } } - 0x0A => { // BITAND + 0x0B => { // BITAND match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(v1), Num(v2)) => { if v1.fract() != 0.0 { @@ -201,7 +210,7 @@ impl VM { } } } - 0x0B => { // BITXOR + 0x0C => { // BITXOR match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(v1), Num(v2)) => { if v1.fract() != 0.0 { @@ -223,7 +232,7 @@ impl VM { } } } - 0x0C => { // BITOR + 0x0D => { // BITOR match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(v1), Num(v2)) => { if v1.fract() != 0.0 { @@ -246,19 +255,19 @@ impl VM { } } // EQ - 0x0D => vm_boolean_equality!(self, ==), + 0x0E => vm_boolean_equality!(self, ==), // NE - 0x0E => vm_boolean_equality!(self, !=), + 0x0F => vm_boolean_equality!(self, !=), // GR - 0x0F => vm_boolean_comparison!(self, >), + 0x10 => vm_boolean_comparison!(self, >), // GE - 0x10 => vm_boolean_comparison!(self, >=), + 0x11 => vm_boolean_comparison!(self, >=), // LS - 0x11 => vm_boolean_comparison!(self, <), + 0x12 => vm_boolean_comparison!(self, <), // LE - 0x12 => vm_boolean_comparison!(self, <=), + 0x13 => vm_boolean_comparison!(self, <=), // OR - 0x13 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + 0x14 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(_v1), Num(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"||\" on non-boolean numbers")) } @@ -273,7 +282,7 @@ impl VM { } } // AND - 0x14 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + 0x15 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(_v1), Num(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"&&\" on non-boolean numbers")) } @@ -288,7 +297,7 @@ impl VM { } } // NOT - 0x15 => match self.stack.pop().unwrap() { + 0x16 => match self.stack.pop().unwrap() { Null => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean value null")) } Num(_v1) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean number")) @@ -303,9 +312,12 @@ impl VM { Fun(_v1) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean function")) } + Ref(_v1) => { + return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean reference")) + } } // NEG - 0x16 => match self.stack.pop().unwrap() { + 0x17 => match self.stack.pop().unwrap() { Null => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number value null")) } Num(v1) => self.stack.push(Num(-v1)), Str(_v1) => { @@ -320,19 +332,22 @@ impl VM { Fun(_v1) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number function")) } + Ref(_v1) => { + return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number reference")) + } } // JMP - 0x17 => { + 0x18 => { let loc = self.read_u16(); self.ip += loc as usize; } // JMP_UP - 0x18 => { + 0x19 => { let loc = self.read_u16(); self.ip -= loc as usize; } // JNE - 0x19 => { + 0x1A => { let condition = self.stack.pop().unwrap(); if let Value::Bool(condition) = condition { if !condition { @@ -347,7 +362,7 @@ impl VM { } // CALL - 0x1A => { + 0x1B => { let num_args = self.read(); let function = self.stack.pop().expect("Stack was empty in call"); if let Value::Fun(function) = function { @@ -364,7 +379,7 @@ impl VM { } } // RET - 0x1B => { + 0x1C => { let (unit_ptr, ip, variables_offset) = self.call_stack.pop().expect("Call stack empty on RET"); let ret = self.stack.pop().expect("Missing return value"); self.stack = self.stack[..variables_offset].to_vec(); @@ -376,13 +391,13 @@ impl VM { } // LIST - 0x1C => { + 0x1D => { let len = self.read(); let list = self.stack.drain(self.stack.len()-len as usize..).collect(); self.stack.push(Value::List(list)); } // SCR - 0x1D => { + 0x1E => { let index = self.stack.pop().expect("stack empty on subscript index"); let list = self.stack.pop().expect("stack empty on subscript list"); if let Value::Num(index) = index { @@ -460,6 +475,7 @@ impl VM { #[derive(Debug, Clone)] pub enum Value { Null, Num(f32), Str(String), Bool(bool), List(Vec), Fun(Function), + Ref(usize), } impl Value { @@ -471,6 +487,7 @@ impl Value { Value::Bool(_) => "bool".to_string(), Value::List(_) => "list".to_string(), Value::Fun(_) => "function".to_string(), + Value::Ref(_) => "reference".to_string(), } } } @@ -493,6 +510,7 @@ impl ToString for Value { output } Fun(v) => format!("", v.unit_ptr), + Ref(v) => format!("", v) } } } diff --git a/kabel/tmp.kab b/kabel/tmp.kab index 40cbb358e694d6d436254fa23c7ff0b8a41994a4..5a073aaa3e1b076b946330c05fe9632fd0b850ba 100644 --- a/kabel/tmp.kab +++ b/kabel/tmp.kab @@ -1,6 +1,3 @@ -// put [3, 2] on stack var i = [3, 2]; -// get reference to i -// set index 0 from i to 3 i[0] = 1; print i;