Skip to content

Commit

Permalink
feat: global variables in vm
Browse files Browse the repository at this point in the history
  • Loading branch information
ZakFarmer committed Oct 24, 2023
1 parent ec9c1a7 commit e64e5ee
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
25 changes: 25 additions & 0 deletions compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::rc::Rc;
use anyhow::Error;
use opcode::Opcode;
use parser::ast::{BooleanLiteral, Expression, IntegerLiteral, Literal, Node, Statement, BlockStatement};
use symbol_table::SymbolTable;

pub mod symbol_table;

Expand Down Expand Up @@ -36,6 +37,8 @@ pub struct Compiler {
instructions: opcode::Instructions,
constants: Vec<Rc<object::Object>>,

symbol_table: SymbolTable,

last_instruction: Option<EmittedInstruction>,
previous_instruction: Option<EmittedInstruction>,
}
Expand All @@ -47,6 +50,7 @@ impl Compiler {
constants: Vec::new(),
last_instruction: None,
previous_instruction: None,
symbol_table: SymbolTable::new(),
}
}

Expand Down Expand Up @@ -141,6 +145,10 @@ impl Compiler {
Statement::Assign(a) => {
self.compile_expression(&a.value)?;

let symbol = self.symbol_table.define(&a.name.value);

self.emit(Opcode::OpSetGlobal, vec![symbol.index]);

return Ok(());
}
Statement::Return(r) => {
Expand Down Expand Up @@ -182,6 +190,23 @@ impl Compiler {

fn compile_expression(&mut self, e: &Expression) -> Result<(), Error> {
match e {
Expression::Identifier(identifier) => {
let symbol = self.symbol_table.resolve(&identifier.value);

match symbol {
Some(symbol) => {
self.emit(Opcode::OpGetGlobal, vec![symbol.index]);
}
None => {
return Err(Error::msg(format!(
"undefined variable: {}",
identifier.value
)));
}
}

return Ok(());
}
Expression::If(if_expression) => {
self.compile_expression(&if_expression.condition)?;

Expand Down
21 changes: 21 additions & 0 deletions vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ use compiler::Bytecode;
use object::Object;
use opcode::Opcode;

const GLOBALS_SIZE: usize = 65536;
const STACK_SIZE: usize = 2048;

pub struct Vm {
constants: Vec<Rc<Object>>,
instructions: opcode::Instructions,

globals: Vec<Rc<Object>>,

stack: Vec<Rc<Object>>,
stack_pointer: usize,
}
Expand All @@ -22,6 +25,8 @@ impl Vm {
constants: bytecode.constants,
instructions: bytecode.instructions,

globals: vec![Rc::new(Object::Null); GLOBALS_SIZE],

stack: vec![Rc::new(Object::Null); STACK_SIZE],
stack_pointer: 0,
}
Expand Down Expand Up @@ -53,6 +58,22 @@ impl Vm {
ip = jump_position;
}
}
Opcode::OpGetGlobal => {
let global_index =
BigEndian::read_u16(&self.instructions.0[ip..ip + 2]) as usize;

ip += 2;

self.push(Rc::clone(&self.globals[global_index]));
}
Opcode::OpSetGlobal => {
let global_index =
BigEndian::read_u16(&self.instructions.0[ip..ip + 2]) as usize;

ip += 2;

self.globals[global_index] = self.pop();
}
Opcode::OpNull => {
self.push(Rc::new(Object::Null));
}
Expand Down

0 comments on commit e64e5ee

Please sign in to comment.