Skip to content

Commit

Permalink
Add support for globals.
Browse files Browse the repository at this point in the history
Add a hashmap which maps symbols to their corresponding object and retrieve an object from this hashmap when its symbol is referenced during runtime.
  • Loading branch information
ummarikar committed Feb 7, 2020
1 parent 34c71cd commit 3c0ce78
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 15 deletions.
8 changes: 4 additions & 4 deletions lang_tests/instance_vars2.som
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
VM:
status: error
stderr:
...line 11, column 11:
...
Unknown variable 'x'
InvalidSymbol
"

instance_vars2 = (
x = (^x)
run = (
x = 1
)
)
36 changes: 36 additions & 0 deletions lang_tests/system_global.som
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"
VM:
status: success
stdout:
true
true
42
42
String
21
21
nil
true
false
"

system_global = (
run = (
((system global: #Integer) == Integer) println.
system global: #Integer put: 42.
((system global: #Integer) == Integer) println.
Integer println.
(system global: #Integer) println.
system global: #Integer put: 'a'.
Integer class println.
system global: #ab put: 21.
(system global: #ab) println.
ab println.
system global: #nil put: 'a'.
system global: #true put: 'b'.
system global: #false put: 'c'.
nil println.
true println.
false println.
)
)
11 changes: 11 additions & 0 deletions lang_tests/system_global_invalid_symbol_err.som
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"
VM:
status: error
stderr: InvalidSymbol
"

system_global_invalid_symbol_err = (
run = (
system global: #ab.
)
)
6 changes: 4 additions & 2 deletions lib/SOM/System.som
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
System = (
printString: string = primitive
printNewline = primitive
global: name = primitive
global: name put: value = primitive
printString: string = primitive
printNewline = primitive
)
23 changes: 16 additions & 7 deletions src/lib/compiler/ast_to_instrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ impl<'a> Compiler<'a> {
"asSymbol" => Ok(MethodBody::Primitive(Primitive::AsSymbol)),
"class" => Ok(MethodBody::Primitive(Primitive::Class)),
"concatenate:" => Ok(MethodBody::Primitive(Primitive::Concatenate)),
"global:" => Ok(MethodBody::Primitive(Primitive::Global)),
"global:put:" => Ok(MethodBody::Primitive(Primitive::GlobalPut)),
"halt" => Ok(MethodBody::Primitive(Primitive::Halt)),
"hashcode" => Ok(MethodBody::Primitive(Primitive::Hashcode)),
"inspect" => Ok(MethodBody::Primitive(Primitive::Inspect)),
Expand Down Expand Up @@ -485,13 +487,20 @@ impl<'a> Compiler<'a> {
vm.instrs_push(Instr::VarLookup(depth, var_num));
}
}
Err(e) => match self.lexer.lexeme_str(&lexeme) {
"nil" => vm.instrs_push(Instr::Builtin(Builtin::Nil)),
"false" => vm.instrs_push(Instr::Builtin(Builtin::False)),
"system" => vm.instrs_push(Instr::Builtin(Builtin::System)),
"true" => vm.instrs_push(Instr::Builtin(Builtin::True)),
_ => return Err(e),
},
Err(_) => {
let lex_string = self.lexer.lexeme_str(&lexeme);

match lex_string {
"nil" => vm.instrs_push(Instr::Builtin(Builtin::Nil)),
"false" => vm.instrs_push(Instr::Builtin(Builtin::False)),
"true" => vm.instrs_push(Instr::Builtin(Builtin::True)),
_ => {
vm.instrs_push(Instr::Global(
vm.add_symbol(lex_string.to_string()),
));
}
}
}
}
Ok(1)
}
Expand Down
3 changes: 3 additions & 0 deletions src/lib/compiler/instrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pub enum Instr {
Block(usize),
Builtin(Builtin),
Global(usize),
ClosureReturn(usize),
Double(f64),
InstVarLookup(usize),
Expand Down Expand Up @@ -36,6 +37,8 @@ pub enum Primitive {
Div,
DoubleDiv,
Equals,
Global,
GlobalPut,
GreaterThan,
GreaterThanEquals,
Halt,
Expand Down
53 changes: 51 additions & 2 deletions src/lib/vm/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub enum VMError {
expected: ObjType,
got: ObjType,
},
/// Tried to access a global before it being initialised.
InvalidSymbol,
/// Tried to do a shl or shr with a value below zero.
NegativeShift,
/// A specialised version of TypeError, because SOM has more than one number type (and casts
Expand Down Expand Up @@ -111,6 +113,7 @@ pub struct VM {
pub system: Val,
pub true_: Val,
blockinfos: UnsafeCell<Vec<BlockInfo>>,
globals: UnsafeCell<HashMap<usize, Val>>,
inline_caches: UnsafeCell<Vec<Option<(Val, Gc<Method>)>>>,
instrs: UnsafeCell<Vec<Instr>>,
sends: UnsafeCell<Vec<(String, usize)>>,
Expand Down Expand Up @@ -156,6 +159,7 @@ impl VM {
system: Val::illegal(),
true_: Val::illegal(),
blockinfos: UnsafeCell::new(Vec::new()),
globals: UnsafeCell::new(HashMap::new()),
inline_caches: UnsafeCell::new(Vec::new()),
instrs: UnsafeCell::new(Vec::new()),
sends: UnsafeCell::new(Vec::new()),
Expand All @@ -167,7 +171,6 @@ impl VM {
reverse_symbols: UnsafeCell::new(HashMap::new()),
frames: UnsafeCell::new(Vec::new()),
};

// The very delicate phase.
//
// Nothing in this phase must store references to the nil object or any classes earlier
Expand All @@ -191,6 +194,10 @@ impl VM {
vm.sym_cls = vm.init_builtin_class("Symbol", false);
vm.system_cls = vm.init_builtin_class("System", false);
vm.true_cls = vm.init_builtin_class("True", false);
unsafe { &mut *vm.globals.get() }.insert(
vm.add_symbol("system".to_string()),
Inst::new(&vm, vm.system_cls.clone()),
);
vm.false_ = Inst::new(&vm, vm.false_cls.clone());
vm.system = Inst::new(&vm, vm.system_cls.clone());
vm.true_ = Inst::new(&vm, vm.true_cls.clone());
Expand Down Expand Up @@ -226,7 +233,14 @@ impl VM {
let path = self
.find_class(name)
.unwrap_or_else(|_| panic!("Can't find builtin class '{}'", name));
self.compile(&path, inst_vars_allowed)

let val = self.compile(&path, inst_vars_allowed);
let idx = self.add_symbol(name.to_string());
unsafe { &mut *self.globals.get() }
.entry(idx)
.or_insert(val.clone());

val
}

/// Inform the user of the error string `error` and then exit.
Expand Down Expand Up @@ -326,6 +340,15 @@ impl VM {
unsafe { &mut *self.stack.get() }.push(Double::new(self, i));
pc += 1;
}
Instr::Global(symbol_off) => {
debug_assert!(unsafe { &*self.symbols.get() }.len() > symbol_off);
if let Some(global) = unsafe { &mut *self.globals.get() }.get(&symbol_off) {
unsafe { &mut *self.stack.get() }.push(global.clone());
} else {
return SendReturn::Err(Box::new(VMError::InvalidSymbol));
}
pc += 1;
}
Instr::InstVarLookup(n) => {
let inst: &Inst = rcv.downcast(self).unwrap();
unsafe { &mut *self.stack.get() }.push(inst.inst_var_lookup(n));
Expand Down Expand Up @@ -478,6 +501,31 @@ impl VM {
));
SendReturn::Val
}
Primitive::Global => {
let name = unsafe { &mut *self.stack.get() }.pop();
let as_string: &String_ = stry!(name.downcast(self));
let s = as_string.as_str();

if let Some(i) = unsafe { &mut *self.reverse_symbols.get() }.get(s) {
if let Some(val) = unsafe { &mut *self.globals.get() }.get(&i) {
unsafe { &mut *self.stack.get() }.push(val.clone());
return SendReturn::Val;
}
}
SendReturn::Err(Box::new(VMError::InvalidSymbol))
}
Primitive::GlobalPut => {
let value = unsafe { &mut *self.stack.get() }.pop();
let name = unsafe { &mut *self.stack.get() }.pop();
let as_string: &String_ = stry!(name.downcast(self));
let s = as_string.as_str();

if let Some(i) = unsafe { &mut *self.reverse_symbols.get() }.get(s) {
unsafe { &mut *self.globals.get() }.insert(*i, value.clone());
unsafe { &mut *self.stack.get() }.push(value);
}
SendReturn::Val
}
Primitive::GreaterThan => {
unsafe { &mut *self.stack.get() }.push(stry!(
rcv.greater_than(self, unsafe { &mut *self.stack.get() }.pop())
Expand Down Expand Up @@ -853,6 +901,7 @@ impl VM {
system: Val::illegal(),
true_: Val::illegal(),
blockinfos: UnsafeCell::new(Vec::new()),
globals: UnsafeCell::new(HashMap::new()),
inline_caches: UnsafeCell::new(Vec::new()),
instrs: UnsafeCell::new(Vec::new()),
sends: UnsafeCell::new(Vec::new()),
Expand Down

0 comments on commit 3c0ce78

Please sign in to comment.