From: Mark Thom Date: Tue, 12 Feb 2019 15:38:46 +0000 (-0700) Subject: fix attributed variables dealing with NeckCut on return X-Git-Tag: v0.8.110~260 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=06021e2373df09a0bfdaa2419bcfd940e98d9d00;p=scryer-prolog.git fix attributed variables dealing with NeckCut on return --- diff --git a/src/prolog/and_stack.rs b/src/prolog/and_stack.rs index b1a5d5a4..368ada0f 100644 --- a/src/prolog/and_stack.rs +++ b/src/prolog/and_stack.rs @@ -41,11 +41,6 @@ impl AndStack { 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 { self.0.len() } diff --git a/src/prolog/machine/attributed_variables.rs b/src/prolog/machine/attributed_variables.rs index 78320678..940d3413 100644 --- a/src/prolog/machine/attributed_variables.rs +++ b/src/prolog/machine/attributed_variables.rs @@ -29,7 +29,7 @@ impl MachineState { 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); } diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index f01a2bb0..e0245a99 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -585,27 +585,38 @@ impl MachineState { 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, diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index ef299842..6a96180a 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -451,9 +451,19 @@ impl MachineState { }, &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); @@ -576,6 +586,8 @@ impl MachineState { 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)) =>