fix goal expansion in disjunctions, add warnings for singleton variables
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "scryer-prolog"
|
name = "scryer-prolog"
|
||||||
version = "0.8.98"
|
version = "0.8.99"
|
||||||
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
repository = "https://github.com/mthom/scryer-prolog"
|
repository = "https://github.com/mthom/scryer-prolog"
|
||||||
@@ -18,7 +18,7 @@ lazy_static = "1.4.0"
|
|||||||
libc = "0.2.62"
|
libc = "0.2.62"
|
||||||
nix = "0.15.0"
|
nix = "0.15.0"
|
||||||
ordered-float = "0.5.0"
|
ordered-float = "0.5.0"
|
||||||
prolog_parser = "0.8.30"
|
prolog_parser = "0.8.31"
|
||||||
ref_thread_local = "0.0.0"
|
ref_thread_local = "0.0.0"
|
||||||
rug = "1.4.0"
|
rug = "1.4.0"
|
||||||
rustyline = "5.0.3"
|
rustyline = "5.0.3"
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use std::vec::Vec;
|
|||||||
pub struct CodeGenerator<TermMarker> {
|
pub struct CodeGenerator<TermMarker> {
|
||||||
flags: MachineFlags,
|
flags: MachineFlags,
|
||||||
marker: TermMarker,
|
marker: TermMarker,
|
||||||
var_count: IndexMap<Rc<Var>, usize>,
|
pub var_count: IndexMap<Rc<Var>, usize>,
|
||||||
non_counted_bt: bool,
|
non_counted_bt: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -867,8 +867,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
self.marker.reset();
|
self.marker.reset();
|
||||||
|
|
||||||
let mut clause_code = match clause {
|
let mut clause_code = match clause {
|
||||||
&PredicateClause::Fact(ref fact) => self.compile_fact(fact),
|
&PredicateClause::Fact(ref fact, ..) => self.compile_fact(fact),
|
||||||
&PredicateClause::Rule(ref rule) => try!(self.compile_rule(rule)),
|
&PredicateClause::Rule(ref rule, ..) => self.compile_rule(rule)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
if num_clauses > 1 {
|
if num_clauses > 1 {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use prolog_parser::parser::OpDesc;
|
|||||||
use prolog_parser::tabled_rc::*;
|
use prolog_parser::tabled_rc::*;
|
||||||
|
|
||||||
use prolog::clause_types::*;
|
use prolog::clause_types::*;
|
||||||
|
use prolog::iterators::*;
|
||||||
use prolog::machine::machine_errors::*;
|
use prolog::machine::machine_errors::*;
|
||||||
use prolog::machine::machine_indices::*;
|
use prolog::machine::machine_indices::*;
|
||||||
use prolog::ordered_float::OrderedFloat;
|
use prolog::ordered_float::OrderedFloat;
|
||||||
@@ -23,41 +24,75 @@ pub type JumpStub = Vec<Term>;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum TopLevel {
|
pub enum TopLevel {
|
||||||
Declaration(Declaration),
|
Declaration(Declaration),
|
||||||
Fact(Term),
|
Fact(Term, usize, usize), // Term, line_num, col_num
|
||||||
Predicate(Predicate),
|
Predicate(Predicate),
|
||||||
Query(Vec<QueryTerm>),
|
Query(Vec<QueryTerm>),
|
||||||
Rule(Rule),
|
Rule(Rule, usize, usize), // Rule, line_num, col_num
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TopLevel {
|
impl TopLevel {
|
||||||
pub fn name(&self) -> Option<ClauseName> {
|
pub fn name(&self) -> Option<ClauseName> {
|
||||||
match self {
|
match self {
|
||||||
&TopLevel::Declaration(_) => None,
|
&TopLevel::Declaration(_) => None,
|
||||||
&TopLevel::Fact(ref term) => term.name(),
|
&TopLevel::Fact(ref term, ..) => term.name(),
|
||||||
&TopLevel::Predicate(ref clauses) => clauses.0.first().and_then(|ref term| term.name()),
|
&TopLevel::Predicate(ref clauses) => clauses.0.first().and_then(|ref term| term.name()),
|
||||||
&TopLevel::Query(_) => None,
|
&TopLevel::Query(_) => None,
|
||||||
&TopLevel::Rule(Rule { ref head, .. }) => Some(head.0.clone()),
|
&TopLevel::Rule(Rule { ref head, .. }, ..) => Some(head.0.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arity(&self) -> usize {
|
pub fn arity(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
&TopLevel::Declaration(_) => 0,
|
&TopLevel::Declaration(_) => 0,
|
||||||
&TopLevel::Fact(ref term) => term.arity(),
|
&TopLevel::Fact(ref term, ..) => term.arity(),
|
||||||
&TopLevel::Predicate(ref clauses) => clauses.0.first().map(|t| t.arity()).unwrap_or(0),
|
&TopLevel::Predicate(ref clauses) => clauses.0.first().map(|t| t.arity()).unwrap_or(0),
|
||||||
&TopLevel::Query(_) => 0,
|
&TopLevel::Query(_) => 0,
|
||||||
&TopLevel::Rule(Rule { ref head, .. }) => head.1.len(),
|
&TopLevel::Rule(Rule { ref head, .. }, ..) => head.1.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_end_of_file_atom(&self) -> bool {
|
pub fn is_end_of_file_atom(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&TopLevel::Fact(Term::Constant(_, Constant::Atom(ref name, _))) => {
|
&TopLevel::Fact(Term::Constant(_, Constant::Atom(ref name, _)), ..) => {
|
||||||
return name.as_str() == "end_of_file"
|
return name.as_str() == "end_of_file"
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn location(&self) -> Option<(usize, usize)> {
|
||||||
|
match self {
|
||||||
|
&TopLevel::Fact(_, line_num, col_num) | &TopLevel::Rule(_, line_num, col_num) =>
|
||||||
|
Some((line_num, col_num)),
|
||||||
|
&TopLevel::Predicate(Predicate(ref clauses)) =>
|
||||||
|
clauses.first().map(|clause| (clause.line_num(), clause.col_num())),
|
||||||
|
_ =>
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn var_count(&self) -> Option<Vec<IndexMap<Rc<Var>, usize>>> {
|
||||||
|
match self {
|
||||||
|
&TopLevel::Fact(ref term, ..) => {
|
||||||
|
let mut var_count = IndexMap::new();
|
||||||
|
|
||||||
|
for term_ref in breadth_first_iter(term, true) {
|
||||||
|
if let TermRef::Var(_, _, var) = term_ref {
|
||||||
|
let entry = var_count.entry(var).or_insert(0);
|
||||||
|
*entry += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(vec![var_count])
|
||||||
|
}
|
||||||
|
&TopLevel::Rule(ref rule, ..) =>
|
||||||
|
Some(vec![rule.var_count()]),
|
||||||
|
&TopLevel::Predicate(ref predicate) =>
|
||||||
|
Some(predicate.var_count()),
|
||||||
|
_ =>
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@@ -110,6 +145,40 @@ pub struct Rule {
|
|||||||
pub clauses: Vec<QueryTerm>,
|
pub clauses: Vec<QueryTerm>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Rule {
|
||||||
|
pub fn var_count(&self) -> IndexMap<Rc<Var>, usize> {
|
||||||
|
let mut var_count = IndexMap::new();
|
||||||
|
|
||||||
|
for root_term in &self.head.1 {
|
||||||
|
// true because the root term is iterable.
|
||||||
|
for term_ref in breadth_first_iter(root_term, true) {
|
||||||
|
if let TermRef::Var(_, _, var) = term_ref {
|
||||||
|
let entry = var_count.entry(var).or_insert(0);
|
||||||
|
*entry += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for term_ref in query_term_post_order_iter(&self.head.2) {
|
||||||
|
if let TermRef::Var(_, _, var) = term_ref {
|
||||||
|
let entry = var_count.entry(var).or_insert(0);
|
||||||
|
*entry += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for clause in &self.clauses {
|
||||||
|
for term_ref in query_term_post_order_iter(clause) {
|
||||||
|
if let TermRef::Var(_, _, var) = term_ref {
|
||||||
|
let entry = var_count.entry(var).or_insert(0);
|
||||||
|
*entry += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var_count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Predicate(pub Vec<PredicateClause>);
|
pub struct Predicate(pub Vec<PredicateClause>);
|
||||||
|
|
||||||
@@ -130,35 +199,72 @@ impl Predicate {
|
|||||||
.first()
|
.first()
|
||||||
.and_then(|clause| clause.name().map(|name| (name, clause.arity())))
|
.and_then(|clause| clause.name().map(|name| (name, clause.arity())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn var_count(&self) -> Vec<IndexMap<Rc<Var>, usize>> {
|
||||||
|
self.0.iter().map(|clause| clause.var_count()).collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type CompiledResult = (Predicate, VecDeque<TopLevel>);
|
pub type CompiledResult = (Predicate, VecDeque<TopLevel>);
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum PredicateClause {
|
pub enum PredicateClause {
|
||||||
Fact(Term),
|
Fact(Term, usize, usize), // Term, line number, column number.
|
||||||
Rule(Rule),
|
Rule(Rule, usize, usize), // Term, line number, column number.
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PredicateClause {
|
impl PredicateClause {
|
||||||
pub fn first_arg(&self) -> Option<&Term> {
|
pub fn first_arg(&self) -> Option<&Term> {
|
||||||
match self {
|
match self {
|
||||||
&PredicateClause::Fact(ref term) => term.first_arg(),
|
&PredicateClause::Fact(ref term, ..) => term.first_arg(),
|
||||||
&PredicateClause::Rule(ref rule) => rule.head.1.first().map(|bt| bt.as_ref()),
|
&PredicateClause::Rule(ref rule, ..) => rule.head.1.first().map(|bt| bt.as_ref()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arity(&self) -> usize {
|
pub fn arity(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
&PredicateClause::Fact(ref term) => term.arity(),
|
&PredicateClause::Fact(ref term, ..) => term.arity(),
|
||||||
&PredicateClause::Rule(ref rule) => rule.head.1.len(),
|
&PredicateClause::Rule(ref rule, ..) => rule.head.1.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> Option<ClauseName> {
|
pub fn name(&self) -> Option<ClauseName> {
|
||||||
match self {
|
match self {
|
||||||
&PredicateClause::Fact(ref term) => term.name(),
|
&PredicateClause::Fact(ref term, ..) => term.name(),
|
||||||
&PredicateClause::Rule(ref rule) => Some(rule.head.0.clone()),
|
&PredicateClause::Rule(ref rule, ..) => Some(rule.head.0.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn line_num(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
&PredicateClause::Fact(_, line_num, _) => line_num,
|
||||||
|
&PredicateClause::Rule(_, line_num, _) => line_num
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn col_num(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
&PredicateClause::Fact(_, _, col_num) => col_num,
|
||||||
|
&PredicateClause::Rule(_, _, col_num) => col_num
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn var_count(&self) -> IndexMap<Rc<Var>, usize> {
|
||||||
|
match self {
|
||||||
|
&PredicateClause::Fact(ref term, ..) => {
|
||||||
|
let mut var_count = IndexMap::new();
|
||||||
|
|
||||||
|
for term_ref in breadth_first_iter(term, true) {
|
||||||
|
if let TermRef::Var(_, _, var) = term_ref {
|
||||||
|
let entry = var_count.entry(var).or_insert(0);
|
||||||
|
*entry += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var_count
|
||||||
|
}
|
||||||
|
&PredicateClause::Rule(ref rule, ..) =>
|
||||||
|
rule.var_count()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,8 @@ impl<'a> QueryIterator<'a> {
|
|||||||
state_stack: vec![],
|
state_stack: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Term::Var(ref cell, ref var) => TermIterState::Var(Level::Root, cell, (*var).clone()),
|
&Term::Var(ref cell, ref var) =>
|
||||||
|
TermIterState::Var(Level::Root, cell, (*var).clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
QueryIterator {
|
QueryIterator {
|
||||||
|
|||||||
@@ -81,10 +81,12 @@ expand_body_term([Arg|Args], ModTerm, N0, N) :-
|
|||||||
append([Arg|Args], '$VAR'(N), ModArgs),
|
append([Arg|Args], '$VAR'(N), ModArgs),
|
||||||
ModTerm = ('$VAR'(N0) = ModArgs).
|
ModTerm = ('$VAR'(N0) = ModArgs).
|
||||||
expand_body_term((P -> Q), (PModTerm -> QModTerm), N0, N) :-
|
expand_body_term((P -> Q), (PModTerm -> QModTerm), N0, N) :-
|
||||||
!, expand_body(P, PModTerm, N0, N1),
|
!,
|
||||||
|
expand_body(P, PModTerm, N0, N1),
|
||||||
expand_body(Q, QModTerm, N1, N).
|
expand_body(Q, QModTerm, N1, N).
|
||||||
expand_body_term((P ; Q), (PModTerm ; QModTerm), N0, N) :-
|
expand_body_term((P ; Q), (PModTerm ; QModTerm), N0, N) :-
|
||||||
!, expand_body(P, PModTerm0, N0, N1),
|
!,
|
||||||
|
expand_body(P, PModTerm0, N0, N1),
|
||||||
expand_body(Q, QModTerm0, N0, N2),
|
expand_body(Q, QModTerm0, N0, N2),
|
||||||
( N1 == N2 -> PModTerm = PModTerm0,
|
( N1 == N2 -> PModTerm = PModTerm0,
|
||||||
QModTerm = QModTerm0,
|
QModTerm = QModTerm0,
|
||||||
|
|||||||
@@ -56,16 +56,18 @@ fn fix_filename(atom_tbl: TabledData<Atom>, filename: &str) -> Result<PathBuf, S
|
|||||||
Ok(path)
|
Ok(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_module<R: Read>(wam: &mut Machine, stream: ParsingStream<R>)
|
fn load_module<R: Read>(
|
||||||
-> Result<Option<ClauseName>, SessionError>
|
wam: &mut Machine,
|
||||||
{
|
stream: ParsingStream<R>,
|
||||||
|
suppress_warnings: bool,
|
||||||
|
) -> Result<Option<ClauseName>, SessionError> {
|
||||||
// follow the operation of compile_user_module, but before
|
// follow the operation of compile_user_module, but before
|
||||||
// compiling, check that a module is declared in the file. if not,
|
// compiling, check that a module is declared in the file. if not,
|
||||||
// throw an exception.
|
// throw an exception.
|
||||||
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
||||||
setup_indices(wam, clause_name!("builtins"), &mut indices)?;
|
setup_indices(wam, clause_name!("builtins"), &mut indices)?;
|
||||||
|
|
||||||
let mut compiler = ListingCompiler::new(&wam.code_repo);
|
let mut compiler = ListingCompiler::new(&wam.code_repo, suppress_warnings);
|
||||||
let results = compiler.gather_items(wam, stream, &mut indices)?;
|
let results = compiler.gather_items(wam, stream, &mut indices)?;
|
||||||
|
|
||||||
let module_name = if let Some(ref module) = &compiler.module {
|
let module_name = if let Some(ref module) = &compiler.module {
|
||||||
@@ -81,9 +83,11 @@ fn load_module<R: Read>(wam: &mut Machine, stream: ParsingStream<R>)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn load_module_from_file(wam: &mut Machine, filename: &str)
|
fn load_module_from_file(
|
||||||
-> Result<Option<ClauseName>, SessionError>
|
wam: &mut Machine,
|
||||||
{
|
filename: &str,
|
||||||
|
suppress_warnings: bool,
|
||||||
|
) -> Result<Option<ClauseName>, SessionError> {
|
||||||
let path = fix_filename(wam.indices.atom_tbl.clone(), filename)?;
|
let path = fix_filename(wam.indices.atom_tbl.clone(), filename)?;
|
||||||
|
|
||||||
let file_handle = File::open(&path).or_else(|_| {
|
let file_handle = File::open(&path).or_else(|_| {
|
||||||
@@ -91,24 +95,51 @@ fn load_module_from_file(wam: &mut Machine, filename: &str)
|
|||||||
Err(SessionError::InvalidFileName(filename))
|
Err(SessionError::InvalidFileName(filename))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
load_module(wam, parsing_stream(file_handle))
|
load_module(wam, parsing_stream(file_handle), suppress_warnings)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PredicateCompileQueue = (Predicate, VecDeque<TopLevel>);
|
pub type PredicateCompileQueue = (Predicate, VecDeque<TopLevel>);
|
||||||
|
|
||||||
// throw errors if declaration or query found.
|
// throw errors if declaration or query found.
|
||||||
fn compile_relation(
|
fn compile_relation(
|
||||||
tl: &TopLevel,
|
cg: &mut CodeGenerator<DebrayAllocator>,
|
||||||
non_counted_bt: bool,
|
tl: &TopLevel
|
||||||
flags: MachineFlags,
|
|
||||||
) -> Result<Code, ParserError> {
|
) -> Result<Code, ParserError> {
|
||||||
let mut cg = CodeGenerator::<DebrayAllocator>::new(non_counted_bt, flags);
|
|
||||||
|
|
||||||
match tl {
|
match tl {
|
||||||
&TopLevel::Declaration(_) | &TopLevel::Query(_) => Err(ParserError::ExpectedRel),
|
&TopLevel::Declaration(_) | &TopLevel::Query(_) => Err(ParserError::ExpectedRel),
|
||||||
&TopLevel::Predicate(ref clauses) => cg.compile_predicate(&clauses.0),
|
&TopLevel::Predicate(ref clauses) => cg.compile_predicate(&clauses.0),
|
||||||
&TopLevel::Fact(ref fact) => Ok(cg.compile_fact(fact)),
|
&TopLevel::Fact(ref fact, ..) => Ok(cg.compile_fact(fact)),
|
||||||
&TopLevel::Rule(ref rule) => cg.compile_rule(rule),
|
&TopLevel::Rule(ref rule, ..) => cg.compile_rule(rule),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn issue_singleton_warnings(
|
||||||
|
tl: &TopLevel,
|
||||||
|
module_name: ClauseName,
|
||||||
|
) {
|
||||||
|
if let Some((line_num, _)) = tl.location() {
|
||||||
|
if let Some(var_counts) = tl.var_count() {
|
||||||
|
for var_count in var_counts {
|
||||||
|
let mut singletons = vec![];
|
||||||
|
|
||||||
|
for (var, count) in var_count {
|
||||||
|
if count == 1 && !var.starts_with("_") && var.as_str() != "!" {
|
||||||
|
singletons.push(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(last_var) = singletons.pop() {
|
||||||
|
print!("Warning: {}:{}: Singleton variables: [",
|
||||||
|
module_name, line_num);
|
||||||
|
|
||||||
|
for var in singletons {
|
||||||
|
print!("{}, ", var);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{}]", last_var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +170,9 @@ pub fn compile_appendix(
|
|||||||
) -> Result<(), ParserError> {
|
) -> Result<(), ParserError> {
|
||||||
for tl in queue.iter() {
|
for tl in queue.iter() {
|
||||||
set_first_index(code);
|
set_first_index(code);
|
||||||
code.append(&mut compile_relation(tl, non_counted_bt, flags)?);
|
let mut cg = CodeGenerator::<DebrayAllocator>::new(non_counted_bt, flags);
|
||||||
|
let decl_code = compile_relation(&mut cg, tl)?;
|
||||||
|
code.extend(decl_code.into_iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -209,7 +242,7 @@ pub fn compile_term(wam: &mut Machine, packet: TopLevelPacket) -> EvalSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TopLevelPacket::Decl(TopLevel::Declaration(decl), _) => {
|
TopLevelPacket::Decl(TopLevel::Declaration(decl), _) => {
|
||||||
let mut compiler = ListingCompiler::new(&wam.code_repo);
|
let mut compiler = ListingCompiler::new(&wam.code_repo, false);
|
||||||
let indices = try_eval_session!(compile_decl(wam, &mut compiler, decl));
|
let indices = try_eval_session!(compile_decl(wam, &mut compiler, decl));
|
||||||
|
|
||||||
try_eval_session!(wam.check_toplevel_code(&indices));
|
try_eval_session!(wam.check_toplevel_code(&indices));
|
||||||
@@ -294,7 +327,7 @@ pub(super) fn compile_into_module<R: Read>(
|
|||||||
let mut indices = default_index_store!(wam.atom_tbl_of(&name));
|
let mut indices = default_index_store!(wam.atom_tbl_of(&name));
|
||||||
try_eval_session!(setup_indices(wam, module_name.clone(), &mut indices));
|
try_eval_session!(setup_indices(wam, module_name.clone(), &mut indices));
|
||||||
|
|
||||||
let mut compiler = ListingCompiler::new(&wam.code_repo);
|
let mut compiler = ListingCompiler::new(&wam.code_repo, true);
|
||||||
|
|
||||||
match compile_into_module_impl(wam, &mut compiler, module_name, src, indices) {
|
match compile_into_module_impl(wam, &mut compiler, module_name, src, indices) {
|
||||||
Ok(()) => EvalSession::EntrySuccess,
|
Ok(()) => EvalSession::EntrySuccess,
|
||||||
@@ -382,14 +415,18 @@ impl ClauseCodeGenerator {
|
|||||||
vec![Box::new(head.clone()), Box::new(tail.clone())],
|
vec![Box::new(head.clone()), Box::new(tail.clone())],
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
PredicateClause::Fact(clause)
|
PredicateClause::Fact(clause, 0, 0)
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let p = self.code.len() + wam.code_repo.code.len() + self.len_offset;
|
let p = self.code.len() + wam.code_repo.code.len() + self.len_offset;
|
||||||
let mut decl_code =
|
let mut cg = CodeGenerator::<DebrayAllocator>::new(false, wam.machine_flags());
|
||||||
compile_relation(&TopLevel::Predicate(predicate), false, wam.machine_flags())?;
|
|
||||||
|
let mut decl_code = compile_relation(
|
||||||
|
&mut cg,
|
||||||
|
&TopLevel::Predicate(predicate),
|
||||||
|
)?;
|
||||||
|
|
||||||
compile_appendix(&mut decl_code, &VecDeque::new(), false, wam.machine_flags())?;
|
compile_appendix(&mut decl_code, &VecDeque::new(), false, wam.machine_flags())?;
|
||||||
|
|
||||||
@@ -404,16 +441,18 @@ impl ClauseCodeGenerator {
|
|||||||
{
|
{
|
||||||
wam.code_repo.code.extend(self.code.into_iter());
|
wam.code_repo.code.extend(self.code.into_iter());
|
||||||
|
|
||||||
for ((name, arity), _) in dynamic_code_dir {
|
|
||||||
wam.indices.dynamic_code_dir.insert((name.owning_module(), name.clone(), arity),
|
|
||||||
DynamicPredicateInfo::default());
|
|
||||||
|
|
||||||
if self.module_name.as_str() == "user" {
|
if self.module_name.as_str() == "user" {
|
||||||
wam.indices.code_dir.entry((name, arity))
|
for ((name, arity), _) in &dynamic_code_dir {
|
||||||
.or_insert(CodeIndex::dynamic_undefined(self.module_name.clone()));
|
wam.indices.code_dir.entry((name.clone(), *arity))
|
||||||
|
.or_insert(CodeIndex::dynamic_undefined(clause_name!("user")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ((name, arity), _) in dynamic_code_dir {
|
||||||
|
wam.indices.dynamic_code_dir.insert((name.owning_module(), name, arity),
|
||||||
|
DynamicPredicateInfo::default());
|
||||||
|
}
|
||||||
|
|
||||||
for ((name, arity), p) in self.pi_to_loc {
|
for ((name, arity), p) in self.pi_to_loc {
|
||||||
let entry = wam
|
let entry = wam
|
||||||
.indices
|
.indices
|
||||||
@@ -432,7 +471,8 @@ pub struct ListingCompiler {
|
|||||||
user_term_dir: TermDir,
|
user_term_dir: TermDir,
|
||||||
orig_term_expansion_lens: (usize, usize),
|
orig_term_expansion_lens: (usize, usize),
|
||||||
orig_goal_expansion_lens: (usize, usize),
|
orig_goal_expansion_lens: (usize, usize),
|
||||||
initialization_goals: (Vec<QueryTerm>, VecDeque<TopLevel>)
|
initialization_goals: (Vec<QueryTerm>, VecDeque<TopLevel>),
|
||||||
|
suppress_warnings: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_toplevel_code(wam: &mut Machine, code: Code, mut indices: IndexStore) {
|
fn add_toplevel_code(wam: &mut Machine, code: Code, mut indices: IndexStore) {
|
||||||
@@ -480,11 +520,14 @@ fn add_non_module_code(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn load_library(wam: &mut Machine, name: ClauseName) -> Result<ClauseName, SessionError>
|
fn load_library(
|
||||||
{
|
wam: &mut Machine,
|
||||||
|
name: ClauseName,
|
||||||
|
suppress_warnings: bool,
|
||||||
|
) -> Result<ClauseName, SessionError> {
|
||||||
match LIBRARIES.borrow().get(name.as_str()) {
|
match LIBRARIES.borrow().get(name.as_str()) {
|
||||||
Some(code) => {
|
Some(code) => {
|
||||||
let module_name = load_module(wam, parsing_stream(code.as_bytes()))?;
|
let module_name = load_module(wam, parsing_stream(code.as_bytes()), suppress_warnings)?;
|
||||||
module_name.ok_or(SessionError::NoModuleDeclaration(name))
|
module_name.ok_or(SessionError::NoModuleDeclaration(name))
|
||||||
}
|
}
|
||||||
None => Err(SessionError::ModuleNotFound)
|
None => Err(SessionError::ModuleNotFound)
|
||||||
@@ -493,7 +536,7 @@ fn load_library(wam: &mut Machine, name: ClauseName) -> Result<ClauseName, Sessi
|
|||||||
|
|
||||||
impl ListingCompiler {
|
impl ListingCompiler {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(code_repo: &CodeRepo) -> Self {
|
pub fn new(code_repo: &CodeRepo, suppress_warnings: bool) -> Self {
|
||||||
ListingCompiler {
|
ListingCompiler {
|
||||||
non_counted_bt_preds: IndexSet::new(),
|
non_counted_bt_preds: IndexSet::new(),
|
||||||
module: None,
|
module: None,
|
||||||
@@ -502,7 +545,8 @@ impl ListingCompiler {
|
|||||||
.term_dir_entry_len((clause_name!("term_expansion"), 2)),
|
.term_dir_entry_len((clause_name!("term_expansion"), 2)),
|
||||||
orig_goal_expansion_lens: code_repo
|
orig_goal_expansion_lens: code_repo
|
||||||
.term_dir_entry_len((clause_name!("goal_expansion"), 2)),
|
.term_dir_entry_len((clause_name!("goal_expansion"), 2)),
|
||||||
initialization_goals: (vec![], VecDeque::from(vec![]))
|
initialization_goals: (vec![], VecDeque::from(vec![])),
|
||||||
|
suppress_warnings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -636,14 +680,17 @@ impl ListingCompiler {
|
|||||||
let non_counted_bt = self.non_counted_bt_preds.contains(&(name.clone(), arity));
|
let non_counted_bt = self.non_counted_bt_preds.contains(&(name.clone(), arity));
|
||||||
|
|
||||||
let p = code.len() + wam.code_repo.code.len() + code_offset;
|
let p = code.len() + wam.code_repo.code.len() + code_offset;
|
||||||
let mut decl_code = compile_relation(
|
let mut cg = CodeGenerator::<DebrayAllocator>::new(non_counted_bt, wam.machine_flags());
|
||||||
&TopLevel::Predicate(decl),
|
|
||||||
non_counted_bt,
|
let decl = TopLevel::Predicate(decl);
|
||||||
wam.machine_flags(),
|
let mut decl_code = compile_relation(&mut cg, &decl)?;
|
||||||
)?;
|
|
||||||
|
|
||||||
compile_appendix(&mut decl_code, &queue, non_counted_bt, wam.machine_flags())?;
|
compile_appendix(&mut decl_code, &queue, non_counted_bt, wam.machine_flags())?;
|
||||||
|
|
||||||
|
if !self.suppress_warnings {
|
||||||
|
issue_singleton_warnings(&decl, self.get_module_name());
|
||||||
|
}
|
||||||
|
|
||||||
let idx = code_dir
|
let idx = code_dir
|
||||||
.entry((name.clone(), arity))
|
.entry((name.clone(), arity))
|
||||||
.or_insert(CodeIndex::default());
|
.or_insert(CodeIndex::default());
|
||||||
@@ -748,7 +795,7 @@ impl ListingCompiler {
|
|||||||
}
|
}
|
||||||
Declaration::UseModule(ModuleSource::Library(name)) => {
|
Declaration::UseModule(ModuleSource::Library(name)) => {
|
||||||
let name = if !wam.indices.modules.contains_key(&name) {
|
let name = if !wam.indices.modules.contains_key(&name) {
|
||||||
load_library(wam, name)?
|
load_library(wam, name, true)?
|
||||||
} else {
|
} else {
|
||||||
name
|
name
|
||||||
};
|
};
|
||||||
@@ -757,7 +804,7 @@ impl ListingCompiler {
|
|||||||
}
|
}
|
||||||
Declaration::UseQualifiedModule(ModuleSource::Library(name), exports) => {
|
Declaration::UseQualifiedModule(ModuleSource::Library(name), exports) => {
|
||||||
let name = if !wam.indices.modules.contains_key(&name) {
|
let name = if !wam.indices.modules.contains_key(&name) {
|
||||||
load_library(wam, name)?
|
load_library(wam, name, true)?
|
||||||
} else {
|
} else {
|
||||||
name
|
name
|
||||||
};
|
};
|
||||||
@@ -782,7 +829,7 @@ impl ListingCompiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Declaration::UseModule(ModuleSource::File(filename)) => {
|
Declaration::UseModule(ModuleSource::File(filename)) => {
|
||||||
let name = load_module_from_file(wam, filename.as_str())?;
|
let name = load_module_from_file(wam, filename.as_str(), true)?;
|
||||||
|
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
|
self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
|
||||||
@@ -791,7 +838,7 @@ impl ListingCompiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Declaration::UseQualifiedModule(ModuleSource::File(filename), exports) => {
|
Declaration::UseQualifiedModule(ModuleSource::File(filename), exports) => {
|
||||||
let name = load_module_from_file(wam, filename.as_str())?;
|
let name = load_module_from_file(wam, filename.as_str(), true)?;
|
||||||
|
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
self.use_qualified_module(
|
self.use_qualified_module(
|
||||||
@@ -877,7 +924,7 @@ impl ListingCompiler {
|
|||||||
|
|
||||||
self.process_and_commit_decl(decl, &mut worker, indices, flags)?;
|
self.process_and_commit_decl(decl, &mut worker, indices, flags)?;
|
||||||
|
|
||||||
if let &Some(ref module) = &self.module {
|
if let Some(ref module) = &self.module {
|
||||||
worker.term_stream.set_atom_tbl(module.atom_tbl.clone());
|
worker.term_stream.set_atom_tbl(module.atom_tbl.clone());
|
||||||
}
|
}
|
||||||
} else if decl.is_end_of_file() {
|
} else if decl.is_end_of_file() {
|
||||||
@@ -997,7 +1044,7 @@ pub fn compile_special_form<R: Read>(
|
|||||||
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
||||||
setup_indices(wam, clause_name!("builtins"), &mut indices)?;
|
setup_indices(wam, clause_name!("builtins"), &mut indices)?;
|
||||||
|
|
||||||
let mut compiler = ListingCompiler::new(&wam.code_repo);
|
let mut compiler = ListingCompiler::new(&wam.code_repo, true);
|
||||||
let results = compiler.gather_items(wam, src, &mut indices)?;
|
let results = compiler.gather_items(wam, src, &mut indices)?;
|
||||||
|
|
||||||
compiler.generate_code(results.worker_results, wam, &mut indices.code_dir, 0)
|
compiler.generate_code(results.worker_results, wam, &mut indices.code_dir, 0)
|
||||||
@@ -1008,8 +1055,9 @@ pub fn compile_listing<R: Read>(
|
|||||||
wam: &mut Machine,
|
wam: &mut Machine,
|
||||||
src: ParsingStream<R>,
|
src: ParsingStream<R>,
|
||||||
indices: IndexStore,
|
indices: IndexStore,
|
||||||
|
suppress_warnings: bool
|
||||||
) -> EvalSession {
|
) -> EvalSession {
|
||||||
let mut compiler = ListingCompiler::new(&wam.code_repo);
|
let mut compiler = ListingCompiler::new(&wam.code_repo, suppress_warnings);
|
||||||
|
|
||||||
match compile_work(&mut compiler, wam, src, indices) {
|
match compile_work(&mut compiler, wam, src, indices) {
|
||||||
EvalSession::Error(e) => {
|
EvalSession::Error(e) => {
|
||||||
@@ -1036,8 +1084,12 @@ pub(super) fn setup_indices(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_user_module<R: Read>(wam: &mut Machine, src: ParsingStream<R>) -> EvalSession {
|
pub fn compile_user_module<R: Read>(
|
||||||
|
wam: &mut Machine,
|
||||||
|
src: ParsingStream<R>,
|
||||||
|
suppress_warnings: bool,
|
||||||
|
) -> EvalSession {
|
||||||
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
||||||
try_eval_session!(setup_indices(wam, clause_name!("builtins"), &mut indices));
|
try_eval_session!(setup_indices(wam, clause_name!("builtins"), &mut indices));
|
||||||
compile_listing(wam, src, indices)
|
compile_listing(wam, src, indices, suppress_warnings)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,11 +27,11 @@ impl Machine {
|
|||||||
let module = idx.0.borrow().1.clone();
|
let module = idx.0.borrow().1.clone();
|
||||||
|
|
||||||
match module.as_str() {
|
match module.as_str() {
|
||||||
"user" => compile_user_module(self, src),
|
"user" => compile_user_module(self, src, true),
|
||||||
_ => compile_into_module(self, module, src, name),
|
_ => compile_into_module(self, module, src, name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => compile_user_module(self, src),
|
None => compile_user_module(self, src, true),
|
||||||
},
|
},
|
||||||
_ => compile_into_module(self, name.owning_module(), src, name),
|
_ => compile_into_module(self, name.owning_module(), src, name),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ impl Machine {
|
|||||||
|
|
||||||
fn compile_top_level(&mut self) {
|
fn compile_top_level(&mut self) {
|
||||||
self.toplevel_idx = self.code_repo.code.len();
|
self.toplevel_idx = self.code_repo.code.len();
|
||||||
compile_user_module(self, parsing_stream(TOPLEVEL.as_bytes()));
|
compile_user_module(self, parsing_stream(TOPLEVEL.as_bytes()), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_scryerrc(&mut self) {
|
fn compile_scryerrc(&mut self) {
|
||||||
@@ -210,7 +210,7 @@ impl Machine {
|
|||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
compile_user_module(self, file_src);
|
compile_user_module(self, file_src, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,14 +268,15 @@ impl Machine {
|
|||||||
&mut wam,
|
&mut wam,
|
||||||
parsing_stream(BUILTINS.as_bytes()),
|
parsing_stream(BUILTINS.as_bytes()),
|
||||||
default_index_store!(atom_tbl.clone()),
|
default_index_store!(atom_tbl.clone()),
|
||||||
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
wam.compile_special_forms();
|
wam.compile_special_forms();
|
||||||
|
|
||||||
compile_user_module(&mut wam, parsing_stream(ERROR.as_bytes()));
|
compile_user_module(&mut wam, parsing_stream(ERROR.as_bytes()), true);
|
||||||
compile_user_module(&mut wam, parsing_stream(LISTS.as_bytes()));
|
compile_user_module(&mut wam, parsing_stream(LISTS.as_bytes()), true);
|
||||||
compile_user_module(&mut wam, parsing_stream(NON_ISO.as_bytes()));
|
compile_user_module(&mut wam, parsing_stream(NON_ISO.as_bytes()), true);
|
||||||
compile_user_module(&mut wam, parsing_stream(SI.as_bytes()));
|
compile_user_module(&mut wam, parsing_stream(SI.as_bytes()), true);
|
||||||
|
|
||||||
wam.compile_top_level();
|
wam.compile_top_level();
|
||||||
wam.compile_scryerrc();
|
wam.compile_scryerrc();
|
||||||
@@ -430,12 +431,12 @@ impl Machine {
|
|||||||
let load_result = match to_src(name) {
|
let load_result = match to_src(name) {
|
||||||
ModuleSource::Library(name) =>
|
ModuleSource::Library(name) =>
|
||||||
if !self.indices.modules.contains_key(&name) {
|
if !self.indices.modules.contains_key(&name) {
|
||||||
load_library(self, name).map(Some)
|
load_library(self, name, false).map(Some)
|
||||||
} else {
|
} else {
|
||||||
Ok(Some(name))
|
Ok(Some(name))
|
||||||
},
|
},
|
||||||
ModuleSource::File(name) =>
|
ModuleSource::File(name) =>
|
||||||
load_module_from_file(self, name.as_str())
|
load_module_from_file(self, name.as_str(), false)
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = load_result.and_then(|name|
|
let result = load_result.and_then(|name|
|
||||||
@@ -477,12 +478,12 @@ impl Machine {
|
|||||||
let load_result = match to_src(name) {
|
let load_result = match to_src(name) {
|
||||||
ModuleSource::Library(name) =>
|
ModuleSource::Library(name) =>
|
||||||
if !self.indices.modules.contains_key(&name) {
|
if !self.indices.modules.contains_key(&name) {
|
||||||
load_library(self, name).map(Some)
|
load_library(self, name, false).map(Some)
|
||||||
} else {
|
} else {
|
||||||
Ok(Some(name))
|
Ok(Some(name))
|
||||||
},
|
},
|
||||||
ModuleSource::File(name) =>
|
ModuleSource::File(name) =>
|
||||||
load_module_from_file(self, name.as_str())
|
load_module_from_file(self, name.as_str(), false)
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = load_result.and_then(|name|
|
let result = load_result.and_then(|name|
|
||||||
@@ -515,7 +516,7 @@ impl Machine {
|
|||||||
let src = readline::input_stream();
|
let src = readline::input_stream();
|
||||||
readline::set_prompt(false);
|
readline::set_prompt(false);
|
||||||
|
|
||||||
if let EvalSession::Error(e) = compile_user_module(self, src) {
|
if let EvalSession::Error(e) = compile_user_module(self, src, false) {
|
||||||
self.throw_session_error(e, (clause_name!("repl"), 0));
|
self.throw_session_error(e, (clause_name!("repl"), 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,6 +150,16 @@ impl<'a, R: Read> TermStream<'a, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn line_num(&self) -> usize {
|
||||||
|
self.parser.line_num()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn col_num(&self) -> usize {
|
||||||
|
self.parser.col_num()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn update_expansion_lens(&mut self) {
|
pub fn update_expansion_lens(&mut self) {
|
||||||
let te_key = (clause_name!("term_expansion"), 2);
|
let te_key = (clause_name!("term_expansion"), 2);
|
||||||
|
|||||||
@@ -287,15 +287,14 @@ fn merge_clauses(tls: &mut VecDeque<TopLevel>) -> Result<TopLevel, ParserError>
|
|||||||
TopLevel::Query(_) if clauses.is_empty() && tls.is_empty() => return Ok(tl),
|
TopLevel::Query(_) if clauses.is_empty() && tls.is_empty() => return Ok(tl),
|
||||||
TopLevel::Declaration(_) if clauses.is_empty() => return Ok(tl),
|
TopLevel::Declaration(_) if clauses.is_empty() => return Ok(tl),
|
||||||
TopLevel::Query(_) => return Err(ParserError::InconsistentEntry),
|
TopLevel::Query(_) => return Err(ParserError::InconsistentEntry),
|
||||||
TopLevel::Fact(_) if is_consistent(&tl, &clauses) => {
|
TopLevel::Fact(..) if is_consistent(&tl, &clauses) =>
|
||||||
if let TopLevel::Fact(fact) = tl {
|
if let TopLevel::Fact(fact, line_num, col_num) = tl {
|
||||||
let clause = PredicateClause::Fact(fact);
|
let clause = PredicateClause::Fact(fact, line_num, col_num);
|
||||||
clauses.push(clause);
|
clauses.push(clause);
|
||||||
}
|
},
|
||||||
}
|
TopLevel::Rule(..) if is_consistent(&tl, &clauses) => {
|
||||||
TopLevel::Rule(_) if is_consistent(&tl, &clauses) => {
|
if let TopLevel::Rule(rule, line_num, col_num) = tl {
|
||||||
if let TopLevel::Rule(rule) = tl {
|
let clause = PredicateClause::Rule(rule, line_num, col_num);
|
||||||
let clause = PredicateClause::Rule(rule);
|
|
||||||
clauses.push(clause);
|
clauses.push(clause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,6 +356,44 @@ fn mark_cut_variables(terms: &mut Vec<Term>) -> bool {
|
|||||||
found_cut_var
|
found_cut_var
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// terms is a list of goals composing one clause in a (;) functor. it
|
||||||
|
// checks that the first (and only) of these clauses is a ->. if so,
|
||||||
|
// it expands its terms using a blocked_!.
|
||||||
|
fn check_for_internal_if_then(terms: &mut Vec<Term>) {
|
||||||
|
if terms.len() != 1 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(Term::Clause(_, ref name, ref subterms, _)) = terms.last() {
|
||||||
|
if name.as_str() != "->" || subterms.len() != 2 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(Term::Clause(_, _, mut subterms, _)) = terms.pop() {
|
||||||
|
let mut conq_terms = VecDeque::from(unfold_by_str(*subterms.pop().unwrap(), ","));
|
||||||
|
let mut pre_cut_terms = VecDeque::from(unfold_by_str(*subterms.pop().unwrap(), ","));
|
||||||
|
|
||||||
|
conq_terms.push_front(Term::Constant(
|
||||||
|
Cell::default(),
|
||||||
|
Constant::Atom(clause_name!("blocked_!"), None))
|
||||||
|
);
|
||||||
|
|
||||||
|
while let Some(term) = pre_cut_terms.pop_back() {
|
||||||
|
conq_terms.push_front(term);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tail_term = conq_terms.pop_back().unwrap();
|
||||||
|
terms.push(fold_by_str(
|
||||||
|
conq_terms.into_iter(),
|
||||||
|
tail_term,
|
||||||
|
clause_name!(","),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn flatten_hook(mut term: Term) -> Term {
|
fn flatten_hook(mut term: Term) -> Term {
|
||||||
if let &mut Term::Clause(_, ref mut name, ref mut terms, _) = &mut term {
|
if let &mut Term::Clause(_, ref mut name, ref mut terms, _) = &mut term {
|
||||||
match (name.as_str(), terms.len()) {
|
match (name.as_str(), terms.len()) {
|
||||||
@@ -387,7 +424,9 @@ fn flatten_hook(mut term: Term) -> Term {
|
|||||||
fn setup_declaration(
|
fn setup_declaration(
|
||||||
indices: &mut CompositeIndices,
|
indices: &mut CompositeIndices,
|
||||||
flags: MachineFlags,
|
flags: MachineFlags,
|
||||||
mut terms: Vec<Box<Term>>
|
mut terms: Vec<Box<Term>>,
|
||||||
|
line_num: usize,
|
||||||
|
col_num: usize,
|
||||||
) -> Result<Declaration, ParserError> {
|
) -> Result<Declaration, ParserError> {
|
||||||
let term = *terms.pop().unwrap();
|
let term = *terms.pop().unwrap();
|
||||||
|
|
||||||
@@ -413,7 +452,7 @@ fn setup_declaration(
|
|||||||
Ok(Declaration::Dynamic(name, arity))
|
Ok(Declaration::Dynamic(name, arity))
|
||||||
}
|
}
|
||||||
("initialization", 1) => {
|
("initialization", 1) => {
|
||||||
let mut rel_worker = RelationWorker::new(flags);
|
let mut rel_worker = RelationWorker::new(flags, line_num, col_num);
|
||||||
let query_terms = rel_worker.setup_query(indices, terms, false)?;
|
let query_terms = rel_worker.setup_query(indices, terms, false)?;
|
||||||
let queue = rel_worker.parse_queue(indices)?;
|
let queue = rel_worker.parse_queue(indices)?;
|
||||||
|
|
||||||
@@ -435,14 +474,18 @@ struct RelationWorker {
|
|||||||
flags: MachineFlags,
|
flags: MachineFlags,
|
||||||
dynamic_clauses: Vec<(Term, Term)>, // Head, Body.
|
dynamic_clauses: Vec<(Term, Term)>, // Head, Body.
|
||||||
queue: VecDeque<VecDeque<Term>>,
|
queue: VecDeque<VecDeque<Term>>,
|
||||||
|
line_num: usize,
|
||||||
|
col_num: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RelationWorker {
|
impl RelationWorker {
|
||||||
fn new(flags: MachineFlags) -> Self {
|
fn new(flags: MachineFlags, line_num: usize, col_num: usize) -> Self {
|
||||||
RelationWorker {
|
RelationWorker {
|
||||||
dynamic_clauses: vec![],
|
dynamic_clauses: vec![],
|
||||||
flags,
|
flags,
|
||||||
queue: VecDeque::new(),
|
queue: VecDeque::new(),
|
||||||
|
line_num,
|
||||||
|
col_num
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,6 +550,8 @@ impl RelationWorker {
|
|||||||
let mut subterms = unfold_by_str(term, ",");
|
let mut subterms = unfold_by_str(term, ",");
|
||||||
mark_cut_variables(&mut subterms);
|
mark_cut_variables(&mut subterms);
|
||||||
|
|
||||||
|
check_for_internal_if_then(&mut subterms);
|
||||||
|
|
||||||
let term = subterms.pop().unwrap();
|
let term = subterms.pop().unwrap();
|
||||||
fold_by_str(subterms.into_iter(), term, clause_name!(","))
|
fold_by_str(subterms.into_iter(), term, clause_name!(","))
|
||||||
})
|
})
|
||||||
@@ -704,12 +749,12 @@ impl RelationWorker {
|
|||||||
Term::Clause(r, name, terms, _) => {
|
Term::Clause(r, name, terms, _) => {
|
||||||
if name == hook.name() && terms.len() == hook.arity() {
|
if name == hook.name() && terms.len() == hook.arity() {
|
||||||
let term = self.setup_fact(Term::Clause(r, name, terms, None), false)?;
|
let term = self.setup_fact(Term::Clause(r, name, terms, None), false)?;
|
||||||
Ok((hook, PredicateClause::Fact(term), VecDeque::from(vec![])))
|
Ok((hook, PredicateClause::Fact(term, 0, 0), VecDeque::from(vec![])))
|
||||||
} else if name.as_str() == ":-" && terms.len() == 2 {
|
} else if name.as_str() == ":-" && terms.len() == 2 {
|
||||||
let rule = self.setup_rule(indices, terms, true, false)?;
|
let rule = self.setup_rule(indices, terms, true, false)?;
|
||||||
let results_queue = self.parse_queue(indices)?;
|
let results_queue = self.parse_queue(indices)?;
|
||||||
|
|
||||||
Ok((hook, PredicateClause::Rule(rule), results_queue))
|
Ok((hook, PredicateClause::Rule(rule, 0, 0), results_queue))
|
||||||
} else {
|
} else {
|
||||||
Err(ParserError::InvalidHook)
|
Err(ParserError::InvalidHook)
|
||||||
}
|
}
|
||||||
@@ -787,15 +832,16 @@ impl RelationWorker {
|
|||||||
terms,
|
terms,
|
||||||
blocks_cuts,
|
blocks_cuts,
|
||||||
true,
|
true,
|
||||||
)?))
|
)?, self.line_num, self.col_num))
|
||||||
} else if name.as_str() == ":-" && terms.len() == 1 {
|
} else if name.as_str() == ":-" && terms.len() == 1 {
|
||||||
Ok(TopLevel::Declaration(setup_declaration(indices, self.flags, terms)?))
|
Ok(TopLevel::Declaration(setup_declaration(indices, self.flags, terms,
|
||||||
|
self.line_num, self.col_num)?))
|
||||||
} else {
|
} else {
|
||||||
let term = Term::Clause(r, name, terms, fixity);
|
let term = Term::Clause(r, name, terms, fixity);
|
||||||
Ok(TopLevel::Fact(try!(self.setup_fact(term, true))))
|
Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
term => Ok(TopLevel::Fact(try!(self.setup_fact(term, true)))),
|
term => Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -875,7 +921,10 @@ fn term_to_toplevel<R>(
|
|||||||
where
|
where
|
||||||
R: Read,
|
R: Read,
|
||||||
{
|
{
|
||||||
let mut rel_worker = RelationWorker::new(flags);
|
let line_num = term_stream.line_num();
|
||||||
|
let col_num = term_stream.col_num();
|
||||||
|
|
||||||
|
let mut rel_worker = RelationWorker::new(flags, line_num, col_num);
|
||||||
let mut indices = composite_indices!(false, &mut term_stream.wam.indices, code_dir);
|
let mut indices = composite_indices!(false, &mut term_stream.wam.indices, code_dir);
|
||||||
|
|
||||||
let tl = rel_worker.try_term_to_tl(&mut indices, term, true)?;
|
let tl = rel_worker.try_term_to_tl(&mut indices, term, true)?;
|
||||||
@@ -928,9 +977,12 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let term_stream = TermStream::new(inner, atom_tbl, flags, wam);
|
let term_stream = TermStream::new(inner, atom_tbl, flags, wam);
|
||||||
|
|
||||||
|
let line_num = term_stream.line_num();
|
||||||
|
let col_num = term_stream.col_num();
|
||||||
|
|
||||||
TopLevelBatchWorker {
|
TopLevelBatchWorker {
|
||||||
term_stream,
|
term_stream,
|
||||||
rel_worker: RelationWorker::new(flags),
|
rel_worker: RelationWorker::new(flags, line_num, col_num),
|
||||||
results: vec![],
|
results: vec![],
|
||||||
dynamic_clause_map: IndexMap::new(),
|
dynamic_clause_map: IndexMap::new(),
|
||||||
in_module: false,
|
in_module: false,
|
||||||
@@ -942,7 +994,10 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
|
|||||||
indices: &mut IndexStore,
|
indices: &mut IndexStore,
|
||||||
term: Term,
|
term: Term,
|
||||||
) -> Result<(TopLevel, RelationWorker), SessionError> {
|
) -> Result<(TopLevel, RelationWorker), SessionError> {
|
||||||
let mut new_rel_worker = RelationWorker::new(self.rel_worker.flags);
|
let line_num = self.term_stream.line_num();
|
||||||
|
let col_num = self.term_stream.col_num();
|
||||||
|
|
||||||
|
let mut new_rel_worker = RelationWorker::new(self.rel_worker.flags, line_num, col_num);
|
||||||
let mut indices = composite_indices!(
|
let mut indices = composite_indices!(
|
||||||
self.in_module,
|
self.in_module,
|
||||||
indices,
|
indices,
|
||||||
@@ -1023,11 +1078,16 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
|
|||||||
self.rel_worker.absorb(new_rel_worker);
|
self.rel_worker.absorb(new_rel_worker);
|
||||||
|
|
||||||
match tl {
|
match tl {
|
||||||
TopLevel::Fact(fact) => preds.push(PredicateClause::Fact(fact)),
|
TopLevel::Fact(fact, line_num, col_num) =>
|
||||||
TopLevel::Rule(rule) => preds.push(PredicateClause::Rule(rule)),
|
preds.push(PredicateClause::Fact(fact, line_num, col_num)),
|
||||||
TopLevel::Predicate(pred) => preds.extend(pred.0),
|
TopLevel::Rule(rule, line_num, col_num) =>
|
||||||
TopLevel::Declaration(decl) => return Ok(Some(decl)),
|
preds.push(PredicateClause::Rule(rule, line_num, col_num)),
|
||||||
TopLevel::Query(_) => return Err(SessionError::NamelessEntry),
|
TopLevel::Predicate(pred) =>
|
||||||
|
preds.extend(pred.0),
|
||||||
|
TopLevel::Declaration(decl) =>
|
||||||
|
return Ok(Some(decl)),
|
||||||
|
TopLevel::Query(_) =>
|
||||||
|
return Err(SessionError::NamelessEntry),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ pub fn submit_query_with_limit(
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn submit_code(wam: &mut Machine, buf: &str) -> EvalSession {
|
pub fn submit_code(wam: &mut Machine, buf: &str) -> EvalSession {
|
||||||
compile_user_module(wam, parsing_stream(buf.as_bytes()))
|
compile_user_module(wam, parsing_stream(buf.as_bytes()), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_macros)]
|
#[allow(unused_macros)]
|
||||||
|
|||||||
Reference in New Issue
Block a user