merge with master
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
use prolog_parser::ast::*;
|
use prolog_parser::ast::*;
|
||||||
|
|
||||||
use crate::prolog::allocator::Allocator;
|
|
||||||
use crate::prolog::clause_types::*;
|
use crate::prolog::clause_types::*;
|
||||||
use crate::prolog::fixtures::*;
|
use crate::prolog::fixtures::*;
|
||||||
use crate::prolog::forms::*;
|
use crate::prolog::forms::*;
|
||||||
@@ -70,7 +69,7 @@ impl<'a> ArithInstructionIterator<'a> {
|
|||||||
pub enum ArithTermRef<'a> {
|
pub enum ArithTermRef<'a> {
|
||||||
Constant(&'a Constant),
|
Constant(&'a Constant),
|
||||||
Op(ClauseName, usize), // name, arity.
|
Op(ClauseName, usize), // name, arity.
|
||||||
Var(Level, &'a Cell<VarReg>, Rc<Var>),
|
Var(&'a Cell<VarReg>, Rc<Var>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for ArithInstructionIterator<'a> {
|
impl<'a> Iterator for ArithInstructionIterator<'a> {
|
||||||
@@ -97,8 +96,8 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TermIterState::Constant(_, _, c) => return Some(Ok(ArithTermRef::Constant(c))),
|
TermIterState::Constant(_, _, c) => return Some(Ok(ArithTermRef::Constant(c))),
|
||||||
TermIterState::Var(lvl, cell, var) => {
|
TermIterState::Var(_, cell, var) => {
|
||||||
return Some(Ok(ArithTermRef::Var(lvl, cell, var.clone())))
|
return Some(Ok(ArithTermRef::Var(cell, var.clone())))
|
||||||
}
|
}
|
||||||
_ => return Some(Err(ArithmeticError::NonEvaluableFunctor(atom!("'.'"), 2))),
|
_ => return Some(Err(ArithmeticError::NonEvaluableFunctor(atom!("'.'"), 2))),
|
||||||
};
|
};
|
||||||
@@ -108,10 +107,10 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ArithmeticEvaluator {
|
pub struct ArithmeticEvaluator<'a> {
|
||||||
|
bindings: &'a AllocVarDict,
|
||||||
interm: Vec<ArithmeticTerm>,
|
interm: Vec<ArithmeticTerm>,
|
||||||
interm_c: usize,
|
interm_c: usize,
|
||||||
arg_c: usize
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ArithmeticTermIter<'a> {
|
pub trait ArithmeticTermIter<'a> {
|
||||||
@@ -128,12 +127,12 @@ impl<'a> ArithmeticTermIter<'a> for &'a Term {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArithmeticEvaluator {
|
impl<'a> ArithmeticEvaluator<'a> {
|
||||||
pub fn new(target_int: usize, arg_c: usize) -> Self {
|
pub fn new(bindings: &'a AllocVarDict, target_int: usize) -> Self {
|
||||||
ArithmeticEvaluator {
|
ArithmeticEvaluator {
|
||||||
|
bindings,
|
||||||
interm: Vec::new(),
|
interm: Vec::new(),
|
||||||
interm_c: target_int,
|
interm_c: target_int,
|
||||||
arg_c
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,33 +283,27 @@ impl ArithmeticEvaluator {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval<'a, Iter, TermMarker>(
|
pub fn eval<Iter>(&mut self, src: Iter) -> Result<ArithCont, ArithmeticError>
|
||||||
&mut self,
|
|
||||||
marker: &mut TermMarker,
|
|
||||||
src: Iter,
|
|
||||||
term_loc: GenContext,
|
|
||||||
) -> Result<ArithCont, ArithmeticError>
|
|
||||||
where
|
where
|
||||||
Iter: ArithmeticTermIter<'a>,
|
Iter: ArithmeticTermIter<'a>,
|
||||||
TermMarker: Allocator<'a>
|
|
||||||
{
|
{
|
||||||
let mut code = vec![];
|
let mut code = vec![];
|
||||||
|
|
||||||
for term_ref in src.iter()? {
|
for term_ref in src.iter()? {
|
||||||
match term_ref? {
|
match term_ref? {
|
||||||
ArithTermRef::Constant(c) => self.push_constant(c)?,
|
ArithTermRef::Constant(c) => self.push_constant(c)?,
|
||||||
ArithTermRef::Var(lvl, cell, name) => {
|
ArithTermRef::Var(cell, name) => {
|
||||||
match marker.bindings().get(&name) {
|
let r = if cell.get().norm().reg_num() == 0 {
|
||||||
Some(&VarData::Temp(_, t, _)) if t != 0 => {},
|
match self.bindings.get(&name) {
|
||||||
Some(&VarData::Perm(p)) if p != 0 => {},
|
Some(&VarData::Temp(_, t, _)) if t != 0 => RegType::Temp(t),
|
||||||
_ => return Err(ArithmeticError::UninstantiatedVar),
|
Some(&VarData::Perm(p)) if p != 0 => RegType::Perm(p),
|
||||||
}
|
_ => return Err(ArithmeticError::UninstantiatedVar),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cell.get().norm()
|
||||||
|
};
|
||||||
|
|
||||||
let mut target = vec![];
|
self.interm.push(ArithmeticTerm::Reg(r));
|
||||||
marker.mark_var(name.clone(), lvl, cell, term_loc, &mut target);
|
|
||||||
code.extend(target.into_iter().map(Line::Query));
|
|
||||||
|
|
||||||
self.interm.push(ArithmeticTerm::Reg(cell.get().norm()));
|
|
||||||
}
|
}
|
||||||
ArithTermRef::Op(name, arity) => {
|
ArithTermRef::Op(name, arity) => {
|
||||||
code.push(Line::Arithmetic(self.instr_from_clause(name, arity)?));
|
code.push(Line::Arithmetic(self.instr_from_clause(name, arity)?));
|
||||||
@@ -318,22 +311,8 @@ impl ArithmeticEvaluator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let GenContext::Last(_) = term_loc {
|
|
||||||
self.tempify_perm_reg();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok((code, self.interm.pop()))
|
Ok((code, self.interm.pop()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tempify_perm_reg(&mut self) {
|
|
||||||
if let Some(interm) = self.interm.pop() {
|
|
||||||
if let ArithmeticTerm::Reg(RegType::Perm(_)) = interm {
|
|
||||||
self.interm.push(ArithmeticTerm::Reg(RegType::Temp(self.arg_c)));
|
|
||||||
} else {
|
|
||||||
self.interm.push(interm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// integer division rounding function -- 9.1.3.1.
|
// integer division rounding function -- 9.1.3.1.
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ pub enum SystemClauseType {
|
|||||||
AbolishModuleClause,
|
AbolishModuleClause,
|
||||||
AssertDynamicPredicateToBack,
|
AssertDynamicPredicateToBack,
|
||||||
AssertDynamicPredicateToFront,
|
AssertDynamicPredicateToFront,
|
||||||
|
AtEndOfExpansion,
|
||||||
AtomChars,
|
AtomChars,
|
||||||
AtomCodes,
|
AtomCodes,
|
||||||
AtomLength,
|
AtomLength,
|
||||||
@@ -208,6 +209,7 @@ pub enum SystemClauseType {
|
|||||||
LiftedHeapLength,
|
LiftedHeapLength,
|
||||||
ModuleAssertDynamicPredicateToFront,
|
ModuleAssertDynamicPredicateToFront,
|
||||||
ModuleAssertDynamicPredicateToBack,
|
ModuleAssertDynamicPredicateToBack,
|
||||||
|
ModuleExists,
|
||||||
ModuleOf,
|
ModuleOf,
|
||||||
ModuleRetractClause,
|
ModuleRetractClause,
|
||||||
NoSuchPredicate,
|
NoSuchPredicate,
|
||||||
@@ -263,6 +265,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::AbolishModuleClause => clause_name!("$abolish_module_clause"),
|
&SystemClauseType::AbolishModuleClause => clause_name!("$abolish_module_clause"),
|
||||||
&SystemClauseType::AssertDynamicPredicateToBack => clause_name!("$assertz"),
|
&SystemClauseType::AssertDynamicPredicateToBack => clause_name!("$assertz"),
|
||||||
&SystemClauseType::AssertDynamicPredicateToFront => clause_name!("$asserta"),
|
&SystemClauseType::AssertDynamicPredicateToFront => clause_name!("$asserta"),
|
||||||
|
&SystemClauseType::AtEndOfExpansion => clause_name!("$at_end_of_expansion"),
|
||||||
&SystemClauseType::AtomChars => clause_name!("$atom_chars"),
|
&SystemClauseType::AtomChars => clause_name!("$atom_chars"),
|
||||||
&SystemClauseType::AtomCodes => clause_name!("$atom_codes"),
|
&SystemClauseType::AtomCodes => clause_name!("$atom_codes"),
|
||||||
&SystemClauseType::AtomLength => clause_name!("$atom_length"),
|
&SystemClauseType::AtomLength => clause_name!("$atom_length"),
|
||||||
@@ -342,6 +345,7 @@ impl SystemClauseType {
|
|||||||
clause_name!("$module_assertz")
|
clause_name!("$module_assertz")
|
||||||
}
|
}
|
||||||
&SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"),
|
&SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"),
|
||||||
|
&SystemClauseType::ModuleExists => clause_name!("$module_exists"),
|
||||||
&SystemClauseType::ModuleOf => clause_name!("$module_of"),
|
&SystemClauseType::ModuleOf => clause_name!("$module_of"),
|
||||||
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
|
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
|
||||||
&SystemClauseType::NumberToChars => clause_name!("$number_to_chars"),
|
&SystemClauseType::NumberToChars => clause_name!("$number_to_chars"),
|
||||||
@@ -392,6 +396,7 @@ impl SystemClauseType {
|
|||||||
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
||||||
match (name, arity) {
|
match (name, arity) {
|
||||||
("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause),
|
("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause),
|
||||||
|
("$at_end_of_expansion", 0) => Some(SystemClauseType::AtEndOfExpansion),
|
||||||
("$atom_chars", 2) => Some(SystemClauseType::AtomChars),
|
("$atom_chars", 2) => Some(SystemClauseType::AtomChars),
|
||||||
("$atom_codes", 2) => Some(SystemClauseType::AtomCodes),
|
("$atom_codes", 2) => Some(SystemClauseType::AtomCodes),
|
||||||
("$atom_length", 2) => Some(SystemClauseType::AtomLength),
|
("$atom_length", 2) => Some(SystemClauseType::AtomLength),
|
||||||
@@ -448,6 +453,7 @@ impl SystemClauseType {
|
|||||||
("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter),
|
("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter),
|
||||||
("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength),
|
("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength),
|
||||||
("$maybe", 0) => Some(SystemClauseType::Maybe),
|
("$maybe", 0) => Some(SystemClauseType::Maybe),
|
||||||
|
("$module_exists", 1) => Some(SystemClauseType::ModuleExists),
|
||||||
("$module_of", 2) => Some(SystemClauseType::ModuleOf),
|
("$module_of", 2) => Some(SystemClauseType::ModuleOf),
|
||||||
("$module_retract_clause", 5) => Some(SystemClauseType::ModuleRetractClause),
|
("$module_retract_clause", 5) => Some(SystemClauseType::ModuleRetractClause),
|
||||||
("$module_head_is_dynamic", 2) => Some(SystemClauseType::ModuleHeadIsDynamic),
|
("$module_head_is_dynamic", 2) => Some(SystemClauseType::ModuleHeadIsDynamic),
|
||||||
@@ -595,8 +601,8 @@ impl ClauseType {
|
|||||||
|
|
||||||
pub fn name(&self) -> ClauseName {
|
pub fn name(&self) -> ClauseName {
|
||||||
match self {
|
match self {
|
||||||
&ClauseType::CallN => clause_name!("call"),
|
|
||||||
&ClauseType::BuiltIn(ref built_in) => built_in.name(),
|
&ClauseType::BuiltIn(ref built_in) => built_in.name(),
|
||||||
|
&ClauseType::CallN => clause_name!("call"),
|
||||||
&ClauseType::Hook(ref hook) => hook.name(),
|
&ClauseType::Hook(ref hook) => hook.name(),
|
||||||
&ClauseType::Inlined(ref inlined) => clause_name!(inlined.name()),
|
&ClauseType::Inlined(ref inlined) => clause_name!(inlined.name()),
|
||||||
&ClauseType::Op(ref name, ..) => name.clone(),
|
&ClauseType::Op(ref name, ..) => name.clone(),
|
||||||
|
|||||||
@@ -360,10 +360,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
self.mark_non_callable(name.clone(), 2, term_loc, vr, code);
|
self.mark_non_callable(name.clone(), 2, term_loc, vr, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.marker.reset_arg(2);
|
let (mut lcode, at_1) = self.call_arith_eval(terms[0].as_ref(), 1)?;
|
||||||
|
let (mut rcode, at_2) = self.call_arith_eval(terms[1].as_ref(), 2)?;
|
||||||
let (mut lcode, at_1) = self.call_arith_eval(terms[0].as_ref(), 1, term_loc, 1)?;
|
|
||||||
let (mut rcode, at_2) = self.call_arith_eval(terms[1].as_ref(), 2, term_loc, 2)?;
|
|
||||||
|
|
||||||
code.append(&mut lcode);
|
code.append(&mut lcode);
|
||||||
code.append(&mut rcode);
|
code.append(&mut rcode);
|
||||||
@@ -498,14 +496,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn call_arith_eval(
|
fn call_arith_eval(
|
||||||
&mut self,
|
&self,
|
||||||
term: &'a Term,
|
term: &'a Term,
|
||||||
target_int: usize,
|
target_int: usize,
|
||||||
term_loc: GenContext,
|
|
||||||
arg_c: usize
|
|
||||||
) -> Result<ArithCont, ArithmeticError> {
|
) -> Result<ArithCont, ArithmeticError> {
|
||||||
let mut evaluator = ArithmeticEvaluator::new(target_int, arg_c);
|
let mut evaluator = ArithmeticEvaluator::new(self.marker.bindings(), target_int);
|
||||||
evaluator.eval(&mut self.marker, term, term_loc)
|
evaluator.eval(term)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_is_call(
|
fn compile_is_call(
|
||||||
@@ -515,17 +511,20 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
use_default_call_policy: bool,
|
use_default_call_policy: bool,
|
||||||
) -> Result<(), ParserError> {
|
) -> Result<(), ParserError> {
|
||||||
self.marker.reset_arg(2);
|
let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?;
|
||||||
|
code.append(&mut acode);
|
||||||
|
|
||||||
Ok(match terms[0].as_ref() {
|
Ok(match terms[0].as_ref() {
|
||||||
&Term::Var(ref vr, ref name) => {
|
&Term::Var(ref vr, ref name) => {
|
||||||
let mut target = vec![];
|
let mut target = vec![];
|
||||||
self.marker.mark_var(name.clone(), Level::Shallow, vr, term_loc, &mut target);
|
|
||||||
|
|
||||||
code.extend(target.into_iter().map(Line::Query));
|
self.marker.reset_arg(2);
|
||||||
|
self.marker
|
||||||
|
.mark_var(name.clone(), Level::Shallow, vr, term_loc, &mut target);
|
||||||
|
|
||||||
let (acode, at) = self.call_arith_eval(terms[1].as_ref(), 1, term_loc, 2)?;
|
if !target.is_empty() {
|
||||||
code.extend(acode.into_iter());
|
code.extend(target.into_iter().map(Line::Query));
|
||||||
|
}
|
||||||
|
|
||||||
if use_default_call_policy {
|
if use_default_call_policy {
|
||||||
code.push(is_call_by_default!(temp_v!(1), at.unwrap_or(interm!(1))))
|
code.push(is_call_by_default!(temp_v!(1), at.unwrap_or(interm!(1))))
|
||||||
@@ -534,9 +533,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Term::Constant(_, ref c @ Constant::Integer(_)) => {
|
&Term::Constant(_, ref c @ Constant::Integer(_)) => {
|
||||||
let (acode, at) = self.call_arith_eval(terms[1].as_ref(), 1, term_loc, 2)?;
|
|
||||||
code.extend(acode.into_iter());
|
|
||||||
|
|
||||||
code.push(Line::Query(put_constant!(
|
code.push(Line::Query(put_constant!(
|
||||||
Level::Shallow,
|
Level::Shallow,
|
||||||
c.clone(),
|
c.clone(),
|
||||||
@@ -550,9 +546,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Term::Constant(_, ref c @ Constant::Float(_)) => {
|
&Term::Constant(_, ref c @ Constant::Float(_)) => {
|
||||||
let (acode, at) = self.call_arith_eval(terms[1].as_ref(), 1, term_loc, 2)?;
|
|
||||||
code.extend(acode.into_iter());
|
|
||||||
|
|
||||||
code.push(Line::Query(put_constant!(
|
code.push(Line::Query(put_constant!(
|
||||||
Level::Shallow,
|
Level::Shallow,
|
||||||
c.clone(),
|
c.clone(),
|
||||||
@@ -566,9 +559,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Term::Constant(_, ref c @ Constant::Rational(_)) => {
|
&Term::Constant(_, ref c @ Constant::Rational(_)) => {
|
||||||
let (acode, at) = self.call_arith_eval(terms[1].as_ref(), 1, term_loc, 2)?;
|
|
||||||
code.extend(acode.into_iter());
|
|
||||||
|
|
||||||
code.push(Line::Query(put_constant!(
|
code.push(Line::Query(put_constant!(
|
||||||
Level::Shallow,
|
Level::Shallow,
|
||||||
c.clone(),
|
c.clone(),
|
||||||
|
|||||||
@@ -56,14 +56,15 @@
|
|||||||
'$del_attr'(Ls0, V, Attr) :-
|
'$del_attr'(Ls0, V, Attr) :-
|
||||||
Ls0 = [Att | Ls1],
|
Ls0 = [Att | Ls1],
|
||||||
nonvar(Att),
|
nonvar(Att),
|
||||||
( Att \= Attr -> '$del_attr_buried'(Ls0, Ls1, V, Attr)
|
( Att \= Attr -> '$del_attr_buried'(Ls0, Ls1, V, Attr)
|
||||||
; '$enqueue_attr_var'(V),
|
; '$enqueue_attr_var'(V),
|
||||||
'$del_attr_head'(V), '$del_attr'(Ls1, V, Attr)
|
'$del_attr_head'(V),
|
||||||
|
'$del_attr'(Ls1, V, Attr)
|
||||||
).
|
).
|
||||||
|
|
||||||
'$del_attr_step'(Ls1, V, Attr) :-
|
'$del_attr_step'(Ls1, V, Attr) :-
|
||||||
( nonvar(Ls1) -> Ls1 = [_ | Ls2], '$del_attr_buried'(Ls1, Ls2, V, Attr)
|
( nonvar(Ls1) -> Ls1 = [_ | Ls2], '$del_attr_buried'(Ls1, Ls2, V, Attr)
|
||||||
; true ).
|
; true ).
|
||||||
|
|
||||||
%% assumptions: Ls0 is a list, Ls1 is its tail;
|
%% assumptions: Ls0 is a list, Ls1 is its tail;
|
||||||
%% the head of Ls0 can be ignored.
|
%% the head of Ls0 can be ignored.
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ user:term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :-
|
|||||||
true/0, unify_with_occurs_check/2, write/1,
|
true/0, unify_with_occurs_check/2, write/1,
|
||||||
write_canonical/1, write_term/2, writeq/1]).
|
write_canonical/1, write_term/2, writeq/1]).
|
||||||
|
|
||||||
|
|
||||||
% the maximum arity flag. needs to be replaced with
|
% the maximum arity flag. needs to be replaced with
|
||||||
% current_prolog_flag(max_arity, MAX_ARITY).
|
% current_prolog_flag(max_arity, MAX_ARITY).
|
||||||
max_arity(255).
|
max_arity(255).
|
||||||
@@ -177,13 +178,13 @@ set_prolog_flag(Flag, _) :-
|
|||||||
|
|
||||||
fail :- '$fail'.
|
fail :- '$fail'.
|
||||||
|
|
||||||
\+ G :- G, !, false.
|
\+ G :- call(G), !, false.
|
||||||
\+ _.
|
\+ _.
|
||||||
|
|
||||||
X \= X :- !, false.
|
X \= X :- !, false.
|
||||||
_ \= _.
|
_ \= _.
|
||||||
|
|
||||||
once(G) :- G, !.
|
once(G) :- call(G), !.
|
||||||
|
|
||||||
repeat.
|
repeat.
|
||||||
repeat :- repeat.
|
repeat :- repeat.
|
||||||
@@ -200,13 +201,14 @@ comma_errors(G1, G2, B) :- '$call_with_default_policy'(','(G1, G2, B)).
|
|||||||
'$set_cp'(B),
|
'$set_cp'(B),
|
||||||
'$call_with_default_policy'(comma_errors(G1, G2, B)).
|
'$call_with_default_policy'(comma_errors(G1, G2, B)).
|
||||||
','(!, Atom, B) :- Atom == !, '$set_cp'(B).
|
','(!, Atom, B) :- Atom == !, '$set_cp'(B).
|
||||||
','(!, G, B) :- '$set_cp'(B), G.
|
','(!, G, B) :- '$set_cp'(B), call(G).
|
||||||
','(G, CF, B) :- compound(CF),
|
','(G, CF, B) :- compound(CF),
|
||||||
'$call_with_default_policy'(CF = ','(G1, G2)),
|
'$call_with_default_policy'(CF = ','(G1, G2)),
|
||||||
!, G,
|
!,
|
||||||
|
call(G),
|
||||||
'$call_with_default_policy'(comma_errors(G1, G2, B)).
|
'$call_with_default_policy'(comma_errors(G1, G2, B)).
|
||||||
','(G, Atom, B) :- Atom == !, !, G, '$set_cp'(B).
|
','(G, Atom, B) :- Atom == !, !, call(G), '$set_cp'(B).
|
||||||
','(G1, G2, _) :- G1, G2.
|
','(G1, G2, _) :- call(G1), call(G2).
|
||||||
|
|
||||||
;(G1, G2) :- '$get_b_value'(B), ;(G1, G2, B).
|
;(G1, G2) :- '$get_b_value'(B), ;(G1, G2, B).
|
||||||
|
|
||||||
@@ -214,37 +216,47 @@ comma_errors(G1, G2, B) :- '$call_with_default_policy'(','(G1, G2, B)).
|
|||||||
;(G1, G4, B) :- compound(G1),
|
;(G1, G4, B) :- compound(G1),
|
||||||
'$call_with_default_policy'(G1 = ->(G2, G3)),
|
'$call_with_default_policy'(G1 = ->(G2, G3)),
|
||||||
!,
|
!,
|
||||||
(G2 -> G3 ; '$set_cp'(B), G4).
|
( call(G2) -> call(G3)
|
||||||
;(G1, G2, B) :- G1 == !, '$set_cp'(B), G2.
|
; '$set_cp'(B),
|
||||||
;(G1, G2, B) :- G2 == !, G1, '$set_cp'(B).
|
call(G4)
|
||||||
;(G, _, _) :- G.
|
).
|
||||||
;(_, G, _) :- G.
|
;(G1, G2, B) :- G1 == !, '$set_cp'(B), call(G2).
|
||||||
|
;(G1, G2, B) :- G2 == !, call(G1), '$set_cp'(B).
|
||||||
|
;(G, _, _) :- call(G).
|
||||||
|
;(_, G, _) :- call(G).
|
||||||
|
|
||||||
G1 -> G2 :- '$get_b_value'(B), '$call_with_default_policy'(->(G1, G2, B)).
|
G1 -> G2 :- '$get_b_value'(B), '$call_with_default_policy'(->(G1, G2, B)).
|
||||||
|
|
||||||
:- non_counted_backtracking (->)/3.
|
:- non_counted_backtracking (->)/3.
|
||||||
->(G1, G2, B) :- G2 == !, G1, '$set_cp'(B).
|
->(G1, G2, B) :- G2 == !, call(G1), '$set_cp'(B).
|
||||||
->(G1, G2, B) :- G1, '$set_cp'(B), G2.
|
->(G1, G2, B) :- call(G1), '$set_cp'(B), call(G2).
|
||||||
|
|
||||||
% univ.
|
% univ.
|
||||||
|
|
||||||
:- non_counted_backtracking univ_errors/3.
|
:- non_counted_backtracking univ_errors/3.
|
||||||
univ_errors(Term, List, N) :-
|
univ_errors(Term, List, N) :-
|
||||||
'$skip_max_list'(N, -1, List, R),
|
'$skip_max_list'(N, -1, List, R),
|
||||||
( var(R) -> ( var(Term), throw(error(instantiation_error, (=..)/2)) % 8.5.3.3 a)
|
( var(R) ->
|
||||||
; true )
|
( var(Term), throw(error(instantiation_error, (=..)/2)) % 8.5.3.3 a)
|
||||||
; R \== [] -> throw(error(type_error(list, List), (=..)/2)) % 8.5.3.3 b)
|
; true
|
||||||
; List = [H|T] -> ( var(H), var(Term), % R == [] => List is a proper list.
|
)
|
||||||
throw(error(instantiation_error, (=..)/2)) % 8.5.3.3 c)
|
; R \== [] ->
|
||||||
; T \== [], nonvar(H), \+ atom(H),
|
throw(error(type_error(list, List), (=..)/2)) % 8.5.3.3 b)
|
||||||
throw(error(type_error(atom, H), (=..)/2)) % 8.5.3.3 d)
|
; List = [H|T] ->
|
||||||
; compound(H), T == [],
|
( var(H), var(Term), % R == [] => List is a proper list.
|
||||||
throw(error(type_error(atomic, H), (=..)/2)) % 8.5.3.3 e)
|
throw(error(instantiation_error, (=..)/2)) % 8.5.3.3 c)
|
||||||
; var(Term), max_arity(M), N - 1 > M,
|
; T \== [], nonvar(H), \+ atom(H),
|
||||||
throw(error(representation_error(max_arity), (=..)/2)) % 8.5.3.3 g)
|
throw(error(type_error(atom, H), (=..)/2)) % 8.5.3.3 d)
|
||||||
; true )
|
; compound(H), T == [],
|
||||||
; var(Term) -> throw(error(domain_error(non_empty_list, List), (=..)/2)) % 8.5.3.3 f)
|
throw(error(type_error(atomic, H), (=..)/2)) % 8.5.3.3 e)
|
||||||
; true ).
|
; var(Term), max_arity(M), N - 1 > M,
|
||||||
|
throw(error(representation_error(max_arity), (=..)/2)) % 8.5.3.3 g)
|
||||||
|
; true
|
||||||
|
)
|
||||||
|
; var(Term) ->
|
||||||
|
throw(error(domain_error(non_empty_list, List), (=..)/2)) % 8.5.3.3 f)
|
||||||
|
; true
|
||||||
|
).
|
||||||
|
|
||||||
Term =.. List :- '$call_with_default_policy'(univ_errors(Term, List, N)),
|
Term =.. List :- '$call_with_default_policy'(univ_errors(Term, List, N)),
|
||||||
'$call_with_default_policy'(univ_worker(Term, List, N)).
|
'$call_with_default_policy'(univ_worker(Term, List, N)).
|
||||||
@@ -371,7 +383,8 @@ catch(G,C,R) :- '$get_current_block'(Bb), '$call_with_default_policy'(catch(G,C,
|
|||||||
|
|
||||||
:- non_counted_backtracking catch/4.
|
:- non_counted_backtracking catch/4.
|
||||||
catch(G,C,R,Bb) :-
|
catch(G,C,R,Bb) :-
|
||||||
'$install_new_block'(NBb), call(G),
|
'$install_new_block'(NBb),
|
||||||
|
call(G),
|
||||||
'$call_with_default_policy'(end_block(Bb, NBb)).
|
'$call_with_default_policy'(end_block(Bb, NBb)).
|
||||||
catch(G,C,R,Bb) :-
|
catch(G,C,R,Bb) :-
|
||||||
'$reset_block'(Bb),
|
'$reset_block'(Bb),
|
||||||
|
|||||||
@@ -1184,7 +1184,7 @@ indomain(1).
|
|||||||
% Examples:
|
% Examples:
|
||||||
%
|
%
|
||||||
% ==
|
% ==
|
||||||
% ?-
|
% ?- sat(A =< B), Vs = [A,B], sat_count(+[1|Vs], Count).
|
||||||
% Vs = [A, B],
|
% Vs = [A, B],
|
||||||
% Count = 3,
|
% Count = 3,
|
||||||
% sat(A=:=A*B).
|
% sat(A=:=A*B).
|
||||||
@@ -1195,7 +1195,7 @@ indomain(1).
|
|||||||
% Vs = [...],
|
% Vs = [...],
|
||||||
% CountOr = 1329227995784915872903807060280344575,
|
% CountOr = 1329227995784915872903807060280344575,
|
||||||
% CountAnd = 1.
|
% CountAnd = 1.
|
||||||
% ==sat(A =< B), Vs = [A,B], sat_count(+[1|Vs], Count).
|
% ==
|
||||||
|
|
||||||
sat_count(Sat0, N) :-
|
sat_count(Sat0, N) :-
|
||||||
catch((parse_sat(Sat0, Sat),
|
catch((parse_sat(Sat0, Sat),
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
|
|
||||||
:- use_module(library(lists), [append/3]).
|
:- use_module(library(lists), [append/3]).
|
||||||
|
|
||||||
user:term_expansion(Term0, (Head :- Body)) :-
|
user:term_expansion(Term0, Term) :-
|
||||||
dcg_rule(Term0, Term),
|
nonvar(Term0),
|
||||||
|
dcg_rule(Term0, (Head :- Body)),
|
||||||
Term = (Head :- Body).
|
Term = (Head :- Body).
|
||||||
|
|
||||||
phrase(GRBody, S0) :-
|
phrase(GRBody, S0) :-
|
||||||
@@ -33,7 +34,7 @@ phrase_((A ; B), S0, S) :-
|
|||||||
%% phrase_((A | B), S0, S) :-
|
%% phrase_((A | B), S0, S) :-
|
||||||
%% ( phrase(A, S0, S) ; phrase(B, S0, S) ).
|
%% ( phrase(A, S0, S) ; phrase(B, S0, S) ).
|
||||||
phrase_({G}, S0, S) :-
|
phrase_({G}, S0, S) :-
|
||||||
( G, S0 = S ).
|
( call(G), S0 = S ).
|
||||||
phrase_(call(G), S0, S) :-
|
phrase_(call(G), S0, S) :-
|
||||||
call(G, S0, S).
|
call(G, S0, S).
|
||||||
phrase_((A -> B), S0, S) :-
|
phrase_((A -> B), S0, S) :-
|
||||||
|
|||||||
@@ -46,8 +46,11 @@ call_cleanup(G, C) :- setup_call_cleanup(true, G, C).
|
|||||||
|
|
||||||
% setup_call_cleanup.
|
% setup_call_cleanup.
|
||||||
|
|
||||||
setup_call_cleanup(S, G, C) :- '$get_b_value'(B),
|
setup_call_cleanup(S, G, C) :-
|
||||||
S, '$set_cp_by_default'(B), '$get_current_block'(Bb),
|
'$get_b_value'(B),
|
||||||
|
call(S),
|
||||||
|
'$set_cp_by_default'(B),
|
||||||
|
'$get_current_block'(Bb),
|
||||||
( '$call_with_default_policy'(var(C)) ->
|
( '$call_with_default_policy'(var(C)) ->
|
||||||
throw(error(instantiation_error, setup_call_cleanup/3))
|
throw(error(instantiation_error, setup_call_cleanup/3))
|
||||||
; '$call_with_default_policy'(scc_helper(C, G, Bb))
|
; '$call_with_default_policy'(scc_helper(C, G, Bb))
|
||||||
@@ -83,10 +86,14 @@ run_cleaners_with_handling :-
|
|||||||
|
|
||||||
:- non_counted_backtracking run_cleaners_without_handling/1.
|
:- non_counted_backtracking run_cleaners_without_handling/1.
|
||||||
run_cleaners_without_handling(Cp) :-
|
run_cleaners_without_handling(Cp) :-
|
||||||
'$get_scc_cleaner'(C), '$get_level'(B), C, '$set_cp_by_default'(B),
|
'$get_scc_cleaner'(C),
|
||||||
|
'$get_level'(B),
|
||||||
|
call(C),
|
||||||
|
'$set_cp_by_default'(B),
|
||||||
'$call_with_default_policy'(run_cleaners_without_handling(Cp)).
|
'$call_with_default_policy'(run_cleaners_without_handling(Cp)).
|
||||||
run_cleaners_without_handling(Cp) :-
|
run_cleaners_without_handling(Cp) :-
|
||||||
'$set_cp_by_default'(Cp), '$restore_cut_policy'.
|
'$set_cp_by_default'(Cp),
|
||||||
|
'$restore_cut_policy'.
|
||||||
|
|
||||||
% call_with_inference_limit
|
% call_with_inference_limit
|
||||||
|
|
||||||
@@ -123,8 +130,12 @@ call_with_inference_limit(G, L, R, Bb, B) :-
|
|||||||
call_with_inference_limit(_, _, R, Bb, B) :-
|
call_with_inference_limit(_, _, R, Bb, B) :-
|
||||||
'$reset_block'(Bb),
|
'$reset_block'(Bb),
|
||||||
'$remove_inference_counter'(B, _),
|
'$remove_inference_counter'(B, _),
|
||||||
( '$get_ball'(Ball), '$get_level'(Cp), '$set_cp_by_default'(Cp)
|
( '$get_ball'(Ball),
|
||||||
; '$remove_call_policy_check'(B), '$fail' ),
|
'$get_level'(Cp),
|
||||||
|
'$set_cp_by_default'(Cp)
|
||||||
|
; '$remove_call_policy_check'(B),
|
||||||
|
'$fail'
|
||||||
|
),
|
||||||
'$erase_ball',
|
'$erase_ball',
|
||||||
'$call_with_default_policy'(handle_ile(B, Ball, R)).
|
'$call_with_default_policy'(handle_ile(B, Ball, R)).
|
||||||
|
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ fn load_module<R: Read>(
|
|||||||
// this impromptu definition (namely, its exports) will be filled out later.
|
// this impromptu definition (namely, its exports) will be filled out later.
|
||||||
let module_decl = ModuleDecl { name: listing_src, exports: vec![] };
|
let module_decl = ModuleDecl { name: listing_src, exports: vec![] };
|
||||||
|
|
||||||
let mut module = Module::new(module_decl, wam.indices.atom_tbl.clone());
|
let mut module = Module::new(module_decl, wam.indices.atom_tbl.clone());
|
||||||
let module_name = module.module_decl.name.clone();
|
let module_name = module.module_decl.name.clone();
|
||||||
|
|
||||||
module.is_impromptu_module = true;
|
module.is_impromptu_module = true;
|
||||||
@@ -94,6 +94,7 @@ fn load_module<R: Read>(
|
|||||||
|
|
||||||
results.and_then(|results| compile_work_impl(&mut compiler, wam, indices, results))
|
results.and_then(|results| compile_work_impl(&mut compiler, wam, indices, results))
|
||||||
.or_else(|e| {
|
.or_else(|e| {
|
||||||
|
wam.indices.take_module(module_name.clone());
|
||||||
compiler.print_error(&e);
|
compiler.print_error(&e);
|
||||||
Err(e)
|
Err(e)
|
||||||
})?;
|
})?;
|
||||||
@@ -201,6 +202,24 @@ pub fn compile_appendix(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn append_trivial_goal(name: &ClauseName, pred: &mut Predicate)
|
||||||
|
{
|
||||||
|
let var = Box::new(Term::Var(Cell::default(), Rc::new(String::from("X"))));
|
||||||
|
let body = QueryTerm::Clause(
|
||||||
|
Cell::default(),
|
||||||
|
ClauseType::from(clause_name!("$at_end_of_expansion"), 0, None),
|
||||||
|
vec![],
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
let rule = Rule {
|
||||||
|
head: (name.clone(), vec![var.clone(), var], body),
|
||||||
|
clauses: vec![]
|
||||||
|
};
|
||||||
|
|
||||||
|
pred.0.push(PredicateClause::Rule(rule, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
impl CodeRepo {
|
impl CodeRepo {
|
||||||
pub fn compile_hook(
|
pub fn compile_hook(
|
||||||
&mut self,
|
&mut self,
|
||||||
@@ -209,13 +228,17 @@ impl CodeRepo {
|
|||||||
) -> Result<(), ParserError> {
|
) -> Result<(), ParserError> {
|
||||||
let key = (hook.name(), hook.arity());
|
let key = (hook.name(), hook.arity());
|
||||||
|
|
||||||
match self.term_dir.get(&key) {
|
match self.term_dir.get_mut(&key) {
|
||||||
Some(preds) => {
|
Some(ref mut preds) => {
|
||||||
|
append_trivial_goal(&key.0, &mut preds.0);
|
||||||
|
|
||||||
let mut cg = CodeGenerator::<DebrayAllocator>::new(false, flags);
|
let mut cg = CodeGenerator::<DebrayAllocator>::new(false, flags);
|
||||||
let mut code = cg.compile_predicate(&(preds.0).0)?;
|
let mut code = cg.compile_predicate(&(preds.0).0)?;
|
||||||
|
|
||||||
compile_appendix(&mut code, &preds.1, false, flags)?;
|
compile_appendix(&mut code, &preds.1, false, flags)?;
|
||||||
|
|
||||||
|
(preds.0).0.pop();
|
||||||
|
|
||||||
Ok(match hook {
|
Ok(match hook {
|
||||||
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
|
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
|
||||||
self.term_expanders = code
|
self.term_expanders = code
|
||||||
@@ -225,7 +248,26 @@ impl CodeRepo {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
None => Ok(()),
|
None => Ok(match hook {
|
||||||
|
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
|
||||||
|
if self.term_expanders.is_empty() {
|
||||||
|
let mut preds = Predicate::new();
|
||||||
|
append_trivial_goal(&key.0, &mut preds);
|
||||||
|
|
||||||
|
let mut cg = CodeGenerator::<DebrayAllocator>::new(false, flags);
|
||||||
|
self.term_expanders = cg.compile_predicate(&preds.0)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
|
||||||
|
if self.goal_expanders.is_empty() {
|
||||||
|
let mut preds = Predicate::new();
|
||||||
|
append_trivial_goal(&key.0, &mut preds);
|
||||||
|
|
||||||
|
let mut cg = CodeGenerator::<DebrayAllocator>::new(false, flags);
|
||||||
|
self.goal_expanders = cg.compile_predicate(&preds.0)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -940,9 +982,12 @@ fn compile_work_impl(
|
|||||||
if let Some(ref mut module) = &mut compiler.module {
|
if let Some(ref mut module) = &mut compiler.module {
|
||||||
// compile the module-level goal and term expansions and store
|
// compile the module-level goal and term expansions and store
|
||||||
// their locations to the module's code_dir.
|
// their locations to the module's code_dir.
|
||||||
let decls = module.take_local_expansions();
|
let mut decls = module.take_local_expansions();
|
||||||
|
|
||||||
if !decls.is_empty() {
|
if !decls.is_empty() {
|
||||||
|
append_trivial_goal(&clause_name!("term_expansion"), &mut decls[0].0);
|
||||||
|
append_trivial_goal(&clause_name!("goal_expansion"), &mut decls[1].0);
|
||||||
|
|
||||||
results.worker_results.extend(decls.into_iter());
|
results.worker_results.extend(decls.into_iter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ impl MachineError {
|
|||||||
],
|
],
|
||||||
SharedOpDesc::new(400, YFX)
|
SharedOpDesc::new(400, YFX)
|
||||||
));
|
));
|
||||||
|
|
||||||
stub.append(&mut functor!(
|
stub.append(&mut functor!(
|
||||||
":",
|
":",
|
||||||
2,
|
2,
|
||||||
|
|||||||
@@ -211,6 +211,8 @@ pub enum IndexPtr {
|
|||||||
DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
|
DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
|
||||||
Undefined,
|
Undefined,
|
||||||
Index(usize),
|
Index(usize),
|
||||||
|
UserGoalExpansion,
|
||||||
|
UserTermExpansion
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
@@ -418,7 +420,7 @@ impl Add<usize> for CodePtr {
|
|||||||
| p @ CodePtr::VerifyAttrInterrupt(_)
|
| p @ CodePtr::VerifyAttrInterrupt(_)
|
||||||
| p @ CodePtr::DynamicTransaction(..) => p,
|
| p @ CodePtr::DynamicTransaction(..) => p,
|
||||||
CodePtr::Local(local) => CodePtr::Local(local + rhs),
|
CodePtr::Local(local) => CodePtr::Local(local + rhs),
|
||||||
CodePtr::CallN(_, local, _) | CodePtr::BuiltInClause(_, local) => {
|
CodePtr::BuiltInClause(_, local) | CodePtr::CallN(_, local, _) => {
|
||||||
CodePtr::Local(local + rhs)
|
CodePtr::Local(local + rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -491,6 +493,19 @@ impl IndexStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_term_and_goal_expansion_indices(&mut self) {
|
||||||
|
self.code_dir.insert((clause_name!("term_expansion"), 2),
|
||||||
|
CodeIndex(Rc::new(RefCell::new(
|
||||||
|
(IndexPtr::UserTermExpansion,
|
||||||
|
clause_name!("user"))
|
||||||
|
))));
|
||||||
|
self.code_dir.insert((clause_name!("goal_expansion"), 2),
|
||||||
|
CodeIndex(Rc::new(RefCell::new(
|
||||||
|
(IndexPtr::UserGoalExpansion,
|
||||||
|
clause_name!("user"))
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn remove_clause_subsection(&mut self, module: ClauseName, name: ClauseName, arity: usize) {
|
pub fn remove_clause_subsection(&mut self, module: ClauseName, name: ClauseName, arity: usize) {
|
||||||
self.dynamic_code_dir.swap_remove(&(module, name, arity));
|
self.dynamic_code_dir.swap_remove(&(module, name, arity));
|
||||||
|
|||||||
@@ -261,6 +261,7 @@ pub struct MachineState {
|
|||||||
pub(super) last_call: bool,
|
pub(super) last_call: bool,
|
||||||
pub(crate) heap_locs: HeapVarDict,
|
pub(crate) heap_locs: HeapVarDict,
|
||||||
pub(crate) flags: MachineFlags,
|
pub(crate) flags: MachineFlags,
|
||||||
|
pub(crate) at_end_of_expansion: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
@@ -316,17 +317,17 @@ impl MachineState {
|
|||||||
Ok(codes)
|
Ok(codes)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn call_at_index(&mut self, arity: usize, p: usize) {
|
pub(super) fn call_at_index(&mut self, arity: usize, p: LocalCodePtr) {
|
||||||
self.cp.assign_if_local(self.p.clone() + 1);
|
self.cp.assign_if_local(self.p.clone() + 1);
|
||||||
self.num_of_args = arity;
|
self.num_of_args = arity;
|
||||||
self.b0 = self.b;
|
self.b0 = self.b;
|
||||||
self.p = dir_entry!(p);
|
self.p = CodePtr::Local(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn execute_at_index(&mut self, arity: usize, p: usize) {
|
pub(super) fn execute_at_index(&mut self, arity: usize, p: LocalCodePtr) {
|
||||||
self.num_of_args = arity;
|
self.num_of_args = arity;
|
||||||
self.b0 = self.b;
|
self.b0 = self.b;
|
||||||
self.p = dir_entry!(p);
|
self.p = CodePtr::Local(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn module_lookup(
|
pub(super) fn module_lookup(
|
||||||
@@ -342,9 +343,9 @@ impl MachineState {
|
|||||||
match idx.0.borrow().0 {
|
match idx.0.borrow().0 {
|
||||||
IndexPtr::Index(compiled_tl_index) => {
|
IndexPtr::Index(compiled_tl_index) => {
|
||||||
if last_call {
|
if last_call {
|
||||||
self.execute_at_index(arity, compiled_tl_index);
|
self.execute_at_index(arity, dir_entry!(compiled_tl_index));
|
||||||
} else {
|
} else {
|
||||||
self.call_at_index(arity, compiled_tl_index);
|
self.call_at_index(arity, dir_entry!(compiled_tl_index));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -353,6 +354,24 @@ impl MachineState {
|
|||||||
self.fail = true;
|
self.fail = true;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
IndexPtr::UserTermExpansion => {
|
||||||
|
if last_call {
|
||||||
|
self.execute_at_index(arity, LocalCodePtr::UserTermExpansion(0));
|
||||||
|
} else {
|
||||||
|
self.call_at_index(arity, LocalCodePtr::UserTermExpansion(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
IndexPtr::UserGoalExpansion => {
|
||||||
|
if last_call {
|
||||||
|
self.execute_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
|
||||||
|
} else {
|
||||||
|
self.call_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -390,9 +409,9 @@ fn try_in_situ(
|
|||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) {
|
if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) {
|
||||||
if last_call {
|
if last_call {
|
||||||
machine_st.execute_at_index(arity, p);
|
machine_st.execute_at_index(arity, LocalCodePtr::DirEntry(p));
|
||||||
} else {
|
} else {
|
||||||
machine_st.call_at_index(arity, p);
|
machine_st.call_at_index(arity, LocalCodePtr::DirEntry(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_st.p = in_situ_dir_entry!(p);
|
machine_st.p = in_situ_dir_entry!(p);
|
||||||
@@ -421,7 +440,7 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
machine_st.e = machine_st.stack.index_or_frame(b).prelude.e;
|
machine_st.e = machine_st.stack.index_or_frame(b).prelude.e;
|
||||||
machine_st.cp = machine_st.stack.index_or_frame(b).prelude.cp;
|
machine_st.cp = machine_st.stack.index_or_frame(b).prelude.cp;
|
||||||
|
|
||||||
machine_st.stack.index_or_frame_mut(b).prelude.bp = machine_st.p.clone() + offset;
|
machine_st.stack.index_or_frame_mut(b).prelude.bp = machine_st.p.local() + offset;
|
||||||
|
|
||||||
let old_tr = machine_st.stack.index_or_frame(b).prelude.tr;
|
let old_tr = machine_st.stack.index_or_frame(b).prelude.tr;
|
||||||
let curr_tr = machine_st.tr;
|
let curr_tr = machine_st.tr;
|
||||||
@@ -467,7 +486,7 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
machine_st.e = machine_st.stack.index_or_frame(b).prelude.e;
|
machine_st.e = machine_st.stack.index_or_frame(b).prelude.e;
|
||||||
machine_st.cp = machine_st.stack.index_or_frame(b).prelude.cp;
|
machine_st.cp = machine_st.stack.index_or_frame(b).prelude.cp;
|
||||||
|
|
||||||
machine_st.stack.index_or_frame_mut(b).prelude.bp = machine_st.p.clone() + 1;
|
machine_st.stack.index_or_frame_mut(b).prelude.bp = machine_st.p.local() + 1;
|
||||||
|
|
||||||
let old_tr = machine_st.stack.index_or_frame(b).prelude.tr;
|
let old_tr = machine_st.stack.index_or_frame(b).prelude.tr;
|
||||||
let curr_tr = machine_st.tr;
|
let curr_tr = machine_st.tr;
|
||||||
@@ -619,7 +638,13 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
IndexPtr::Undefined =>
|
IndexPtr::Undefined =>
|
||||||
return try_in_situ(machine_st, name, arity, indices, false),
|
return try_in_situ(machine_st, name, arity, indices, false),
|
||||||
IndexPtr::Index(compiled_tl_index) => {
|
IndexPtr::Index(compiled_tl_index) => {
|
||||||
machine_st.call_at_index(arity, compiled_tl_index)
|
machine_st.call_at_index(arity, LocalCodePtr::DirEntry(compiled_tl_index))
|
||||||
|
}
|
||||||
|
IndexPtr::UserTermExpansion => {
|
||||||
|
machine_st.call_at_index(arity, LocalCodePtr::UserTermExpansion(0));
|
||||||
|
}
|
||||||
|
IndexPtr::UserGoalExpansion => {
|
||||||
|
machine_st.call_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,7 +665,13 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
IndexPtr::Undefined =>
|
IndexPtr::Undefined =>
|
||||||
return try_in_situ(machine_st, name, arity, indices, true),
|
return try_in_situ(machine_st, name, arity, indices, true),
|
||||||
IndexPtr::Index(compiled_tl_index) => {
|
IndexPtr::Index(compiled_tl_index) => {
|
||||||
machine_st.execute_at_index(arity, compiled_tl_index)
|
machine_st.execute_at_index(arity, dir_entry!(compiled_tl_index))
|
||||||
|
}
|
||||||
|
IndexPtr::UserTermExpansion => {
|
||||||
|
machine_st.execute_at_index(arity, LocalCodePtr::UserTermExpansion(0));
|
||||||
|
}
|
||||||
|
IndexPtr::UserGoalExpansion => {
|
||||||
|
machine_st.execute_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -840,6 +871,10 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
|
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
|
||||||
match ClauseType::from(name.clone(), arity, None) {
|
match ClauseType::from(name.clone(), arity, None) {
|
||||||
|
ClauseType::BuiltIn(built_in) => {
|
||||||
|
machine_st.setup_built_in_call(built_in.clone());
|
||||||
|
self.call_builtin(machine_st, &built_in, indices, parsing_stream)?;
|
||||||
|
}
|
||||||
ClauseType::CallN => {
|
ClauseType::CallN => {
|
||||||
machine_st.handle_internal_call_n(arity);
|
machine_st.handle_internal_call_n(arity);
|
||||||
|
|
||||||
@@ -849,10 +884,6 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
|
|
||||||
machine_st.p = CodePtr::CallN(arity, machine_st.p.local(), machine_st.last_call);
|
machine_st.p = CodePtr::CallN(arity, machine_st.p.local(), machine_st.last_call);
|
||||||
}
|
}
|
||||||
ClauseType::BuiltIn(built_in) => {
|
|
||||||
machine_st.setup_built_in_call(built_in.clone());
|
|
||||||
self.call_builtin(machine_st, &built_in, indices, parsing_stream)?;
|
|
||||||
}
|
|
||||||
ClauseType::Inlined(inlined) => {
|
ClauseType::Inlined(inlined) => {
|
||||||
machine_st.execute_inlined(&inlined);
|
machine_st.execute_inlined(&inlined);
|
||||||
|
|
||||||
@@ -874,7 +905,7 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
|
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
|
||||||
|
|
||||||
return Err(machine_st
|
return Err(machine_st
|
||||||
.error_form(MachineError::type_error(ValidType::Callable, name), stub));
|
.error_form(MachineError::type_error(ValidType::Callable, name), stub));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1093,10 +1124,10 @@ impl SCCCutPolicy {
|
|||||||
if let Some(&(_, b_cutoff, prev_block)) = self.cont_pts.last() {
|
if let Some(&(_, b_cutoff, prev_block)) = self.cont_pts.last() {
|
||||||
if machine_st.b < b_cutoff {
|
if machine_st.b < b_cutoff {
|
||||||
let (idx, arity) = if machine_st.block < prev_block {
|
let (idx, arity) = if machine_st.block < prev_block {
|
||||||
(self.r_c_w_h, 0)
|
(dir_entry!(self.r_c_w_h), 0)
|
||||||
} else {
|
} else {
|
||||||
machine_st[temp_v!(1)] = Addr::Con(Constant::Usize(b_cutoff));
|
machine_st[temp_v!(1)] = Addr::Con(Constant::Usize(b_cutoff));
|
||||||
(self.r_c_wo_h, 1)
|
(dir_entry!(self.r_c_wo_h), 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
if machine_st.last_call {
|
if machine_st.last_call {
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ impl MachineState {
|
|||||||
last_call: false,
|
last_call: false,
|
||||||
heap_locs: HeapVarDict::new(),
|
heap_locs: HeapVarDict::new(),
|
||||||
flags: MachineFlags::default(),
|
flags: MachineFlags::default(),
|
||||||
|
at_end_of_expansion: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,6 +106,7 @@ impl MachineState {
|
|||||||
last_call: false,
|
last_call: false,
|
||||||
heap_locs: HeapVarDict::new(),
|
heap_locs: HeapVarDict::new(),
|
||||||
flags: MachineFlags::default(),
|
flags: MachineFlags::default(),
|
||||||
|
at_end_of_expansion: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1988,6 +1990,19 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn set_ball(&mut self) {
|
||||||
|
self.ball.reset();
|
||||||
|
|
||||||
|
let addr = self[temp_v!(1)].clone();
|
||||||
|
self.ball.boundary = self.heap.h;
|
||||||
|
|
||||||
|
copy_term(
|
||||||
|
CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut self.ball.stub),
|
||||||
|
addr,
|
||||||
|
AttrVarPolicy::DeepCopy,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn handle_internal_call_n(&mut self, arity: usize) {
|
pub(super) fn handle_internal_call_n(&mut self, arity: usize) {
|
||||||
let arity = arity + 1;
|
let arity = arity + 1;
|
||||||
let pred = self.registers[1].clone();
|
let pred = self.registers[1].clone();
|
||||||
@@ -2004,19 +2019,6 @@ impl MachineState {
|
|||||||
self.fail = true;
|
self.fail = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn set_ball(&mut self) {
|
|
||||||
self.ball.reset();
|
|
||||||
|
|
||||||
let addr = self[temp_v!(1)].clone();
|
|
||||||
self.ball.boundary = self.heap.h;
|
|
||||||
|
|
||||||
copy_term(
|
|
||||||
CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut self.ball.stub),
|
|
||||||
addr,
|
|
||||||
AttrVarPolicy::DeepCopy,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn setup_call_n(&mut self, arity: usize) -> Option<PredicateKey> {
|
pub(super) fn setup_call_n(&mut self, arity: usize) -> Option<PredicateKey> {
|
||||||
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
|
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
|
||||||
let addr = self.store(self.deref(self.registers[arity].clone()));
|
let addr = self.store(self.deref(self.registers[arity].clone()));
|
||||||
@@ -3240,7 +3242,7 @@ impl MachineState {
|
|||||||
or_frame.prelude.e = self.e;
|
or_frame.prelude.e = self.e;
|
||||||
or_frame.prelude.cp = self.cp;
|
or_frame.prelude.cp = self.cp;
|
||||||
or_frame.prelude.b = self.b;
|
or_frame.prelude.b = self.b;
|
||||||
or_frame.prelude.bp = self.p.clone() + 1;
|
or_frame.prelude.bp = self.p.local() + 1;
|
||||||
or_frame.prelude.tr = self.tr;
|
or_frame.prelude.tr = self.tr;
|
||||||
or_frame.prelude.pstr_tr = self.pstr_tr;
|
or_frame.prelude.pstr_tr = self.pstr_tr;
|
||||||
or_frame.prelude.h = self.heap.h;
|
or_frame.prelude.h = self.heap.h;
|
||||||
@@ -3279,7 +3281,7 @@ impl MachineState {
|
|||||||
or_frame.prelude.e = self.e;
|
or_frame.prelude.e = self.e;
|
||||||
or_frame.prelude.cp = self.cp;
|
or_frame.prelude.cp = self.cp;
|
||||||
or_frame.prelude.b = self.b;
|
or_frame.prelude.b = self.b;
|
||||||
or_frame.prelude.bp = self.p.clone() + offset;
|
or_frame.prelude.bp = self.p.local() + offset;
|
||||||
or_frame.prelude.tr = self.tr;
|
or_frame.prelude.tr = self.tr;
|
||||||
or_frame.prelude.pstr_tr = self.pstr_tr;
|
or_frame.prelude.pstr_tr = self.pstr_tr;
|
||||||
or_frame.prelude.h = self.heap.h;
|
or_frame.prelude.h = self.heap.h;
|
||||||
|
|||||||
@@ -272,7 +272,8 @@ impl Machine {
|
|||||||
self.run_query();
|
self.run_query();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(prolog_stream: PrologStream) -> Self {
|
pub fn new(prolog_stream: PrologStream) -> Self
|
||||||
|
{
|
||||||
let mut wam = Machine {
|
let mut wam = Machine {
|
||||||
machine_st: MachineState::new(),
|
machine_st: MachineState::new(),
|
||||||
inner_heap: Heap::with_capacity(256 * 256),
|
inner_heap: Heap::with_capacity(256 * 256),
|
||||||
@@ -285,6 +286,8 @@ impl Machine {
|
|||||||
|
|
||||||
let atom_tbl = wam.indices.atom_tbl.clone();
|
let atom_tbl = wam.indices.atom_tbl.clone();
|
||||||
|
|
||||||
|
wam.indices.add_term_and_goal_expansion_indices();
|
||||||
|
|
||||||
compile_listing(
|
compile_listing(
|
||||||
&mut wam,
|
&mut wam,
|
||||||
parsing_stream(BUILTINS.as_bytes()),
|
parsing_stream(BUILTINS.as_bytes()),
|
||||||
@@ -739,7 +742,7 @@ impl MachineState {
|
|||||||
let b = self.b;
|
let b = self.b;
|
||||||
|
|
||||||
self.b0 = self.stack.index_or_frame(b).prelude.b0;
|
self.b0 = self.stack.index_or_frame(b).prelude.b0;
|
||||||
self.p = self.stack.index_or_frame(b).prelude.bp.clone();
|
self.p = CodePtr::Local(self.stack.index_or_frame(b).prelude.bp);
|
||||||
|
|
||||||
if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.p {
|
if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.p {
|
||||||
self.fail = p == 0;
|
self.fail = p == 0;
|
||||||
|
|||||||
@@ -108,17 +108,7 @@ impl Module {
|
|||||||
let goal_expansions =
|
let goal_expansions =
|
||||||
mem::replace(&mut self.local_goal_expansions, (Predicate::new(), VecDeque::new()));
|
mem::replace(&mut self.local_goal_expansions, (Predicate::new(), VecDeque::new()));
|
||||||
|
|
||||||
let mut result = vec![];
|
vec![term_expansions, goal_expansions]
|
||||||
|
|
||||||
if !(term_expansions.0).0.is_empty() {
|
|
||||||
result.push(term_expansions);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !(goal_expansions.0).0.is_empty() {
|
|
||||||
result.push(goal_expansions);
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
381
src/prolog/machine/stack.rs
Normal file
381
src/prolog/machine/stack.rs
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
use crate::prolog::machine::machine_indices::*;
|
||||||
|
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
use std::alloc;
|
||||||
|
use std::mem;
|
||||||
|
use std::ops::{Index, IndexMut};
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
const STACK_ALIGN: usize = mem::align_of::<Addr>();
|
||||||
|
const INIT_STACK_SIZE: usize = 10 * 1024 * 1024;
|
||||||
|
|
||||||
|
const fn prelude_size<Prelude>() -> usize {
|
||||||
|
let size = mem::size_of::<Prelude>();
|
||||||
|
let align = mem::align_of::<Addr>();
|
||||||
|
|
||||||
|
(size & !(align - 1)) + align
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Stack {
|
||||||
|
size: usize,
|
||||||
|
base: *const u8,
|
||||||
|
top: *const u8,
|
||||||
|
_marker: PhantomData<Addr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Stack {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.drop_in_place();
|
||||||
|
self.deallocate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct FramePrelude {
|
||||||
|
is_or_frame: u8,
|
||||||
|
pub num_cells: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AndFramePrelude {
|
||||||
|
pub univ_prelude: FramePrelude,
|
||||||
|
pub e: usize,
|
||||||
|
pub cp: LocalCodePtr,
|
||||||
|
pub interrupt_cp: LocalCodePtr,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AndFrame {
|
||||||
|
pub prelude: AndFramePrelude,
|
||||||
|
_marker: PhantomData<Addr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AndFrame {
|
||||||
|
pub fn size_of(num_cells: usize) -> usize {
|
||||||
|
prelude_size::<AndFramePrelude>() + num_cells * mem::size_of::<Addr>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index<usize> for AndFrame {
|
||||||
|
type Output = Addr;
|
||||||
|
|
||||||
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
let prelude_offset = prelude_size::<AndFramePrelude>();
|
||||||
|
let index_offset = (index - 1) * mem::size_of::<Addr>();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let ptr = mem::transmute::<&AndFrame, *const u8>(self);
|
||||||
|
let ptr = ptr as usize + prelude_offset + index_offset;
|
||||||
|
|
||||||
|
&*(ptr as *const Addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexMut<usize> for AndFrame {
|
||||||
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
|
let prelude_offset = prelude_size::<AndFramePrelude>();
|
||||||
|
let index_offset = (index - 1) * mem::size_of::<Addr>();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let ptr = mem::transmute::<&mut AndFrame, *const u8>(self);
|
||||||
|
let ptr = ptr as usize + prelude_offset + index_offset;
|
||||||
|
|
||||||
|
&mut *(ptr as *mut Addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for AndFrame {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let prelude_offset = prelude_size::<AndFramePrelude>();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let ptr = mem::transmute::<&mut AndFrame, *const u8>(self);
|
||||||
|
let ptr = ptr as usize + prelude_offset;
|
||||||
|
|
||||||
|
for idx in 0 .. self.prelude.univ_prelude.num_cells {
|
||||||
|
let index_offset = idx * mem::size_of::<Addr>();
|
||||||
|
let ptr = (ptr + index_offset) as *mut Addr;
|
||||||
|
|
||||||
|
ptr::drop_in_place(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OrFramePrelude {
|
||||||
|
pub univ_prelude: FramePrelude,
|
||||||
|
pub e: usize,
|
||||||
|
pub cp: LocalCodePtr,
|
||||||
|
pub b: usize,
|
||||||
|
pub bp: LocalCodePtr,
|
||||||
|
pub tr: usize,
|
||||||
|
pub pstr_tr: usize,
|
||||||
|
pub h: usize,
|
||||||
|
pub b0: usize,
|
||||||
|
pub attr_var_init_queue_b: usize,
|
||||||
|
pub attr_var_init_bindings_b: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OrFrame {
|
||||||
|
pub prelude: OrFramePrelude,
|
||||||
|
_marker: PhantomData<Addr>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index<usize> for OrFrame {
|
||||||
|
type Output = Addr;
|
||||||
|
|
||||||
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
let prelude_offset = prelude_size::<OrFramePrelude>();
|
||||||
|
let index_offset = index * mem::size_of::<Addr>();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let ptr = mem::transmute::<&OrFrame, *const u8>(self);
|
||||||
|
let ptr = ptr as usize + prelude_offset + index_offset;
|
||||||
|
|
||||||
|
&*(ptr as *const Addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexMut<usize> for OrFrame {
|
||||||
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
|
let prelude_offset = prelude_size::<OrFramePrelude>();
|
||||||
|
let index_offset = index * mem::size_of::<Addr>();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let ptr = mem::transmute::<&mut OrFrame, *const u8>(self);
|
||||||
|
let ptr = ptr as usize + prelude_offset + index_offset;
|
||||||
|
|
||||||
|
&mut *(ptr as *mut Addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for OrFrame {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let prelude_offset = prelude_size::<OrFramePrelude>();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let ptr = mem::transmute::<&mut OrFrame, *const u8>(self);
|
||||||
|
let ptr = ptr as usize + prelude_offset;
|
||||||
|
|
||||||
|
for idx in 0 .. self.prelude.univ_prelude.num_cells {
|
||||||
|
let index_offset = idx * mem::size_of::<Addr>();
|
||||||
|
let ptr = (ptr + index_offset) as *mut Addr;
|
||||||
|
|
||||||
|
ptr::drop_in_place(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OrFrame {
|
||||||
|
pub fn size_of(num_cells: usize) -> usize {
|
||||||
|
prelude_size::<OrFramePrelude>() + num_cells * mem::size_of::<Addr>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stack {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let mut stack = Stack { size: 0, base: ptr::null(), top: ptr::null(),
|
||||||
|
_marker: PhantomData };
|
||||||
|
|
||||||
|
unsafe { stack.grow(); }
|
||||||
|
stack
|
||||||
|
}
|
||||||
|
|
||||||
|
fn empty_stack() -> Self {
|
||||||
|
Stack { size: 0, base: ptr::null(), top: ptr::null(),
|
||||||
|
_marker: PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn take(&mut self) -> Stack {
|
||||||
|
mem::replace(self, Stack::empty_stack())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn free_space(&self) -> usize {
|
||||||
|
debug_assert!(self.top >= self.base,
|
||||||
|
"self.top = {:?} < {:?} = self.base",
|
||||||
|
self.top, self.base);
|
||||||
|
|
||||||
|
self.size - (self.top as usize - self.base as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn grow(&mut self) {
|
||||||
|
if self.size == 0 {
|
||||||
|
let layout = alloc::Layout::from_size_align_unchecked(INIT_STACK_SIZE, STACK_ALIGN);
|
||||||
|
|
||||||
|
self.base = alloc::alloc(layout) as *const _;
|
||||||
|
self.top = self.base as *const _;
|
||||||
|
self.size = INIT_STACK_SIZE;
|
||||||
|
|
||||||
|
self.top = self.top.offset(mem::align_of::<Addr>() as isize);
|
||||||
|
} else {
|
||||||
|
let layout = alloc::Layout::from_size_align_unchecked(self.size, STACK_ALIGN);
|
||||||
|
let top_dist = self.top as usize - self.base as usize;
|
||||||
|
|
||||||
|
self.base = alloc::realloc(self.base as *mut _, layout, self.size*2) as *const _;
|
||||||
|
self.top = (self.base as usize + top_dist) as *const _;
|
||||||
|
self.size *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn new_frame_ptr(&mut self, frame_size: usize) -> *const u8 {
|
||||||
|
loop {
|
||||||
|
if self.free_space() >= frame_size {
|
||||||
|
return (self.top as usize + frame_size) as *const _;
|
||||||
|
} else {
|
||||||
|
self.grow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocate_and_frame(&mut self, num_cells: usize) -> usize {
|
||||||
|
let frame_size = AndFrame::size_of(num_cells);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let new_top = self.new_frame_ptr(frame_size);
|
||||||
|
|
||||||
|
for idx in 0 .. num_cells {
|
||||||
|
let offset = prelude_size::<AndFramePrelude>() + idx * mem::size_of::<Addr>();
|
||||||
|
ptr::write((self.top as usize + offset) as *mut Addr, Addr::HeapCell(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
let and_frame = &mut *(self.top as *mut AndFrame);
|
||||||
|
|
||||||
|
and_frame.prelude.univ_prelude.is_or_frame = 0;
|
||||||
|
and_frame.prelude.univ_prelude.num_cells = num_cells;
|
||||||
|
|
||||||
|
let e = self.top as usize - self.base as usize;
|
||||||
|
self.top = new_top;
|
||||||
|
e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocate_or_frame(&mut self, num_cells: usize) -> usize {
|
||||||
|
let frame_size = OrFrame::size_of(num_cells);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let new_top = self.new_frame_ptr(frame_size);
|
||||||
|
|
||||||
|
for idx in 0 .. num_cells {
|
||||||
|
let offset = prelude_size::<OrFramePrelude>() + idx * mem::size_of::<Addr>();
|
||||||
|
ptr::write((self.top as usize + offset) as *mut Addr, Addr::HeapCell(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
let or_frame = &mut *(self.top as *mut OrFrame);
|
||||||
|
|
||||||
|
or_frame.prelude.univ_prelude.is_or_frame = 1;
|
||||||
|
or_frame.prelude.univ_prelude.num_cells = num_cells;
|
||||||
|
|
||||||
|
let b = self.top as usize - self.base as usize;
|
||||||
|
self.top = new_top;
|
||||||
|
b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn index_and_frame(&self, e: usize) -> &AndFrame {
|
||||||
|
unsafe {
|
||||||
|
let ptr = self.base as usize + e;
|
||||||
|
&*(ptr as *const AndFrame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn index_and_frame_mut(&mut self, e: usize) -> &mut AndFrame {
|
||||||
|
unsafe {
|
||||||
|
let ptr = self.base as usize + e;
|
||||||
|
&mut *(ptr as *mut AndFrame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn index_or_frame(&self, b: usize) -> &OrFrame {
|
||||||
|
unsafe {
|
||||||
|
let ptr = self.base as usize + b;
|
||||||
|
&*(ptr as *const OrFrame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn index_or_frame_mut(&mut self, b: usize) -> &mut OrFrame {
|
||||||
|
unsafe {
|
||||||
|
let ptr = self.base as usize + b;
|
||||||
|
&mut *(ptr as *mut OrFrame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deallocate(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
let layout = alloc::Layout::from_size_align_unchecked(self.size, STACK_ALIGN);
|
||||||
|
alloc::dealloc(self.base as *mut u8, layout);
|
||||||
|
|
||||||
|
self.top = ptr::null();
|
||||||
|
self.base = ptr::null();
|
||||||
|
self.size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn truncate_to_frame(&mut self, b: usize) {
|
||||||
|
if b == 0 {
|
||||||
|
self.truncate(mem::align_of::<Addr>());
|
||||||
|
} else {
|
||||||
|
let univ_prelude = self.index_or_frame(b).prelude.univ_prelude;
|
||||||
|
let size = OrFrame::size_of(univ_prelude.num_cells);
|
||||||
|
|
||||||
|
self.truncate(b + size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn truncate(&mut self, b: usize) {
|
||||||
|
let mut b = b + self.base as usize;
|
||||||
|
let base = b;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
while b as *const _ < self.top {
|
||||||
|
let univ_prelude = ptr::read(b as *const FramePrelude);
|
||||||
|
|
||||||
|
let offset = if univ_prelude.is_or_frame == 0 {
|
||||||
|
let frame_ptr = b as *mut AndFrame;
|
||||||
|
let frame = &mut *frame_ptr;
|
||||||
|
let size_of_frame = AndFrame::size_of(frame.prelude.univ_prelude.num_cells);
|
||||||
|
|
||||||
|
ptr::drop_in_place(frame_ptr);
|
||||||
|
|
||||||
|
b + size_of_frame
|
||||||
|
} else {
|
||||||
|
debug_assert!(univ_prelude.is_or_frame == 1);
|
||||||
|
|
||||||
|
let frame_ptr = b as *mut OrFrame;
|
||||||
|
let frame = &mut *frame_ptr;
|
||||||
|
let size_of_frame = OrFrame::size_of(frame.prelude.univ_prelude.num_cells);
|
||||||
|
|
||||||
|
ptr::drop_in_place(frame_ptr);
|
||||||
|
|
||||||
|
b + size_of_frame
|
||||||
|
};
|
||||||
|
|
||||||
|
b = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if base < self.top as usize {
|
||||||
|
self.top = base as *const _;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drop_in_place(&mut self) {
|
||||||
|
self.truncate(mem::align_of::<Addr>());
|
||||||
|
|
||||||
|
debug_assert!(if self.top.is_null() {
|
||||||
|
self.top == self.base
|
||||||
|
} else {
|
||||||
|
self.top as usize == self.base as usize + mem::align_of::<Addr>()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -637,6 +637,11 @@ impl MachineState {
|
|||||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
&SystemClauseType::AtEndOfExpansion => {
|
||||||
|
if self.cp == LocalCodePtr::TopLevel(0, 0) {
|
||||||
|
self.at_end_of_expansion = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
&SystemClauseType::AtomChars => {
|
&SystemClauseType::AtomChars => {
|
||||||
let a1 = self[temp_v!(1)].clone();
|
let a1 = self[temp_v!(1)].clone();
|
||||||
|
|
||||||
@@ -772,9 +777,9 @@ impl MachineState {
|
|||||||
let p = self.attr_var_init.project_attrs_loc;
|
let p = self.attr_var_init.project_attrs_loc;
|
||||||
|
|
||||||
if self.last_call {
|
if self.last_call {
|
||||||
self.execute_at_index(2, p);
|
self.execute_at_index(2, dir_entry!(p));
|
||||||
} else {
|
} else {
|
||||||
self.call_at_index(2, p);
|
self.call_at_index(2, dir_entry!(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -1010,7 +1015,10 @@ impl MachineState {
|
|||||||
|
|
||||||
match subsection {
|
match subsection {
|
||||||
Some(dynamic_predicate_info) => {
|
Some(dynamic_predicate_info) => {
|
||||||
self.execute_at_index(2, dynamic_predicate_info.clauses_subsection_p);
|
self.execute_at_index(
|
||||||
|
2,
|
||||||
|
dir_entry!(dynamic_predicate_info.clauses_subsection_p)
|
||||||
|
);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
None => self.fail = true,
|
None => self.fail = true,
|
||||||
@@ -1628,6 +1636,16 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
&SystemClauseType::ModuleExists => {
|
||||||
|
let module = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
|
|
||||||
|
match module {
|
||||||
|
Addr::Con(Constant::Atom(ref name, _)) => {
|
||||||
|
self.fail = !indices.modules.contains_key(name);
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
}
|
||||||
&SystemClauseType::ModuleOf => {
|
&SystemClauseType::ModuleOf => {
|
||||||
let module = self.store(self.deref(self[temp_v!(2)].clone()));
|
let module = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||||
|
|
||||||
@@ -1645,7 +1663,9 @@ impl MachineState {
|
|||||||
|
|
||||||
self.unify(target, module);
|
self.unify(target, module);
|
||||||
}
|
}
|
||||||
_ => self.fail = true,
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => self.fail = true,
|
_ => self.fail = true,
|
||||||
};
|
};
|
||||||
@@ -1944,7 +1964,10 @@ impl MachineState {
|
|||||||
|
|
||||||
match subsection {
|
match subsection {
|
||||||
Some(dynamic_predicate_info) => {
|
Some(dynamic_predicate_info) => {
|
||||||
self.execute_at_index(2, dynamic_predicate_info.clauses_subsection_p);
|
self.execute_at_index(
|
||||||
|
2,
|
||||||
|
dir_entry!(dynamic_predicate_info.clauses_subsection_p)
|
||||||
|
);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|||||||
@@ -364,6 +364,9 @@ impl MachineState {
|
|||||||
let code = vec![call_clause!(ClauseType::Hook(hook), 2, 0, true)];
|
let code = vec![call_clause!(ClauseType::Hook(hook), 2, 0, true)];
|
||||||
wam.code_repo.cached_query = code;
|
wam.code_repo.cached_query = code;
|
||||||
|
|
||||||
|
self.cp = LocalCodePtr::TopLevel(0, 0);
|
||||||
|
self.at_end_of_expansion = false;
|
||||||
|
|
||||||
self.query_stepper(
|
self.query_stepper(
|
||||||
&mut wam.indices,
|
&mut wam.indices,
|
||||||
&mut wam.policies,
|
&mut wam.policies,
|
||||||
@@ -371,7 +374,7 @@ impl MachineState {
|
|||||||
&mut readline::input_stream(),
|
&mut readline::input_stream(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if self.fail {
|
if self.fail || self.at_end_of_expansion {
|
||||||
self.reset_with_heap_preservation();
|
self.reset_with_heap_preservation();
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -678,6 +678,26 @@ impl RelationWorker {
|
|||||||
self.queue.push_back(clauses);
|
self.queue.push_back(clauses);
|
||||||
Ok(QueryTerm::Jump(stub))
|
Ok(QueryTerm::Jump(stub))
|
||||||
}
|
}
|
||||||
|
("\\+", 1) => {
|
||||||
|
terms.push(Box::new(Term::Constant(
|
||||||
|
Cell::default(),
|
||||||
|
Constant::Atom(clause_name!("$fail"), None)
|
||||||
|
)));
|
||||||
|
|
||||||
|
let conq = Term::Constant(
|
||||||
|
Cell::default(),
|
||||||
|
Constant::Atom(clause_name!("true"), None)
|
||||||
|
);
|
||||||
|
|
||||||
|
let prec = Term::Clause(Cell::default(), clause_name!("->"), terms, None);
|
||||||
|
let terms = vec![Box::new(prec), Box::new(conq)];
|
||||||
|
|
||||||
|
let term = Term::Clause(Cell::default(), clause_name!(";"), terms, None);
|
||||||
|
let (stub, clauses) = self.fabricate_disjunct(term);
|
||||||
|
|
||||||
|
self.queue.push_back(clauses);
|
||||||
|
Ok(QueryTerm::Jump(stub))
|
||||||
|
}
|
||||||
("$get_level", 1) => {
|
("$get_level", 1) => {
|
||||||
if let Term::Var(_, ref var) = *terms[0] {
|
if let Term::Var(_, ref var) = *terms[0] {
|
||||||
Ok(QueryTerm::GetLevelAndUnify(Cell::default(), var.clone()))
|
Ok(QueryTerm::GetLevelAndUnify(Cell::default(), var.clone()))
|
||||||
@@ -693,7 +713,7 @@ impl RelationWorker {
|
|||||||
let ct = indices.get_clause_type(name, terms.len(), fixity);
|
let ct = indices.get_clause_type(name, terms.len(), fixity);
|
||||||
Ok(QueryTerm::Clause(Cell::default(), ct, terms, false))
|
Ok(QueryTerm::Clause(Cell::default(), ct, terms, false))
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Term::Var(..) => Ok(QueryTerm::Clause(
|
Term::Var(..) => Ok(QueryTerm::Clause(
|
||||||
Cell::default(),
|
Cell::default(),
|
||||||
ClauseType::CallN,
|
ClauseType::CallN,
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ macro_rules! return_from_clause {
|
|||||||
|
|
||||||
macro_rules! dir_entry {
|
macro_rules! dir_entry {
|
||||||
($idx:expr) => {
|
($idx:expr) => {
|
||||||
CodePtr::Local(LocalCodePtr::DirEntry($idx))
|
LocalCodePtr::DirEntry($idx)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
'$submit_query_and_print_results'(Term0, VarList) :-
|
'$submit_query_and_print_results'(Term0, VarList) :-
|
||||||
( expand_goals(Term0, Term) -> true
|
( expand_goals(Term0, Term) -> true
|
||||||
; Term = Term0
|
; Term0 = Term
|
||||||
),
|
),
|
||||||
( '$get_b_value'(B), call(Term), '$write_eqs_and_read_input'(B, VarList),
|
( '$get_b_value'(B), call(Term), '$write_eqs_and_read_input'(B, VarList),
|
||||||
!
|
!
|
||||||
@@ -235,6 +235,7 @@ use_module(Module, QualifiedExports) :-
|
|||||||
; throw(error(instantiation_error, use_module/2))
|
; throw(error(instantiation_error, use_module/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
|
|
||||||
% expand goals in initialization directives.
|
% expand goals in initialization directives.
|
||||||
user:term_expansion(Term0, (:- initialization(ExpandedGoals))) :-
|
user:term_expansion(Term0, (:- initialization(ExpandedGoals))) :-
|
||||||
nonvar(Term0),
|
nonvar(Term0),
|
||||||
@@ -242,15 +243,25 @@ user:term_expansion(Term0, (:- initialization(ExpandedGoals))) :-
|
|||||||
expand_goals(Goals, ExpandedGoals),
|
expand_goals(Goals, ExpandedGoals),
|
||||||
Goals \== ExpandedGoals.
|
Goals \== ExpandedGoals.
|
||||||
|
|
||||||
|
|
||||||
|
'$module_expand_goal'(UnexpandedGoals, ExpandedGoals) :-
|
||||||
|
( '$module_of'(Module, UnexpandedGoals),
|
||||||
|
'$module_exists'(Module),
|
||||||
|
Module:goal_expansion(UnexpandedGoals, ExpandedGoals),
|
||||||
|
UnexpandedGoals \== ExpandedGoals ->
|
||||||
|
true
|
||||||
|
; user:goal_expansion(UnexpandedGoals, ExpandedGoals)
|
||||||
|
).
|
||||||
|
|
||||||
expand_goals(UnexpandedGoals, ExpandedGoals) :-
|
expand_goals(UnexpandedGoals, ExpandedGoals) :-
|
||||||
nonvar(UnexpandedGoals),
|
nonvar(UnexpandedGoals),
|
||||||
var(ExpandedGoals),
|
var(ExpandedGoals),
|
||||||
( expand_goal(UnexpandedGoals, Goals) -> true
|
( '$module_expand_goal'(UnexpandedGoals, Goals) ->
|
||||||
|
true
|
||||||
; Goals = UnexpandedGoals
|
; Goals = UnexpandedGoals
|
||||||
),
|
),
|
||||||
( Goals = (Goal0, Goals0) ->
|
( Goals = (Goal0, Goals0) ->
|
||||||
( expand_goal(Goal0, Goal1) ->
|
( expand_goals(Goal0, Goal1) ->
|
||||||
Expanded = true,
|
|
||||||
expand_goals(Goals0, Goals1),
|
expand_goals(Goals0, Goals1),
|
||||||
thread_goals(Goal1, ExpandedGoals, Goals1, (','))
|
thread_goals(Goal1, ExpandedGoals, Goals1, (','))
|
||||||
; expand_goals(Goals0, Goals1),
|
; expand_goals(Goals0, Goals1),
|
||||||
@@ -264,6 +275,9 @@ expand_goals(UnexpandedGoals, ExpandedGoals) :-
|
|||||||
expand_goals(Goals0, ExpandedGoals0),
|
expand_goals(Goals0, ExpandedGoals0),
|
||||||
expand_goals(Goals1, ExpandedGoals1),
|
expand_goals(Goals1, ExpandedGoals1),
|
||||||
ExpandedGoals = (ExpandedGoals0 ; ExpandedGoals1)
|
ExpandedGoals = (ExpandedGoals0 ; ExpandedGoals1)
|
||||||
|
; Goals = (\+ Goals0) ->
|
||||||
|
expand_goals(Goals0, Goals1),
|
||||||
|
ExpandedGoals = (\+ Goals1)
|
||||||
; thread_goals(Goals, ExpandedGoals, (','))
|
; thread_goals(Goals, ExpandedGoals, (','))
|
||||||
; Goals = ExpandedGoals
|
; Goals = ExpandedGoals
|
||||||
).
|
).
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ impl fmt::Display for IndexPtr {
|
|||||||
&IndexPtr::DynamicUndefined => write!(f, "undefined"),
|
&IndexPtr::DynamicUndefined => write!(f, "undefined"),
|
||||||
&IndexPtr::Undefined => write!(f, "undefined"),
|
&IndexPtr::Undefined => write!(f, "undefined"),
|
||||||
&IndexPtr::Index(i) => write!(f, "{}", i),
|
&IndexPtr::Index(i) => write!(f, "{}", i),
|
||||||
|
&IndexPtr::UserTermExpansion => write!(f, "user:term_expansion"),
|
||||||
|
&IndexPtr::UserGoalExpansion => write!(f, "user:goal_expansion"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
:- module(tests_on_builtins, []).
|
||||||
|
|
||||||
:- use_module(library(lists)).
|
:- use_module(library(lists)).
|
||||||
:- use_module(library(non_iso)).
|
:- use_module(library(non_iso)).
|
||||||
|
|||||||
54
src/tests/call_with_inference_limit.pl
Normal file
54
src/tests/call_with_inference_limit.pl
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
:- module(tests_on_call_with_inference_limit, []).
|
||||||
|
|
||||||
|
:- use_module(library(lists)).
|
||||||
|
:- use_module(library(non_iso)).
|
||||||
|
|
||||||
|
:- dynamic(f/1).
|
||||||
|
:- dynamic(g/1).
|
||||||
|
|
||||||
|
test_queries_on_call_with_inference_limit :-
|
||||||
|
catch(call_with_inference_limit(throw(error), 0, inference_limit_exceeded),
|
||||||
|
error,
|
||||||
|
true),
|
||||||
|
catch(call_with_inference_limit(throw(error), 1, inference_limit_exceeded),
|
||||||
|
error,
|
||||||
|
true),
|
||||||
|
\+ call_with_inference_limit(g(X), 5, R),
|
||||||
|
maplist(assertz, [g(1), g(2), g(3), g(4), g(5)]),
|
||||||
|
findall([R,X],
|
||||||
|
call_with_inference_limit(g(X), 10, R),
|
||||||
|
[[true, 1],
|
||||||
|
[true, 2],
|
||||||
|
[true, 3],
|
||||||
|
[true, 4],
|
||||||
|
[!, 5]]),
|
||||||
|
findall([R,X],
|
||||||
|
(call_with_inference_limit(g(X), 10, R), call(true)),
|
||||||
|
[[true, 1],
|
||||||
|
[true, 2],
|
||||||
|
[true, 3],
|
||||||
|
[true, 4],
|
||||||
|
[!, 5]]),
|
||||||
|
findall([R,X],
|
||||||
|
(call_with_inference_limit(g(X), 4, R), call(true)),
|
||||||
|
[[true, 1],
|
||||||
|
[true, 2],
|
||||||
|
[inference_limit_exceeded, _]]),
|
||||||
|
findall([X,R1,R2],
|
||||||
|
(call_with_inference_limit(g(X), 4, R1),
|
||||||
|
call_with_inference_limit(g(X), 5, R2)),
|
||||||
|
[[1,true,!],
|
||||||
|
[2,true,!],
|
||||||
|
[3,true,!],
|
||||||
|
[4,true,!],
|
||||||
|
[5,!,!]]),
|
||||||
|
\+ \+ assertz((f(X) :- call_with_inference_limit(g(X), 8, _))),
|
||||||
|
findall([R,X],
|
||||||
|
call_with_inference_limit(f(X), 12, R),
|
||||||
|
[[true,1],
|
||||||
|
[true,2],
|
||||||
|
[true,3],
|
||||||
|
[true,4],
|
||||||
|
[!,5]]).
|
||||||
|
|
||||||
|
:- initialization(test_queries_on_call_with_inference_limit).
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
:- module(tests_on_facts, []).
|
||||||
|
|
||||||
:- dynamic(p/2).
|
:- dynamic(p/2).
|
||||||
:- dynamic(p/3).
|
:- dynamic(p/3).
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
:- module(test_on_predicates, []).
|
||||||
|
|
||||||
:- dynamic(p/2).
|
:- dynamic(p/2).
|
||||||
:- dynamic(p/3).
|
:- dynamic(p/3).
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
:- module(tests_on_rules, []).
|
||||||
|
|
||||||
:- dynamic(p/3).
|
:- dynamic(p/3).
|
||||||
:- dynamic(p/2).
|
:- dynamic(p/2).
|
||||||
:- dynamic(q/2).
|
:- dynamic(q/2).
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
:- module(test_on_setup_call_cleanup, []).
|
||||||
|
|
||||||
:- use_module(library(non_iso)).
|
:- use_module(library(non_iso)).
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user