use crate::forms::*;
use crate::instructions::*;
use crate::machine::machine_indices::*;
+use crate::targets::*;
use std::cell::Cell;
use std::rc::Rc;
-pub(crate) trait Allocator<'a> {
+pub(crate) trait Allocator {
fn new() -> Self;
- fn mark_anon_var<Target>(&mut self, _: Level, _: GenContext, _: &mut Code)
- where
- Target: crate::targets::CompilationTarget<'a>;
- fn mark_non_var<Target>(
+ fn mark_anon_var<'a, Target: CompilationTarget<'a>>(
&mut self,
- _: Level,
- _: GenContext,
- _: &'a Cell<RegType>,
- _: &mut Code,
- ) where
- Target: crate::targets::CompilationTarget<'a>;
- fn mark_reserved_var<Target>(
+ lvl: Level,
+ context: GenContext,
+ code: &mut Code,
+ );
+
+ fn mark_non_var<'a, Target: CompilationTarget<'a>>(
+ &mut self,
+ lvl: Level,
+ context: GenContext,
+ cell: &'a Cell<RegType>,
+ code: &mut Code,
+ );
+
+ fn mark_reserved_var<'a, Target: CompilationTarget<'a>>(
&mut self,
- _: Rc<String>,
- _: Level,
- _: &'a Cell<VarReg>,
- _: GenContext,
- _: &mut Code,
- _: RegType,
- _: bool,
- ) where
- Target: crate::targets::CompilationTarget<'a>;
- fn mark_var<Target>(
+ var_name: Rc<String>,
+ lvl: Level,
+ cell: &'a Cell<VarReg>,
+ term_loc: GenContext,
+ code: &mut Code,
+ r: RegType,
+ is_new_var: bool,
+ );
+
+ fn mark_var<'a, Target: CompilationTarget<'a>>(
&mut self,
- _: Rc<String>,
- _: Level,
- _: &'a Cell<VarReg>,
- _: GenContext,
- _: &mut Code,
- ) where
- Target: crate::targets::CompilationTarget<'a>;
+ var_name: Rc<String>,
+ lvl: Level,
+ cell: &'a Cell<VarReg>,
+ context: GenContext,
+ code: &mut Code,
+ );
fn reset(&mut self);
fn reset_contents(&mut self) {}
- fn reset_arg(&mut self, _: usize);
+ fn reset_arg(&mut self, arg_num: usize);
fn reset_at_head(&mut self, args: &Vec<Term>);
fn advance_arg(&mut self);
fn take_bindings(self) -> AllocVarDict;
- fn drain_var_data(
+ fn drain_var_data<'a>(
&mut self,
vs: VariableFixtures<'a>,
num_of_chunks: usize,
+use crate::allocator::*;
use crate::arena::*;
use crate::atom_table::*;
use crate::fixtures::*;
pub(crate) enum ArithTermRef<'a> {
Literal(&'a Literal),
Op(Atom, usize), // name, arity.
- Var(&'a Cell<VarReg>, Rc<String>),
+ Var(Level, &'a Cell<VarReg>, Rc<String>),
}
impl<'a> Iterator for ArithInstructionIterator<'a> {
}
}
TermIterState::Literal(_, _, c) => return Some(Ok(ArithTermRef::Literal(c))),
- TermIterState::Var(_, cell, var) => {
- return Some(Ok(ArithTermRef::Var(cell, var.clone())));
+ TermIterState::Var(lvl, cell, var) => {
+ // the expression is the second argument of an
+ // is/2 but the iterator can't see that, so the
+ // level needs to be demoted manually.
+ return Some(Ok(ArithTermRef::Var(lvl.child_level(), cell, var.clone())));
}
_ => {
return Some(Err(ArithmeticError::NonEvaluableFunctor(
}
#[derive(Debug)]
-pub(crate) struct ArithmeticEvaluator<'a> {
- bindings: &'a AllocVarDict,
+pub(crate) struct ArithmeticEvaluator<'a, TermMarker> {
+ marker: &'a mut TermMarker,
interm: Vec<ArithmeticTerm>,
interm_c: usize,
}
Ok(())
}
-impl<'a> ArithmeticEvaluator<'a> {
- pub(crate) fn new(bindings: &'a AllocVarDict, target_int: usize) -> Self {
+impl<'a, TermMarker: Allocator> ArithmeticEvaluator<'a, TermMarker> {
+ pub(crate) fn new(marker: &'a mut TermMarker, target_int: usize) -> Self {
ArithmeticEvaluator {
- bindings,
+ marker,
interm: Vec::new(),
interm_c: target_int,
}
}
}
- pub(crate) fn eval(&mut self, src: &'a Term) -> Result<ArithCont, ArithmeticError> {
+ pub(crate) fn eval(
+ &mut self,
+ src: &'a Term,
+ term_loc: GenContext,
+ ) -> Result<ArithCont, ArithmeticError>
+ {
let mut code = vec![];
let mut iter = src.iter()?;
while let Some(term_ref) = iter.next() {
match term_ref? {
ArithTermRef::Literal(c) => push_literal(&mut self.interm, c)?,
- ArithTermRef::Var(cell, name) => {
+ ArithTermRef::Var(lvl, cell, name) => {
let r = if cell.get().norm().reg_num() == 0 {
- match self.bindings.get(&name) {
- Some(&VarData::Temp(_, t, _)) if t != 0 => RegType::Temp(t),
- Some(&VarData::Perm(p)) if p != 0 => RegType::Perm(p),
- _ => return Err(ArithmeticError::UninstantiatedVar),
- }
+ let mut getter = || {
+ use crate::targets::QueryInstruction;
+
+ loop {
+ match self.marker.bindings().get(&name) {
+ Some(&VarData::Temp(_, t, _)) if t != 0 =>
+ return RegType::Temp(t),
+ Some(&VarData::Perm(p)) if p != 0 =>
+ return RegType::Perm(p),
+ _ => {
+ self.marker.mark_var::<QueryInstruction>(
+ name.clone(),
+ lvl,
+ cell,
+ term_loc,
+ &mut code,
+ );
+ }
+ }
+ }
+ };
+
+ getter()
+ /*
+ _ => return Err(ArithmeticError::UninstantiatedVar),
+ */
} else {
cell.get().norm()
};
global_jmp_by_locs_offset: usize,
}
-impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
+impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> {
pub(crate) fn new(atom_tbl: &'b mut AtomTable, settings: CodeGenSettings) -> Self {
CodeGenerator {
atom_tbl,
}
}
- fn update_var_count<Iter: Iterator<Item = TermRef<'a>>>(&mut self, iter: Iter) {
+ fn update_var_count<'a, Iter: Iterator<Item = TermRef<'a>>>(&mut self, iter: Iter) {
for term in iter {
if let TermRef::Var(_, _, var) = term {
let entry = self.var_count.entry(var).or_insert(0);
}
}
- fn get_var_count(&self, var: &'a String) -> usize {
+ fn get_var_count(&self, var: &String) -> usize {
*self.var_count.get(var).unwrap()
}
&mut self,
name: Rc<String>,
term_loc: GenContext,
- vr: &'a Cell<VarReg>,
+ vr: &Cell<VarReg>,
code: &mut Code,
) -> RegType {
let mut target = Code::new();
name: Rc<String>,
arg: usize,
term_loc: GenContext,
- vr: &'a Cell<VarReg>,
+ vr: &Cell<VarReg>,
code: &mut Code,
) -> RegType {
match self.marker.bindings().get(&name) {
}
}
- fn add_or_increment_void_instr<Target>(target: &mut Code)
+ fn add_or_increment_void_instr<'a, Target>(target: &mut Code)
where
Target: crate::targets::CompilationTarget<'a>,
{
target.push(Target::to_void(1));
}
- fn deep_var_instr<Target: crate::targets::CompilationTarget<'a>>(
+ fn deep_var_instr<'a, Target: crate::targets::CompilationTarget<'a>>(
&mut self,
cell: &'a Cell<VarReg>,
- var: &'a Rc<String>,
+ var: &Rc<String>,
term_loc: GenContext,
is_exposed: bool,
target: &mut Code,
}
}
- fn subterm_to_instr<Target: crate::targets::CompilationTarget<'a>>(
+ fn subterm_to_instr<'a, Target: crate::targets::CompilationTarget<'a>>(
&mut self,
subterm: &'a Term,
term_loc: GenContext,
};
}
- fn compile_target<Target, Iter>(
+ fn compile_target<'a, Target, Iter>(
&mut self,
iter: Iter,
term_loc: GenContext,
target
}
- fn collect_var_data(&mut self, mut iter: ChunkedIterator<'a>) -> ConjunctInfo<'a> {
+ fn collect_var_data<'a>(&mut self, mut iter: ChunkedIterator<'a>) -> ConjunctInfo<'a> {
let mut vs = VariableFixtures::new();
while let Some((chunk_num, lt_arity, chunked_terms)) = iter.next() {
dealloc_index
}
- fn compile_inlined(
+ fn compile_inlined<'a>(
&mut self,
ct: &InlinedClauseType,
terms: &'a Vec<Term>,
&InlinedClauseType::CompareNumber(mut cmp) => {
self.marker.reset_arg(2);
- let (mut lcode, at_1) = self.call_arith_eval(&terms[0], 1)?;
- let (mut rcode, at_2) = self.call_arith_eval(&terms[1], 2)?;
+ let (mut lcode, at_1) = self.compile_arith_expr(&terms[0], 1, term_loc)?;
+ let (mut rcode, at_2) = self.compile_arith_expr(&terms[1], 2, term_loc)?;
let at_1 = if let &Term::Var(ref vr, ref name) = &terms[0] {
ArithmeticTerm::Reg(self.mark_non_callable(name.clone(), 1, term_loc, vr, code))
Ok(())
}
- fn call_arith_eval(
+ fn compile_arith_expr(
&mut self,
- term: &'a Term,
+ term: &Term,
target_int: usize,
+ term_loc: GenContext,
) -> Result<ArithCont, ArithmeticError> {
- let mut evaluator = ArithmeticEvaluator::new(&self.marker.bindings(), target_int);
- evaluator.eval(term)
+ let mut evaluator = ArithmeticEvaluator::new(&mut self.marker, target_int);
+ evaluator.eval(term, term_loc)
}
fn compile_is_call(
&mut self,
- terms: &'a Vec<Term>,
+ terms: &Vec<Term>,
code: &mut Code,
term_loc: GenContext,
use_default_call_policy: bool,
) -> Result<(), CompilationError> {
- let (mut acode, at) = self.call_arith_eval(&terms[1], 1)?;
- code.append(&mut acode);
+ macro_rules! compile_expr {
+ ($self:expr, $terms:expr, $term_loc:expr, $code:expr) => ({
+ let (acode, at) = $self.compile_arith_expr(&$terms[1], 1, $term_loc)?;
+ $code.extend(acode.into_iter());
+ at
+ });
+ }
self.marker.reset_arg(2);
- match &terms[0] {
+ let at = match &terms[0] {
&Term::Var(ref vr, ref name) => {
- let mut target = vec![];
-
self.marker.mark_var::<QueryInstruction>(
name.clone(),
Level::Shallow,
vr,
term_loc,
- &mut target,
+ code,
);
- if !target.is_empty() {
- code.extend(target.into_iter());
- }
- }
- &Term::Literal(_, c @ Literal::Integer(_))
- | &Term::Literal(_, c @ Literal::Fixnum(_)) => {
- let v = HeapCellValue::from(c);
- 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(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
-
- self.marker.advance_arg();
+ compile_expr!(self, terms, term_loc, code)
}
- &Term::Literal(_, c @ Literal::Rational(_)) => {
+ &Term::Literal(_, c @ Literal::Integer(_) |
+ c @ Literal::Float(_) |
+ c @ Literal::Rational(_) |
+ c @ Literal::Fixnum(_)) => {
let v = HeapCellValue::from(c);
code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
self.marker.advance_arg();
+ compile_expr!(self, terms, term_loc, code)
}
_ => {
code.push(instr!("$fail", 0));
return Ok(());
}
- }
-
- let at = if let &Term::Var(ref vr, ref name) = &terms[1] {
- ArithmeticTerm::Reg(self.mark_non_callable(name.clone(), 2, term_loc, vr, code))
- } else {
- at.unwrap_or(interm!(1))
};
+ let at = at.unwrap_or(interm!(1));
+
Ok(if use_default_call_policy {
code.push(instr!("is", default, temp_v!(1), at, 0));
} else {
}
#[inline]
- fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &'a Cell<VarReg>) {
+ fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &Cell<VarReg>) {
let r = self.marker.get(Rc::new(String::from("!")));
cell.set(VarReg::Norm(r));
code.push(instr!("$set_cp", cell.get().norm(), 0));
fn compile_get_level_and_unify(
&mut self,
code: &mut Code,
- cell: &'a Cell<VarReg>,
+ cell: &Cell<VarReg>,
var: Rc<String>,
term_loc: GenContext,
) {
code.push(instr!("get_level_and_unify", cell.get().norm()));
}
- fn compile_seq(
+ fn compile_seq<'a>(
&mut self,
iter: ChunkedIterator<'a>,
conjunct_info: &ConjunctInfo<'a>,
}
}
- fn compile_cleanup(
+ fn compile_cleanup<'a>(
&mut self,
code: &mut Code,
- conjunct_info: &ConjunctInfo,
+ conjunct_info: &ConjunctInfo<'a>,
toc: &'a QueryTerm,
) {
// add a proceed to bookend any trailing cuts.
}
}
- pub(crate) fn compile_rule<'c: 'a>(
- &mut self,
- rule: &'c Rule,
- ) -> Result<Code, CompilationError> {
+ pub(crate) fn compile_rule(&mut self, rule: &Rule) -> Result<Code, CompilationError> {
let iter = ChunkedIterator::from_rule(rule);
let conjunct_info = self.collect_var_data(iter);
UnsafeVarMarker::from_safe_vars(safe_vars)
}
- pub(crate) fn compile_fact<'c: 'a>(&mut self, term: &'c Term) -> Code {
+ pub(crate) fn compile_fact(&mut self, term: &Term) -> Code {
self.update_var_count(post_order_iter(term));
let mut vs = VariableFixtures::new();
fn compile_query_line(
&mut self,
- term: &'a QueryTerm,
+ term: &QueryTerm,
term_loc: GenContext,
code: &mut Code,
num_perm_vars_left: usize,
subseqs
}
- fn compile_pred_subseq<'c: 'a, I: Indexer>(
+ fn compile_pred_subseq<I: Indexer>(
&mut self,
- clauses: &'c [PredicateClause],
+ clauses: &[PredicateClause],
optimal_index: usize,
) -> Result<Code, CompilationError> {
let mut code = VecDeque::new();
Ok(Vec::from(code))
}
- pub(crate) fn compile_predicate<'c: 'a>(
+ pub(crate) fn compile_predicate(
&mut self,
- clauses: &'c Vec<PredicateClause>,
+ clauses: &Vec<PredicateClause>,
) -> Result<Code, CompilationError> {
let mut code = Code::new();
- /*
- let optimal_index = match Self::first_instantiated_index(&clauses) {
- Some(index) => index,
- None => 0, // Default to first argument indexing.
- };
- */
-
let split_pred = Self::split_predicate(&clauses);
let multi_seq = split_pred.len() > 1;
}
}
- fn evacuate_arg<'a, Target>(&mut self, chunk_num: usize, target: &mut Vec<Instruction>)
- where
- Target: CompilationTarget<'a>,
- {
+ fn evacuate_arg<'a, Target: CompilationTarget<'a>>(
+ &mut self,
+ chunk_num: usize,
+ code: &mut Code,
+ ) {
match self.alloc_in_last_goal_hint(chunk_num) {
Some((var, r)) => {
let k = self.arg_c;
if r != k {
let r = RegType::Temp(r);
- target.push(Target::move_to_register(r, k));
+ code.push(Target::move_to_register(r, k));
self.contents.swap_remove(&k);
self.contents.insert(r.reg_num(), var.clone());
}
}
-impl<'a> Allocator<'a> for DebrayAllocator {
+impl Allocator for DebrayAllocator {
fn new() -> DebrayAllocator {
DebrayAllocator {
arity: 0,
}
}
- fn mark_anon_var<Target>(
+ fn mark_anon_var<'a, Target: CompilationTarget<'a>>(
&mut self,
lvl: Level,
term_loc: GenContext,
- target: &mut Vec<Instruction>,
- )
- where
- Target: CompilationTarget<'a>,
- {
+ code: &mut Code,
+ ) {
let r = RegType::Temp(self.alloc_reg_to_non_var());
match lvl {
- Level::Deep => target.push(Target::subterm_to_variable(r)),
+ Level::Deep => code.push(Target::subterm_to_variable(r)),
Level::Root | Level::Shallow => {
let k = self.arg_c;
if let GenContext::Last(chunk_num) = term_loc {
- self.evacuate_arg::<Target>(chunk_num, target);
+ self.evacuate_arg::<Target>(chunk_num, code);
}
self.arg_c += 1;
- target.push(Target::argument_to_variable(r, k));
+ code.push(Target::argument_to_variable(r, k));
}
};
}
- fn mark_non_var<Target>(
+ fn mark_non_var<'a, Target: CompilationTarget<'a>>(
&mut self,
lvl: Level,
term_loc: GenContext,
- cell: &Cell<RegType>,
- target: &mut Vec<Instruction>,
- ) where
- Target: CompilationTarget<'a>,
- {
+ cell: &'a Cell<RegType>,
+ code: &mut Code,
+ ) {
let r = cell.get();
let r = match lvl {
let k = self.arg_c;
if let GenContext::Last(chunk_num) = term_loc {
- self.evacuate_arg::<Target>(chunk_num, target);
+ self.evacuate_arg::<Target>(chunk_num, code);
}
self.arg_c += 1;
cell.set(r);
}
- fn mark_var<Target: CompilationTarget<'a>>(
+ fn mark_var<'a, Target: CompilationTarget<'a>>(
&mut self,
var: Rc<String>,
lvl: Level,
cell: &'a Cell<VarReg>,
term_loc: GenContext,
- target: &mut Vec<Instruction>,
+ code: &mut Code,
) {
let (r, is_new_var) = match self.get(var.clone()) {
RegType::Temp(0) => {
// here, r is temporary *and* unassigned.
- let o = self.alloc_reg_to_var::<Target>(&var, lvl, term_loc, target);
+ let o = self.alloc_reg_to_var::<Target>(&var, lvl, term_loc, code);
cell.set(VarReg::Norm(RegType::Temp(o)));
(RegType::Temp(o), true)
r => (r, false),
};
- self.mark_reserved_var::<Target>(var, lvl, cell, term_loc, target, r, is_new_var);
+ self.mark_reserved_var::<Target>(var, lvl, cell, term_loc, code, r, is_new_var);
}
- fn mark_reserved_var<Target: CompilationTarget<'a>>(
+ fn mark_reserved_var<'a, Target: CompilationTarget<'a>>(
&mut self,
var: Rc<String>,
lvl: Level,
cell: &'a Cell<VarReg>,
term_loc: GenContext,
- target: &mut Vec<Instruction>,
+ code: &mut Code,
r: RegType,
is_new_var: bool,
) {
let k = self.arg_c;
if self.is_curr_arg_distinct_from(&var) {
- self.evacuate_arg::<Target>(term_loc.chunk_num(), target);
+ self.evacuate_arg::<Target>(term_loc.chunk_num(), code);
}
self.arg_c += 1;
if !self.in_place(&var, term_loc, r, k) {
if is_new_var {
- target.push(Target::argument_to_variable(r, k));
+ code.push(Target::argument_to_variable(r, k));
} else {
- target.push(Target::argument_to_value(r, k));
+ code.push(Target::argument_to_value(r, k));
}
}
}
Level::Deep if is_new_var => {
if let GenContext::Head = term_loc {
if self.occurs_shallowly_in_head(&var, r.reg_num()) {
- target.push(Target::subterm_to_value(r));
+ code.push(Target::subterm_to_value(r));
} else {
- target.push(Target::subterm_to_variable(r));
+ code.push(Target::subterm_to_variable(r));
}
} else {
- target.push(Target::subterm_to_variable(r));
+ code.push(Target::subterm_to_variable(r));
}
}
- Level::Deep => target.push(Target::subterm_to_value(r)),
+ Level::Deep => code.push(Target::subterm_to_value(r)),
};
if !r.is_perm() {
staggered_sc(_, G) :- call('$call'(G)).
-! :- !.
+!.
:- non_counted_backtracking set_cp/1.