aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler.rs8
-rw-r--r--src/error.rs5
-rw-r--r--src/vm.rs35
3 files changed, 45 insertions, 3 deletions
diff --git a/src/compiler.rs b/src/compiler.rs
index f691922..8275618 100644
--- a/src/compiler.rs
+++ b/src/compiler.rs
@@ -380,6 +380,14 @@ impl Compiler {
self.assign(&name, block);
}
+ (Token::If, _, _, _) => {
+ self.eat();
+ self.expression(block);
+ let jump = block.add(Op::Illegal, self.line());
+ self.scope(block);
+ block.patch(Op::JmpFalse(block.curr()), jump);
+ }
+
(Token::LeftBrace, _, _, _) => {
self.scope(block);
}
diff --git a/src/error.rs b/src/error.rs
index 22e0d1a..d79a5fb 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -7,6 +7,8 @@ use crate::tokenizer::Token;
pub enum ErrorKind {
TypeError(Op, Vec<Value>),
AssertFailed(Value, Value),
+ InvalidProgram,
+
SyntaxError(usize, Token),
}
@@ -33,6 +35,9 @@ impl fmt::Display for ErrorKind {
ErrorKind::SyntaxError(line, token) => {
write!(f, "Syntax error on line {} at token {:?}", line, token)
}
+ ErrorKind::InvalidProgram => {
+ write!(f, "[!!!] Invalid program")
+ }
}
}
}
diff --git a/src/vm.rs b/src/vm.rs
index 1d66c12..7f121d4 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -21,6 +21,8 @@ pub enum Value {
#[derive(Debug, Clone, Copy)]
pub enum Op {
+ Illegal,
+
Pop,
Constant(Value),
@@ -34,6 +36,9 @@ pub enum Op {
Or,
Not,
+ Jmp(usize),
+ JmpFalse(usize),
+
Equal, // ==
Less, // <
Greater, // >
@@ -69,7 +74,7 @@ impl Block {
}
pub fn add(&mut self, op: Op, token_position: usize) -> usize {
- let len = self.ops.len();
+ let len = self.curr();
if token_position != self.last_line_offset {
self.line_offsets.insert(len, token_position);
self.last_line_offset = token_position;
@@ -79,12 +84,20 @@ impl Block {
}
pub fn add_from(&mut self, ops: &[Op], token_position: usize) -> usize {
- let len = self.ops.len();
+ let len = self.curr();
for op in ops {
self.add(*op, token_position);
}
len
}
+
+ pub fn curr(&self) -> usize {
+ self.ops.len()
+ }
+
+ pub fn patch(&mut self, op: Op, pos: usize) {
+ self.ops[pos] = op;
+ }
}
#[derive(Debug)]
@@ -135,7 +148,7 @@ impl VM {
}
pub fn run(&mut self) -> Result<(), Error>{
- const PRINT_WHILE_RUNNING: bool = false;
+ const PRINT_WHILE_RUNNING: bool = true;
const PRINT_BLOCK: bool = true;
if PRINT_BLOCK {
@@ -159,6 +172,10 @@ impl VM {
let op = self.block.ops[self.ip];
match op {
+ Op::Illegal => {
+ error!(self, ErrorKind::InvalidProgram);
+ }
+
Op::Pop => {
self.stack.pop();
}
@@ -243,6 +260,18 @@ impl VM {
}
}
+ Op::Jmp(line) => {
+ self.ip = line;
+ continue;
+ }
+
+ Op::JmpFalse(line) => {
+ if Some(Value::Bool(false)) == self.stack.pop() {
+ self.ip = line;
+ continue;
+ }
+ }
+
Op::AssertEqual => {
let (a, b) = self.pop_twice();
if a != b {