correct module bugs
This commit is contained in:
11
README.md
11
README.md
@@ -251,4 +251,15 @@ been exported to the toplevel. To export them, write
|
||||
```
|
||||
prolog> :- use_module(library(lists)).
|
||||
prolog> :- use_module(library(control)).
|
||||
```
|
||||
|
||||
To define modules inline at the REPL, use the ":{{"\"}}:" delimiters:
|
||||
|
||||
```
|
||||
prolog> :{{
|
||||
:- module(test, [local_member/2]).
|
||||
:- use_module(library(lists)).
|
||||
|
||||
local_member(X, Xs) :- member(X, Xs).
|
||||
}}:
|
||||
```
|
||||
24
src/main.rs
24
src/main.rs
@@ -15,7 +15,7 @@ mod tests;
|
||||
pub static LISTS: &str = include_str!("./prolog/lib/lists.pl");
|
||||
pub static CONTROL: &str = include_str!("./prolog/lib/control.pl");
|
||||
|
||||
fn process_buffer(wam: &mut Machine, buffer: &str)
|
||||
fn parse_and_compile_line(wam: &mut Machine, buffer: &str)
|
||||
{
|
||||
match parse_code(wam, buffer) {
|
||||
Ok(packet) => {
|
||||
@@ -39,20 +39,22 @@ fn prolog_repl() {
|
||||
|
||||
load_init_str(&mut wam, LISTS);
|
||||
load_init_str(&mut wam, CONTROL);
|
||||
|
||||
|
||||
loop {
|
||||
print!("prolog> ");
|
||||
|
||||
let buffer = read();
|
||||
match read() {
|
||||
Input::Line(line) => parse_and_compile_line(&mut wam, line.as_str()),
|
||||
Input::Batch(batch) => {
|
||||
compile_listing(&mut wam, batch.as_str());
|
||||
},
|
||||
Input::Quit => break,
|
||||
Input::Clear => {
|
||||
wam.clear();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if buffer == "quit\n" {
|
||||
break;
|
||||
} else if buffer == "clear\n" {
|
||||
wam.clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
process_buffer(&mut wam, buffer.as_str());
|
||||
wam.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,18 +133,12 @@ impl PredicateClause {
|
||||
|
||||
pub type OpDirKey = (ClauseName, Fixity);
|
||||
// name and fixity -> operator type and precedence.
|
||||
pub type OpDir = HashMap<OpDirKey, (Specifier, usize)>;
|
||||
pub type OpDir = HashMap<OpDirKey, (Specifier, usize, ClauseName)>;
|
||||
|
||||
pub type CodeDir = HashMap<PredicateKey, (PredicateKeyType, usize, ClauseName)>;
|
||||
pub type CodeDir = HashMap<PredicateKey, (usize, ClauseName)>;
|
||||
|
||||
pub type PredicateKey = (ClauseName, usize); // name, arity.
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum PredicateKeyType {
|
||||
BuiltIn,
|
||||
User
|
||||
}
|
||||
|
||||
pub struct ModuleDecl {
|
||||
pub name: ClauseName,
|
||||
pub exports: Vec<PredicateKey>
|
||||
@@ -377,7 +371,7 @@ impl From<ParserError> for EvalSession {
|
||||
pub struct OpDecl(pub usize, pub Specifier, pub ClauseName);
|
||||
|
||||
impl OpDecl {
|
||||
pub fn submit(&self, op_dir: &mut OpDir) -> Result<(), EvalError>
|
||||
pub fn submit(&self, module: ClauseName, op_dir: &mut OpDir) -> Result<(), EvalError>
|
||||
{
|
||||
let (prec, spec, name) = (self.0, self.1, self.2.clone());
|
||||
|
||||
@@ -398,9 +392,9 @@ impl OpDecl {
|
||||
if prec > 0 {
|
||||
match spec {
|
||||
XFY | XFX | YFX => op_dir.insert((name.clone(), Fixity::In),
|
||||
(spec, prec)),
|
||||
XF | YF => op_dir.insert((name.clone(), Fixity::Post), (spec, prec)),
|
||||
FX | FY => op_dir.insert((name.clone(), Fixity::Pre), (spec,prec)),
|
||||
(spec, prec, module.clone())),
|
||||
XF | YF => op_dir.insert((name.clone(), Fixity::Post), (spec, prec, module.clone())),
|
||||
FX | FY => op_dir.insert((name.clone(), Fixity::Pre), (spec, prec, module.clone())),
|
||||
_ => None
|
||||
};
|
||||
} else {
|
||||
|
||||
@@ -628,154 +628,150 @@ pub fn build_code_and_op_dirs() -> (CodeDir, OpDir)
|
||||
{
|
||||
let mut code_dir = HashMap::new();
|
||||
let mut op_dir = HashMap::new();
|
||||
|
||||
op_dir.insert((clause_name!(":-"), Fixity::In), (XFX, 1200));
|
||||
op_dir.insert((clause_name!(":-"), Fixity::Pre), (FX, 1200));
|
||||
op_dir.insert((clause_name!("?-"), Fixity::Pre), (FX, 1200));
|
||||
|
||||
let builtin = ClauseName::BuiltIn("builtin");
|
||||
|
||||
op_dir.insert((clause_name!(":-"), Fixity::In), (XFX, 1200, builtin.clone()));
|
||||
op_dir.insert((clause_name!(":-"), Fixity::Pre), (FX, 1200, builtin.clone()));
|
||||
op_dir.insert((clause_name!("?-"), Fixity::Pre), (FX, 1200, builtin.clone()));
|
||||
|
||||
// control operators.
|
||||
op_dir.insert((clause_name!("\\+"), Fixity::Pre), (FY, 900));
|
||||
op_dir.insert((clause_name!("="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("\\+"), Fixity::Pre), (FY, 900, builtin.clone()));
|
||||
op_dir.insert((clause_name!("="), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
|
||||
// arithmetic operators.
|
||||
op_dir.insert((clause_name!("is"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("+"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((clause_name!("-"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((clause_name!("/\\"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((clause_name!("\\/"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((clause_name!("xor"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((clause_name!("//"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("/"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("div"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("*"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("-"), Fixity::Pre), (FY, 200));
|
||||
op_dir.insert((clause_name!("rdiv"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("<<"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!(">>"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("mod"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("rem"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("is"), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!("+"), Fixity::In), (YFX, 500, builtin.clone()));
|
||||
op_dir.insert((clause_name!("-"), Fixity::In), (YFX, 500, builtin.clone()));
|
||||
op_dir.insert((clause_name!("/\\"), Fixity::In), (YFX, 500, builtin.clone()));
|
||||
op_dir.insert((clause_name!("\\/"), Fixity::In), (YFX, 500, builtin.clone()));
|
||||
op_dir.insert((clause_name!("xor"), Fixity::In), (YFX, 500, builtin.clone()));
|
||||
op_dir.insert((clause_name!("//"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
op_dir.insert((clause_name!("/"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
op_dir.insert((clause_name!("div"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
op_dir.insert((clause_name!("*"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
op_dir.insert((clause_name!("-"), Fixity::Pre), (FY, 200, builtin.clone()));
|
||||
op_dir.insert((clause_name!("rdiv"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
op_dir.insert((clause_name!("<<"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
op_dir.insert((clause_name!(">>"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
op_dir.insert((clause_name!("mod"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
op_dir.insert((clause_name!("rem"), Fixity::In), (YFX, 400, builtin.clone()));
|
||||
|
||||
// arithmetic comparison operators.
|
||||
op_dir.insert((clause_name!(">"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("<"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("=\\="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("=:="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!(">="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("=<"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!(">"), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!("<"), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!("=\\="), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!("=:="), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!(">="), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!("=<"), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
|
||||
// control operators.
|
||||
op_dir.insert((clause_name!(";"), Fixity::In), (XFY, 1100));
|
||||
op_dir.insert((clause_name!("->"), Fixity::In), (XFY, 1050));
|
||||
op_dir.insert((clause_name!(";"), Fixity::In), (XFY, 1100, builtin.clone()));
|
||||
op_dir.insert((clause_name!("->"), Fixity::In), (XFY, 1050, builtin.clone()));
|
||||
|
||||
op_dir.insert((clause_name!("=.."), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("=="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("\\=="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("@=<"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("@>="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("@<"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("@>"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("=@="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("\\=@="), Fixity::In), (XFX, 700));
|
||||
|
||||
let builtin = ClauseName::BuiltIn("builtin");
|
||||
op_dir.insert((clause_name!("=.."), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!("=="), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!("\\=="), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!("@=<"), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!("@>="), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!("@<"), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!("@>"), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!("=@="), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
op_dir.insert((clause_name!("\\=@="), Fixity::In), (XFX, 700, builtin.clone()));
|
||||
|
||||
// there are 63 registers in the VM, so call/N is defined for all 0 <= N <= 62
|
||||
// (an extra register is needed for the predicate name)
|
||||
for arity in 0 .. 63 {
|
||||
code_dir.insert((clause_name!("call"), arity),
|
||||
(PredicateKeyType::BuiltIn, 0, builtin.clone()));
|
||||
code_dir.insert((clause_name!("call"), arity), (0, builtin.clone()));
|
||||
}
|
||||
|
||||
code_dir.insert((clause_name!("atomic"), 1),
|
||||
(PredicateKeyType::BuiltIn, 1, builtin.clone()));
|
||||
code_dir.insert((clause_name!("var"), 1),
|
||||
(PredicateKeyType::BuiltIn, 3, builtin.clone()));
|
||||
code_dir.insert((clause_name!("false"), 0),
|
||||
(PredicateKeyType::BuiltIn, 61, builtin.clone()));
|
||||
code_dir.insert((clause_name!("atomic"), 1), (1, builtin.clone()));
|
||||
code_dir.insert((clause_name!("var"), 1), (3, builtin.clone()));
|
||||
code_dir.insert((clause_name!("false"), 0), (61, builtin.clone()));
|
||||
code_dir.insert((clause_name!("\\+"), 1),
|
||||
(PredicateKeyType::BuiltIn, 62, builtin.clone()));
|
||||
(62, builtin.clone()));
|
||||
code_dir.insert((clause_name!("duplicate_term"), 2),
|
||||
(PredicateKeyType::BuiltIn, 71, builtin.clone()));
|
||||
(71, builtin.clone()));
|
||||
code_dir.insert((clause_name!("catch"), 3),
|
||||
(PredicateKeyType::BuiltIn, 5, builtin.clone()));
|
||||
(5, builtin.clone()));
|
||||
code_dir.insert((clause_name!("throw"), 1),
|
||||
(PredicateKeyType::BuiltIn, 59, builtin.clone()));
|
||||
(59, builtin.clone()));
|
||||
code_dir.insert((clause_name!("="), 2),
|
||||
(PredicateKeyType::BuiltIn, 73, builtin.clone()));
|
||||
(73, builtin.clone()));
|
||||
code_dir.insert((clause_name!("true"), 0),
|
||||
(PredicateKeyType::BuiltIn, 75, builtin.clone()));
|
||||
(75, builtin.clone()));
|
||||
|
||||
code_dir.insert((clause_name!(","), 2),
|
||||
(PredicateKeyType::BuiltIn, 76, builtin.clone()));
|
||||
(76, builtin.clone()));
|
||||
code_dir.insert((clause_name!(";"), 2),
|
||||
(PredicateKeyType::BuiltIn, 120, builtin.clone()));
|
||||
(120, builtin.clone()));
|
||||
code_dir.insert((clause_name!("->"), 2),
|
||||
(PredicateKeyType::BuiltIn, 138, builtin.clone()));
|
||||
(138, builtin.clone()));
|
||||
|
||||
code_dir.insert((clause_name!("functor"), 3),
|
||||
(PredicateKeyType::BuiltIn, 146, builtin.clone()));
|
||||
(146, builtin.clone()));
|
||||
code_dir.insert((clause_name!("arg"), 3),
|
||||
(PredicateKeyType::BuiltIn, 150, builtin.clone()));
|
||||
(150, builtin.clone()));
|
||||
code_dir.insert((clause_name!("integer"), 1),
|
||||
(PredicateKeyType::BuiltIn, 147, builtin.clone()));
|
||||
(147, builtin.clone()));
|
||||
code_dir.insert((clause_name!("display"), 1),
|
||||
(PredicateKeyType::BuiltIn, 192, builtin.clone()));
|
||||
(192, builtin.clone()));
|
||||
|
||||
code_dir.insert((clause_name!("is"), 2),
|
||||
(PredicateKeyType::BuiltIn, 194, builtin.clone()));
|
||||
(194, builtin.clone()));
|
||||
code_dir.insert((clause_name!(">"), 2),
|
||||
(PredicateKeyType::BuiltIn, 196, builtin.clone()));
|
||||
(196, builtin.clone()));
|
||||
code_dir.insert((clause_name!("<"), 2),
|
||||
(PredicateKeyType::BuiltIn, 198, builtin.clone()));
|
||||
(198, builtin.clone()));
|
||||
code_dir.insert((clause_name!(">="), 2),
|
||||
(PredicateKeyType::BuiltIn, 200, builtin.clone()));
|
||||
(200, builtin.clone()));
|
||||
code_dir.insert((clause_name!("=<"), 2),
|
||||
(PredicateKeyType::BuiltIn, 202, builtin.clone()));
|
||||
(202, builtin.clone()));
|
||||
code_dir.insert((clause_name!("=\\="), 2),
|
||||
(PredicateKeyType::BuiltIn, 204, builtin.clone()));
|
||||
(204, builtin.clone()));
|
||||
code_dir.insert((clause_name!("=:="), 2),
|
||||
(PredicateKeyType::BuiltIn, 206, builtin.clone()));
|
||||
(206, builtin.clone()));
|
||||
code_dir.insert((clause_name!("=.."), 2),
|
||||
(PredicateKeyType::BuiltIn, 208, builtin.clone()));
|
||||
(208, builtin.clone()));
|
||||
|
||||
code_dir.insert((clause_name!("length"), 2),
|
||||
(PredicateKeyType::BuiltIn, 261, builtin.clone()));
|
||||
(261, builtin.clone()));
|
||||
code_dir.insert((clause_name!("setup_call_cleanup"), 3),
|
||||
(PredicateKeyType::BuiltIn, 294, builtin.clone()));
|
||||
(294, builtin.clone()));
|
||||
code_dir.insert((clause_name!("call_with_inference_limit"), 3),
|
||||
(PredicateKeyType::BuiltIn, 393, builtin.clone()));
|
||||
(393, builtin.clone()));
|
||||
|
||||
code_dir.insert((clause_name!("compound"), 1),
|
||||
(PredicateKeyType::BuiltIn, 372, builtin.clone()));
|
||||
(372, builtin.clone()));
|
||||
code_dir.insert((clause_name!("rational"), 1),
|
||||
(PredicateKeyType::BuiltIn, 374, builtin.clone()));
|
||||
(374, builtin.clone()));
|
||||
code_dir.insert((clause_name!("string"), 1),
|
||||
(PredicateKeyType::BuiltIn, 376, builtin.clone()));
|
||||
(376, builtin.clone()));
|
||||
code_dir.insert((clause_name!("float"), 1),
|
||||
(PredicateKeyType::BuiltIn, 378, builtin.clone()));
|
||||
(378, builtin.clone()));
|
||||
code_dir.insert((clause_name!("nonvar"), 1),
|
||||
(PredicateKeyType::BuiltIn, 380, builtin.clone()));
|
||||
(380, builtin.clone()));
|
||||
|
||||
code_dir.insert((clause_name!("ground"), 1),
|
||||
(PredicateKeyType::BuiltIn, 384, builtin.clone()));
|
||||
(384, builtin.clone()));
|
||||
code_dir.insert((clause_name!("=="), 2),
|
||||
(PredicateKeyType::BuiltIn, 385, builtin.clone()));
|
||||
(385, builtin.clone()));
|
||||
code_dir.insert((clause_name!("\\=="), 2),
|
||||
(PredicateKeyType::BuiltIn, 386, builtin.clone()));
|
||||
(386, builtin.clone()));
|
||||
code_dir.insert((clause_name!("@>="), 2),
|
||||
(PredicateKeyType::BuiltIn, 387, builtin.clone()));
|
||||
(387, builtin.clone()));
|
||||
code_dir.insert((clause_name!("@=<"), 2),
|
||||
(PredicateKeyType::BuiltIn, 388, builtin.clone()));
|
||||
(388, builtin.clone()));
|
||||
code_dir.insert((clause_name!("@>"), 2),
|
||||
(PredicateKeyType::BuiltIn, 389, builtin.clone()));
|
||||
(389, builtin.clone()));
|
||||
code_dir.insert((clause_name!("@<"), 2),
|
||||
(PredicateKeyType::BuiltIn, 390, builtin.clone()));
|
||||
(390, builtin.clone()));
|
||||
code_dir.insert((clause_name!("=@="), 2),
|
||||
(PredicateKeyType::BuiltIn, 391, builtin.clone()));
|
||||
(391, builtin.clone()));
|
||||
code_dir.insert((clause_name!("\\=@="), 2),
|
||||
(PredicateKeyType::BuiltIn, 392, builtin.clone()));
|
||||
(392, builtin.clone()));
|
||||
code_dir.insert((clause_name!("compare"), 3),
|
||||
(PredicateKeyType::BuiltIn, 464, builtin.clone()));
|
||||
(464, builtin.clone()));
|
||||
|
||||
(code_dir, op_dir)
|
||||
}
|
||||
|
||||
@@ -446,30 +446,43 @@ pub fn parse_code(wam: &Machine, buffer: &str) -> Result<TopLevelPacket, ParserE
|
||||
worker.parse_code(&wam.op_dir)
|
||||
}
|
||||
|
||||
pub fn read() -> String {
|
||||
let _ = stdout().flush();
|
||||
pub enum Input {
|
||||
Quit,
|
||||
Clear,
|
||||
Line(String),
|
||||
Batch(String)
|
||||
}
|
||||
|
||||
let mut buffer = String::new();
|
||||
fn read_lines(buffer: &mut String, end_delim: &str) -> String {
|
||||
let mut result = String::new();
|
||||
let stdin = stdin();
|
||||
|
||||
buffer.clear();
|
||||
stdin.read_line(buffer).unwrap();
|
||||
|
||||
while &*buffer.trim() != end_delim {
|
||||
result += buffer.as_str();
|
||||
buffer.clear();
|
||||
stdin.read_line(buffer).unwrap();
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn read() -> Input {
|
||||
let _ = stdout().flush();
|
||||
let mut buffer = String::new();
|
||||
|
||||
let stdin = stdin();
|
||||
stdin.read_line(&mut buffer).unwrap();
|
||||
|
||||
if &*buffer.trim() == ":{" {
|
||||
buffer.clear();
|
||||
|
||||
stdin.read_line(&mut buffer).unwrap();
|
||||
|
||||
while &*buffer.trim() != "}:" {
|
||||
result += buffer.as_str();
|
||||
buffer.clear();
|
||||
stdin.read_line(&mut buffer).unwrap();
|
||||
}
|
||||
} else {
|
||||
result = buffer;
|
||||
match &*buffer.trim() {
|
||||
":{" => Input::Line(read_lines(&mut buffer, "}:")),
|
||||
":{{" => Input::Batch(read_lines(&mut buffer, "}}:")),
|
||||
"quit" => Input::Quit,
|
||||
"clear" => Input::Clear,
|
||||
_ => Input::Line(buffer)
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
// throw errors if declaration or query found.
|
||||
@@ -533,7 +546,7 @@ fn compile_decl(wam: &mut Machine, tl: TopLevel, queue: Vec<TopLevel>) -> EvalSe
|
||||
{
|
||||
match tl {
|
||||
TopLevel::Declaration(Declaration::Op(op_decl)) => {
|
||||
try_eval_session!(op_decl.submit(&mut wam.op_dir));
|
||||
try_eval_session!(op_decl.submit(clause_name!("user"), &mut wam.op_dir));
|
||||
EvalSession::EntrySuccess
|
||||
},
|
||||
TopLevel::Declaration(Declaration::UseModule(name)) =>
|
||||
@@ -585,8 +598,10 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
|
||||
let mut code = Vec::new();
|
||||
|
||||
let mut worker = TopLevelWorker::new(src_str.as_bytes(), wam.atom_tbl());
|
||||
let tls = try_eval_session!(worker.parse_batch(&mut op_dir));
|
||||
|
||||
|
||||
let tls = try_eval_session!(worker.parse_batch(&mut op_dir));
|
||||
|
||||
for tl in tls {
|
||||
match tl {
|
||||
TopLevelPacket::Query(..) =>
|
||||
@@ -622,15 +637,14 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
|
||||
try_eval_session!(compile_appendix(&mut decl_code, queue));
|
||||
|
||||
code.extend(decl_code.into_iter());
|
||||
code_dir.insert((decl.name().unwrap(), decl.arity()),
|
||||
(PredicateKeyType::User, p, get_module_name(&module)));
|
||||
code_dir.insert((decl.name().unwrap(), decl.arity()), (p, get_module_name(&module)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mut module) = module {
|
||||
module.code_dir = code_dir;
|
||||
module.op_dir = op_dir;
|
||||
module.code_dir.extend(code_dir.into_iter());
|
||||
module.op_dir.extend(op_dir.into_iter());
|
||||
|
||||
wam.add_module(module, code);
|
||||
} else {
|
||||
|
||||
@@ -37,7 +37,7 @@ impl<'a> CodeDirs<'a> {
|
||||
-> Option<(usize, ClauseName)>
|
||||
{
|
||||
let code_dir = self.get_current_code_dir(p);
|
||||
code_dir.get(&(name, arity)).map(|idx| (idx.1, idx.2.clone()))
|
||||
code_dir.get(&(name, arity)).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ use std::rc::Rc;
|
||||
|
||||
struct MachineCodeIndex<'a> {
|
||||
code_dir: &'a mut CodeDir,
|
||||
op_dir: &'a mut OpDir
|
||||
op_dir: &'a mut OpDir,
|
||||
}
|
||||
|
||||
pub struct Machine {
|
||||
@@ -54,7 +54,7 @@ impl<'a> SubModuleUser for MachineCodeIndex<'a> {
|
||||
|
||||
fn code_dir(&mut self) -> &mut CodeDir {
|
||||
self.code_dir
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
@@ -73,7 +73,50 @@ impl Machine {
|
||||
cached_query: None
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_module(&mut self, module_name: ClauseName) {
|
||||
let iter = if let Some(submodule) = self.modules.get(&module_name) {
|
||||
submodule.module_decl.exports.iter().cloned()
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
for (name, arity) in iter {
|
||||
let name = name.defrock_brackets();
|
||||
|
||||
match self.code_dir.get(&(name.clone(), arity)).cloned() {
|
||||
Some((_, ref mod_name)) if mod_name == &module_name => {
|
||||
self.code_dir.remove(&(name.clone(), arity));
|
||||
|
||||
// remove or respecify ops.
|
||||
if arity == 2 {
|
||||
if let Some((_, _, mod_name)) = self.op_dir.get(&(name.clone(), Fixity::In)).cloned()
|
||||
{
|
||||
if mod_name == module_name {
|
||||
self.op_dir.remove(&(name.clone(), Fixity::In));
|
||||
}
|
||||
}
|
||||
} else if arity == 1 {
|
||||
if let Some((_, _, mod_name)) = self.op_dir.get(&(name.clone(), Fixity::Pre)).cloned()
|
||||
{
|
||||
if mod_name == module_name {
|
||||
self.op_dir.remove(&(name.clone(), Fixity::Pre));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((_, _, mod_name)) = self.op_dir.get(&(name.clone(), Fixity::Post)).cloned()
|
||||
{
|
||||
if mod_name == module_name {
|
||||
self.op_dir.remove(&(name.clone(), Fixity::Post));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn failed(&self) -> bool {
|
||||
self.ms.fail
|
||||
}
|
||||
@@ -83,10 +126,13 @@ impl Machine {
|
||||
}
|
||||
|
||||
pub fn use_module_in_toplevel(&mut self, name: ClauseName) -> EvalSession {
|
||||
self.remove_module(name.clone());
|
||||
|
||||
match self.modules.get(&name) {
|
||||
Some(ref module) => {
|
||||
let mut indices = MachineCodeIndex { code_dir: &mut self.code_dir,
|
||||
op_dir: &mut self.op_dir };
|
||||
|
||||
indices.use_module(module)
|
||||
},
|
||||
None => EvalSession::from(EvalError::ModuleNotFound)
|
||||
@@ -114,7 +160,7 @@ impl Machine {
|
||||
pub fn add_user_code(&mut self, name: ClauseName, arity: usize, code: Code) -> EvalSession
|
||||
{
|
||||
match self.code_dir.get(&(name.clone(), arity)) {
|
||||
Some(&(PredicateKeyType::BuiltIn, _, _)) =>
|
||||
Some(&(_, ref mod_name)) if mod_name == &clause_name!("builtin") =>
|
||||
return EvalSession::from(EvalError::ImpermissibleEntry(format!("{}/{}", name, arity))),
|
||||
_ => {}
|
||||
};
|
||||
@@ -122,7 +168,7 @@ impl Machine {
|
||||
let offset = self.code.len();
|
||||
|
||||
self.code.extend(code.into_iter());
|
||||
self.code_dir.insert((name, arity), (PredicateKeyType::User, offset, clause_name!("user")));
|
||||
self.code_dir.insert((name, arity), (offset, clause_name!("user")));
|
||||
|
||||
EvalSession::EntrySuccess
|
||||
}
|
||||
|
||||
Submodule src/prolog/parser updated: efb52afa2c...e95c45f411
Reference in New Issue
Block a user