add library(reif)
This commit is contained in:
@@ -43,7 +43,7 @@ Extend rusty-wam to include the following, among other features:
|
||||
- [x] Support for `attribute_goals/2` and `project_attributes/2`
|
||||
- [ ] `call_residue/2` and `call_residue_vars/2`
|
||||
* `if_` and related predicates, following the developments of the
|
||||
paper "Indexing `dif/2`".
|
||||
paper "Indexing `dif/2`" (_in progress_).
|
||||
* All-solutions predicates (`findall/{3,4}`, `bagof/3`, `setof/3`).
|
||||
* Clause creation and destruction (`asserta/1`, `assertz/1`,
|
||||
`retract/1`, `abolish/1`) with logical update semantics.
|
||||
|
||||
@@ -457,16 +457,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
|
||||
|
||||
Ok(match terms[0].as_ref() {
|
||||
&Term::Var(ref vr, ref name) => {
|
||||
let mut target = Vec::new();
|
||||
let mut target = vec![];
|
||||
|
||||
self.marker.reset_arg(2);
|
||||
self.marker.mark_var(name.clone(), Level::Shallow, vr,
|
||||
term_loc, &mut target);
|
||||
|
||||
if !target.is_empty() {
|
||||
for query_instr in target {
|
||||
code.push(Line::Query(query_instr));
|
||||
}
|
||||
code.extend(target.into_iter().map(Line::Query));
|
||||
}
|
||||
|
||||
if use_default_call_policy {
|
||||
@@ -476,9 +474,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
|
||||
}
|
||||
},
|
||||
&Term::Constant(_, ref c @ Constant::Number(_)) => {
|
||||
code.push(Line::Query(put_constant!(Level::Shallow,
|
||||
c.clone(),
|
||||
temp_v!(1))));
|
||||
code.push(Line::Query(put_constant!(Level::Shallow, c.clone(), temp_v!(1))));
|
||||
|
||||
if use_default_call_policy {
|
||||
code.push(is_call_by_default!(temp_v!(1), at.unwrap_or(interm!(1))))
|
||||
@@ -510,7 +506,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
|
||||
code.extend(target.into_iter().map(|query_instr| Line::Query(query_instr)));
|
||||
}
|
||||
|
||||
code.push(get_level_and_unify!(cell.get().norm()));
|
||||
code.push(get_level_and_unify!(cell.get().norm()));
|
||||
}
|
||||
|
||||
fn compile_seq(&mut self, iter: ChunkedIterator<'a>, conjunct_info: &ConjunctInfo<'a>,
|
||||
|
||||
@@ -382,6 +382,7 @@ pub enum BuiltInClauseType {
|
||||
NotEq,
|
||||
PartialString,
|
||||
Read,
|
||||
ReifySwitch,
|
||||
Sort,
|
||||
}
|
||||
|
||||
@@ -459,9 +460,10 @@ impl BuiltInClauseType {
|
||||
&BuiltInClauseType::KeySort => clause_name!("keysort"),
|
||||
&BuiltInClauseType::Nl => clause_name!("nl"),
|
||||
&BuiltInClauseType::NotEq => clause_name!("\\=="),
|
||||
&BuiltInClauseType::PartialString => clause_name!("partial_string"),
|
||||
&BuiltInClauseType::Read => clause_name!("read"),
|
||||
&BuiltInClauseType::ReifySwitch => clause_name!("$reify_switch"),
|
||||
&BuiltInClauseType::Sort => clause_name!("sort"),
|
||||
&BuiltInClauseType::PartialString => clause_name!("partial_string")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,9 +482,10 @@ impl BuiltInClauseType {
|
||||
&BuiltInClauseType::KeySort => 2,
|
||||
&BuiltInClauseType::NotEq => 2,
|
||||
&BuiltInClauseType::Nl => 0,
|
||||
&BuiltInClauseType::Read => 1,
|
||||
&BuiltInClauseType::Sort => 2,
|
||||
&BuiltInClauseType::PartialString => 1,
|
||||
&BuiltInClauseType::Read => 1,
|
||||
&BuiltInClauseType::ReifySwitch => 3,
|
||||
&BuiltInClauseType::Sort => 2,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,9 +509,10 @@ impl BuiltInClauseType {
|
||||
("keysort", 2) => Some(BuiltInClauseType::KeySort),
|
||||
("nl", 0) => Some(BuiltInClauseType::Nl),
|
||||
("\\==", 2) => Some(BuiltInClauseType::NotEq),
|
||||
("sort", 2) => Some(BuiltInClauseType::Sort),
|
||||
("read", 1) => Some(BuiltInClauseType::Read),
|
||||
("partial_string", 2) => Some(BuiltInClauseType::PartialString),
|
||||
("read", 1) => Some(BuiltInClauseType::Read),
|
||||
("$reify_switch", 3) => Some(BuiltInClauseType::ReifySwitch),
|
||||
("sort", 2) => Some(BuiltInClauseType::Sort),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
73
src/prolog/lib/reif.pl
Normal file
73
src/prolog/lib/reif.pl
Normal file
@@ -0,0 +1,73 @@
|
||||
:- module(reif, [if_/3, (=)/3, (,)/3, (;)/3, cond_t/3, dif/3,
|
||||
memberd_t/3, tfilter/3, tmember/2, tmember_t/3,
|
||||
tpartition/4]).
|
||||
|
||||
:- use_module(library(control), [(\=)/2]).
|
||||
:- use_module(library(dif)).
|
||||
|
||||
/* in essence, '$reify_switch'(T, Then_0, Else_0) is this:
|
||||
( T == true -> call(Then_0)
|
||||
; T == false -> call(Else_0)
|
||||
; nonvar(T) -> throw(error(type_error(boolean, T), _))
|
||||
; throw(error(instantiation_error, _))
|
||||
).
|
||||
but without creating choice points.
|
||||
*/
|
||||
|
||||
if_(If_1, Then_0, Else_0) :-
|
||||
call(If_1, T),
|
||||
'$reify_switch'(T, Then_0, Else_0).
|
||||
|
||||
=(X, Y, T) :-
|
||||
( X == Y -> T = true
|
||||
; X \= Y -> T = false
|
||||
; T = true, X = Y
|
||||
; T = false, dif(X, Y)
|
||||
).
|
||||
|
||||
dif(X, Y, T) :-
|
||||
=(X, Y, NT),
|
||||
non(NT, T).
|
||||
|
||||
non(true, false).
|
||||
non(false, true).
|
||||
|
||||
tfilter(C_2, Es, Fs) :-
|
||||
i_tfilter(Es, C_2, Fs).
|
||||
|
||||
i_tfilter([], _, []).
|
||||
i_tfilter([E|Es], C_2, Fs0) :-
|
||||
if_(call(C_2, E), Fs0 = [E|Fs], Fs0 = Fs),
|
||||
i_tfilter(Es, C_2, Fs).
|
||||
|
||||
tpartition(P_2, Xs, Ts, Fs) :-
|
||||
i_tpartition(Xs, P_2, Ts, Fs).
|
||||
|
||||
i_tpartition([], _P_2, [], []).
|
||||
i_tpartition([X|Xs], P_2, Ts0, Fs0) :-
|
||||
if_( call(P_2, X)
|
||||
, ( Ts0 = [X|Ts], Fs0 = Fs )
|
||||
, ( Fs0 = [X|Fs], Ts0 = Ts ) ),
|
||||
i_tpartition(Xs, P_2, Ts, Fs).
|
||||
|
||||
','(A_1, B_1, T) :-
|
||||
if_(A_1, call(B_1, T), T = false).
|
||||
|
||||
';'(A_1, B_1, T) :-
|
||||
if_(A_1, T = true, call(B_1, T)).
|
||||
|
||||
cond_t(If_1, Then_0, T) :-
|
||||
if_(If_1, ( Then_0, T = true ), T = false ).
|
||||
|
||||
memberd_t(E, Xs, T) :-
|
||||
i_memberd_t(Xs, E, T).
|
||||
|
||||
i_memberd_t([], _, false).
|
||||
i_memberd_t([X|Xs], E, T) :-
|
||||
if_( X = E, T = true, i_memberd_t(Xs, E, T) ).
|
||||
|
||||
tmember(P_2, [X|Xs]) :-
|
||||
if_( call(P_2, X), true, tmember(P_2, Xs) ).
|
||||
|
||||
tmember_t(P_2, [X|Xs], T) :-
|
||||
if_( call(P_2, X), T = true, tmember_t(P_2, Xs, T) ).
|
||||
@@ -156,12 +156,14 @@ impl MachineState {
|
||||
|
||||
fn print_attribute_goals(&mut self, var_dict: &HeapVarDict)
|
||||
{
|
||||
let attr_goals = mem::replace(&mut self.attr_var_init.attribute_goals, vec![]);
|
||||
let mut attr_goals = mem::replace(&mut self.attr_var_init.attribute_goals, vec![]);
|
||||
|
||||
if attr_goals.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.term_dedup(&mut attr_goals);
|
||||
|
||||
let mut output = PrinterOutputter::new();
|
||||
|
||||
for goal_addr in attr_goals {
|
||||
|
||||
@@ -114,6 +114,7 @@ impl MachineError {
|
||||
pub enum ValidType {
|
||||
Atom,
|
||||
Atomic,
|
||||
Boolean,
|
||||
// Byte,
|
||||
Callable,
|
||||
// Character,
|
||||
@@ -134,6 +135,7 @@ impl ValidType {
|
||||
match self {
|
||||
ValidType::Atom => "atom",
|
||||
ValidType::Atomic => "atomic",
|
||||
ValidType::Boolean => "boolean",
|
||||
// ValidType::Byte => "byte",
|
||||
ValidType::Callable => "callable",
|
||||
// ValidType::Character => "character",
|
||||
|
||||
@@ -572,6 +572,48 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
&BuiltInClauseType::ReifySwitch => {
|
||||
let truth_value = machine_st[temp_v!(1)].clone();
|
||||
let truth_value = machine_st.store(machine_st.deref(truth_value));
|
||||
|
||||
match truth_value {
|
||||
Addr::Con(Constant::Atom(atom, spec)) =>
|
||||
match atom.as_str() {
|
||||
"true" => {
|
||||
let t_branch = machine_st[temp_v!(2)].clone();
|
||||
|
||||
machine_st[temp_v!(1)] = t_branch;
|
||||
self.call_n(machine_st, 1, indices)
|
||||
},
|
||||
"false" => {
|
||||
let f_branch = machine_st[temp_v!(3)].clone();
|
||||
|
||||
machine_st[temp_v!(1)] = f_branch;
|
||||
self.call_n(machine_st, 1, indices)
|
||||
}
|
||||
_ => {
|
||||
let truth_value = Addr::Con(Constant::Atom(atom, spec));
|
||||
|
||||
let stub = MachineError::functor_stub(clause_name!("if_"), 3);
|
||||
let err = MachineError::type_error(ValidType::Boolean, truth_value);
|
||||
|
||||
Err(machine_st.error_form(err, stub))
|
||||
}
|
||||
},
|
||||
ref addr if addr.is_ref() => {
|
||||
let stub = MachineError::functor_stub(clause_name!("if_"), 3);
|
||||
let err = MachineError::instantiation_error();
|
||||
|
||||
Err(machine_st.error_form(err, stub))
|
||||
},
|
||||
addr => {
|
||||
let stub = MachineError::functor_stub(clause_name!("if_"), 3);
|
||||
let err = MachineError::type_error(ValidType::Boolean, addr);
|
||||
|
||||
Err(machine_st.error_form(err, stub))
|
||||
}
|
||||
}
|
||||
},
|
||||
&BuiltInClauseType::CopyTerm => {
|
||||
machine_st.duplicate_term();
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
|
||||
@@ -321,6 +321,7 @@ static DCGS: &str = include_str!("../lib/dcgs.pl");
|
||||
static ATTS: &str = include_str!("../lib/atts.pl");
|
||||
static DIF: &str = include_str!("../lib/dif.pl");
|
||||
static FREEZE: &str = include_str!("../lib/freeze.pl");
|
||||
static REIF: &str = include_str!("../lib/reif.pl");
|
||||
|
||||
impl Machine {
|
||||
fn compile_special_forms(&mut self) {
|
||||
@@ -351,6 +352,7 @@ impl Machine {
|
||||
compile_user_module(self, ATTS.as_bytes());
|
||||
compile_user_module(self, DIF.as_bytes());
|
||||
compile_user_module(self, FREEZE.as_bytes());
|
||||
compile_user_module(self, REIF.as_bytes());
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
|
||||
@@ -409,7 +409,7 @@ impl MachineState {
|
||||
for (h, addr) in bindings {
|
||||
self.heap[h] = HeapCellValue::Addr(addr);
|
||||
}
|
||||
},
|
||||
},
|
||||
&SystemClauseType::RemoveCallPolicyCheck => {
|
||||
let restore_default =
|
||||
match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
|
||||
|
||||
Reference in New Issue
Block a user