add term variables
This commit is contained in:
@@ -33,7 +33,7 @@ Extend rusty-wam to include the following, among other features:
|
|||||||
* Default representation of strings as list of chars, using a packed
|
* Default representation of strings as list of chars, using a packed
|
||||||
internal representation (_done_).
|
internal representation (_done_).
|
||||||
- A representation of 'partial strings' as difference lists
|
- A representation of 'partial strings' as difference lists
|
||||||
of characters (_in progress_).
|
of characters (_done_).
|
||||||
* `term_expansion/2` and `goal_expansion/2` (_in progress_).
|
* `term_expansion/2` and `goal_expansion/2` (_in progress_).
|
||||||
* Definite Clause Grammars.
|
* Definite Clause Grammars.
|
||||||
* Attributed variables using the SICStus Prolog interface and
|
* Attributed variables using the SICStus Prolog interface and
|
||||||
@@ -153,6 +153,7 @@ The following predicates are built-in to rusty-wam.
|
|||||||
* `member/2`
|
* `member/2`
|
||||||
* `memberchk/2`
|
* `memberchk/2`
|
||||||
* `nonvar/1`
|
* `nonvar/1`
|
||||||
|
* `numbervars/{2,3}`
|
||||||
* `once/1`
|
* `once/1`
|
||||||
* `partial_string/2`
|
* `partial_string/2`
|
||||||
* `rational/1`
|
* `rational/1`
|
||||||
@@ -163,6 +164,7 @@ The following predicates are built-in to rusty-wam.
|
|||||||
* `setup_call_cleanup/3`
|
* `setup_call_cleanup/3`
|
||||||
* `sort/2`
|
* `sort/2`
|
||||||
* `string/1`
|
* `string/1`
|
||||||
|
* `term_variables/2`
|
||||||
* `throw/1`
|
* `throw/1`
|
||||||
* `true/0`
|
* `true/0`
|
||||||
* `var/1`
|
* `var/1`
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ pub enum SystemClauseType {
|
|||||||
SetDoubleQuotes,
|
SetDoubleQuotes,
|
||||||
SkipMaxList,
|
SkipMaxList,
|
||||||
Succeed,
|
Succeed,
|
||||||
|
TermVariables,
|
||||||
UnwindStack
|
UnwindStack
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,6 +276,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::SetDoubleQuotes => clause_name!("$set_double_quotes"),
|
&SystemClauseType::SetDoubleQuotes => clause_name!("$set_double_quotes"),
|
||||||
&SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"),
|
&SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"),
|
||||||
&SystemClauseType::Succeed => clause_name!("$succeed"),
|
&SystemClauseType::Succeed => clause_name!("$succeed"),
|
||||||
|
&SystemClauseType::TermVariables => clause_name!("$term_variables"),
|
||||||
&SystemClauseType::UnwindStack => clause_name!("$unwind_stack"),
|
&SystemClauseType::UnwindStack => clause_name!("$unwind_stack"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -308,6 +310,7 @@ impl SystemClauseType {
|
|||||||
("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))),
|
("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))),
|
||||||
("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes),
|
("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes),
|
||||||
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
|
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
|
||||||
|
("$term_variables", 2) => Some(SystemClauseType::TermVariables),
|
||||||
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
|
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
:- 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).
|
|
||||||
19
src/prolog/lib/terms.pl
Normal file
19
src/prolog/lib/terms.pl
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
:- 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).
|
||||||
@@ -120,7 +120,7 @@ impl<'a> SubModuleUser for MachineCodeIndices<'a> {
|
|||||||
static LISTS: &str = include_str!("../lib/lists.pl");
|
static LISTS: &str = include_str!("../lib/lists.pl");
|
||||||
static CONTROL: &str = include_str!("../lib/control.pl");
|
static CONTROL: &str = include_str!("../lib/control.pl");
|
||||||
static QUEUES: &str = include_str!("../lib/queues.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 {
|
impl Machine {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
@@ -144,7 +144,7 @@ impl Machine {
|
|||||||
compile_user_module(&mut wam, LISTS.as_bytes());
|
compile_user_module(&mut wam, LISTS.as_bytes());
|
||||||
compile_user_module(&mut wam, CONTROL.as_bytes());
|
compile_user_module(&mut wam, CONTROL.as_bytes());
|
||||||
compile_user_module(&mut wam, QUEUES.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
|
wam
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
use prolog_parser::ast::*;
|
use prolog_parser::ast::*;
|
||||||
|
|
||||||
|
use prolog::heap_iter::*;
|
||||||
use prolog::instructions::*;
|
use prolog::instructions::*;
|
||||||
use prolog::machine::MachineCodeIndices;
|
use prolog::machine::MachineCodeIndices;
|
||||||
use prolog::machine::machine_errors::*;
|
use prolog::machine::machine_errors::*;
|
||||||
use prolog::machine::machine_state::*;
|
use prolog::machine::machine_state::*;
|
||||||
use prolog::num::{ToPrimitive, Zero};
|
use prolog::num::{ToPrimitive, Zero};
|
||||||
use prolog::num::bigint::{BigInt};
|
use prolog::num::bigint::{BigInt};
|
||||||
//use prolog::term_writer::*;
|
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
struct BrentAlgState {
|
struct BrentAlgState {
|
||||||
@@ -435,6 +436,47 @@ impl MachineState {
|
|||||||
return Err(err);
|
return Err(err);
|
||||||
},
|
},
|
||||||
&SystemClauseType::Succeed => {},
|
&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()
|
&SystemClauseType::UnwindStack => self.unwind_stack()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user