fix attributed variables dealing with NeckCut on return
This commit is contained in:
@@ -41,11 +41,6 @@ impl AndStack {
|
|||||||
self.0.push(Frame::new(global_index, len, e, cp, n));
|
self.0.push(Frame::new(global_index, len, e, cp, n));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn top(&self) -> Option<&Frame> {
|
|
||||||
self.0.last()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.0.len()
|
self.0.len()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ impl MachineState {
|
|||||||
pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr)
|
pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr)
|
||||||
{
|
{
|
||||||
if self.attr_var_init.bindings.is_empty() {
|
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);
|
self.p = CodePtr::VerifyAttrInterrupt(self.attr_var_init.verify_attrs_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -585,29 +585,40 @@ impl MachineState {
|
|||||||
if p < code_repo.in_situ_code.len() => {},
|
if p < code_repo.in_situ_code.len() => {},
|
||||||
CodePtr::Local(_) =>
|
CodePtr::Local(_) =>
|
||||||
break,
|
break,
|
||||||
CodePtr::VerifyAttrInterrupt(p) => {
|
CodePtr::VerifyAttrInterrupt(p) =>
|
||||||
let rs = self.calculate_register_threshold();
|
self.verify_attr_interrupt(p),
|
||||||
|
|
||||||
self.allocate(rs); // store temp vars in perm vars slots.
|
|
||||||
|
|
||||||
let e = self.e;
|
|
||||||
self.and_stack[e].special_form_cp = self.attr_var_init.cp;
|
|
||||||
|
|
||||||
for i in 1 .. self.and_stack[e].len() + 1 {
|
|
||||||
self.and_stack[e][i] = self[RegType::Temp(i)].clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.verify_attributes();
|
|
||||||
|
|
||||||
self.num_of_args = 2;
|
|
||||||
self.b0 = self.b;
|
|
||||||
self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
|
|
||||||
},
|
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn verify_attr_interrupt(&mut self, p: usize) {
|
||||||
|
let rs = self.calculate_register_threshold();
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
let e = self.e;
|
||||||
|
self.and_stack[e].special_form_cp = self.attr_var_init.cp;
|
||||||
|
|
||||||
|
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,
|
fn record_var_places(&self, chunk_num: usize, alloc_locs: &AllocVarDict,
|
||||||
heap_locs: &mut HeapVarDict)
|
heap_locs: &mut HeapVarDict)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -451,9 +451,19 @@ impl MachineState {
|
|||||||
},
|
},
|
||||||
&SystemClauseType::RestoreCodePtrFromSpecialFormCP => {
|
&SystemClauseType::RestoreCodePtrFromSpecialFormCP => {
|
||||||
let e = self.e;
|
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();
|
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);
|
self.p = CodePtr::Local(self.and_stack[e].special_form_cp);
|
||||||
@@ -576,6 +586,8 @@ impl MachineState {
|
|||||||
|
|
||||||
for item in iter {
|
for item in iter {
|
||||||
match item {
|
match item {
|
||||||
|
HeapCellValue::Addr(Addr::AttrVar(h)) =>
|
||||||
|
vars.push(Ref::AttrVar(h)),
|
||||||
HeapCellValue::Addr(Addr::HeapCell(h)) =>
|
HeapCellValue::Addr(Addr::HeapCell(h)) =>
|
||||||
vars.push(Ref::HeapCell(h)),
|
vars.push(Ref::HeapCell(h)),
|
||||||
HeapCellValue::Addr(Addr::StackCell(fr, sc)) =>
|
HeapCellValue::Addr(Addr::StackCell(fr, sc)) =>
|
||||||
|
|||||||
Reference in New Issue
Block a user