add atts.pl, various fixes

This commit is contained in:
Mark Thom
2019-01-30 21:31:48 -07:00
parent 4f87fb8535
commit fcffb90549
12 changed files with 261 additions and 45 deletions

8
Cargo.lock generated
View File

@@ -86,8 +86,7 @@ dependencies = [
[[package]]
name = "prolog_parser"
version = "0.7.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
version = "0.8.0"
dependencies = [
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -108,12 +107,12 @@ dependencies = [
[[package]]
name = "rusty-wam"
version = "0.7.17"
version = "0.8.0"
dependencies = [
"downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"prolog_parser 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
"prolog_parser 0.8.0",
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -152,7 +151,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
"checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe"
"checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f"
"checksum prolog_parser 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "73457bb9d32e6c60048f7cb10f41ed6f9d07053bccd188ff14f79e0af3046789"
"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"

View File

@@ -1,6 +1,6 @@
[package]
name = "rusty-wam"
version = "0.7.17"
version = "0.8.0"
authors = ["Mark Thom <markjordanthom@gmail.com>"]
repository = "https://github.com/mthom/rusty-wam"
description = "The Warren Abstract Machine in Rust."
@@ -10,7 +10,7 @@ license = "BSD-3-Clause"
downcast = "0.9.1"
num = "0.2"
ordered-float = "0.5.0"
prolog_parser = "0.7.22"
prolog_parser = { version = "0.8.0", path = "../prolog_parser" }
[dependencies.termion]
version = "1.4.0"

View File

@@ -100,12 +100,12 @@ pub(crate) trait CopierTarget: IndexMut<usize, Output=HeapCellValue>
scan += 1;
},
Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => {
Addr::AttrVar(..) | Addr::HeapCell(_) | Addr::StackCell(_, _) => {
let ra = a;
let rd = self.store(self.deref(ra.clone()));
match rd.clone() {
Addr::AttrVar(h) | Addr::HeapCell(h) if h >= old_h => {
Addr::AttrVar(h, _) | Addr::HeapCell(h) if h >= old_h => {
self[scan] = HeapCellValue::Addr(rd);
scan += 1;
},

View File

@@ -65,7 +65,8 @@ impl<'a> HCPreOrderIterator<'a> {
da
},
Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => da,
Addr::HeapCell(_) | Addr::StackCell(_, _) => da,
Addr::AttrVar(h, _) => self.follow_heap(h + 1),
Addr::Str(s) => self.follow_heap(s) // record terms of structure.
}
}

View File

@@ -373,6 +373,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
fn offset_as_string(&self, addr: Addr) -> Option<String> {
match addr {
Addr::AttrVar(h, _) =>
Some(format!("_{}", h + 1)),
Addr::HeapCell(h) | Addr::Lis(h) | Addr::Str(h) =>
Some(format!("_{}", h)),
Addr::StackCell(fr, sc) =>

View File

@@ -238,9 +238,12 @@ pub struct Module {
#[derive(Copy, Clone, PartialEq)]
pub enum SystemClauseType {
CheckCutPoint,
DeleteAttribute,
DeleteHeadAttribute,
DynamicModuleResolution,
ExpandGoal,
ExpandTerm,
GetAttributedVariableList,
GetBValue,
GetSCCCleaner,
InstallSCCCleaner,
@@ -273,9 +276,12 @@ impl SystemClauseType {
pub fn name(&self) -> ClauseName {
match self {
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr"),
&SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
&SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"),
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
&SystemClauseType::GetAttributedVariableList => clause_name!("$get_attr_list"),
&SystemClauseType::GetBValue => clause_name!("$get_b_value"),
&SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"),
&SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"),
@@ -311,9 +317,12 @@ impl SystemClauseType {
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
match (name, arity) {
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
("$del_attr", 1) => Some(SystemClauseType::DeleteAttribute),
("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute),
("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution),
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList),
("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
("$get_double_quotes", 1) => Some(SystemClauseType::GetDoubleQuotes),
("$get_scc_cleaner", 1) => Some(SystemClauseType::GetSCCCleaner),
@@ -708,7 +717,7 @@ pub type CodeDeque = VecDeque<Line>;
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum Addr {
AttrVar(usize),
AttrVar(usize, usize), // the location of the AttrVal in the heap, the location of the attribute list.
Con(Constant),
Lis(usize),
HeapCell(usize),
@@ -751,14 +760,15 @@ impl PartialOrd<Ref> for Addr {
impl Addr {
pub fn is_ref(&self) -> bool {
match self {
&Addr::HeapCell(_) | &Addr::StackCell(_, _) => true,
&Addr::AttrVar(..) | &Addr::HeapCell(_) | &Addr::StackCell(_, _) => true,
_ => false
}
}
pub fn as_var(&self) -> Option<Ref> {
match self {
&Addr::HeapCell(hc) => Some(Ref::HeapCell(hc)),
&Addr::AttrVar(h, _) => Some(Ref::HeapCell(h)),
&Addr::HeapCell(h) => Some(Ref::HeapCell(h)),
&Addr::StackCell(fr, sc) => Some(Ref::StackCell(fr, sc)),
_ => None
}
@@ -777,7 +787,6 @@ impl Add<usize> for Addr {
fn add(self, rhs: usize) -> Self::Output {
match self {
Addr::AttrVar(a) => Addr::AttrVar(a + rhs),
Addr::Lis(a) => Addr::Lis(a + rhs),
Addr::HeapCell(h) => Addr::HeapCell(h + rhs),
Addr::Str(s) => Addr::Str(s + rhs),
@@ -791,7 +800,6 @@ impl Sub<usize> for Addr {
fn sub(self, rhs: usize) -> Self::Output {
match self {
Addr::AttrVar(a) => Addr::AttrVar(a - rhs),
Addr::Lis(a) => Addr::Lis(a - rhs),
Addr::HeapCell(h) => Addr::HeapCell(h - rhs),
Addr::Str(s) => Addr::Str(s - rhs),

119
src/prolog/lib/atts.pl Normal file
View File

@@ -0,0 +1,119 @@
:- module(atts, [attribute/1, absent_attr/2, get_attr/2, put_attr/2,
absent_from_list/2, get_from_list/2, add_to_list/2,
del_attr/3, del_attr_step/2, del_attr_non_head/3]).
:- use_module(library(control)).
:- use_module(library(dcgs)).
:- use_module(library(terms)).
:- op(1199, fx, attribute).
absent_attr(V, Attr) :-
'$get_attr_list'(V, Ls),
absent_from_list(Ls, Attr).
absent_from_list(X, _) :-
var(X), !.
absent_from_list([L|Ls], Attr) :-
( L \= Attr -> absent_from_list(Ls, Attr) ).
get_attr(V, Attr) :-
'$get_attr_list'(V, Ls), nonvar(Ls), get_from_list(Ls, Attr).
get_from_list([L|Ls], Attr) :-
nonvar(L),
( L \= Attr -> nonvar(Ls), get_from_list(Ls, Attr)
; copy_term(L, L0), L0 = Attr
; get_from_list(Ls, Attr)
).
put_attr(V, Attr) :-
'$get_attr_list'(V, Ls), add_to_list(Ls, Attr).
add_to_list(Ls, Attr) :-
( var(Ls) -> Ls = [Attr | _]
; Ls = [_ | Ls0] -> add_to_list(Ls0, Attr)
).
del_attr(Ls0, _, _) :-
var(Ls0), !.
del_attr(Ls0, V, Attr) :-
Ls0 = [Att | Ls1],
nonvar(Att),
( Att \= Attr -> del_attr_non_head(Ls0, Ls1, Attr)
; '$del_attr_head'(V), del_attr(Ls1, V, Attr)
).
del_attr_step(Ls1, Attr) :-
( nonvar(Ls1) -> Ls1 = [_ | Ls2], del_attr_non_head(Ls1, Ls2, Attr)
; true ).
%% assumptions: Ls0 is a list, Ls1 is its tail;
%% the head of Ls0 can be ignored.
del_attr_non_head(Ls0, Ls1, Attr) :-
Ls0 = [_, Att | _],
nonvar(Att),
!,
( Att \= Attr -> del_attr_step(Ls1, Attr)
; '$del_attr'(Ls0), %% set tail of Ls0 = tail of Ls1. can be undone by backtracking.
del_attr_step(Ls1, Attr)
).
del_attr_non_head(_, _, _).
user:term_expansion(Term0, Terms) :-
nonvar(Term0),
Term0 = (:- attribute Atts),
nonvar(Atts),
phrase(put_attrs_var_check, Terms, Terms1),
phrase(put_attrs(Atts), Terms1, Terms2),
phrase(get_attrs_var_check, Terms2, Terms3),
phrase(get_attrs(Atts), Terms3).
put_attrs_var_check -->
{ numbervars([Var, Attr], 0, _) },
[(put_atts(Var, Attr) :- nonvar(Var), throw(error(type_error(variable, Var), put_atts/2))),
(put_atts(Var, Attr) :- var(Attr), throw(error(instantiation_error, put_atts/2)))].
get_attrs_var_check -->
{ numbervars([Var, Attr], 0, _) },
[(get_atts(Var, Attr) :- nonvar(Var), throw(error(type_error(variable, Var), get_atts/2))),
(get_atts(Var, Attr) :- var(Attr), !, '$get_attr_list'(Var, Attr))].
put_attrs(Name/Arity) -->
put_attr(Name, Arity),
{ numbervars([Var, Attr], 0, _) },
[(put_atts(Var, Attr) :- lists:maplist(put_atts(Var), Attr))].
put_attrs((Name/Arity, Atts)) -->
{ nonvar(Atts) },
put_attr(Name, Arity),
put_attrs(Atts).
get_attrs(Name/Arity) -->
get_attr(Name, Arity).
get_attrs((Name/Arity, Atts)) -->
{ nonvar(Atts) },
get_attr(Name, Arity),
get_attrs(Atts).
put_attr(Name, Arity) -->
{ functor(Attr, Name, Arity),
numbervars(Attr, 0, Arity),
V = '$VAR'(Arity) },
[(put_atts(V, +Attr) :- !, functor(Attr, _, _), put_attr(V, Attr)),
(put_atts(V, Attr) :- !, functor(Attr, _, _), put_attr(V, Attr)),
(put_atts(V, -Attr) :- !, functor(Attr, _, _), '$get_attr_list'(V, Ls), del_attr(Ls, V, Attr))].
get_attr(Name, Arity) -->
{ functor(Attr, Name, Arity),
numbervars(Attr, 0, Arity),
V = '$VAR'(Arity) },
[(get_atts(V, +Attr) :- !, functor(Attr, _, _), get_attr(V, Attr)),
(get_atts(V, Attr) :- !, functor(Attr, _, _), get_attr(V, Attr)),
(get_atts(V, -Attr) :- !, functor(Attr, _, _), absent_attr(V, Attr))].
user:goal_expansion(Term, [M:put_atts(Var, Attr)]) :-
nonvar(Term),
Term = put_atts(Var, M, Attr).
user:goal_expansion(Term, [M:get_atts(Var, Attr)]) :-
nonvar(Term),
Term = get_atts(Var, M, Attr).

View File

@@ -78,7 +78,7 @@ impl MachineState {
pub(crate) fn store(&self, a: Addr) -> Addr {
match a {
Addr::AttrVar(h) => self.heap[h+1].as_addr(h+1),
Addr::AttrVar(h, _) => self.heap[h].as_addr(h),
Addr::HeapCell(h) => self.heap[h].as_addr(h),
Addr::StackCell(fr, sc) => self.and_stack[fr][sc].clone(),
addr => addr
@@ -220,7 +220,7 @@ impl MachineState {
if d1 != d2 {
match (self.store(d1.clone()), self.store(d2.clone())) {
(Addr::AttrVar(h), addr) | (addr, Addr::AttrVar(h)) => {
(Addr::AttrVar(h, _), addr) | (addr, Addr::AttrVar(h, _)) => {
pdl.push(Addr::HeapCell(h+1));
pdl.push(addr);
},
@@ -352,7 +352,7 @@ impl MachineState {
self.pstr_tr += 1;
}
fn trail(&mut self, r: TrailRef) {
pub(super) fn trail(&mut self, r: TrailRef) {
match r {
TrailRef::HeapCell(h) =>
if h < self.hb {
@@ -1168,11 +1168,11 @@ impl MachineState {
let addr = self.store(self.deref(a1));
let offset = match addr {
Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => v,
Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(..) => v,
Addr::Con(Constant::String(_)) if self.flags.double_quotes.is_chars() => l,
Addr::Con(_) => c,
Addr::Lis(_) => l,
Addr::Str(_) => s
Addr::Str(_) => s,
};
match offset {
@@ -1789,6 +1789,17 @@ impl MachineState {
match d {
Addr::HeapCell(_) | Addr::StackCell(..) => self.fail = true,
Addr::AttrVar(h, _) => {
let addr = self.heap[h].as_addr(h);
if let Some(_) = addr.as_var() {
if self.store(self.deref(addr)).as_var().is_some() {
self.fail = true;
}
}
self.p += 1;
},
_ => self.p += 1
};
},
@@ -1797,6 +1808,17 @@ impl MachineState {
match d {
Addr::HeapCell(_) | Addr::StackCell(_,_) => self.p += 1,
Addr::AttrVar(h, _) => {
let addr = self.heap[h].as_addr(h);
if let Some(_) = addr.as_var() {
if self.store(self.deref(addr)).as_var().is_none() {
self.fail = true;
}
}
self.p += 1;
},
_ => self.fail = true
};
},
@@ -1844,7 +1866,7 @@ impl MachineState {
},
Addr::Lis(_) =>
self.try_functor_compound_case(clause_name!("."), 2),
Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(..) => {
Addr::AttrVar(..) | Addr::HeapCell(_) | Addr::StackCell(..) => {
let name = self.store(self.deref(self[temp_v!(2)].clone()));
let arity = self.store(self.deref(self[temp_v!(3)].clone()));

View File

@@ -203,6 +203,36 @@ impl MachineState {
_ => self.fail = true
};
},
&SystemClauseType::DeleteAttribute => {
let ls0 = self.store(self.deref(self[temp_v!(1)].clone()));
if let Addr::Lis(l1) = ls0 {
if let Addr::Lis(l2) = self.store(self.deref(Addr::HeapCell(l1 + 1))) {
let addr = self.heap[l1 + 1].as_addr(l1 + 1);
self.heap[l1 + 1] = HeapCellValue::Addr(Addr::HeapCell(l2 + 1));
self.trail(TrailRef::AttrVarLink(l2 + 1, addr));
}
}
},
&SystemClauseType::DeleteHeadAttribute => {
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
match addr {
Addr::AttrVar(_, attr_var) => {
let addr = self.heap[attr_var].as_addr(attr_var).clone();
let addr = self.store(self.deref(addr));
match addr {
Addr::Lis(l) => {
self.heap[attr_var] = HeapCellValue::Addr(Addr::HeapCell(l+1));
self.trail(TrailRef::AttrVarLink(attr_var, Addr::Lis(l)));
},
_ => {}
}
},
_ => {}
}
},
&SystemClauseType::DynamicModuleResolution => {
let module_name = self.store(self.deref(self[temp_v!(1)].clone()));
@@ -237,6 +267,40 @@ impl MachineState {
self.p = CodePtr::Local(LocalCodePtr::UserTermExpansion(0));
return Ok(());
},
&SystemClauseType::GetAttributedVariableList => {
let attr_var = self.store(self.deref(self[temp_v!(1)].clone()));
let mut attr_var_list = match attr_var {
Addr::AttrVar(_, attr_var_list) => attr_var_list,
attr_var @ Addr::HeapCell(_) | attr_var @ Addr::StackCell(..) => {
// create an AttrVar in the heap.
let h = self.heap.h;
self.heap.push(HeapCellValue::Addr(Addr::AttrVar(h, h + 2)));
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + 1)));
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + 2)));
match attr_var.as_var().unwrap() {
Ref::HeapCell(r) => {
self.heap[r] = HeapCellValue::Addr(Addr::HeapCell(h));
self.trail(TrailRef::HeapCell(r));
},
Ref::StackCell(fr, sc) => {
self.and_stack[fr][sc] = Addr::HeapCell(h);
self.trail(TrailRef::StackCell(fr, sc));
}
}
h + 2
},
_ => {
self.fail = true;
return Ok(());
}
};
let list_var = self[temp_v!(2)].clone();
self.unify(Addr::HeapCell(attr_var_list), list_var);
},
&SystemClauseType::GetDoubleQuotes => {
let a1 = self[temp_v!(1)].clone();

View File

@@ -196,7 +196,7 @@ impl<'a, R: Read> TermStream<'a, R> {
fn parse_expansion_output(&mut self, term_string: &str, op_dir: &OpDir)
-> Result<Term, ParserError>
{
let mut parser = Parser::new(term_string.trim().as_bytes(), self.indices.atom_tbl.clone(),
let mut parser = Parser::new(term_string.trim().as_bytes(), self.parser.get_atom_tbl(),
self.flags);
parser.read_term(composite_op!(self.in_module, &self.indices.op_dir, op_dir))
}
@@ -288,6 +288,18 @@ impl<'a, R: Read> TermStream<'a, R> {
}
impl MachineState {
fn print_with_locs(&self, target: usize, var_dict: &HeapVarDict) -> PrinterOutputter {
let output = PrinterOutputter::new();
let mut printer = HCPrinter::from_heap_locs(&self, output, &var_dict);
printer.quoted = true;
printer.numbervars = true;
printer.see_all_locs();
printer.print(Addr::HeapCell(target))
}
fn try_expand_term(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies,
code_repo: &mut CodeRepo, term: &Term, hook: CompileTimeHook)
-> Option<String>
@@ -308,17 +320,7 @@ impl MachineState {
self.reset();
None
} else {
let mut output = {
let output = PrinterOutputter::new();
let mut printer = HCPrinter::from_heap_locs(&self, output, &var_dict);
printer.quoted = true;
printer.numbervars = true;
printer.see_all_locs();
printer.print(Addr::HeapCell(h))
};
let mut output = self.print_with_locs(h, &var_dict);
output.push_char('.');
self.reset();

View File

@@ -146,7 +146,7 @@ impl fmt::Display for Addr {
match self {
&Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
&Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
&Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
&Addr::AttrVar(h, attr_var_list) => write!(f, "Addr::AttrVar({}, {})", h, attr_var_list),
&Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
&Addr::StackCell(fr, sc)=> write!(f, "Addr::StackCell({}, {})", fr, sc),
&Addr::Str(s) => write!(f, "Addr::Str({})", s)