* Default representation of strings as list of chars, using a packed
internal representation (_done_).
- A representation of 'partial strings' as difference lists
- of characters (_in progress_).
+ of characters (_done_).
* `term_expansion/2` and `goal_expansion/2` (_in progress_).
* Definite Clause Grammars.
* Attributed variables using the SICStus Prolog interface and
* `member/2`
* `memberchk/2`
* `nonvar/1`
+* `numbervars/{2,3}`
* `once/1`
* `partial_string/2`
* `rational/1`
* `setup_call_cleanup/3`
* `sort/2`
* `string/1`
+* `term_variables/2`
* `throw/1`
* `true/0`
* `var/1`
SetDoubleQuotes,
SkipMaxList,
Succeed,
+ TermVariables,
UnwindStack
}
&SystemClauseType::SetDoubleQuotes => clause_name!("$set_double_quotes"),
&SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"),
&SystemClauseType::Succeed => clause_name!("$succeed"),
+ &SystemClauseType::TermVariables => clause_name!("$term_variables"),
&SystemClauseType::UnwindStack => clause_name!("$unwind_stack"),
}
}
("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))),
("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes),
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
+ ("$term_variables", 2) => Some(SystemClauseType::TermVariables),
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
_ => None
}
+++ /dev/null
-:- module(numbervars, [numbervars/2, numbervars/3]).
-
-numbervars(Term, NewTerm) :- duplicate_term(Term, NewTerm), numbervars(Term, NewTerm, 0, _).
-
-numbervars(Term, NewTerm, N) :-
- ( integer(N), N >= 0 -> duplicate_term(Term, NewTerm), numbervars(Term, NewTerm, N, _)
- ; integer(N) -> throw(error(domain_error(not_less_than_zero, N), numbervars/3))
- ; throw(error(type_error(integer, N), numbervars/3))
- ).
-
-numbervars(Term, NewTerm, N1, N2) :-
- var(Term), !, NewTerm = '$VAR'(N1), N2 is N1 + 1.
-numbervars(Term, NewTerm, N1, N2) :- compound(Term), !,
- Term =.. [Name | Args],
- NewTerm =.. [Name | NewArgs],
- fold_numbervars(Args, NewArgs, N1, N2).
-numbervars(_, _, N, N).
-
-marked_already(Term, NewTerm) :-
- var(Term), nonvar(NewTerm), NewTerm = '$VAR'(_).
-marked_already(Term, NewTerm) :-
- atomic(Term).
-
-fold_numbervars([HeadTerm | Terms], [NewHeadTerm | NewTerms], N1, Nn) :-
- ( marked_already(HeadTerm, NewHeadTerm) -> N1 = N2
- ; numbervars(HeadTerm, NewHeadTerm, N1, N2)
- ),
- fold_numbervars(Terms, NewTerms, N2, Nn).
-fold_numbervars([], [], N, N).
--- /dev/null
+:- module(terms, [term_variables/2, numbervars/2, numbervars/3]).
+
+term_variables(Term, Vars) :- '$term_variables'(Term, Vars).
+
+numbervars(Term, N) :-
+ integer(N),
+ term_variables(Term, Vars),
+ numberlist(Vars, N, N1).
+
+numbervars(Term, N0, N) :-
+ integer(N0),
+ integer(N),
+ term_variables(Term, Vars),
+ numberlist(Vars, N0, N).
+
+numberlist([], N,N).
+numberlist(['$VAR'(N0)|Vars], N0,N) :-
+ N1 is N0+1,
+ numberlist(Vars, N1,N).
static LISTS: &str = include_str!("../lib/lists.pl");
static CONTROL: &str = include_str!("../lib/control.pl");
static QUEUES: &str = include_str!("../lib/queues.pl");
-static NUMVARS: &str = include_str!("../lib/numbervars.pl");
+static TERMS: &str = include_str!("../lib/terms.pl");
impl Machine {
pub fn new() -> Self {
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, NUMVARS.as_bytes());
+ compile_user_module(&mut wam, TERMS.as_bytes());
wam
}
use prolog_parser::ast::*;
+use prolog::heap_iter::*;
use prolog::instructions::*;
use prolog::machine::MachineCodeIndices;
use prolog::machine::machine_errors::*;
use prolog::machine::machine_state::*;
use prolog::num::{ToPrimitive, Zero};
use prolog::num::bigint::{BigInt};
-//use prolog::term_writer::*;
+use std::collections::HashSet;
use std::rc::Rc;
struct BrentAlgState {
return Err(err);
},
&SystemClauseType::Succeed => {},
+ &SystemClauseType::TermVariables => {
+ let a1 = self[temp_v!(1)].clone();
+ let mut vars = Vec::new();
+
+ {
+ let iter = HCPreOrderIterator::new(self, a1);
+
+ for item in iter {
+ match item {
+ HeapCellValue::Addr(Addr::HeapCell(h)) =>
+ vars.push(Ref::HeapCell(h)),
+ HeapCellValue::Addr(Addr::StackCell(fr, sc)) =>
+ vars.push(Ref::StackCell(fr, sc)),
+ _ => {}
+ }
+ }
+ }
+
+ let mut h = self.heap.h;
+ let outcome = Addr::HeapCell(h);
+
+ let mut seen_vars = HashSet::new();
+
+ for r in vars {
+ if seen_vars.contains(&r) {
+ continue;
+ }
+
+ self.heap.push(HeapCellValue::Addr(Addr::Lis(h+1)));
+ self.heap.push(HeapCellValue::Addr(r.as_addr()));
+
+ h += 2;
+
+ seen_vars.insert(r);
+ }
+
+ self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::EmptyList)));
+
+ let a2 = self[temp_v!(2)].clone();
+ self.unify(a2, outcome);
+ },
&SystemClauseType::UnwindStack => self.unwind_stack()
};