better implementation for if/else

This commit is contained in:
Shautvast 2025-11-17 10:44:51 +01:00
parent 0d8786ebff
commit d8079f34f6
3 changed files with 49 additions and 44 deletions

View file

@ -211,3 +211,10 @@ fn add(a: string, b: string) -> string:
a + " " + b a + " " + b
``` ```
* get() is the entry point for http GET method calls, likewise for POST, PUT, DELETE, etc. * 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

View file

@ -8,12 +8,7 @@ use crate::symbol_builder::{Symbol, calculate_type, infer_type};
use crate::tokens::TokenType; use crate::tokens::TokenType;
use crate::tokens::TokenType::Unknown; use crate::tokens::TokenType::Unknown;
use crate::value::Value; use crate::value::Value;
use crate::vm::{ 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};
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::{Registry, SymbolTable}; use crate::{Registry, SymbolTable};
use std::collections::HashMap; use std::collections::HashMap;
use std::ops::Deref; use std::ops::Deref;
@ -165,22 +160,28 @@ impl Compiler {
else_branch, else_branch,
} => { } => {
self.compile_expression(namespace, condition, symbols, registry)?; self.compile_expression(namespace, condition, symbols, registry)?;
compile(
Some(&format!("{}.?",namespace)), self.emit_byte(OP_DUP);
then_branch, self.emit_bytes(OP_GOTO_NIF, 0);
symbols, let goto_addr1 = self.chunk.code.len()-1;
registry, self.emit_byte(OP_POP);
)?; self.compile_statements(then_branch, symbols, registry, namespace)?;
if else_branch.is_none() { self.emit_bytes(OP_GOTO, 0);
self.emit_byte(OP_IF); let goto_addr2 = self.chunk.code.len()-1;
} else { if else_branch.is_some() {
self.emit_byte(OP_IF_ELSE); self.chunk.code[goto_addr1] = self.chunk.code.len() as u16;
compile( self.emit_bytes(OP_GOTO_IF, 0);
Some(format!("{}.:", namespace).as_str()), let goto_addr3 = self.chunk.code.len() - 1;
self.compile_statements(
else_branch.as_ref().unwrap(), else_branch.as_ref().unwrap(),
symbols, symbols,
registry, 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 { Statement::ForStatement {
@ -303,7 +304,11 @@ impl Compiler {
return Err(self.raise(UndeclaredVariable(name.to_string()))); 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)?; self.compile_expression(namespace, value, symbols, registry)?;
let name_index = self.vars.get(variable_name); let name_index = self.vars.get(variable_name);
if let Some(name_index) = name_index { if let Some(name_index) = name_index {

View file

@ -250,31 +250,13 @@ impl Vm {
self.push(result); self.push(result);
} }
} }
OP_IF => { OP_GOTO_NIF => {
let condition = self.pop(); let b = self.pop();
if condition == Value::Bool(true) { let goto_addr = self.read(chunk);
if let Some(then) = self.registry.get(&format!("{}.?", chunk.name)) { if b == Value::Bool(false) {
let result = interpret_function(then, vec![])?; self.ip = goto_addr;
self.push(result);
} }
} }
}
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 => { OP_GOTO_IF => {
let b = self.pop(); let b = self.pop();
let goto_addr = self.read(chunk); let goto_addr = self.read(chunk);
@ -282,6 +264,15 @@ impl Vm {
self.ip = goto_addr; 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_ASSIGN: u16 = 41;
pub const OP_LIST_GET: u16 = 42; pub const OP_LIST_GET: u16 = 42;
pub const OP_CALL_BUILTIN: u16 = 43; pub const OP_CALL_BUILTIN: u16 = 43;
pub const OP_IF: u16 = 44; pub const OP_DUP: u16 = 44;
pub const OP_IF_ELSE: u16 = 45; // pub const OP_IF_ELSE: u16 = 45;
pub const OP_GOTO_IF: u16 = 46; pub const OP_GOTO_IF: u16 = 46;
pub const OP_GOTO_NIF: u16 = 48;
pub const OP_GOTO: u16 = 47;