address issue #153
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "scryer-prolog"
|
name = "scryer-prolog"
|
||||||
version = "0.8.88"
|
version = "0.8.89"
|
||||||
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
||||||
repository = "https://github.com/mthom/scryer-prolog"
|
repository = "https://github.com/mthom/scryer-prolog"
|
||||||
description = "A modern Prolog implementation written mostly in Rust."
|
description = "A modern Prolog implementation written mostly in Rust."
|
||||||
|
|||||||
@@ -675,9 +675,6 @@ current_predicate(Pred) :-
|
|||||||
-> throw(error(type_error(predicate_indicator, Pred), current_predicate/1))
|
-> throw(error(type_error(predicate_indicator, Pred), current_predicate/1))
|
||||||
; '$get_next_db_ref'(Ref, _),
|
; '$get_next_db_ref'(Ref, _),
|
||||||
'$iterate_db_refs'(Ref, Pred)
|
'$iterate_db_refs'(Ref, Pred)
|
||||||
; Pred = call/N,
|
|
||||||
max_arity(Max),
|
|
||||||
between:between(0, Max, N)
|
|
||||||
).
|
).
|
||||||
|
|
||||||
'$iterate_op_db_refs'(Ref, Priority, Spec, Op) :-
|
'$iterate_op_db_refs'(Ref, Priority, Spec, Op) :-
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ pub type OssifiedOpDir = BTreeMap<OrderedOpDirKey, (usize, Specifier)>;
|
|||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum DBRef {
|
pub enum DBRef {
|
||||||
BuiltInPred(ClauseName, usize, Option<SharedOpDesc>),
|
|
||||||
NamedPred(ClauseName, usize, Option<SharedOpDesc>),
|
NamedPred(ClauseName, usize, Option<SharedOpDesc>),
|
||||||
Op(usize, Specifier, ClauseName, Rc<OssifiedOpDir>, SharedOpDesc)
|
Op(usize, Specifier, ClauseName, Rc<OssifiedOpDir>, SharedOpDesc)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,9 +153,10 @@ impl SubModuleUser for IndexStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static BUILTINS: &str = include_str!("../lib/builtins.pl");
|
static BUILTINS: &str = include_str!("../lib/builtins.pl");
|
||||||
|
static ERROR: &str = include_str!("../lib/error.pl");
|
||||||
|
static LISTS: &str = include_str!("../lib/lists.pl");
|
||||||
|
static NON_ISO: &str = include_str!("../lib/non_iso.pl");
|
||||||
static TOPLEVEL: &str = include_str!("../toplevel.pl");
|
static TOPLEVEL: &str = include_str!("../toplevel.pl");
|
||||||
static BETWEEN: &str = include_str!("../lib/between.pl");
|
|
||||||
static NON_ISO: &str = include_str!("../lib/non_iso.pl");
|
|
||||||
|
|
||||||
impl Machine {
|
impl Machine {
|
||||||
fn compile_special_forms(&mut self) {
|
fn compile_special_forms(&mut self) {
|
||||||
@@ -229,7 +230,8 @@ impl Machine {
|
|||||||
wam.compile_special_forms();
|
wam.compile_special_forms();
|
||||||
wam.compile_top_level();
|
wam.compile_top_level();
|
||||||
|
|
||||||
compile_user_module(&mut wam, parsing_stream(BETWEEN.as_bytes()));
|
compile_user_module(&mut wam, parsing_stream(ERROR.as_bytes()));
|
||||||
|
compile_user_module(&mut wam, parsing_stream(LISTS.as_bytes()));
|
||||||
compile_user_module(&mut wam, parsing_stream(NON_ISO.as_bytes()));
|
compile_user_module(&mut wam, parsing_stream(NON_ISO.as_bytes()));
|
||||||
|
|
||||||
wam.compile_scryerrc();
|
wam.compile_scryerrc();
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ use prolog::ordered_float::OrderedFloat;
|
|||||||
use prolog::read::{PrologStream, readline};
|
use prolog::read::{PrologStream, readline};
|
||||||
use prolog::rug::Integer;
|
use prolog::rug::Integer;
|
||||||
|
|
||||||
use ref_thread_local::RefThreadLocal;
|
|
||||||
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::io::{stdout, Write};
|
use std::io::{stdout, Write};
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
@@ -36,6 +34,13 @@ impl BrentAlgState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_builtin_predicate(name: &ClauseName) -> bool {
|
||||||
|
let in_builtins = name.owning_module().as_str() == "builtins";
|
||||||
|
let hidden_name = name.as_str().starts_with("$");
|
||||||
|
|
||||||
|
in_builtins || hidden_name
|
||||||
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
// a step in Brent's algorithm.
|
// a step in Brent's algorithm.
|
||||||
fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult>
|
fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult>
|
||||||
@@ -260,65 +265,31 @@ impl MachineState {
|
|||||||
|
|
||||||
fn get_next_db_ref(&mut self, indices: &IndexStore, db_ref: &DBRef) {
|
fn get_next_db_ref(&mut self, indices: &IndexStore, db_ref: &DBRef) {
|
||||||
match db_ref {
|
match db_ref {
|
||||||
&DBRef::BuiltInPred(ref name, arity, _) => {
|
|
||||||
let key = (name.as_str(), arity);
|
|
||||||
|
|
||||||
match CLAUSE_TYPE_FORMS.borrow().range(&key ..).skip(1).next() {
|
|
||||||
Some(((_, arity), ct)) => {
|
|
||||||
let a2 = self[temp_v!(2)].clone();
|
|
||||||
|
|
||||||
if let Some(r) = a2.as_var() {
|
|
||||||
self.bind(r, Addr::DBRef(DBRef::BuiltInPred(ct.name(), *arity, ct.spec())));
|
|
||||||
} else {
|
|
||||||
self.fail = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None =>
|
|
||||||
match indices.code_dir.iter().next() {
|
|
||||||
Some(((ref name, arity), idx)) => {
|
|
||||||
let a2 = self[temp_v!(2)].clone();
|
|
||||||
|
|
||||||
if idx.is_undefined() {
|
|
||||||
self.fail = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(r) = a2.as_var() {
|
|
||||||
let spec = get_clause_spec(name.clone(), *arity,
|
|
||||||
composite_op!(&indices.op_dir));
|
|
||||||
self.bind(r, Addr::DBRef(DBRef::NamedPred(name.clone(), *arity, spec)));
|
|
||||||
} else {
|
|
||||||
self.fail = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
self.fail = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
&DBRef::NamedPred(ref name, arity, _) => {
|
&DBRef::NamedPred(ref name, arity, _) => {
|
||||||
let key = (name.clone(), arity);
|
let key = (name.clone(), arity);
|
||||||
|
let mut iter = indices.code_dir.range(key ..).skip(1);
|
||||||
|
|
||||||
match indices.code_dir.range(key ..).skip(1).next() {
|
while let Some(((name, arity), idx)) = iter.next() {
|
||||||
Some(((name, arity), idx)) => {
|
if idx.is_undefined() {
|
||||||
let a2 = self[temp_v!(2)].clone();
|
self.fail = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if idx.is_undefined() {
|
if is_builtin_predicate(&name) {
|
||||||
self.fail = true;
|
continue;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(r) = a2.as_var() {
|
let a2 = self[temp_v!(2)].clone();
|
||||||
let spec = get_clause_spec(name.clone(), *arity,
|
|
||||||
composite_op!(&indices.op_dir));
|
if let Some(r) = a2.as_var() {
|
||||||
self.bind(r, Addr::DBRef(DBRef::NamedPred(name.clone(), *arity, spec)));
|
let spec = get_clause_spec(name.clone(), *arity,
|
||||||
} else {
|
composite_op!(&indices.op_dir));
|
||||||
self.fail = true;
|
self.bind(r, Addr::DBRef(DBRef::NamedPred(name.clone(), *arity, spec)));
|
||||||
}
|
return;
|
||||||
},
|
}
|
||||||
None => self.fail = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.fail = true;
|
||||||
},
|
},
|
||||||
&DBRef::Op(_, spec, ref name, ref op_dir, _) => {
|
&DBRef::Op(_, spec, ref name, ref op_dir, _) => {
|
||||||
let fixity = match spec {
|
let fixity = match spec {
|
||||||
@@ -900,19 +871,25 @@ impl MachineState {
|
|||||||
match self.store(self.deref(a1)) {
|
match self.store(self.deref(a1)) {
|
||||||
addr @ Addr::HeapCell(_)
|
addr @ Addr::HeapCell(_)
|
||||||
| addr @ Addr::StackCell(..)
|
| addr @ Addr::StackCell(..)
|
||||||
| addr @ Addr::AttrVar(_) =>
|
| addr @ Addr::AttrVar(_) => {
|
||||||
match CLAUSE_TYPE_FORMS.borrow().iter().next() {
|
let mut iter = indices.code_dir.iter();
|
||||||
Some(((_, arity), ct)) => {
|
|
||||||
let db_ref = DBRef::BuiltInPred(ct.name(), *arity, ct.spec());
|
while let Some(((name, arity), _)) = iter.next() {
|
||||||
let r = addr.as_var().unwrap();
|
if is_builtin_predicate(&name) {
|
||||||
|
continue;
|
||||||
self.bind(r, Addr::DBRef(db_ref));
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
self.fail = true;
|
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
let spec = get_clause_spec(name.clone(), *arity,
|
||||||
|
composite_op!(&indices.op_dir));
|
||||||
|
let db_ref = DBRef::NamedPred(name.clone(), *arity, spec);
|
||||||
|
let r = addr.as_var().unwrap();
|
||||||
|
|
||||||
|
self.bind(r, Addr::DBRef(db_ref));
|
||||||
|
return return_from_clause!(self.last_call, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.fail = true;
|
||||||
|
},
|
||||||
Addr::DBRef(DBRef::Op(..)) => self.fail = true,
|
Addr::DBRef(DBRef::Op(..)) => self.fail = true,
|
||||||
Addr::DBRef(ref db_ref) =>
|
Addr::DBRef(ref db_ref) =>
|
||||||
self.get_next_db_ref(&indices, db_ref),
|
self.get_next_db_ref(&indices, db_ref),
|
||||||
@@ -961,7 +938,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Addr::DBRef(DBRef::BuiltInPred(..)) | Addr::DBRef(DBRef::NamedPred(..)) =>
|
Addr::DBRef(DBRef::NamedPred(..)) =>
|
||||||
self.fail = true,
|
self.fail = true,
|
||||||
Addr::DBRef(ref db_ref) =>
|
Addr::DBRef(ref db_ref) =>
|
||||||
self.get_next_db_ref(&indices, db_ref),
|
self.get_next_db_ref(&indices, db_ref),
|
||||||
@@ -976,7 +953,7 @@ impl MachineState {
|
|||||||
match self.store(self.deref(a1)) {
|
match self.store(self.deref(a1)) {
|
||||||
Addr::DBRef(db_ref) =>
|
Addr::DBRef(db_ref) =>
|
||||||
match db_ref {
|
match db_ref {
|
||||||
DBRef::BuiltInPred(name, arity, spec) | DBRef::NamedPred(name, arity, spec) => {
|
DBRef::NamedPred(name, arity, spec) => {
|
||||||
let a2 = self[temp_v!(2)].clone();
|
let a2 = self[temp_v!(2)].clone();
|
||||||
let a3 = self[temp_v!(3)].clone();
|
let a3 = self[temp_v!(3)].clone();
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
repl :-
|
'$repl' :-
|
||||||
catch(read_and_match, E, '$print_exception'(E)),
|
catch('$read_and_match', E, '$print_exception'(E)),
|
||||||
false. %% this is for GC, until we get actual GC.
|
false. %% this is for GC, until we get actual GC.
|
||||||
repl :- repl.
|
'$repl' :- '$repl'.
|
||||||
|
|
||||||
read_and_match :-
|
'$read_and_match' :-
|
||||||
write_term('?- ', [quoted(false)]),
|
write_term('?- ', [quoted(false)]),
|
||||||
read_term(Term, [variable_names(VarList)]),
|
read_term(Term, [variable_names(VarList)]),
|
||||||
'$instruction_match'(Term, VarList).
|
'$instruction_match'(Term, VarList).
|
||||||
|
|||||||
@@ -164,7 +164,6 @@ impl fmt::Display for HeapCellValue {
|
|||||||
impl fmt::Display for DBRef {
|
impl fmt::Display for DBRef {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&DBRef::BuiltInPred(ref name, arity, _) => write!(f, "db_ref:builtin:{}/{}", name, arity),
|
|
||||||
&DBRef::NamedPred(ref name, arity, _) => write!(f, "db_ref:named:{}/{}", name, arity),
|
&DBRef::NamedPred(ref name, arity, _) => write!(f, "db_ref:named:{}/{}", name, arity),
|
||||||
&DBRef::Op(priority, spec, ref name, ..) => write!(f, "db_ref:op({}, {}, {})", priority,
|
&DBRef::Op(priority, spec, ref name, ..) => write!(f, "db_ref:op({}, {}, {})", priority,
|
||||||
spec, name)
|
spec, name)
|
||||||
|
|||||||
Reference in New Issue
Block a user