pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr)
{
if self.attr_var_init.bindings.is_empty() {
- self.attr_var_init.cp = self.p.local() + 1;
+ self.attr_var_init.cp = self.p.local();
self.p = CodePtr::VerifyAttrInterrupt(self.attr_var_init.verify_attrs_loc);
}
if p < code_repo.in_situ_code.len() => {},
CodePtr::Local(_) =>
break,
- CodePtr::VerifyAttrInterrupt(p) => {
- let rs = self.calculate_register_threshold();
-
- self.allocate(rs); // store temp vars in perm vars slots.
+ CodePtr::VerifyAttrInterrupt(p) =>
+ self.verify_attr_interrupt(p),
+ _ => {}
+ };
+ }
+ }
- let e = self.e;
- self.and_stack[e].special_form_cp = self.attr_var_init.cp;
+ fn verify_attr_interrupt(&mut self, p: usize) {
+ let rs = self.calculate_register_threshold();
- for i in 1 .. self.and_stack[e].len() + 1 {
- self.and_stack[e][i] = self[RegType::Temp(i)].clone();
- }
+ // store temp vars in perm vars slots along with
+ // self.b0 and self.num_of_args. why self.bo? if we return to a
+ // NeckCut after finishing the interrupt, it won't
+ // work correctly if self.b == self.b0. we must
+ // change it back when we return, as if nothing happened.
+ self.allocate(rs + 2);
- self.verify_attributes();
+ let e = self.e;
+ self.and_stack[e].special_form_cp = self.attr_var_init.cp;
- self.num_of_args = 2;
- self.b0 = self.b;
- self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
- },
- _ => {}
- };
+ for i in 1 .. rs + 1 {
+ self.and_stack[e][i] = self[RegType::Temp(i)].clone();
}
+
+ self.and_stack[e][rs + 1] = Addr::Con(Constant::Usize(self.b0));
+ self.and_stack[e][rs + 2] = Addr::Con(Constant::Usize(self.num_of_args));
+
+ self.verify_attributes();
+
+ self.num_of_args = 2;
+ self.b0 = self.b;
+ self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
}
fn record_var_places(&self, chunk_num: usize, alloc_locs: &AllocVarDict,
},
&SystemClauseType::RestoreCodePtrFromSpecialFormCP => {
let e = self.e;
+
+ let frame_len = self.and_stack[e].len();
- for i in 1 .. self.and_stack[e].len() + 1 {
+ for i in 1 .. frame_len - 1 {
self[RegType::Temp(i)] = self.and_stack[e][i].clone();
+ }
+
+ if let &Addr::Con(Constant::Usize(b0)) = &self.and_stack[e][frame_len - 1] {
+ self.b0 = b0;
+ }
+
+ if let &Addr::Con(Constant::Usize(num_of_args)) = &self.and_stack[e][frame_len] {
+ self.num_of_args = num_of_args;
}
self.p = CodePtr::Local(self.and_stack[e].special_form_cp);
for item in iter {
match item {
+ HeapCellValue::Addr(Addr::AttrVar(h)) =>
+ vars.push(Ref::AttrVar(h)),
HeapCellValue::Addr(Addr::HeapCell(h)) =>
vars.push(Ref::HeapCell(h)),
HeapCellValue::Addr(Addr::StackCell(fr, sc)) =>