Skip to content

Commit

Permalink
Implement the 'instVarAt:put:' primitive.
Browse files Browse the repository at this point in the history
  • Loading branch information
ltratt committed Jun 15, 2020
1 parent ec29caf commit 0263235
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 1 deletion.
19 changes: 19 additions & 0 deletions lang_tests/inst_var_at_put.som
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"
VM:
status: success
stdout:
5
instance of inst_var_at_put
6
"

inst_var_at_put = (
| x |

run = (
x := 5.
(self instVarAt: 1) println.
(self instVarAt: 1 put: 6) println.
x println.
)
)
18 changes: 18 additions & 0 deletions lang_tests/inst_var_at_put_bad_idx.som
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"
VM:
status: error
stderr:
Traceback...
...
Index 2 not valid for array of length 1.
"

inst_var_at_put_bad_idx = (
| x |

run = (
x := 5.
self instVarAt: 2 put: 6.
x println.
)
)
9 changes: 8 additions & 1 deletion src/lib/vm/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,14 @@ impl VM {
self.stack.push(v);
SendReturn::Val
}
Primitive::InstVarAtPut => unimplemented!(),
Primitive::InstVarAtPut => {
let v = self.stack.pop();
let n = stry!(self.stack.pop().as_usize(self));
let inst = stry!(rcv.tobj(self));
stry!(inst.inst_var_at_put(self, n, v));
self.stack.push(rcv);
SendReturn::Val
}
Primitive::InstVarNamed => unimplemented!(),
Primitive::InvokeOnWith => todo!(),
Primitive::IsDigits => unimplemented!(),
Expand Down
15 changes: 15 additions & 0 deletions src/lib/vm/objects/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,21 @@ pub trait Obj: std::fmt::Debug {
}
}

/// Return the instance variable at `i` (using SOM indexing).
fn inst_var_at_put(&self, vm: &VM, i: usize, v: Val) -> Result<(), Box<VMError>> {
if i > 0 && i <= self.num_inst_vars() {
Ok(unsafe { self.unchecked_inst_var_set(i - 1, v) })
} else {
Err(VMError::new(
vm,
VMErrorKind::IndexError {
tried: i,
max: self.num_inst_vars(),
},
))
}
}

/// Lookup an instance variable in this object. If `usize` exceeds the number of instance
/// variables this will lead to undefined behaviour.
unsafe fn unchecked_inst_var_get(&self, _: usize) -> Val {
Expand Down

0 comments on commit 0263235

Please sign in to comment.