implement new disjunction compilation

This commit is contained in:
Mark
2023-06-17 16:28:56 -06:00
parent b205abe949
commit 0e583d620a
32 changed files with 2877 additions and 2980 deletions

View File

@@ -23,13 +23,9 @@ fn capture_offset(line: &Instruction, index: usize, stack: &mut Vec<usize>) -> b
{
stack.push(index + offset);
}
&Instruction::JmpByCall(_, offset, _) => {
&Instruction::JmpByCall(offset) => {
stack.push(index + offset);
}
&Instruction::JmpByExecute(_, offset, _) => {
stack.push(index + offset);
return true;
}
&Instruction::Proceed => {
return true;
}

View File

@@ -44,62 +44,6 @@ pub(super) fn bootstrapping_compile(
Ok(())
}
// throw errors if declaration or query found.
pub(super) fn compile_relation(
cg: &mut CodeGenerator,
tl: &TopLevel,
) -> Result<Code, CompilationError> {
match tl {
&TopLevel::Query(_) => Err(CompilationError::ExpectedRel),
&TopLevel::Predicate(ref clauses) => cg.compile_predicate(&clauses),
&TopLevel::Fact(ref fact, ..) => cg.compile_fact(fact),
&TopLevel::Rule(ref rule, ..) => cg.compile_rule(rule),
}
}
/*
pub(super) fn compile_appendix(
code: &mut Code,
mut queue: VecDeque<TopLevel>,
jmp_by_locs: Vec<usize>,
non_counted_bt: bool,
atom_tbl: &mut AtomTable,
) -> Result<(), CompilationError> {
let mut jmp_by_locs = VecDeque::from(jmp_by_locs);
while let Some(jmp_by_offset) = jmp_by_locs.pop_front() {
let code_len = code.len();
match &mut code[jmp_by_offset] {
&mut Instruction::JmpByCall(_, ref mut offset, ..) |
&mut Instruction::JmpByExecute(_, ref mut offset, ..) => {
*offset = code_len - jmp_by_offset;
}
_ => {
unreachable!()
}
}
// false because the inner predicate is a one-off, hence not extensible.
let settings = CodeGenSettings {
global_clock_tick: None,
is_extensible: false,
non_counted_bt,
};
let mut cg = CodeGenerator::new(atom_tbl, settings);
let tl = queue.pop_front().unwrap();
let decl_code = compile_relation(&mut cg, &tl)?;
jmp_by_locs.extend(cg.jmp_by_locs.into_iter().map(|offset| offset + code.len()));
code.extend(decl_code.into_iter());
}
Ok(())
}
*/
fn lower_bound_of_target_clause(skeleton: &PredicateSkeleton, target_pos: usize) -> usize {
if target_pos == 0 {
return 0;
@@ -1351,17 +1295,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
settings,
);
let mut clause_code = cg.compile_predicate(&vec![clause])?;
/*
compile_appendix(
&mut clause_code,
queue,
cg.jmp_by_locs,
settings.non_counted_bt,
cg.atom_tbl,
)?;
*/
let clause_code = cg.compile_predicate(vec![clause])?;
Ok(StandaloneCompileResult {
clause_code,
@@ -1389,24 +1323,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
clauses.push(self.try_term_to_tl(term, &mut preprocessor)?);
}
// let queue = preprocessor.parse_queue(self)?;
let mut cg = CodeGenerator::new(
&mut LS::machine_st(&mut self.payload).atom_tbl,
settings,
);
let mut code = cg.compile_predicate(&clauses)?;
/*
compile_appendix(
&mut code,
queue,
cg.jmp_by_locs,
settings.non_counted_bt,
cg.atom_tbl,
)?;
*/
let mut code = cg.compile_predicate(clauses)?;
if settings.is_extensible {
let mut clause_clause_locs = VecDeque::new();

View File

@@ -1,4 +1,3 @@
/*
================================================================================
@@ -9,7 +8,6 @@ paper "Compiling Large Disjunctions" to Scryer Prolog.
*/
use crate::atom_table::*;
use crate::fixtures::VariableFixtures;
use crate::forms::*;
use crate::instructions::*;
use crate::iterators::*;
@@ -18,16 +16,18 @@ use crate::machine::machine_errors::CompilationError;
use crate::machine::preprocessor::*;
use crate::parser::ast::*;
use crate::parser::rug::Rational;
use crate::variable_records::*;
use indexmap::{IndexMap, IndexSet};
use std::cell::Cell;
use std::cmp::Ordering;
use std::collections::VecDeque;
use std::hash::{Hash, Hasher};
use std::ops::{Deref, DerefMut};
#[derive(Debug, Clone)]
struct BranchNumber {
#[derive(Debug, Clone)] //, PartialOrd, PartialEq, Eq, Hash)]
pub struct BranchNumber {
branch_num: Rational,
delta: Rational,
}
@@ -35,7 +35,7 @@ struct BranchNumber {
impl Default for BranchNumber {
fn default() -> Self {
Self {
branch_num: Rational::from(1 << 63),
branch_num: Rational::from(1usize << 63),
delta: Rational::from(1),
}
}
@@ -87,9 +87,10 @@ impl BranchNumber {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct VarInfo {
var_ptr: VarPtr,
chunk_type: ChunkType,
classify_info: ClassifyInfo,
lvl: Level,
}
@@ -102,6 +103,11 @@ pub struct ChunkInfo {
vars: Vec<VarInfo>,
}
#[derive(Debug)]
pub struct BranchArm {
pub arm_terms: Vec<QueryTerm>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct BranchInfo {
branch_num: BranchNumber,
@@ -114,7 +120,7 @@ impl BranchInfo {
}
}
type BranchMapInt = IndexMap<Var, Vec<BranchInfo>>;
type BranchMapInt = IndexMap<VarPtr, Vec<BranchInfo>>;
#[derive(Debug, Clone)]
pub struct BranchMap(BranchMapInt);
@@ -145,82 +151,77 @@ pub struct ClassifyInfo {
enum TraversalState {
// construct a QueryTerm::Branch with number of disjuncts, reset
// the chunk type to that of the chunk preceding the disjunct.
BuildDisjunct(ChunkType, usize),
// the chunk type to that of the chunk preceding the disjunct and the chunk_num.
BuildDisjunct(usize),
// add the last disjunct to a QueryTerm::Branch, continuing from
// where it leaves off.
BuildFinalDisjunct(usize),
Fail,
GetCutPoint(usize),
LocalCut(usize),
GetCutPoint{ var_num: usize, prev_b: bool },
Cut { var_num: usize, is_global: bool },
ResetCallPolicy(CallPolicy),
Term(Term),
AddBranchNum(BranchNumber), // set current_branch_number, add it to the root set
RemoveBranchNum, // remove latest branch number from the root set
RepBranchNum(BranchNumber), // replace current_branch_number and the latest in the root set
IncrChunkNum, // increment self.current_chunk_number
SetLastChunkType, // consider remaining terms as belonging to a last chunk
}
impl Term {
#[inline]
fn is_var(&self) -> bool {
if let Term::Var(..) = self {
true
} else {
false
}
}
#[inline]
fn is_compound(&self) -> bool {
match self {
Term::Clause(..) | Term::Cons(..) => true,
_ => false,
}
}
RemoveBranchNum, // pop the current_branch_num and from the root set.
AddBranchNum(BranchNumber), // set current_branch_num, add it to the root set
RepBranchNum(BranchNumber), // replace current_branch_num and the latest in the root set
// SetChunkType(ChunkType), // consider remaining terms as belonging to a last chunk
}
#[derive(Debug)]
pub struct VariableClassifier {
call_policy: CallPolicy,
current_branch_num: BranchNumber,
current_chunk_num: usize,
current_chunk_type: ChunkType,
branch_map: BranchMap,
var_num: usize,
root_set: RootSet,
global_cut_var_num: Option<usize>,
}
#[derive(Debug)]
pub enum VarClassification {
Void,
Temp,
Perm,
#[derive(Debug, Default)]
pub struct VarData {
pub records: VariableRecords,
pub global_cut_var_num: Option<usize>,
pub allocates: bool,
}
#[derive(Clone, Debug)]
pub struct VarRecord {
pub classification: VarClassification,
pub chunk_occurrences: Vec<usize>,
pub num_occurrences: usize,
}
impl VarData {
fn emit_initial_get_level(&mut self, build_stack: &mut ChunkedTermVec) {
let global_cut_var_num =
if let &Some(global_cut_var_num) = &self.global_cut_var_num {
match &self.records[global_cut_var_num].allocation {
VarAlloc::Perm(..) => Some(global_cut_var_num),
VarAlloc::Temp { term_loc, .. } if term_loc.chunk_num() > 0 => {
Some(global_cut_var_num)
}
_ => None
}
} else {
None
};
impl Default for VarRecord {
fn default() -> Self {
VarRecord {
classification: VarClassification::Void,
chunk_occurrences: vec![],
num_occurrences: 0,
if let Some(global_cut_var_num) = global_cut_var_num {
let term = QueryTerm::GetLevel(global_cut_var_num);
self.records[global_cut_var_num].allocation = VarAlloc::Perm(0, PermVarAllocation::Pending);
match build_stack.front_mut() {
Some(ChunkedTerms::Branch(_)) => {
build_stack.push_front(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
}
Some(ChunkedTerms::Chunk(chunk)) => {
chunk.push_front(term);
}
None => {
unreachable!()
}
}
}
}
}
pub struct VarData {
pub records: Vec<VarRecord>,
pub fixtures: VariableFixtures,
}
pub type ClassifyFactResult = (Term, VarData);
pub type ClassifyRuleResult = (Term, Vec<QueryTerm>, VarData);
pub type ClassifyRuleResult = (Term, ChunkedTermVec, VarData);
fn merge_branch_seq<Iter: Iterator<Item = BranchInfo>>(branches: Iter) -> BranchInfo {
let mut branch_info = BranchInfo::new(BranchNumber::default());
@@ -228,6 +229,7 @@ fn merge_branch_seq<Iter: Iterator<Item = BranchInfo>>(branches: Iter) -> Branch
for mut branch in branches {
branch_info.branch_num = branch.branch_num;
/*
if let Some(last_chunk) = branch_info.chunks.last_mut() {
if let Some(first_moved_chunk) = branch.chunks.first_mut() {
if last_chunk.chunk_num == first_moved_chunk.chunk_num {
@@ -238,6 +240,7 @@ fn merge_branch_seq<Iter: Iterator<Item = BranchInfo>>(branches: Iter) -> Branch
}
}
}
*/
branch_info.chunks.extend(branch.chunks.drain(..));
}
@@ -248,82 +251,37 @@ fn merge_branch_seq<Iter: Iterator<Item = BranchInfo>>(branches: Iter) -> Branch
branch_info
}
fn flatten_into_disjunct(build_stack: &mut Vec<QueryTerm>, preceding_len: usize) {
let iter = build_stack.drain(preceding_len + 1 ..);
fn flatten_into_disjunct(build_stack: &mut ChunkedTermVec, preceding_len: usize) {
let branch_vec = build_stack.drain(preceding_len + 1 ..).collect();
if let QueryTerm::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] {
disjuncts.push(iter.collect());
if let ChunkedTerms::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] {
disjuncts.push(branch_vec);
} else {
unreachable!();
}
}
fn term_in_other_chunk(term: &Term) -> Option<bool> {
match term {
Term::Clause(_, name, terms) => Some(!ClauseType::is_inbuilt(*name, terms.len())),
Term::Literal(_, Literal::Atom(atom!("!")) | Literal::Char('!')) => Some(false),
Term::Literal(_, Literal::Atom(name)) => Some(!ClauseType::is_inbuilt(*name, 0)),
Term::Var(..) => Some(true),
_ => None,
}
}
// returns true if SetLastChunkType was pushed.
// expects that iter iterates over a conjunct of Terms in reverse order.
fn insert_set_last_chunk_type(
state_stack: &mut Vec<TraversalState>,
mut iter: impl Iterator<Item = TraversalState>,
) -> bool {
let beg = state_stack.len();
let mut will_break = false;
let mut last_chunk_delim = beg;
while let Some(traversal_st) = iter.next() {
match traversal_st {
TraversalState::Term(term) => {
will_break = false;
match term_in_other_chunk(&term) {
Some(true) if last_chunk_delim > beg => will_break = true,
Some(_) => last_chunk_delim += 1,
None => will_break = true,
}
if will_break {
// recall that iter iterates in reverse order.
// therefore this is the correct push order.
state_stack.push(TraversalState::SetLastChunkType);
state_stack.push(traversal_st);
break;
}
}
_ => {
state_stack.push(traversal_st);
}
}
}
state_stack.extend(iter);
will_break
}
impl VariableClassifier {
pub fn new(call_policy: CallPolicy) -> Self {
Self {
call_policy,
current_branch_num: BranchNumber::default(),
current_chunk_num: 0,
current_chunk_type: ChunkType::Head,
branch_map: BranchMap(BranchMapInt::new()),
root_set: RootSet::new(),
var_num: 0,
global_cut_var_num: None,
}
}
pub fn classify_fact(mut self, term: Term) -> Result<ClassifyFactResult, CompilationError> {
self.classify_head_variables(&term)?;
Ok((term, self.branch_map.separate_and_classify_variables(self.var_num)))
Ok((term, self.branch_map.separate_and_classify_variables(
self.var_num,
self.global_cut_var_num,
self.current_chunk_num,
)))
}
pub fn classify_rule<'a, LS: LoadState<'a>>(
@@ -333,9 +291,21 @@ impl VariableClassifier {
body: Term,
) -> Result<ClassifyRuleResult, CompilationError> {
self.classify_head_variables(&head)?;
let query_terms = self.classify_body_variables(loader, body)?;
self.root_set.insert(self.current_branch_num.clone());
Ok((head, query_terms, self.branch_map.separate_and_classify_variables(self.var_num)))
let mut query_terms = self.classify_body_variables(loader, body)?;
self.merge_branches();
let mut var_data = self.branch_map.separate_and_classify_variables(
self.var_num,
self.global_cut_var_num,
self.current_chunk_num,
);
var_data.emit_initial_get_level(&mut query_terms);
Ok((head, query_terms, var_data))
}
fn merge_branches(&mut self) {
@@ -359,24 +329,49 @@ impl VariableClassifier {
}
}
fn probe_body_term(&mut self, term: &Term, term_loc: GenContext) {
let mut classify_info = ClassifyInfo { arg_c: 0, arity: term.arity() };
fn try_set_chunk_at_inlined_boundary(&mut self) -> bool {
if self.current_chunk_type.is_last() {
self.current_chunk_type = ChunkType::Mid;
self.current_chunk_num += 1;
true
} else {
false
}
}
fn try_set_chunk_at_call_boundary(&mut self) -> bool {
if self.current_chunk_type.is_last() {
self.current_chunk_num += 1;
true
} else {
self.current_chunk_type = ChunkType::Last;
false
}
}
fn probe_body_term(&mut self, arg_c: usize, arity: usize, term: &Term) {
let classify_info = ClassifyInfo { arg_c, arity };
// second arg is true to iterate the root, which may be a variable
for term_ref in breadth_first_iter(term, true) {
if let TermRef::Var(lvl, _, var_name) = term_ref {
let var_info = VarInfo { var_ptr: VarPtr::from(&var_name), lvl, classify_info };
self.probe_body_var(var_name, term_loc, var_info);
}
if let Level::Shallow = term_ref.level() {
classify_info.arg_c += 1;
for term_ref in breadth_first_iter(term, RootIterationPolicy::Iterated) {
if let TermRef::Var(lvl, _, var_ptr) = term_ref {
// root terms are shallow here (since we're iterating a
// body term) so take the child level.
let lvl = lvl.child_level();
self.probe_body_var(VarInfo {
var_ptr,
lvl,
classify_info,
chunk_type: self.current_chunk_type,
});
}
}
}
fn probe_body_var(&mut self, var_name: Var, term_loc: GenContext, var_info: VarInfo) {
let branch_info_v = self.branch_map.entry(var_name)
fn probe_body_var(&mut self, var_info: VarInfo) {
let term_loc = self.current_chunk_type.to_gen_context(self.current_chunk_num);
let branch_info_v = self.branch_map.entry(var_info.var_ptr.clone())
.or_insert_with(|| vec![]);
let needs_new_branch = if let Some(last_bi) = branch_info_v.last() {
@@ -409,18 +404,17 @@ impl VariableClassifier {
chunk_info.vars.push(var_info);
}
fn probe_in_situ_var(&mut self, chunk_type: ChunkType, var_num: usize) {
let classify_info = ClassifyInfo { arg_c: 0, arity: 0 };
fn probe_in_situ_var(&mut self, var_num: usize) {
let classify_info = ClassifyInfo { arg_c: 1, arity: 1 };
let var_info = VarInfo {
var_ptr: VarPtr::InSitu(var_num),
var_ptr: VarPtr::from(Var::InSitu(var_num)),
classify_info,
chunk_type: self.current_chunk_type,
lvl: Level::Shallow,
};
let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
self.probe_body_var(Var::Generated(var_num), term_loc, var_info);
self.probe_body_var(var_info);
}
fn classify_head_variables(&mut self, term: &Term) -> Result<(), CompilationError> {
@@ -430,43 +424,55 @@ impl VariableClassifier {
_ => return Err(CompilationError::InvalidRuleHead),
}
let mut classify_info = ClassifyInfo { arg_c: 0, arity: term.arity() };
let mut classify_info = ClassifyInfo { arg_c: 1, arity: term.arity() };
// false argument to breadth_first_iter because the root is not iterable.
for term_ref in breadth_first_iter(term, false) {
if let TermRef::Var(lvl, _, var_name) = term_ref {
// the body of the if let here is an inlined
// "probe_head_var". note the difference between it
// and "probe_body_var".
let branch_info_v = self.branch_map.entry(Var::from(var_name))
.or_insert_with(|| vec![]);
match term {
Term::Clause(_, _, terms) => {
for term in terms.into_iter() {
for term_ref in breadth_first_iter(term, RootIterationPolicy::Iterated) {
if let TermRef::Var(lvl, _, var_ptr) = term_ref {
// a body term, so we need the child level here.
let lvl = lvl.child_level();
let needs_new_branch = branch_info_v.is_empty();
// the body of the if let here is an inlined
// "probe_head_var". note the difference between it
// and "probe_body_var".
let branch_info_v = self.branch_map.entry(var_ptr.clone())
.or_insert_with(|| vec![]);
if needs_new_branch {
branch_info_v.push(BranchInfo::new(self.current_branch_num.clone()));
let needs_new_branch = branch_info_v.is_empty();
if needs_new_branch {
branch_info_v.push(BranchInfo::new(self.current_branch_num.clone()));
}
let branch_info = branch_info_v.last_mut().unwrap();
let needs_new_chunk = branch_info.chunks.is_empty();
if needs_new_chunk {
branch_info.chunks.push(ChunkInfo {
chunk_num: self.current_chunk_num,
term_loc: GenContext::Head,
vars: vec![],
});
}
let chunk_info = branch_info.chunks.last_mut().unwrap();
let var_info = VarInfo {
var_ptr,
classify_info,
chunk_type: self.current_chunk_type,
lvl,
};
chunk_info.vars.push(var_info);
}
}
classify_info.arg_c += 1;
}
let branch_info = branch_info_v.last_mut().unwrap();
let needs_new_chunk = branch_info.chunks.is_empty();
if needs_new_chunk {
branch_info.chunks.push(ChunkInfo {
chunk_num: self.current_chunk_num,
term_loc: GenContext::Head,
vars: vec![]
});
}
let chunk_info = branch_info.chunks.last_mut().unwrap();
let var_info = VarInfo { var_ptr: VarPtr::from(&var_name), classify_info, lvl };
chunk_info.vars.push(var_info);
}
if let Level::Shallow = term_ref.level() {
classify_info.arg_c += 1;
}
_ => {}
}
Ok(())
@@ -476,10 +482,11 @@ impl VariableClassifier {
&mut self,
loader: &mut Loader<'a, LS>,
term: Term,
) -> Result<Vec<QueryTerm>, CompilationError> {
) -> Result<ChunkedTermVec, CompilationError> {
let mut state_stack = vec![TraversalState::Term(term)];
let mut build_stack = vec![];
let mut chunk_type = ChunkType::Head;
let mut build_stack = ChunkedTermVec::new();
self.current_chunk_type = ChunkType::Mid;
while let Some(traversal_st) = state_stack.pop() {
match traversal_st {
@@ -495,64 +502,78 @@ impl VariableClassifier {
self.root_set.insert(branch_num.clone());
self.current_branch_num = branch_num;
}
TraversalState::IncrChunkNum => {
self.current_chunk_num += 1;
chunk_type = ChunkType::Mid;
build_stack.push(QueryTerm::ChunkTypeBoundary(chunk_type));
}
TraversalState::ResetCallPolicy(call_policy) => {
self.call_policy = call_policy;
}
TraversalState::SetLastChunkType => {
chunk_type = ChunkType::Last;
build_stack.push(QueryTerm::ChunkTypeBoundary(chunk_type));
}
TraversalState::BuildDisjunct(reset_chunk_type, preceding_len) => {
chunk_type = reset_chunk_type;
build_stack.push(QueryTerm::ChunkTypeBoundary(chunk_type));
TraversalState::BuildDisjunct(preceding_len) => {
flatten_into_disjunct(&mut build_stack, preceding_len);
// self.current_chunk_type = ChunkType::Last;
self.current_chunk_type = ChunkType::Mid;
self.current_chunk_num += 1;
}
TraversalState::BuildFinalDisjunct(preceding_len) => {
flatten_into_disjunct(&mut build_stack, preceding_len);
}
TraversalState::GetCutPoint(var_num) => {
let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
self.probe_in_situ_var(term_loc, var_num);
build_stack.push(QueryTerm::GetCutPoint(var_num));
self.current_chunk_type = ChunkType::Mid;
self.current_chunk_num += 1;
}
TraversalState::LocalCut(var_num) => {
let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
TraversalState::GetCutPoint { var_num, prev_b } => {
if self.try_set_chunk_at_inlined_boundary() {
build_stack.add_chunk();
}
self.probe_in_situ_var(term_loc, var_num);
build_stack.push(QueryTerm::LocalCut(var_num));
self.probe_in_situ_var(var_num);
build_stack.push_chunk_term(QueryTerm::GetCutPoint { var_num, prev_b });
}
TraversalState::Cut { var_num, is_global } => {
if self.try_set_chunk_at_inlined_boundary() {
build_stack.add_chunk();
}
self.probe_in_situ_var(var_num);
build_stack.push_chunk_term(
if is_global {
QueryTerm::GlobalCut(var_num)
} else {
QueryTerm::LocalCut(var_num)
}
);
}
TraversalState::Fail => {
build_stack.push(QueryTerm::Fail);
build_stack.push_chunk_term(QueryTerm::Fail);
}
TraversalState::Term(term) => {
// return true iff new chunk should be added.
let update_chunk_data = |classifier: &mut Self, predicate_name, arity| {
if ClauseType::is_inlined(predicate_name, arity) {
classifier.try_set_chunk_at_inlined_boundary()
} else {
classifier.try_set_chunk_at_call_boundary()
}
};
match term {
Term::Clause(_, atom!(","), terms) if terms.len() == 2 => {
let iter = unfold_by_str(terms[1], atom!(","))
Term::Clause(_, atom!(","), mut terms) if terms.len() == 2 => {
let tail = terms.pop().unwrap();
let head = terms.pop().unwrap();
let iter = unfold_by_str(tail, atom!(","))
.into_iter()
.rev()
.chain(std::iter::once(terms[0]))
.chain(std::iter::once(head))
.map(TraversalState::Term);
if ChunkType::Mid != chunk_type {
if insert_set_last_chunk_type(&mut state_stack, iter) {
if chunk_type.is_last() {
chunk_type = ChunkType::Mid;
}
}
} else {
state_stack.extend(iter);
}
state_stack.extend(iter);
}
Term::Clause(_, atom!(";"), terms) if terms.len() == 2 => {
Term::Clause(_, atom!(";"), mut terms) if terms.len() == 2 => {
let tail = terms.pop().unwrap();
let head = terms.pop().unwrap();
let first_branch_num = self.current_branch_num.split();
let branches: Vec<_> = std::iter::once(terms[0])
.chain(unfold_by_str(terms[1], atom!(";")).into_iter())
let branches: Vec<_> = std::iter::once(head)
.chain(unfold_by_str(tail, atom!(";")).into_iter())
.collect();
let mut branch_numbers = vec![first_branch_num];
@@ -568,7 +589,7 @@ impl VariableClassifier {
}
let build_stack_len = build_stack.len();
build_stack.push(QueryTerm::Branch(Vec::with_capacity(branches.len())));
build_stack.reserve_branch(branches.len());
state_stack.push(TraversalState::RepBranchNum(
self.current_branch_num.halve_delta(),
@@ -578,47 +599,52 @@ impl VariableClassifier {
let final_disjunct_loc = state_stack.len();
for (term, branch_num) in iter.rev() {
state_stack.push(TraversalState::BuildDisjunct(chunk_type, build_stack_len));
state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
state_stack.push(TraversalState::RemoveBranchNum);
state_stack.push(TraversalState::Term(term));
state_stack.push(TraversalState::AddBranchNum(branch_num));
}
state_stack[final_disjunct_loc] =
TraversalState::BuildFinalDisjunct(build_stack_len);
if let TraversalState::BuildDisjunct(build_stack_len) = state_stack[final_disjunct_loc] {
state_stack[final_disjunct_loc] = TraversalState::BuildFinalDisjunct(build_stack_len);
}
}
Term::Clause(_, atom!("->"), mut terms) if terms.len() == 2 => {
let then_term = terms.pop().unwrap();
let if_term = terms.pop().unwrap();
let iter = vec![TraversalState::Term(then_term),
TraversalState::LocalCut(self.var_num),
TraversalState::Term(if_term),
TraversalState::GetCutPoint(self.var_num)]
.into_iter();
let prev_b = if matches!(state_stack.last(), Some(TraversalState::RemoveBranchNum)) {
// check if the second-to-last element is a regular BuildDisjunct, as we don't
// want to add GetPrevLevel in case of a TrustMe.
matches!(state_stack.iter().rev().nth(1), Some(TraversalState::BuildDisjunct(..)))
} else {
false
};
state_stack.push(TraversalState::Term(then_term));
state_stack.push(TraversalState::Cut { var_num: self.var_num, is_global: false });
state_stack.push(TraversalState::Term(if_term));
state_stack.push(TraversalState::GetCutPoint { var_num: self.var_num, prev_b });
self.var_num += 1;
if ChunkType::Mid != chunk_type {
if insert_set_last_chunk_type(&mut state_stack, iter) {
if chunk_type.is_last() {
chunk_type = ChunkType::Mid;
}
}
}
}
Term::Clause(_, atom!("\\+"), terms) if terms.len() == 1 => {
Term::Clause(_, atom!("\\+"), mut terms) if terms.len() == 1 => {
let not_term = terms.pop().unwrap();
let build_stack_len = build_stack.len();
build_stack.reserve_branch(2);
state_stack.push(TraversalState::BuildFinalDisjunct(build_stack_len));
state_stack.push(TraversalState::Term(Term::Clause(Cell::default(), atom!("$succeed"), vec![])));
state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
state_stack.push(TraversalState::Fail);
state_stack.push(TraversalState::LocalCut(self.var_num));
state_stack.push(TraversalState::Term(terms[0]));
state_stack.push(TraversalState::GetCutPoint(self.var_num));
state_stack.push(TraversalState::Cut { var_num: self.var_num, is_global: false });
state_stack.push(TraversalState::Term(not_term));
state_stack.push(TraversalState::GetCutPoint { var_num: self.var_num, prev_b: true });
self.var_num += 1;
}
Term::Clause(_, atom!(":"), mut terms) if terms.len() == 2 => {
let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
let predicate_name = terms.pop().unwrap();
let module_name = terms.pop().unwrap();
@@ -627,11 +653,11 @@ impl VariableClassifier {
Term::Literal(_, Literal::Atom(module_name)),
Term::Literal(_, Literal::Atom(predicate_name)),
) => {
if !ClauseType::is_inbuilt(predicate_name, 0) {
state_stack.push(TraversalState::IncrChunkNum);
if update_chunk_data(self, predicate_name, 0) {
build_stack.add_chunk();
}
build_stack.push(
build_stack.push_chunk_term(
qualified_clause_to_query_term(
loader,
module_name,
@@ -645,15 +671,15 @@ impl VariableClassifier {
Term::Literal(_, Literal::Atom(module_name)),
Term::Clause(_, name, terms),
) => {
if !ClauseType::is_inbuilt(name, terms.len()) {
state_stack.push(TraversalState::IncrChunkNum);
if update_chunk_data(self, name, terms.len()) {
build_stack.add_chunk();
}
for term in terms.iter() {
self.probe_body_term(term, term_loc);
for (arg_c, term) in terms.iter().enumerate() {
self.probe_body_term(arg_c + 1, terms.len(), term);
}
build_stack.push(
build_stack.push_chunk_term(
qualified_clause_to_query_term(
loader,
module_name,
@@ -664,15 +690,17 @@ impl VariableClassifier {
);
}
(module_name, predicate_name) => {
state_stack.push(TraversalState::IncrChunkNum);
if update_chunk_data(self, atom!("call"), 2) {
build_stack.add_chunk();
}
self.probe_body_term(&module_name, term_loc);
self.probe_body_term(&predicate_name, term_loc);
self.probe_body_term(1, 0, &module_name);
self.probe_body_term(2, 0, &predicate_name);
terms.push(module_name);
terms.push(predicate_name);
build_stack.push(
build_stack.push_chunk_term(
clause_to_query_term(
loader,
atom!("call"),
@@ -683,30 +711,22 @@ impl VariableClassifier {
}
}
}
Term::Clause(cell, atom!("$call_with_inference_counting"), terms) if terms.len() == 1 => {
let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
for term in terms.iter() {
self.probe_body_term(term, term_loc);
}
Term::Clause(_, atom!("$call_with_inference_counting"), mut terms) if terms.len() == 1 => {
state_stack.push(TraversalState::ResetCallPolicy(self.call_policy));
state_stack.push(TraversalState::Term(terms[0]));
state_stack.push(TraversalState::Term(terms.pop().unwrap()));
self.call_policy = CallPolicy::Counted;
}
Term::Clause(cell, name, terms) => {
if !ClauseType::is_inbuilt(name, terms.len()) {
state_stack.push(TraversalState::IncrChunkNum);
Term::Clause(_, name, terms) => {
if update_chunk_data(self, name, terms.len()) {
build_stack.add_chunk();
}
let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
for term in terms.iter() {
self.probe_body_term(term, term_loc);
for (arg_c, term) in terms.iter().enumerate() {
self.probe_body_term(arg_c + 1, terms.len(), term);
}
build_stack.push(
build_stack.push_chunk_term(
clause_to_query_term(
loader,
name,
@@ -716,14 +736,24 @@ impl VariableClassifier {
);
}
Term::Literal(_, Literal::Atom(atom!("!")) | Literal::Char('!')) => {
build_stack.push(QueryTerm::GlobalCut);
}
Term::Literal(cell, Literal::Atom(name)) => {
if !ClauseType::is_inbuilt(name, 0) {
state_stack.push(TraversalState::IncrChunkNum);
if self.global_cut_var_num.is_none() {
self.global_cut_var_num = Some(self.var_num);
self.var_num += 1;
}
build_stack.push(
self.probe_in_situ_var(self.global_cut_var_num.unwrap());
state_stack.push(TraversalState::Cut {
var_num: self.global_cut_var_num.unwrap(),
is_global: true,
});
}
Term::Literal(_, Literal::Atom(name)) => {
if update_chunk_data(self, name, 0) {
build_stack.add_chunk();
}
build_stack.push_chunk_term(
clause_to_query_term(
loader,
name,
@@ -732,7 +762,6 @@ impl VariableClassifier {
),
);
}
_ => {
return Err(CompilationError::InadmissibleQueryTerm);
}
@@ -746,61 +775,76 @@ impl VariableClassifier {
}
impl BranchMap {
pub fn separate_and_classify_variables(&mut self, mut var_num: usize) -> VarData {
pub fn separate_and_classify_variables(
&mut self,
var_num: usize,
global_cut_var_num: Option<usize>,
current_chunk_num: usize,
) -> VarData {
let mut var_data = VarData {
records: vec![VarRecord::default(); self.len()],
fixtures: VariableFixtures::new(),
records: VariableRecords::new(var_num),
global_cut_var_num,
allocates: current_chunk_num > 0,
};
for (var, branches) in self.iter_mut() {
for branch in branches.iter_mut() {
let mut num_occurrences = 0;
let idx = if let Var::Generated(var_num) = var {
*var_num
let (mut var_num, var_num_incr) =
if let Var::InSitu(var_num) = *var.borrow() {
(var_num, false)
} else {
var_num += 1;
var_num - 1
(var_data.records.len(), true)
};
var_data.records[idx].classification =
if branch.chunks.len() > 1 {
VarClassification::Perm
} else {
branch.chunks
.first()
.map(|chunk| if chunk.vars.len() > 1 {
VarClassification::Temp
} else {
VarClassification::Void
})
.unwrap_or(VarClassification::Void)
};
for branch in branches.iter_mut() {
if var_num_incr {
var_num = var_data.records.len();
var_data.records.push(VariableRecord::default());
}
var_data.records[idx].chunk_occurrences.reserve(branch.chunks.len());
if branch.chunks.len() <= 1 { // true iff var is a temporary variable.
debug_assert_eq!(branch.chunks.len(), 1);
for chunk in branch.chunks.iter_mut() {
var_data.records[idx].num_occurrences += chunk.vars.len();
let chunk = &mut branch.chunks[0];
let mut temp_var_data = TempVarData::new();
if let VarClassification::Temp = classification {
for var_info in chunk.vars.iter_mut() {
var_info.var_ptr.set(Var::Generated(var_num));
var_data.fixtures.mark_temp_var(&var_info);
}
} else {
for var_info in chunk.vars.iter_mut() {
var_info.var_ptr.set(Var::Generated(var_num));
for var_info in chunk.vars.iter_mut() {
if var_info.lvl == Level::Shallow {
let term_loc = var_info.chunk_type.to_gen_context(chunk.chunk_num);
temp_var_data.use_set.insert((term_loc, var_info.classify_info.arg_c));
}
}
var_data.records[idx].chunk_occurrences.push(chunk.chunk_num);
var_data.records[var_num].allocation = VarAlloc::Temp {
term_loc: chunk.term_loc,
temp_reg: 0,
temp_var_data,
safety: VarSafetyStatus::Needed,
to_perm_var_num: None,
};
} // else VarAlloc is already a Perm variant, as it's the default.
for chunk in branch.chunks.iter_mut() {
var_data.records[var_num].num_occurrences += chunk.vars.len();
for var_info in chunk.vars.iter_mut() {
var_info.var_ptr.set(Var::Generated(var_num));
}
}
}
}
debug_assert_eq!(var_data.records.len(), var_num);
// debug_assert_eq!(var_data.records.len(), var_num);
var_data.fixtures.populate_restricting_sets();
var_data.records.populate_restricting_sets();
var_data
}
}
#[cfg(test)]
mod tests {
#[test]
fn disjunct_compilation() {
let mut wam = MachineState::new();
let mut op_dir = default_op_dir();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -444,10 +444,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let tl = preprocessor.try_term_to_tl(self, term)?;
Ok(match tl {
TopLevel::Fact(fact) => PredicateClause::Fact(fact),
TopLevel::Rule(rule) => PredicateClause::Rule(rule),
TopLevel::Query(_) => return Err(SessionError::QueryCannotBeDefinedAsFact),
_ => unreachable!(),
TopLevel::Fact(fact, var_data) => PredicateClause::Fact(fact, var_data),
TopLevel::Rule(rule, var_data) => PredicateClause::Rule(rule, var_data),
})
}

View File

@@ -1428,7 +1428,7 @@ impl MachineState {
}
}
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar, h) => {
term_stack.push(Term::Var(Cell::default(), Var::Generated(h)));
term_stack.push(Term::Var(Cell::default(), VarPtr::from(format!("_{}", h))));
}
(HeapCellValueTag::Cons | HeapCellValueTag::CStr | HeapCellValueTag::Fixnum |
HeapCellValueTag::Char | HeapCellValueTag::F64) => {

View File

@@ -2,7 +2,6 @@ use crate::parser::ast::*;
use crate::arena::*;
use crate::atom_table::*;
use crate::fixtures::*;
use crate::forms::*;
use crate::machine::loader::*;
use crate::machine::machine_state::*;
@@ -227,8 +226,8 @@ impl CodeIndex {
}
}
pub(crate) type HeapVarDict = IndexMap<Var, HeapCellValue, FxBuildHasher>;
pub(crate) type AllocVarDict = IndexMap<Var, VarAlloc, FxBuildHasher>;
pub(crate) type HeapVarDict = IndexMap<VarPtr, HeapCellValue, FxBuildHasher>;
// pub(crate) type AllocVarDict = IndexMap<Var, VarAlloc, FxBuildHasher>;
pub(crate) type GlobalVarDir = IndexMap<Atom, (Ball, Option<HeapCellValue>), FxBuildHasher>;

View File

@@ -500,13 +500,13 @@ impl MachineState {
pub fn read_term(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult {
fn push_var_eq_functors<'a>(
heap: &mut Heap,
iter: impl Iterator<Item = (&'a Var, &'a HeapCellValue)>,
iter: impl Iterator<Item = (&'a VarPtr, &'a HeapCellValue)>,
atom_tbl: &mut AtomTable,
) -> Vec<HeapCellValue> {
let mut list_of_var_eqs = vec![];
for (var, binding) in iter {
let var_atom = atom_tbl.build_with(&var.to_string());
let var_atom = atom_tbl.build_with(&var.borrow().to_string());
let h = heap.len();
heap.push(atom_as_cell!(atom!("="), 2));
@@ -672,7 +672,7 @@ impl MachineState {
let printer = match self.try_from_list(self.registers[6], stub_gen) {
Ok(addrs) => {
let mut var_names: IndexMap<HeapCellValue, Var> = IndexMap::new();
let mut var_names: IndexMap<HeapCellValue, VarPtr> = IndexMap::new();
for addr in addrs {
read_heap_cell!(addr,
@@ -690,18 +690,18 @@ impl MachineState {
read_heap_cell!(atom,
(HeapCellValueTag::Char, c) => {
var_names.insert(var, Var::from(c.to_string()));
var_names.insert(var, VarPtr::from(c.to_string()));
}
(HeapCellValueTag::Atom, (name, _arity)) => {
debug_assert_eq!(_arity, 0);
var_names.insert(var, Var::from(name.as_str()));
var_names.insert(var, VarPtr::from(name.as_str()));
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.heap[s])
.get_name_and_arity();
debug_assert_eq!(arity, 0);
var_names.insert(var, Var::from(name.as_str()));
var_names.insert(var, VarPtr::from(name.as_str()));
}
_ => {
unreachable!();

View File

@@ -68,7 +68,7 @@ pub struct Machine {
pub(super) user_error: Stream,
pub(super) load_contexts: Vec<LoadContext>,
pub(super) runtime: Runtime,
pub(super) foreign_function_table: ForeignFunctionTable,
pub(super) foreign_function_table: ForeignFunctionTable,
}
#[derive(Debug)]
@@ -365,46 +365,46 @@ impl Machine {
Instruction::BreakFromDispatchLoop,
Instruction::InstallVerifyAttr,
Instruction::VerifyAttrInterrupt,
Instruction::ExecuteTermGreaterThan(0),
Instruction::ExecuteTermLessThan(0),
Instruction::ExecuteTermGreaterThanOrEqual(0),
Instruction::ExecuteTermLessThanOrEqual(0),
Instruction::ExecuteTermEqual(0),
Instruction::ExecuteTermNotEqual(0),
Instruction::ExecuteNumberGreaterThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0),
Instruction::ExecuteNumberLessThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0),
Instruction::ExecuteNumberGreaterThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0),
Instruction::ExecuteNumberLessThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0),
Instruction::ExecuteNumberEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0),
Instruction::ExecuteNumberNotEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0),
Instruction::ExecuteIs(temp_v!(1), ar_reg!(temp_v!(2)), 0),
Instruction::ExecuteAcyclicTerm(0),
Instruction::ExecuteArg(0),
Instruction::ExecuteCompare(0),
Instruction::ExecuteCopyTerm(0),
Instruction::ExecuteFunctor(0),
Instruction::ExecuteGround(0),
Instruction::ExecuteKeySort(0),
Instruction::ExecuteRead(0),
Instruction::ExecuteSort(0),
Instruction::ExecuteN(1, 0),
Instruction::ExecuteN(2, 0),
Instruction::ExecuteN(3, 0),
Instruction::ExecuteN(4, 0),
Instruction::ExecuteN(5, 0),
Instruction::ExecuteN(6, 0),
Instruction::ExecuteN(7, 0),
Instruction::ExecuteN(8, 0),
Instruction::ExecuteN(9, 0),
Instruction::ExecuteIsAtom(temp_v!(1), 0),
Instruction::ExecuteIsAtomic(temp_v!(1), 0),
Instruction::ExecuteIsCompound(temp_v!(1), 0),
Instruction::ExecuteIsInteger(temp_v!(1), 0),
Instruction::ExecuteIsNumber(temp_v!(1), 0),
Instruction::ExecuteIsRational(temp_v!(1), 0),
Instruction::ExecuteIsFloat(temp_v!(1), 0),
Instruction::ExecuteIsNonVar(temp_v!(1), 0),
Instruction::ExecuteIsVar(temp_v!(1), 0)
Instruction::ExecuteTermGreaterThan,
Instruction::ExecuteTermLessThan,
Instruction::ExecuteTermGreaterThanOrEqual,
Instruction::ExecuteTermLessThanOrEqual,
Instruction::ExecuteTermEqual,
Instruction::ExecuteTermNotEqual,
Instruction::ExecuteNumberGreaterThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberLessThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberGreaterThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberLessThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteNumberNotEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
Instruction::ExecuteIs(temp_v!(1), ar_reg!(temp_v!(2))),
Instruction::ExecuteAcyclicTerm,
Instruction::ExecuteArg,
Instruction::ExecuteCompare,
Instruction::ExecuteCopyTerm,
Instruction::ExecuteFunctor,
Instruction::ExecuteGround,
Instruction::ExecuteKeySort,
Instruction::ExecuteRead,
Instruction::ExecuteSort,
Instruction::ExecuteN(1),
Instruction::ExecuteN(2),
Instruction::ExecuteN(3),
Instruction::ExecuteN(4),
Instruction::ExecuteN(5),
Instruction::ExecuteN(6),
Instruction::ExecuteN(7),
Instruction::ExecuteN(8),
Instruction::ExecuteN(9),
Instruction::ExecuteIsAtom(temp_v!(1)),
Instruction::ExecuteIsAtomic(temp_v!(1)),
Instruction::ExecuteIsCompound(temp_v!(1)),
Instruction::ExecuteIsInteger(temp_v!(1)),
Instruction::ExecuteIsNumber(temp_v!(1)),
Instruction::ExecuteIsRational(temp_v!(1)),
Instruction::ExecuteIsFloat(temp_v!(1)),
Instruction::ExecuteIsNonVar(temp_v!(1)),
Instruction::ExecuteIsVar(temp_v!(1))
].into_iter());
for (p, instr) in self.code[impls_offset ..].iter().enumerate() {
@@ -690,6 +690,8 @@ impl Machine {
fn try_call(&mut self, name: Atom, arity: usize, idx: IndexPtr) -> CallResult {
let compiled_tl_index = idx.p() as usize;
// println!("calling {}/{}", name.as_str(), arity);
match idx.tag() {
IndexPtrTag::DynamicUndefined => {
self.machine_st.fail = true;
@@ -713,6 +715,8 @@ impl Machine {
fn try_execute(&mut self, name: Atom, arity: usize, idx: IndexPtr) -> CallResult {
let compiled_tl_index = idx.p() as usize;
// println!("executing {}/{}", name.as_str(), arity);
match idx.tag() {
IndexPtrTag::DynamicUndefined => {
self.machine_st.fail = true;

View File

@@ -10,20 +10,8 @@ use crate::parser::ast::*;
use indexmap::IndexSet;
use std::cell::Cell;
use std::collections::VecDeque;
use std::convert::TryFrom;
pub(crate) fn fold_by_str<I>(terms: I, mut term: Term, sym: Atom) -> Term
where
I: DoubleEndedIterator<Item = Term>,
{
for prec in terms.rev() {
term = Term::Clause(Cell::default(), sym, vec![prec, term]);
}
term
}
pub(crate) fn to_op_decl(
prec: u16,
spec: Atom,
@@ -546,16 +534,15 @@ impl Preprocessor {
}
}
fn setup_fact(&mut self, term: Term) -> Result<Fact, CompilationError> {
fn setup_fact(&mut self, term: Term) -> Result<(Fact, VarData), CompilationError> {
match term {
Term::Clause(..) | Term::Literal(_, Literal::Atom(..)) => {
let mut classifier = VariableClassifier::new(
let classifier = VariableClassifier::new(
self.settings.default_call_policy(),
);
let (head, var_data) = classifier.classify_fact(term)?;
Ok(Fact { head, var_data })
Ok((Fact { head }, var_data))
}
_ => Err(CompilationError::InadmissibleFact),
}
@@ -566,28 +553,22 @@ impl Preprocessor {
loader: &mut Loader<'a, LS>,
head: Term,
body: Term,
) -> Result<Rule, CompilationError> {
let mut classifier = VariableClassifier::new(
) -> Result<(Rule, VarData), CompilationError> {
let classifier = VariableClassifier::new(
self.settings.default_call_policy(),
);
let (head, mut query_terms, var_data) =
classifier.classify_rule(loader, head, body)?;
let clauses = query_terms.drain(1..).collect();
let qt = query_terms.pop().unwrap();
let (head, clauses, var_data) = classifier.classify_rule(loader, head, body)?;
match head {
Term::Clause(_, name, terms) => Ok(Rule {
head: (name, terms, qt),
Term::Clause(_, name, terms) => Ok((Rule {
head: (name, terms),
clauses,
var_data,
}),
Term::Literal(_, Literal::Atom(name)) => Ok(Rule {
head: (name, vec![], qt),
}, var_data)),
Term::Literal(_, Literal::Atom(name)) => Ok((Rule {
head: (name, vec![]),
clauses,
var_data,
}),
}, var_data)),
_ => Err(CompilationError::InvalidRuleHead),
}
}
@@ -613,20 +594,29 @@ impl Preprocessor {
term: Term,
) -> Result<TopLevel, CompilationError> {
match term {
Term::Clause(r, name, terms) => {
Term::Clause(r, name, mut terms) => {
let is_rule = name == atom!(":-") && terms.len() == 2;
if is_rule {
Ok(TopLevel::Rule(self.setup_rule(loader, terms[0], terms[1])?))
let tail = terms.pop().unwrap();
let head = terms.pop().unwrap();
let (rule, var_data) = self.setup_rule(loader, head, tail)?;
Ok(TopLevel::Rule(rule, var_data))
} else {
let term = Term::Clause(r, name, terms);
Ok(TopLevel::Fact(self.setup_fact(term)?))
let (fact, var_data) = self.setup_fact(term)?;
Ok(TopLevel::Fact(fact, var_data))
}
}
term => Ok(TopLevel::Fact(self.setup_fact(term)?)),
term => {
let (fact, var_data) = self.setup_fact(term)?;
Ok(TopLevel::Fact(fact, var_data))
}
}
}
/*
fn try_terms_to_tls<'a, I: IntoIterator<Item = Term>, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
@@ -640,4 +630,5 @@ impl Preprocessor {
Ok(results)
}
*/
}

View File

@@ -1409,7 +1409,7 @@ impl Machine {
let vars: Vec<_> = vars
.union(&result.supp_vars) // difference + union does not cancel.
.map(|v| Term::Var(Cell::default(), Var::Generated(v.get_value())))
.map(|v| Term::Var(Cell::default(), VarPtr::from(format!("_{}", v.get_value()))))
.collect();
let helper_clause_loc = self.code.len();
@@ -1571,8 +1571,8 @@ impl Machine {
#[inline(always)]
pub(crate) fn is_reset_cont_marker(&self, p: usize) -> bool {
match &self.code[p] {
&Instruction::CallResetContinuationMarker(_) |
&Instruction::ExecuteResetContinuationMarker(_) => true,
&Instruction::CallResetContinuationMarker |
&Instruction::ExecuteResetContinuationMarker => true,
_ => false
}
}
@@ -4911,9 +4911,7 @@ impl Machine {
let p_functor = self.deref_register(2);
let p = to_local_code_ptr(&self.machine_st.heap, p_functor).unwrap();
let num_cells = *self.code[p].perm_vars_mut().unwrap();
let num_cells = self.machine_st.stack.index_and_frame(e).prelude.num_cells;
let mut addrs = vec![];
for idx in 1..num_cells + 1 {