* `compound/1`
* `copy_term/2`
* `cyclic_term/1`
+* `dif/2`
* `expand_goal/2`
* `expand_term/2`
* `false/0`
};
}
- fn compile_target<Target, Iter>(&mut self, iter: Iter, term_loc: GenContext, is_exposed: bool) -> Vec<Target>
+ fn compile_target<Target, Iter>(&mut self, iter: Iter, term_loc: GenContext, is_exposed: bool)
+ -> Vec<Target>
where Target: CompilationTarget<'a>, Iter: Iterator<Item=TermRef<'a>>
{
let mut target = Vec::new();
})
}
+ #[inline]
+ fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &'a Cell<VarReg>)
+ {
+ let r = self.marker.get(Rc::new(String::from("!")));
+ cell.set(VarReg::Norm(r));
+ code.push(set_cp!(cell.get().norm()));
+ }
+
fn compile_seq(&mut self, iter: ChunkedIterator<'a>, conjunct_info: &ConjunctInfo<'a>,
code: &mut Code, is_exposed: bool)
-> Result<(), ParserError>
code.push(get_level_and_unify!(cell.get().norm()));
},
&QueryTerm::UnblockedCut(ref cell) =>
- code.push(set_cp!(cell.get().norm())),
+ self.compile_unblocked_cut(code, cell),
&QueryTerm::BlockedCut =>
code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut)
let mut final_index = 0;
for index in self.temp_lb .. {
- if !self.in_use.contains(&index) {
+ if !self.in_use.contains(&index) {
final_index = index;
break;
}
}
+ self.in_use.insert(final_index);
self.temp_lb = final_index + 1;
-
final_index
}
RegType::Temp(k)
},
_ if r.reg_num() == 0 => RegType::Temp(self.alloc_reg_to_non_var()),
- _ => r
+ _ => {
+ self.in_use.insert(r.reg_num());
+ r
+ }
};
cell.set(r);
status.1.push(cell);
match status.0 {
- VarStatus::Temp(cn, ref mut tvd) if cn == chunk_num => {
+ VarStatus::Temp(cn, ref mut tvd) if cn == chunk_num =>
if let Level::Shallow = lvl {
self.record_temp_info(tvd, arg_c, term_loc);
- }
- },
+ },
_ => status.0 = VarStatus::Perm(chunk_num)
};
UserTermExpansion(usize)
}
-impl LocalCodePtr {
+impl LocalCodePtr {
pub fn assign_if_local(&mut self, cp: CodePtr) {
match cp {
CodePtr::Local(local) => *self = local,
--- /dev/null
+[:- module(dif, [dif/2]).
+
+:- use_module(library(atts)).
+:- use_module(library(control), [(\=)/2]).
+
+:- attribute dif/2.
+
+dif_set_variables([], _, _).
+dif_set_variables([Var|Vars], X, Y) :-
+ put_atts(Var, dif(X, Y)),
+ dif_set_variables(Vars, X, Y).
+
+verify_dif_attrs([dif(X, Y) | Attrs], Var, [X \== Y | Goals]) :-
+ ( get_atts(Var, +dif(X, Y)) -> true
+ ; put_atts(Var, +dif(X, Y))
+ ),
+ verify_dif_attrs(Attrs, Var, Goals).
+verify_dif_attrs([_ | Attrs], Var, Goals) :-
+ verify_dif_attrs(Attrs, Var, Goals).
+verify_dif_attrs([], _, []).
+
+verify_dif_attrs_no_var([dif(X, Y) | Attrs], [X \== Y | Goals]) :-
+ verify_dif_attrs_no_var(Attrs, Goals).
+verify_dif_attrs_no_var([_ | Attrs], Goals) :-
+ verify_dif_attrs_no_var(Attrs, Goals).
+verify_dif_attrs_no_var([], []).
+
+verify_attributes(Var, Value, Goals) :-
+ ( get_atts(Var, Attrs) ->
+ ( var(Value) -> verify_dif_attrs(Attrs, Value, Goals)
+ ; verify_dif_attrs_no_var(Attrs, Goals)
+ )
+ ).
+
+% Probably the world's worst dif/2 implementation. I'm open to
+% suggestions for improvement.
+
+dif(X, Y) :- ( X \= Y -> true
+ ; term_variables(X, XVars), term_variables(Y, YVars),
+ ( XVars == [], YVars == [] -> false
+ ; dif_set_variables(XVars, X, Y),
+ dif_set_variables(YVars, X, Y)
+ )
+ ).
+
+gather_dif_goals(Attrs, Goal, Goal) :-
+ var(Attrs), !.
+gather_dif_goals([dif(X, Y)|Attrs], OldGoal, Goal) :-
+ ( var(OldGoal), !, gather_dif_goals(Attrs, dif(X, Y), Goal)
+ ; !, gather_dif_goals(Attrs, (dif(X, Y), OldGoal), Goal)
+ ).
+gather_dif_goals([_|Attrs], OldGoal, Goal) :-
+ gather_dif_goals(Attrs, OldGoal, Goal).
+
+attribute_goals(X, Goal) :-
+ '$get_attr_list'(X, Attrs),
+ gather_dif_goals(Attrs, _, Goal).
verify_attrs([Module|Modules], Var, Value, [Goals|ListOfGoalLists]) :-
catch(Module:verify_attributes(Var, Value, Goals),
- error(evaluation_error((M:verify_attributes)/3), verify_attrs/3),
+ error(evaluation_error((Module:verify_attributes)/3), verify_attributes/3),
Goals = []),
verify_attrs(Modules, Var, Value, ListOfGoalLists).
verify_attrs([], _, _, []).
use prolog::machine::*;
-pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
+pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
+pub static PROJECT_ATTRS: &str = include_str!("project_attributes.pl");
pub(super) type Bindings = Vec<(usize, Addr)>;
pub(super) struct AttrVarInitializer {
pub(super) bindings: Bindings,
pub(super) cp: LocalCodePtr,
- pub(super) verify_attrs_loc: usize
+ pub(super) verify_attrs_loc: usize,
+ pub(super) project_attrs_loc: usize
}
impl AttrVarInitializer {
- pub(super) fn new(p: usize) -> Self {
+ pub(super) fn new(verify_attrs_loc: usize, project_attrs_loc: usize) -> Self {
AttrVarInitializer {
bindings: vec![],
cp: LocalCodePtr::default(),
- verify_attrs_loc: p,
+ verify_attrs_loc,
+ project_attrs_loc
}
}
e: 0,
num_of_args: 0,
cp: LocalCodePtr::default(),
- attr_var_init: AttrVarInitializer::new(0),
+ attr_var_init: AttrVarInitializer::new(0, 0),
fail: false,
heap: Heap::with_capacity(256),
mode: MachineMode::Write,
static TERMS: &str = include_str!("../lib/terms.pl");
static DCGS: &str = include_str!("../lib/dcgs.pl");
static ATTS: &str = include_str!("../lib/atts.pl");
+static DIF: &str = include_str!("../lib/dif.pl");
impl Machine {
fn compile_special_forms(&mut self) {
self.machine_st.attr_var_init.verify_attrs_loc = self.code_repo.code.len();
self.code_repo.code.extend(code.into_iter());
},
- Err(_) => panic!("Machine::compile_special_forms() failed")
+ Err(_) => panic!("Machine::compile_special_forms() failed at VERIFY_ATTRS")
+ }
+
+ match compile_special_form(self, PROJECT_ATTRS.as_bytes()) {
+ Ok(code) => {
+ self.machine_st.attr_var_init.project_attrs_loc = self.code_repo.code.len();
+ self.code_repo.code.extend(code.into_iter());
+ },
+ Err(_) => panic!("Machine::compile_special_forms() failed at PROJECT_ATTRS")
}
}
+ fn compile_libraries(&mut self) {
+ compile_user_module(self, LISTS.as_bytes());
+ compile_user_module(self, CONTROL.as_bytes());
+ compile_user_module(self, QUEUES.as_bytes());
+ compile_user_module(self, ERROR.as_bytes());
+ compile_user_module(self, TERMS.as_bytes());
+ compile_user_module(self, DCGS.as_bytes());
+ compile_user_module(self, ATTS.as_bytes());
+ compile_user_module(self, DIF.as_bytes());
+ }
+
pub fn new() -> Self {
let mut wam = Machine {
machine_st: MachineState::new(),
compile_listing(&mut wam, BUILTINS.as_bytes(),
default_index_store!(atom_tbl.clone()));
- compile_user_module(&mut wam, LISTS.as_bytes());
- compile_user_module(&mut wam, CONTROL.as_bytes());
- compile_user_module(&mut wam, QUEUES.as_bytes());
- compile_user_module(&mut wam, ERROR.as_bytes());
- compile_user_module(&mut wam, TERMS.as_bytes());
- compile_user_module(&mut wam, DCGS.as_bytes());
- compile_user_module(&mut wam, ATTS.as_bytes());
-
+ wam.compile_libraries();
wam.compile_special_forms();
+
wam
}
for i in 1 .. rs + 1 {
self.and_stack[e][i] = self[RegType::Temp(i)].clone();
}
-
+
self.and_stack[e][rs + 1] = Addr::Con(Constant::Usize(self.b0));
self.and_stack[e][rs + 2] = Addr::Con(Constant::Usize(self.num_of_args));
--- /dev/null
+:- use_module(library(dcgs)).
+
+driver(QueryVars, AttrVars) :-
+ phrase(gather_modules(AttrVars), Modules0),
+ sort(Modules0, Modules),
+ call_project_attributes(Modules, QueryVars, AttrVars),
+ call_attribute_goals(QueryVars),
+ call_attribute_goals(AttrVars).
+
+call_project_attributes([], _, _).
+call_project_attributes([Module|Modules], QueryVars, AttrVars) :-
+ ( catch(Module:project_attributes(QueryVars, AttrVars),
+ error(evaluation_error((Module:project_attributes/2), project_attributes/2)),
+ true) -> true
+ ; true
+ ),
+ call_project_attributes(Modules, QueryVars, AttrVars).
+
+call_attribute_goals([]).
+call_attribute_goals([AttrVar | AttrVars]) :-
+ ( '$get_attr_list'(AttrVar, Ls) -> call_goals(Ls, AttrVar)
+ ; true
+ ),
+ call_attribute_goals(AttrVars).
+
+call_goals(Ls, _) :- var(Ls), !.
+call_goals([Attr|Attrs], X) :-
+ '$module_of'(Module, Attr),
+ ( catch(Module:attribute_goals(X, Goal),
+ error(evaluation_error((Module:attribute_goals/2), attribute_goals/2)),
+ writeq(Goal)) -> true
+ ; true
+ ),
+ call_goals(Attrs, X).
+
+gather_modules([]) --> [].
+gather_modules([AttrVar|AttrVars]) -->
+ { '$get_attr_list'(AttrVar, Attrs) },
+ gather_modules_for_attrs(Attrs),
+ gather_modules(AttrVars).
+
+gather_modules_for_attrs(Attrs) --> { var(Attrs), ! }.
+gather_modules_for_attrs([Attr|Attrs]) -->
+ { '$module_of'(Module, Attr) },
+ [Module],
+ gather_modules_for_attrs(Attrs).
post_order_iter(term)
}
- fn to_structure(ct: ClauseType, arity: usize, r: RegType) -> Self
- {
+ fn to_structure(ct: ClauseType, arity: usize, r: RegType) -> Self {
QueryInstruction::PutStructure(ct, arity, r)
}
let mut found_cut_var = false;
for item in terms.iter_mut() {
- found_cut_var = mark_cut_variable(item);
+ found_cut_var = mark_cut_variable(item) || found_cut_var;
}
found_cut_var
fn fabricate_disjunct(&self, body_term: Term) -> (JumpStub, VecDeque<Term>)
{
- let mut cut_var_found = false;
-
- let mut vars = self.compute_head(&body_term);
+ let vars = self.compute_head(&body_term);
let clauses: Vec<_> = unfold_by_str(body_term, ";").into_iter()
.map(|term| {
let mut subterms = unfold_by_str(term, ",");
- cut_var_found = mark_cut_variables(&mut subterms);
+ mark_cut_variables(&mut subterms);
let term = subterms.pop().unwrap();
fold_by_str(subterms.into_iter(), term, clause_name!(","))
}).collect();
- if cut_var_found {
- vars.push(Term::Var(Cell::default(), rc_atom!("!")));
- }
-
let results = clauses.into_iter()
.map(|clause| self.fabricate_rule_body(&vars, clause))
.collect();
impl fmt::Display for ClauseType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
+ &ClauseType::System(SystemClauseType::SetCutPoint(r)) =>
+ write!(f, "$set_cp({})", r),
&ClauseType::Named(ref name, ref idx) | &ClauseType::Op(OpDecl(.., ref name), ref idx) =>
{
let idx = idx.0.borrow();