Revert "remove Term"

This reverts commit 3b5879841aedecba5057c70c71da0ba23e5cd84a.
This commit is contained in:
Mark Thom
2025-03-15 13:19:26 -07:00
committed by Mark Thom
parent eef7b06919
commit 9e1e99f961
53 changed files with 3726 additions and 4517 deletions

View File

@@ -3,17 +3,13 @@ use crate::codegen::CodeGenSettings;
use crate::forms::*;
use crate::instructions::*;
use crate::machine::disjuncts::*;
use crate::machine::heap::*;
use crate::machine::loader::*;
use crate::machine::machine_errors::*;
use crate::machine::CodeIndex;
use crate::parser::ast::*;
use crate::types::*;
use fxhash::FxBuildHasher;
use indexmap::IndexMap;
use indexmap::IndexSet;
use std::cell::Cell;
use std::convert::TryFrom;
pub(crate) fn to_op_decl(prec: u16, spec: OpDeclSpec, name: Atom) -> OpDecl {
OpDecl::new(OpDesc::build_with(prec, spec), name)
@@ -25,47 +21,43 @@ pub(crate) fn to_op_decl_spec(spec: Atom) -> Result<OpDeclSpec, CompilationError
})
}
fn setup_op_decl(term: &FocusedHeapRefMut) -> Result<OpDecl, CompilationError> {
let (focus, _cell) = subterm_index(term.heap, term.focus);
let name = match term_predicate_key(term.heap, focus + 3) {
Some((name, 0)) => name,
_ => {
fn setup_op_decl(mut terms: Vec<Term>) -> Result<OpDecl, CompilationError> {
// should allow non-partial lists?
let name = match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => name,
other => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclNameType(term.heap[focus + 3]),
DirectiveError::InvalidOpDeclNameType(other),
));
}
};
let spec = match term_predicate_key(term.heap, focus + 2) {
Some((name, _)) => name,
None => {
let spec = match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => name,
other => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus + 2]),
));
DirectiveError::InvalidOpDeclSpecDomain(other),
))
}
};
let spec = to_op_decl_spec(spec)?;
let prec = term.deref_loc(focus + 1);
let prec = read_heap_cell!(prec,
(HeapCellValueTag::Fixnum, n) => {
match u16::try_from(n.get_num()) {
Ok(n) if n <= 1200 => n,
_ => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclPrecDomain(n),
));
}
let prec = match terms.pop().unwrap() {
Term::Literal(_, Literal::Fixnum(bi)) => match u16::try_from(bi.get_num()) {
Ok(n) if n <= 1200 => n,
_ => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclPrecDomain(bi),
));
}
}
_ => {
},
other => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclPrecType(prec),
DirectiveError::InvalidOpDeclPrecType(other),
));
}
);
};
if name == "[]" || name == "{}" {
return Err(CompilationError::InvalidDirective(
@@ -88,162 +80,129 @@ fn setup_op_decl(term: &FocusedHeapRefMut) -> Result<OpDecl, CompilationError> {
Ok(to_op_decl(prec, spec, name))
}
fn setup_predicate_indicator(term: &FocusedHeapRefMut) -> Result<PredicateKey, CompilationError> {
let key_opt = term_predicate_key(term.heap, term.focus);
fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, CompilationError> {
match term {
Term::Clause(_, slash, ref mut terms)
if (*slash == atom!("/") || *slash == atom!("//")) && terms.len() == 2 =>
{
let arity = terms.pop().unwrap();
let name = terms.pop().unwrap();
if let Some((atom!("/") | atom!("//"), 2)) = key_opt {
let arity_loc = term.nth_arg(term.focus, 2).unwrap();
let arity = match Number::try_from(term.deref_loc(arity_loc)) {
Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
Ok(Number::Integer(n)) => (&*n).try_into().ok(),
_ => None,
}
.ok_or(CompilationError::InvalidModuleExport)?;
let name_loc = term.nth_arg(term.focus, 1).unwrap();
let name = term_predicate_key(term.heap, name_loc)
.map(|(name, _)| name)
let arity = match arity {
Term::Literal(_, Literal::Integer(n)) => (&*n).try_into().ok(),
Term::Literal(_, Literal::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
_ => None,
}
.ok_or(CompilationError::InvalidModuleExport)?;
if matches!(key_opt, Some((atom!("/"), _))) {
Ok((name, arity))
} else {
Ok((name, arity + 2))
let name = match name {
Term::Literal(_, Literal::Atom(name)) => Some(name),
_ => None,
}
.ok_or(CompilationError::InvalidModuleExport)?;
if *slash == atom!("/") {
Ok((name, arity))
} else {
Ok((name, arity + 2))
}
}
} else {
Err(CompilationError::InvalidModuleExport)
_ => Err(CompilationError::InvalidModuleExport),
}
}
fn setup_module_export(term: &FocusedHeapRefMut) -> Result<ModuleExport, CompilationError> {
setup_predicate_indicator(term)
fn setup_module_export(mut term: Term) -> Result<ModuleExport, CompilationError> {
setup_predicate_indicator(&mut term)
.map(ModuleExport::PredicateKey)
.or_else(|_| {
let key_opt = term_predicate_key(term.heap, term.focus);
if let Some((atom!("op"), 3)) = key_opt {
Ok(ModuleExport::OpDecl(setup_op_decl(term)?))
if let Term::Clause(_, name, terms) = term {
if terms.len() == 3 && name == atom!("op") {
Ok(ModuleExport::OpDecl(setup_op_decl(terms)?))
} else {
Err(CompilationError::InvalidModuleDecl)
}
} else {
Err(CompilationError::InvalidModuleDecl)
}
})
}
/* TODO: should be unnecessary now.
pub(crate) fn build_rule_body(vars: &[Term], body_term: Term) -> Term {
let head_term = Term::Clause(Cell::default(), atom!(""), vars.to_vec());
let rule = vec![head_term, body_term];
Term::Clause(Cell::default(), atom!(":-"), rule)
}
*/
pub(super) fn setup_module_export_list(
term: FocusedHeapRefMut,
mut export_list: Term,
) -> Result<Vec<ModuleExport>, CompilationError> {
let mut exports = vec![];
let mut focus = term.focus;
loop {
read_heap_cell!(term.heap[focus],
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if h == focus {
break;
} else {
focus = h;
}
}
(HeapCellValueTag::Lis, l) => {
let term = FocusedHeapRefMut {
heap: term.heap,
focus: l,
};
while let Term::Cons(_, t1, t2) = export_list {
let module_export = setup_module_export(*t1)?;
exports.push(setup_module_export(&term)?);
focus = l + 1;
}
(HeapCellValueTag::Atom, (name, _arity)) => {
if name == atom!("[]") {
return Ok(exports);
} else {
break;
}
}
_ => {
break;
}
);
exports.push(module_export);
export_list = *t2;
}
Err(CompilationError::InvalidModuleDecl)
if let Term::Literal(_, Literal::Atom(atom!("[]"))) = export_list {
Ok(exports)
} else {
Err(CompilationError::InvalidModuleDecl)
}
}
fn setup_module_decl(mut term: FocusedHeapRefMut) -> Result<ModuleDecl, CompilationError> {
let name = term_predicate_key(term.heap, term.focus + 1)
.map(|(name, _)| name)
.ok_or(CompilationError::InvalidModuleDecl)?;
fn setup_module_decl(mut terms: Vec<Term>) -> Result<ModuleDecl, CompilationError> {
let export_list = terms.pop().unwrap();
let name = terms.pop().unwrap();
term.focus = term.focus + 2;
let exports = setup_module_export_list(term)?;
let name = match name {
Term::Literal(_, Literal::Atom(name)) => Some(name),
_ => None,
}
.ok_or(CompilationError::InvalidModuleDecl)?;
let exports = setup_module_export_list(export_list)?;
Ok(ModuleDecl { name, exports })
}
fn setup_use_module_decl(term: &FocusedHeapRefMut) -> Result<ModuleSource, CompilationError> {
read_heap_cell!(term.deref_loc(term.focus+1),
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(term.heap[s]).get_name_and_arity();
if (name, arity) == (atom!("library"), 1) {
read_heap_cell!(term.deref_loc(s+1),
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
return Ok(ModuleSource::Library(name));
}
}
_ => {
}
)
}
return Err(CompilationError::InvalidModuleDecl);
}
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
Ok(ModuleSource::File(name))
} else {
Err(CompilationError::InvalidUseModuleDecl)
fn setup_use_module_decl(mut terms: Vec<Term>) -> Result<ModuleSource, CompilationError> {
match terms.pop().unwrap() {
Term::Clause(_, name, mut terms) if name == atom!("library") && terms.len() == 1 => {
match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)),
_ => Err(CompilationError::InvalidModuleDecl),
}
}
_ => {
Err(CompilationError::InvalidUseModuleDecl)
}
)
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::File(name)),
_ => Err(CompilationError::InvalidUseModuleDecl),
}
}
type UseModuleExport = (ModuleSource, IndexSet<ModuleExport>);
fn setup_qualified_import(term: FocusedHeapRefMut) -> Result<UseModuleExport, CompilationError> {
let module_src = setup_use_module_decl(&term)?;
fn setup_qualified_import(mut terms: Vec<Term>) -> Result<UseModuleExport, CompilationError> {
let mut export_list = terms.pop().unwrap();
let module_src = match terms.pop().unwrap() {
Term::Clause(_, name, mut terms) if name == atom!("library") && terms.len() == 1 => {
match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)),
_ => Err(CompilationError::InvalidModuleDecl),
}
}
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::File(name)),
_ => Err(CompilationError::InvalidUseModuleDecl),
}?;
let mut exports = IndexSet::new();
let mut focus = term.focus + 2;
while let HeapCellValueTag::Lis = term.heap[focus].get_tag() {
focus = term.heap[focus].get_value() as usize;
let term = FocusedHeapRefMut {
heap: term.heap,
focus,
};
exports.insert(setup_module_export(&term)?);
focus = focus + 1;
while let Term::Cons(_, t1, t2) = export_list {
exports.insert(setup_module_export(*t1)?);
export_list = *t2;
}
if term.heap[focus] == empty_list_as_cell!() {
if let Term::Literal(_, Literal::Atom(atom!("[]"))) = export_list {
Ok((module_src, exports))
} else {
Err(CompilationError::InvalidModuleDecl)
@@ -290,20 +249,18 @@ fn setup_qualified_import(term: FocusedHeapRefMut) -> Result<UseModuleExport, Co
*/
fn setup_meta_predicate<'a, LS: LoadState<'a>>(
term: TermWriteResult,
mut terms: Vec<Term>,
loader: &mut Loader<'a, LS>,
) -> Result<(Atom, Atom, Vec<MetaSpec>), CompilationError> {
fn get_meta_specs(
term: FocusedHeapRefMut,
arity: usize,
) -> Result<Vec<MetaSpec>, CompilationError> {
fn get_name_and_meta_specs(
name: Atom,
terms: &mut [Term],
) -> Result<(Atom, Vec<MetaSpec>), CompilationError> {
let mut meta_specs = vec![];
for meta_spec_loc in term.focus + 1..term.focus + arity + 1 {
read_heap_cell!(term.deref_loc(meta_spec_loc),
(HeapCellValueTag::Atom, (meta_spec, arity)) => {
debug_assert_eq!(arity, 0);
for meta_spec in terms.iter_mut() {
match meta_spec {
Term::Literal(_, Literal::Atom(meta_spec)) => {
let meta_spec = match meta_spec {
atom!("+") => MetaSpec::Plus,
atom!("-") => MetaSpec::Minus,
@@ -314,322 +271,263 @@ fn setup_meta_predicate<'a, LS: LoadState<'a>>(
meta_specs.push(meta_spec);
}
(HeapCellValueTag::Fixnum, n) => {
match usize::try_from(n.get_num()) {
Ok(n) if n <= MAX_ARITY => {
meta_specs.push(MetaSpec::RequiresExpansionWithArgument(n));
}
_ => {
return Err(CompilationError::InvalidMetaPredicateDecl);
}
Term::Literal(_, Literal::Fixnum(n)) => match usize::try_from(n.get_num()) {
Ok(n) if n <= MAX_ARITY => {
meta_specs.push(MetaSpec::RequiresExpansionWithArgument(n));
}
}
_ => {
return Err(CompilationError::InvalidMetaPredicateDecl);
}
},
_ => {
return Err(CompilationError::InvalidMetaPredicateDecl);
}
);
}
}
Ok(meta_specs)
Ok((name, meta_specs))
}
let heap = loader.machine_heap();
let cell = heap_bound_store(heap, heap_bound_deref(heap, heap[term.focus + 1]));
match terms.pop().unwrap() {
Term::Clause(_, name, mut terms) if name == atom!(":") && terms.len() == 2 => {
let spec = terms.pop().unwrap();
let module_name = terms.pop().unwrap();
read_heap_cell!(cell,
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(heap[s]).get_name_and_arity();
match (name, arity) {
(atom!(":"), 2) => {
let module_name = heap[s+1];
let spec = heap[s+2];
read_heap_cell!(module_name,
(HeapCellValueTag::Atom, (module_name, arity)) => {
if arity == 0 {
read_heap_cell!(spec,
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(heap[s])
.get_name_and_arity();
let term = FocusedHeapRefMut { heap, focus: s };
return Ok((module_name, name, get_meta_specs(term, arity)?));
}
_ => {
}
);
} else {
return Err(CompilationError::InvalidMetaPredicateDecl);
}
}
_ => {
}
);
}
_ => {
let term = FocusedHeapRefMut { heap, focus: s };
let specs = get_meta_specs(term, arity)?;
let module_name = loader.payload.compilation_target.module_name();
return Ok((module_name, name, specs));
}
match module_name {
Term::Literal(_, Literal::Atom(module_name)) => match spec {
Term::Clause(_, name, mut terms) => {
let (name, meta_specs) = get_name_and_meta_specs(name, &mut terms)?;
Ok((module_name, name, meta_specs))
}
_ => Err(CompilationError::InvalidMetaPredicateDecl),
},
_ => Err(CompilationError::InvalidMetaPredicateDecl),
}
Err(CompilationError::InvalidMetaPredicateDecl)
}
_ => {
Err(CompilationError::InvalidMetaPredicateDecl)
Term::Clause(_, name, mut terms) => {
let (name, meta_specs) = get_name_and_meta_specs(name, &mut terms)?;
Ok((
loader.payload.compilation_target.module_name(),
name,
meta_specs,
))
}
)
_ => Err(CompilationError::InvalidMetaPredicateDecl),
}
}
pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
mut term: TermWriteResult,
mut terms: Vec<Term>,
) -> Result<Declaration, CompilationError> {
let mut focus = term.focus;
let machine_st = LS::machine_st(&mut loader.payload);
let term = terms.pop().unwrap();
loop {
let decl = machine_st.heap[focus];
read_heap_cell!(decl,
(HeapCellValueTag::Atom, (name, arity)) => {
let mut focused = FocusedHeapRefMut::from(&mut machine_st.heap, focus);
return match (name, arity) {
(atom!("dynamic"), 1) => {
let (name, arity) = setup_predicate_indicator(&focused)?;
Ok(Declaration::Dynamic(name, arity))
}
(atom!("module"), 2) => {
Ok(Declaration::Module(setup_module_decl(focused)?))
}
(atom!("op"), 3) => {
Ok(Declaration::Op(setup_op_decl(&focused)?))
}
(atom!("non_counted_backtracking"), 1) => {
focused.focus = focused.nth_arg(focused.focus, 1).unwrap();
let (name, arity) = setup_predicate_indicator(&focused)?;
Ok(Declaration::NonCountedBacktracking(name, arity))
}
(atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(&focused)?)),
(atom!("use_module"), 2) => {
let (name, exports) = setup_qualified_import(focused)?;
Ok(Declaration::UseQualifiedModule(name, exports))
}
(atom!("meta_predicate"), 1) => {
term.focus = focus;
let (module_name, name, meta_specs) = setup_meta_predicate(term, loader)?;
Ok(Declaration::MetaPredicate(module_name, name, meta_specs))
}
_ => Err(CompilationError::InvalidDirective(
DirectiveError::InvalidDirective(name, arity)
))
};
match term {
Term::Clause(_, name, mut terms) => match (name, terms.len()) {
(atom!("dynamic"), 1) => {
let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?;
Ok(Declaration::Dynamic(name, arity))
}
(HeapCellValueTag::Str, s) => {
focus = s;
(atom!("module"), 2) => Ok(Declaration::Module(setup_module_decl(terms)?)),
(atom!("op"), 3) => Ok(Declaration::Op(setup_op_decl(terms)?)),
(atom!("non_counted_backtracking"), 1) => {
let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?;
Ok(Declaration::NonCountedBacktracking(name, arity))
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if focus != h {
focus = h;
} else {
return Err(CompilationError::InvalidDirective(
DirectiveError::ExpectedDirective(decl),
));
}
(atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(terms)?)),
(atom!("use_module"), 2) => {
let (name, exports) = setup_qualified_import(terms)?;
Ok(Declaration::UseQualifiedModule(name, exports))
}
_ => {
return Err(CompilationError::InvalidDirective(
DirectiveError::ExpectedDirective(decl),
));
(atom!("meta_predicate"), 1) => {
let (module_name, name, meta_specs) = setup_meta_predicate(terms, loader)?;
Ok(Declaration::MetaPredicate(module_name, name, meta_specs))
}
);
_ => Err(CompilationError::InvalidDirective(
DirectiveError::InvalidDirective(name, terms.len()),
)),
},
other => Err(CompilationError::InvalidDirective(
DirectiveError::ExpectedDirective(other),
)),
}
}
fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
module_name: Atom,
arity: usize,
term: &TermWriteResult,
terms: Vec<Term>,
meta_specs: Vec<MetaSpec>,
) -> IndexMap<usize, CodeIndex, FxBuildHasher> {
use crate::machine::heap::Heap;
let mut index_ptrs = IndexMap::with_hasher(FxBuildHasher::default());
) -> Vec<Term> {
let mut arg_terms = Vec::with_capacity(terms.len());
let focus = {
let heap = loader.machine_heap();
let focus_cell =
heap_bound_store(heap, heap_bound_deref(heap, heap_loc_as_cell!(term.focus)));
if focus_cell.get_tag() == HeapCellValueTag::Str {
focus_cell.get_value() as usize
} else {
return index_ptrs;
}
};
for (subterm_loc, meta_spec) in (focus + 1..focus + arity + 1).zip(meta_specs) {
for (term, meta_spec) in terms.into_iter().zip(meta_specs.iter()) {
if let MetaSpec::RequiresExpansionWithArgument(supp_args) = meta_spec {
let predicate_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc);
if let Some((name, arity)) = predicate_key_opt {
if let Some(name) = term.name() {
if name == atom!("$call") {
arg_terms.push(term);
continue;
}
struct QualifiedNameInfo {
module_name: Atom,
name: Atom,
arity: usize,
qualified_term_loc: usize,
}
let arity = term.arity();
fn get_qualified_name(
heap: &Heap,
module_term_loc: usize,
qualified_term_loc: usize,
) -> Option<QualifiedNameInfo> {
let (module_term_loc, _) = subterm_index(heap, module_term_loc);
let (qualified_term_loc, _) = subterm_index(heap, qualified_term_loc);
read_heap_cell!(heap[module_term_loc],
(HeapCellValueTag::Atom, (module_name, arity)) => {
if arity == 0 {
if let Some((name, arity)) = term_predicate_key(heap, qualified_term_loc) {
return Some(QualifiedNameInfo {
module_name,
name,
arity,
qualified_term_loc,
});
}
}
module_term: &Term,
qualified_term: &Term,
) -> Option<(Atom, Atom)> {
if let Term::Literal(_, Literal::Atom(module_name)) = module_term {
if let Some(name) = qualified_term.name() {
return Some((*module_name, name));
}
_ => {}
);
}
None
}
let (subterm_loc, _) = subterm_index(loader.machine_heap(), subterm_loc);
let subterm_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc);
fn identity_fn(_module_name: Atom, term: Term) -> Term {
term
}
let (module_name, key, term_loc) = if subterm_key_opt == Some((atom!(":"), 2)) {
match get_qualified_name(
loader.machine_heap(),
subterm_loc + 1,
subterm_loc + 2,
) {
Some(QualifiedNameInfo {
module_name,
name,
arity,
qualified_term_loc,
}) => (module_name, (name, arity + supp_args), qualified_term_loc),
None => {
fn tag_with_module_name(module_name: Atom, term: Term) -> Term {
Term::Clause(
Cell::default(),
atom!(":"),
vec![
Term::Literal(Cell::default(), Literal::Atom(module_name)),
term,
],
)
}
let process_term: fn(Atom, Term) -> Term;
let (module_name, key, term) = match term {
Term::Clause(cell, atom!(":"), mut terms) if terms.len() == 2 => {
if let Some((module_name, name)) = get_qualified_name(&terms[0], &terms[1])
{
process_term = tag_with_module_name;
(
module_name,
(name, terms[1].arity() + supp_args),
terms.pop().unwrap(),
)
} else {
arg_terms.push(Term::Clause(cell, atom!(":"), terms));
continue;
}
}
} else {
(module_name, (name, arity + supp_args), subterm_loc)
term => {
process_term = identity_fn;
(module_name, (name, arity + supp_args), term)
}
};
if let Some(index_ptr) = fetch_index_ptr(loader.machine_heap(), term_loc) {
index_ptrs.insert(term_loc, index_ptr);
continue;
}
let term = match term {
Term::Clause(cell, name, mut terms) => {
if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
arg_terms
.push(process_term(module_name, Term::Clause(cell, name, terms)));
index_ptrs.insert(
term_loc,
loader.get_or_insert_qualified_code_index(module_name, key),
);
continue;
}
let idx = loader.get_or_insert_qualified_code_index(module_name, key);
terms.push(Term::Literal(Cell::default(), Literal::CodeIndex(idx)));
process_term(module_name, Term::Clause(cell, name, terms))
}
Term::Literal(cell, Literal::Atom(name)) => {
let idx = loader.get_or_insert_qualified_code_index(module_name, key);
process_term(
module_name,
Term::Clause(
cell,
name,
vec![Term::Literal(Cell::default(), Literal::CodeIndex(idx))],
),
)
}
term => term,
};
arg_terms.push(term);
continue;
}
}
arg_terms.push(term);
}
index_ptrs
arg_terms
}
#[inline]
pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
key: PredicateKey,
terms: &TermWriteResult,
term: HeapCellValue,
name: Atom,
mut terms: Vec<Term>,
call_policy: CallPolicy,
) -> QueryClause {
// supplementary code vector indices are unnecessary for
// root-level clauses.
blunt_index_ptr(loader.machine_heap(), key, terms.focus);
) -> QueryTerm {
if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
// supplementary code vector indices are unnecessary for
// root-level clauses.
terms.pop();
}
let mut ct = loader.get_clause_type(key.0, key.1);
let mut ct = loader.get_clause_type(name, terms.len());
if let ClauseType::Named(arity, name, idx) = ct {
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
let module_name = loader.payload.compilation_target.module_name();
let code_indices =
build_meta_predicate_clause(loader, module_name, arity, terms, meta_specs);
let terms = build_meta_predicate_clause(loader, module_name, terms, meta_specs);
return QueryClause {
ct: ClauseType::Named(key.1, key.0, idx),
term,
code_indices,
return QueryTerm::Clause(
Cell::default(),
ClauseType::Named(arity, name, idx),
terms,
call_policy,
};
);
}
ct = ClauseType::Named(key.1, key.0, idx);
ct = ClauseType::Named(arity, name, idx);
}
QueryClause {
ct,
term,
code_indices: IndexMap::with_hasher(FxBuildHasher::default()),
call_policy,
}
QueryTerm::Clause(Cell::default(), ct, terms, call_policy)
}
#[inline]
pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
key: PredicateKey,
module_name: Atom,
terms: &TermWriteResult,
term: HeapCellValue,
name: Atom,
mut terms: Vec<Term>,
call_policy: CallPolicy,
) -> QueryClause {
// supplementary code vector indices are unnecessary for
// root-level clauses.
blunt_index_ptr(loader.machine_heap(), key, terms.focus);
) -> QueryTerm {
if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
// supplementary code vector indices are unnecessary for
// root-level clauses.
terms.pop();
}
let mut ct = loader.get_qualified_clause_type(module_name, key.0, key.1);
let mut ct = loader.get_qualified_clause_type(module_name, name, terms.len());
if let ClauseType::Named(arity, name, idx) = ct {
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
let code_indices =
build_meta_predicate_clause(loader, module_name, arity, &terms, meta_specs);
let terms = build_meta_predicate_clause(loader, module_name, terms, meta_specs);
return QueryClause {
ct: ClauseType::Named(key.1, key.0, idx),
term,
code_indices,
return QueryTerm::Clause(
Cell::default(),
ClauseType::Named(arity, name, idx),
terms,
call_policy,
};
);
}
ct = ClauseType::Named(key.1, key.0, idx);
ct = ClauseType::Named(arity, name, idx);
}
QueryClause {
ct,
term,
code_indices: IndexMap::with_hasher(FxBuildHasher::default()),
call_policy,
}
QueryTerm::Clause(Cell::default(), ct, terms, call_policy)
}
#[derive(Debug)]
@@ -642,66 +540,70 @@ impl Preprocessor {
Preprocessor { settings }
}
pub fn setup_fact<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
term: TermWriteResult,
) -> Result<(Fact, VarData), CompilationError> {
let heap = loader.machine_heap();
fn setup_fact(&mut self, term: Term) -> Result<(Fact, VarData), CompilationError> {
match term {
Term::Clause(..) | Term::Literal(_, Literal::Atom(..)) => {
let classifier = VariableClassifier::new(self.settings.default_call_policy());
if term_predicate_key(heap, term.focus).is_some() {
let classifier = VariableClassifier::new(self.settings.default_call_policy());
let var_data = classifier.classify_fact(loader, &term)?;
Ok((
Fact {
term_loc: term.focus,
},
var_data,
))
} else {
Err(CompilationError::InadmissibleFact)
let (head, var_data) = classifier.classify_fact(term)?;
Ok((Fact { head }, var_data))
}
_ => Err(CompilationError::InadmissibleFact),
}
}
fn setup_rule<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
term: TermWriteResult,
head: Term,
body: Term,
) -> Result<(Rule, VarData), CompilationError> {
let classifier = VariableClassifier::new(self.settings.default_call_policy());
let (clauses, var_data) = classifier.classify_rule(loader, &term)?;
let heap = loader.machine_heap();
let head_loc = term_nth_arg(heap, term.focus, 1).unwrap();
let (head, clauses, var_data) = classifier.classify_rule(loader, head, body)?;
if term_predicate_key(heap, head_loc).is_some() {
Ok((
match head {
Term::Clause(_, name, terms) => Ok((
Rule {
term_loc: term.focus,
head: (name, terms),
clauses,
},
var_data,
))
} else {
Err(CompilationError::InvalidRuleHead)
)),
Term::Literal(_, Literal::Atom(name)) => Ok((
Rule {
head: (name, vec![]),
clauses,
},
var_data,
)),
_ => Err(CompilationError::InvalidRuleHead),
}
}
pub(super) fn try_term_to_tl<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
term: TermWriteResult,
term: Term,
) -> Result<PredicateClause, CompilationError> {
let heap = &LS::machine_st(&mut loader.payload).heap;
match term {
Term::Clause(r, name, mut terms) => {
let is_rule = name == atom!(":-") && terms.len() == 2;
match term_predicate_key(heap, term.focus) {
Some((atom!(":-"), 2)) => {
let (rule, var_data) = self.setup_rule(loader, term)?;
Ok(PredicateClause::Rule(rule, var_data))
if is_rule {
let tail = terms.pop().unwrap();
let head = terms.pop().unwrap();
let (rule, var_data) = self.setup_rule(loader, head, tail)?;
Ok(PredicateClause::Rule(rule, var_data))
} else {
let term = Term::Clause(r, name, terms);
let (fact, var_data) = self.setup_fact(term)?;
Ok(PredicateClause::Fact(fact, var_data))
}
}
_ => {
let (fact, var_data) = self.setup_fact(loader, term)?;
term => {
let (fact, var_data) = self.setup_fact(term)?;
Ok(PredicateClause::Fact(fact, var_data))
}
}