flatten the instruction dispatch loop

This commit is contained in:
Mark Thom
2021-12-19 18:57:57 -07:00
parent 3db86f1e25
commit 955e1799c8
52 changed files with 14247 additions and 10021 deletions

View File

@@ -4,7 +4,6 @@ use crate::{perm_v, temp_v};
use crate::allocator::*;
use crate::arithmetic::*;
use crate::clause_types::*;
use crate::fixtures::*;
use crate::forms::*;
use crate::indexing::*;
@@ -13,6 +12,7 @@ use crate::iterators::*;
use crate::targets::*;
use crate::types::*;
use crate::instr;
use crate::machine::machine_errors::*;
use indexmap::{IndexMap, IndexSet};
@@ -57,7 +57,9 @@ impl<'a> ConjunctInfo<'a> {
let mut code_index = 0;
for phase in 0.. {
while let Line::Query(ref query_instr) = &code[code_index] {
while code[code_index].is_query_instr() {
let query_instr = &mut code[code_index];
if !unsafe_var_marker.mark_safe_vars(query_instr) {
unsafe_var_marker.mark_phase(query_instr, phase);
}
@@ -75,7 +77,8 @@ impl<'a> ConjunctInfo<'a> {
code_index = 0;
for phase in 0.. {
while let Line::Query(ref mut query_instr) = &mut code[code_index] {
while code[code_index].is_query_instr() {
let query_instr = &mut code[code_index];
unsafe_var_marker.mark_unsafe_vars(query_instr, phase);
code_index += 1;
}
@@ -103,9 +106,9 @@ impl CodeGenSettings {
}
#[inline]
pub(crate) fn internal_try_me_else(&self, offset: usize) -> ChoiceInstruction {
pub(crate) fn internal_try_me_else(&self, offset: usize) -> Instruction {
if let Some(global_clock_time) = self.global_clock_tick {
ChoiceInstruction::DynamicInternalElse(
Instruction::DynamicInternalElse(
global_clock_time,
Death::Infinity,
if offset == 0 {
@@ -115,13 +118,13 @@ impl CodeGenSettings {
},
)
} else {
ChoiceInstruction::TryMeElse(offset)
Instruction::TryMeElse(offset)
}
}
pub(crate) fn try_me_else(&self, offset: usize) -> ChoiceInstruction {
pub(crate) fn try_me_else(&self, offset: usize) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
ChoiceInstruction::DynamicElse(
Instruction::DynamicElse(
global_clock_tick,
Death::Infinity,
if offset == 0 {
@@ -131,13 +134,13 @@ impl CodeGenSettings {
},
)
} else {
ChoiceInstruction::TryMeElse(offset)
Instruction::TryMeElse(offset)
}
}
pub(crate) fn internal_retry_me_else(&self, offset: usize) -> ChoiceInstruction {
pub(crate) fn internal_retry_me_else(&self, offset: usize) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
ChoiceInstruction::DynamicInternalElse(
Instruction::DynamicInternalElse(
global_clock_tick,
Death::Infinity,
if offset == 0 {
@@ -147,13 +150,13 @@ impl CodeGenSettings {
},
)
} else {
ChoiceInstruction::RetryMeElse(offset)
Instruction::RetryMeElse(offset)
}
}
pub(crate) fn retry_me_else(&self, offset: usize) -> ChoiceInstruction {
pub(crate) fn retry_me_else(&self, offset: usize) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
ChoiceInstruction::DynamicElse(
Instruction::DynamicElse(
global_clock_tick,
Death::Infinity,
if offset == 0 {
@@ -163,33 +166,33 @@ impl CodeGenSettings {
},
)
} else if self.non_counted_bt {
ChoiceInstruction::DefaultRetryMeElse(offset)
Instruction::DefaultRetryMeElse(offset)
} else {
ChoiceInstruction::RetryMeElse(offset)
Instruction::RetryMeElse(offset)
}
}
pub(crate) fn internal_trust_me(&self) -> ChoiceInstruction {
pub(crate) fn internal_trust_me(&self) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
ChoiceInstruction::DynamicInternalElse(
Instruction::DynamicInternalElse(
global_clock_tick,
Death::Infinity,
NextOrFail::Fail(0),
)
} else if self.non_counted_bt {
ChoiceInstruction::DefaultTrustMe(0)
Instruction::DefaultTrustMe(0)
} else {
ChoiceInstruction::TrustMe(0)
Instruction::TrustMe(0)
}
}
pub(crate) fn trust_me(&self) -> ChoiceInstruction {
pub(crate) fn trust_me(&self) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
ChoiceInstruction::DynamicElse(global_clock_tick, Death::Infinity, NextOrFail::Fail(0))
Instruction::DynamicElse(global_clock_tick, Death::Infinity, NextOrFail::Fail(0))
} else if self.non_counted_bt {
ChoiceInstruction::DefaultTrustMe(0)
Instruction::DefaultTrustMe(0)
} else {
ChoiceInstruction::TrustMe(0)
Instruction::TrustMe(0)
}
}
}
@@ -238,12 +241,11 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
vr: &'a Cell<VarReg>,
code: &mut Code,
) -> RegType {
let mut target = Vec::new();
self.marker
.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
let mut target = Code::new();
self.marker.mark_var::<QueryInstruction>(name, Level::Shallow, vr, term_loc, &mut target);
if !target.is_empty() {
code.extend(target.into_iter().map(Line::Query));
code.extend(target.into_iter());
}
vr.get().norm()
@@ -271,7 +273,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
}
}
fn add_or_increment_void_instr<Target>(target: &mut Vec<Target>)
fn add_or_increment_void_instr<Target>(target: &mut Code)
where
Target: crate::targets::CompilationTarget<'a>,
{
@@ -291,13 +293,12 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
var: &'a Rc<String>,
term_loc: GenContext,
is_exposed: bool,
target: &mut Vec<Target>,
target: &mut Code,
) {
if is_exposed || self.get_var_count(var.as_ref()) > 1 {
self.marker
.mark_var(var.clone(), Level::Deep, cell, term_loc, target);
self.marker.mark_var::<Target>(var.clone(), Level::Deep, cell, term_loc, target);
} else {
Self::add_or_increment_void_instr(target);
Self::add_or_increment_void_instr::<Target>(target);
}
}
@@ -306,27 +307,26 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
subterm: &'a Term,
term_loc: GenContext,
is_exposed: bool,
target: &mut Vec<Target>,
target: &mut Code,
) {
match subterm {
&Term::AnonVar if is_exposed => {
self.marker.mark_anon_var(Level::Deep, term_loc, target);
self.marker.mark_anon_var::<Target>(Level::Deep, term_loc, target);
}
&Term::AnonVar => {
Self::add_or_increment_void_instr(target);
Self::add_or_increment_void_instr::<Target>(target);
}
&Term::Cons(ref cell, ..)
| &Term::Clause(ref cell, ..)
| Term::PartialString(ref cell, ..) => {
self.marker
.mark_non_var(Level::Deep, term_loc, cell, target);
self.marker.mark_non_var::<Target>(Level::Deep, term_loc, cell, target);
target.push(Target::clause_arg_to_instr(cell.get()));
}
&Term::Literal(_, ref constant) => {
target.push(Target::constant_subterm(constant.clone()));
}
&Term::Var(ref cell, ref var) => {
self.deep_var_instr(cell, var, term_loc, is_exposed, target);
self.deep_var_instr::<Target>(cell, var, term_loc, is_exposed, target);
}
};
}
@@ -336,12 +336,12 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
iter: Iter,
term_loc: GenContext,
is_exposed: bool,
) -> Vec<Target>
) -> Code
where
Target: crate::targets::CompilationTarget<'a>,
Iter: Iterator<Item = TermRef<'a>>,
{
let mut target = Vec::new();
let mut target: Code = Vec::new();
for term in iter {
match term {
@@ -349,38 +349,38 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
if let GenContext::Head = term_loc {
self.marker.advance_arg();
} else {
self.marker.mark_anon_var(lvl, term_loc, &mut target);
self.marker.mark_anon_var::<Target>(lvl, term_loc, &mut target);
}
}
TermRef::Clause(lvl, cell, ct, terms) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
target.push(Target::to_structure(ct, terms.len(), cell.get()));
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_structure(ct.name(), terms.len(), cell.get()));
for subterm in terms {
self.subterm_to_instr(subterm, term_loc, is_exposed, &mut target);
self.subterm_to_instr::<Target>(subterm, term_loc, is_exposed, &mut target);
}
}
TermRef::Cons(lvl, cell, head, tail) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_list(lvl, cell.get()));
self.subterm_to_instr(head, term_loc, is_exposed, &mut target);
self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
self.subterm_to_instr::<Target>(head, term_loc, is_exposed, &mut target);
self.subterm_to_instr::<Target>(tail, term_loc, is_exposed, &mut target);
}
TermRef::Literal(lvl @ Level::Shallow, cell, Literal::String(ref string)) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_pstr(lvl, *string, cell.get(), false));
}
TermRef::Literal(lvl @ Level::Shallow, cell, constant) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_constant(lvl, *constant, cell.get()));
}
TermRef::PartialString(lvl, cell, string, tail) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
if let Some(tail) = tail {
target.push(Target::to_pstr(lvl, string, cell.get(), true));
self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
self.subterm_to_instr::<Target>(tail, term_loc, is_exposed, &mut target);
} else {
target.push(Target::to_pstr(lvl, string, cell.get(), false));
}
@@ -388,7 +388,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
TermRef::Var(lvl @ Level::Shallow, cell, ref var) if var.as_str() == "!" => {
if self.marker.is_unbound(var.clone()) {
if term_loc != GenContext::Head {
self.marker.mark_reserved_var(
self.marker.mark_reserved_var::<Target>(
var.clone(),
lvl,
cell,
@@ -401,12 +401,10 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
}
}
self.marker
.mark_var(var.clone(), lvl, cell, term_loc, &mut target);
self.marker.mark_var::<Target>(var.clone(), lvl, cell, term_loc, &mut target);
}
TermRef::Var(lvl @ Level::Shallow, cell, var) => {
self.marker
.mark_var(var.clone(), lvl, cell, term_loc, &mut target);
self.marker.mark_var::<Target>(var.clone(), lvl, cell, term_loc, &mut target);
}
_ => {}
};
@@ -451,13 +449,13 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
match qt {
&QueryTerm::Jump(ref vars) => {
self.jmp_by_locs.push(code.len());
code.push(jmp_call!(vars.len(), 0, pvs));
code.push(instr!("jmp_by_call", vars.len(), 0, pvs));
}
&QueryTerm::Clause(_, ref ct, ref terms, true) => {
code.push(call_clause_by_default!(ct.clone(), terms.len(), pvs));
&QueryTerm::Clause(_, ref ct, _, true) => {
code.push(call_clause_by_default!(ct.clone(), pvs));
}
&QueryTerm::Clause(_, ref ct, ref terms, false) => {
code.push(call_clause!(ct.clone(), terms.len(), pvs));
&QueryTerm::Clause(_, ref ct, _, false) => {
code.push(call_clause!(ct.clone(), pvs));
}
_ => {}
}
@@ -465,25 +463,29 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
fn lco(code: &mut Code) -> usize {
let mut dealloc_index = code.len() - 1;
let last_instr = code.pop();
match code.last_mut() {
Some(&mut Line::Control(ref mut ctrl)) => match ctrl {
&mut ControlInstruction::CallClause(_, _, _, ref mut last_call, _) => {
*last_call = true;
}
&mut ControlInstruction::JmpBy(_, _, _, ref mut last_call) => {
*last_call = true;
}
&mut ControlInstruction::Proceed => {}
_ => {
dealloc_index += 1;
}
},
Some(&mut Line::Cut(CutInstruction::Cut(_))) => {
dealloc_index += 1;
match last_instr {
Some(instr @ Instruction::Proceed) => {
code.push(instr);
}
_ => {}
};
Some(instr @ Instruction::Cut(_)) => {
dealloc_index += 1;
code.push(instr);
}
Some(mut instr) if instr.is_ctrl_instr() => {
code.push(if instr.perm_vars_mut().is_some() {
instr.to_execute()
} else {
dealloc_index += 1;
instr
});
}
Some(instr) => {
code.push(instr);
}
None => {}
}
dealloc_index
}
@@ -496,7 +498,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
code: &mut Code,
) -> Result<(), CompilationError> {
match ct {
&InlinedClauseType::CompareNumber(cmp, ..) => {
&InlinedClauseType::CompareNumber(mut cmp) => {
self.marker.reset_arg(2);
let (mut lcode, at_1) = self.call_arith_eval(&terms[0], 1)?;
@@ -523,71 +525,71 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
&Term::Literal(_, Literal::Char(_))
| &Term::Literal(_, Literal::Atom(atom!("[]")))
| &Term::Literal(_, Literal::Atom(..)) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_atom!(r));
code.push(instr!("atom", r, 0));
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsAtomic(..) => match &terms[0] {
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) | &Term::PartialString(..) => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
&Term::Literal(_, Literal::String(_)) => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
&Term::Literal(..) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_atomic!(r));
code.push(instr!("atomic", r, 0));
}
},
&InlinedClauseType::IsCompound(..) => match &terms[0] {
&Term::Clause(..) | &Term::Cons(..) | &Term::PartialString(..) |
&Term::Literal(_, Literal::String(..)) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_compound!(r));
code.push(instr!("compound", r, 0));
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsRational(..) => match &terms[0] {
&Term::Literal(_, Literal::Rational(_)) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_rational!(r));
code.push(instr!("rational", r, 0));
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsFloat(..) => match &terms[0] {
&Term::Literal(_, Literal::Float(_)) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_float!(r));
code.push(instr!("float", r, 0));
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsNumber(..) => match &terms[0] {
@@ -595,41 +597,41 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
| &Term::Literal(_, Literal::Rational(_))
| &Term::Literal(_, Literal::Integer(_))
| &Term::Literal(_, Literal::Fixnum(_)) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_number!(r));
code.push(instr!("number", r, 0));
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsNonVar(..) => match &terms[0] {
&Term::AnonVar => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_nonvar!(r));
code.push(instr!("nonvar", r, 0));
}
_ => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
},
&InlinedClauseType::IsInteger(..) => match &terms[0] {
&Term::Literal(_, Literal::Integer(_)) | &Term::Literal(_, Literal::Fixnum(_)) => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_integer!(r));
code.push(instr!("integer", r, 0));
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsVar(..) => match &terms[0] {
@@ -637,15 +639,15 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
| &Term::Clause(..)
| &Term::Cons(..)
| &Term::PartialString(..) => {
code.push(fail!());
code.push(instr!("$fail", 0));
}
&Term::AnonVar => {
code.push(succeed!());
code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_var!(r));
code.push(instr!("var", r, 0));
}
},
}
@@ -678,34 +680,39 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
&Term::Var(ref vr, ref name) => {
let mut target = vec![];
self.marker
.mark_var(name.clone(), Level::Shallow, vr, term_loc, &mut target);
self.marker.mark_var::<QueryInstruction>(
name.clone(),
Level::Shallow,
vr,
term_loc,
&mut target,
);
if !target.is_empty() {
code.extend(target.into_iter().map(Line::Query));
code.extend(target.into_iter());
}
}
&Term::Literal(_, c @ Literal::Integer(_))
| &Term::Literal(_, c @ Literal::Fixnum(_)) => {
let v = HeapCellValue::from(c);
code.push(Line::Query(put_constant!(Level::Shallow, v, temp_v!(1))));
code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
self.marker.advance_arg();
}
&Term::Literal(_, c @ Literal::Float(_)) => {
let v = HeapCellValue::from(c);
code.push(Line::Query(put_constant!(Level::Shallow, v, temp_v!(1))));
code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
self.marker.advance_arg();
}
&Term::Literal(_, c @ Literal::Rational(_)) => {
let v = HeapCellValue::from(c);
code.push(Line::Query(put_constant!(Level::Shallow, v, temp_v!(1))));
code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
self.marker.advance_arg();
}
_ => {
code.push(fail!());
code.push(instr!("$fail", 0));
return Ok(());
}
}
@@ -717,9 +724,9 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
};
Ok(if use_default_call_policy {
code.push(is_call_by_default!(temp_v!(1), at));
code.push(instr!("is", default, temp_v!(1), at, 0));
} else {
code.push(is_call!(temp_v!(1), at));
code.push(instr!("is", temp_v!(1), at, 0));
})
}
@@ -727,7 +734,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &'a Cell<VarReg>) {
let r = self.marker.get(Rc::new(String::from("!")));
cell.set(VarReg::Norm(r));
code.push(set_cp!(cell.get().norm()));
code.push(instr!("$set_cp", cell.get().norm(), 0));
}
fn compile_get_level_and_unify(
@@ -737,21 +744,16 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
var: Rc<String>,
term_loc: GenContext,
) {
let mut target = Vec::new();
let mut target = Code::new();
self.marker.reset_arg(1);
self.marker
.mark_var(var, Level::Shallow, cell, term_loc, &mut target);
self.marker.mark_var::<QueryInstruction>(var, Level::Shallow, cell, term_loc, &mut target);
if !target.is_empty() {
code.extend(
target
.into_iter()
.map(|query_instr| Line::Query(query_instr)),
);
code.extend(target.into_iter());
}
code.push(get_level_and_unify!(cell.get().norm()));
code.push(instr!("get_level_and_unify", cell.get().norm()));
}
fn compile_seq(
@@ -775,9 +777,9 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
}
&QueryTerm::UnblockedCut(ref cell) => self.compile_unblocked_cut(code, cell),
&QueryTerm::BlockedCut => code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut)
Instruction::NeckCut
} else {
Line::Cut(CutInstruction::Cut(perm_v!(1)))
Instruction::Cut(perm_v!(1))
}),
&QueryTerm::Clause(
_,
@@ -810,10 +812,10 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
if conjunct_info.allocates() {
let perm_vars = conjunct_info.perm_vars();
body.push(Line::Control(ControlInstruction::Allocate(perm_vars)));
body.push(Instruction::Allocate(perm_vars));
if conjunct_info.has_deep_cut {
body.push(Line::Cut(CutInstruction::GetLevel(perm_v!(1))));
body.push(Instruction::GetLevel(perm_v!(1)));
}
}
}
@@ -826,8 +828,9 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
) {
// add a proceed to bookend any trailing cuts.
match toc {
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => code.push(proceed!()),
&QueryTerm::Clause(_, ClauseType::Inlined(..), ..) => code.push(proceed!()),
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => {
code.push(instr!("proceed"));
}
_ => {}
};
@@ -843,7 +846,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
}
}
code.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate));
code.insert(dealloc_index, instr!("deallocate"));
}
}
@@ -865,16 +868,13 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
self.compile_seq_prelude(&conjunct_info, &mut code);
let iter = FactIterator::from_rule_head_clause(args);
let mut fact = self.compile_target(iter, GenContext::Head, false);
let mut fact = self.compile_target::<FactInstruction, _>(iter, GenContext::Head, false);
let mut unsafe_var_marker = UnsafeVarMarker::new();
if !fact.is_empty() {
unsafe_var_marker = self.mark_unsafe_fact_vars(&mut fact);
for fact_instr in fact {
code.push(Line::Fact(fact_instr));
}
code.extend(fact.into_iter());
}
let iter = ChunkedIterator::from_rule_body(p1, clauses);
@@ -886,18 +886,18 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
Ok(code)
}
fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact) -> UnsafeVarMarker {
fn mark_unsafe_fact_vars(&self, fact: &mut Code) -> UnsafeVarMarker {
let mut safe_vars = IndexSet::new();
for fact_instr in fact.iter_mut() {
match fact_instr {
&mut FactInstruction::UnifyValue(r) => {
&mut Instruction::UnifyValue(r) => {
if !safe_vars.contains(&r) {
*fact_instr = FactInstruction::UnifyLocalValue(r);
*fact_instr = Instruction::UnifyLocalValue(r);
safe_vars.insert(r);
}
}
&mut FactInstruction::UnifyVariable(r) => {
&mut Instruction::UnifyVariable(r) => {
safe_vars.insert(r);
}
_ => {}
@@ -923,18 +923,20 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
self.marker.reset_at_head(args);
let iter = FactInstruction::iter(term);
let mut compiled_fact = self.compile_target(iter, GenContext::Head, false);
let mut compiled_fact = self.compile_target::<FactInstruction, _>(
iter,
GenContext::Head,
false,
);
self.mark_unsafe_fact_vars(&mut compiled_fact);
if !compiled_fact.is_empty() {
for fact_instr in compiled_fact {
code.push(Line::Fact(fact_instr));
}
code.extend(compiled_fact.into_iter());
}
}
code.push(proceed!());
code.push(instr!("proceed"));
code
}
@@ -949,12 +951,10 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
self.marker.reset_arg(term.arity());
let iter = query_term_post_order_iter(term);
let query = self.compile_target(iter, term_loc, is_exposed);
let query = self.compile_target::<QueryInstruction, _>(iter, term_loc, is_exposed);
if !query.is_empty() {
for query_instr in query {
code.push(Line::Query(query_instr));
}
code.extend(query.into_iter());
}
self.add_conditional_call(code, term, num_perm_vars_left);
@@ -1061,12 +1061,12 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
if clauses.len() > 1 {
let choice = match i {
0 => self.settings.internal_try_me_else(clause_code.len() + 1),
//ChoiceInstruction::TryMeElse(clause_code.len() + 1),
//Instruction::TryMeElse(clause_code.len() + 1),
_ if i == clauses.len() - 1 => self.settings.internal_trust_me(),
_ => self.settings.internal_retry_me_else(clause_code.len() + 1),
};
code.push_back(Line::Choice(choice));
code.push_back(choice);
} else if self.settings.is_extensible {
/*
generate stub choice instructions for extensible
@@ -1079,9 +1079,8 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
over them.
*/
code.push_front(Line::Choice(self.settings.internal_try_me_else(0)));
//Line::Choice(ChoiceInstruction::TryMeElse(0)));
skip_stub_try_me_else = !self.settings.is_dynamic(); //true;
code.push_front(self.settings.internal_try_me_else(0));
skip_stub_try_me_else = !self.settings.is_dynamic();
}
let arg = match clause.args() {
@@ -1109,7 +1108,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
self.global_jmp_by_locs_offset = jmp_by_locs_len;
if !index_code.is_empty() {
code.push_front(Line::IndexingCode(index_code));
code.push_front(Instruction::IndexingCode(index_code));
if skip_stub_try_me_else {
// skip the TryMeElse(0) also.
@@ -1160,13 +1159,13 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
_ => self.settings.retry_me_else(code_segment.len() + 1),
};
code.push(Line::Choice(choice));
code.push(choice);
} else if self.settings.is_extensible {
code.push(Line::Choice(self.settings.try_me_else(0)));
code.push(self.settings.try_me_else(0));
}
if self.settings.is_extensible {
let segment_is_indexed = to_indexing_line(&code_segment[0]).is_some();
let segment_is_indexed = code_segment[0].to_indexing_line().is_some();
for clause_index_info in self.skeleton.clauses[skel_lower_bound..].iter_mut() {
clause_index_info.clause_start +=