M kabel/opcodes.txt => kabel/opcodes.txt +29 -28
@@ 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
M kabel/src/codegen.rs => kabel/src/codegen.rs +14 -1
@@ 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 {
M kabel/src/debug.rs => kabel/src/debug.rs +9 -0
@@ 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 += " ";
M kabel/src/extension.rs => kabel/src/extension.rs +1 -1
@@ 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
}
M kabel/src/opcodes.rs => kabel/src/opcodes.rs +69 -66
@@ 4,6 4,7 @@
pub enum OpCode {
LOAD,
VAR,
+ REF,
ASN,
ASNARR,
DECL,
@@ 49,39 50,40 @@ impl From<OpCode> 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<u8> 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,
M kabel/src/vm.rs => kabel/src/vm.rs +57 -39
@@ 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<Value>), 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!("<function {}>", v.unit_ptr),
+ Ref(v) => format!("<reference {}>", v)
}
}
}
M kabel/tmp.kab => kabel/tmp.kab +0 -3
@@ 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;