diff --git a/README.md b/README.md index 9845858..3c053db 100644 --- a/README.md +++ b/README.md @@ -211,3 +211,10 @@ fn add(a: string, b: string) -> string: a + " " + b ``` * get() is the entry point for http GET method calls, likewise for POST, PUT, DELETE, etc. + +ISSUES +* Make everything an expression. If is a statement and so it can not be type checked +* improve indenting +* add an extra pass that creates a more IR-like representation (enum instead of bytes) + * easier debugging + * chunk debug to stdout can be removed \ No newline at end of file diff --git a/src/bytecode_compiler.rs b/src/bytecode_compiler.rs index 2f0833f..7b19d36 100644 --- a/src/bytecode_compiler.rs +++ b/src/bytecode_compiler.rs @@ -8,12 +8,7 @@ use crate::symbol_builder::{Symbol, calculate_type, infer_type}; use crate::tokens::TokenType; use crate::tokens::TokenType::Unknown; use crate::value::Value; -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_GOTO_IF, OP_GREATER, - OP_GREATER_EQUAL, OP_IF, OP_IF_ELSE, OP_LESS, OP_LESS_EQUAL, OP_LIST_GET, OP_MULTIPLY, - OP_NEGATE, OP_NOT, OP_OR, OP_POP, OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT, -}; +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_DUP, OP_EQUAL, OP_GET, OP_GOTO, OP_GOTO_IF, OP_GOTO_NIF, OP_GREATER, OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_LIST_GET, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_OR, OP_POP, OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT}; use crate::{Registry, SymbolTable}; use std::collections::HashMap; use std::ops::Deref; @@ -165,22 +160,28 @@ impl Compiler { else_branch, } => { self.compile_expression(namespace, condition, symbols, registry)?; - compile( - Some(&format!("{}.?",namespace)), - then_branch, - symbols, - registry, - )?; - if else_branch.is_none() { - self.emit_byte(OP_IF); - } else { - self.emit_byte(OP_IF_ELSE); - compile( - Some(format!("{}.:", namespace).as_str()), + + self.emit_byte(OP_DUP); + self.emit_bytes(OP_GOTO_NIF, 0); + let goto_addr1 = self.chunk.code.len()-1; + self.emit_byte(OP_POP); + self.compile_statements(then_branch, symbols, registry, namespace)?; + self.emit_bytes(OP_GOTO, 0); + let goto_addr2 = self.chunk.code.len()-1; + if else_branch.is_some() { + self.chunk.code[goto_addr1] = self.chunk.code.len() as u16; + self.emit_bytes(OP_GOTO_IF, 0); + let goto_addr3 = self.chunk.code.len() - 1; + + self.compile_statements( else_branch.as_ref().unwrap(), symbols, registry, + namespace, )?; + + self.chunk.code[goto_addr2] = self.chunk.code.len() as u16; // fill in the placeholder + self.chunk.code[goto_addr3] = self.chunk.code.len() as u16; // fill in the placeholder } } Statement::ForStatement { @@ -303,7 +304,11 @@ impl Compiler { return Err(self.raise(UndeclaredVariable(name.to_string()))); } } - Expression::Assignment { variable_name, value, .. } => { + Expression::Assignment { + variable_name, + value, + .. + } => { self.compile_expression(namespace, value, symbols, registry)?; let name_index = self.vars.get(variable_name); if let Some(name_index) = name_index { diff --git a/src/vm.rs b/src/vm.rs index a4d2cb1..f21d694 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -250,31 +250,13 @@ impl Vm { self.push(result); } } - OP_IF => { - let condition = self.pop(); - if condition == Value::Bool(true) { - if let Some(then) = self.registry.get(&format!("{}.?", chunk.name)) { - let result = interpret_function(then, vec![])?; - self.push(result); - } + OP_GOTO_NIF => { + let b = self.pop(); + let goto_addr = self.read(chunk); + if b == Value::Bool(false) { + self.ip = goto_addr; } } - OP_IF_ELSE => { - let condition = self.pop(); - self.push(if condition == Value::Bool(true) { - if let Some(then) = self.registry.get(&format!("{}.?", chunk.name)) { - interpret_function(then, vec![])? - } else { - return Err(Something); - } - } else { - if let Some(then) = self.registry.get(&format!("{}.:", chunk.name)) { - interpret_function(then, vec![])? - } else { - return Err(Something); - } - }); - } OP_GOTO_IF => { let b = self.pop(); let goto_addr = self.read(chunk); @@ -282,6 +264,15 @@ impl Vm { self.ip = goto_addr; } } + OP_GOTO => { + let goto_addr = self.read(chunk); + self.ip = goto_addr; + } + OP_DUP =>{ + let value = self.pop(); + self.push(value.clone()); + self.push(value); + } _ => {} } } @@ -393,6 +384,8 @@ pub const OP_DEF_F64: u16 = 40; pub const OP_ASSIGN: u16 = 41; pub const OP_LIST_GET: u16 = 42; pub const OP_CALL_BUILTIN: u16 = 43; -pub const OP_IF: u16 = 44; -pub const OP_IF_ELSE: u16 = 45; +pub const OP_DUP: u16 = 44; +// pub const OP_IF_ELSE: u16 = 45; pub const OP_GOTO_IF: u16 = 46; +pub const OP_GOTO_NIF: u16 = 48; +pub const OP_GOTO: u16 = 47;