limit hash lookups to metacall
This commit is contained in:
@@ -136,7 +136,7 @@ pub type OpDirKey = (ClauseName, Fixity);
|
||||
// name and fixity -> operator type and precedence.
|
||||
pub type OpDir = HashMap<OpDirKey, (Specifier, usize, ClauseName)>;
|
||||
|
||||
pub type CodeDir = HashMap<PredicateKey, (usize, ClauseName)>;
|
||||
pub type CodeDir = HashMap<PredicateKey, CodeIndex>;
|
||||
|
||||
pub type TermDir = HashMap<PredicateKey, Predicate>;
|
||||
|
||||
@@ -198,11 +198,19 @@ pub trait SubModuleUser {
|
||||
}
|
||||
|
||||
if let Some(code_data) = submodule.code_dir.get(&(name.clone(), arity)) {
|
||||
if let Some(ref mut global_code_data) = self.code_dir().get_mut(&(name.clone(), arity)) {
|
||||
global_code_data.1 = code_data.1.clone();
|
||||
global_code_data.0.set(code_data.0.get());
|
||||
|
||||
return true; // done to appease the borrow checker.
|
||||
}
|
||||
|
||||
self.code_dir().insert((name, arity), code_data.clone());
|
||||
true
|
||||
} else {
|
||||
false
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn use_qualified_module(&mut self, submodule: &Module, exports: Vec<PredicateKey>) -> EvalSession
|
||||
@@ -698,8 +706,8 @@ pub enum ClauseType {
|
||||
Is,
|
||||
KeySort,
|
||||
NotEq,
|
||||
Op(ClauseName, Fixity),
|
||||
Named(ClauseName),
|
||||
Op(ClauseName, Fixity, CodeIndex),
|
||||
Named(ClauseName, CodeIndex),
|
||||
SetupCallCleanup,
|
||||
Sort,
|
||||
Throw,
|
||||
@@ -776,7 +784,7 @@ impl ClauseType {
|
||||
&ClauseType::Compare | &ClauseType::CompareTerm(_)
|
||||
| &ClauseType::Inlined(InlinedClauseType::CompareNumber(_))
|
||||
| &ClauseType::NotEq | &ClauseType::Is | &ClauseType::Eq => Some(Fixity::In),
|
||||
&ClauseType::Op(_, fixity) => Some(fixity),
|
||||
&ClauseType::Op(_, fixity, _) => Some(fixity),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
@@ -800,8 +808,8 @@ impl ClauseType {
|
||||
&ClauseType::Is => clause_name!("is"),
|
||||
&ClauseType::KeySort => clause_name!("keysort"),
|
||||
&ClauseType::NotEq => clause_name!("\\=="),
|
||||
&ClauseType::Op(ref name, _) => name.clone(),
|
||||
&ClauseType::Named(ref name) => name.clone(),
|
||||
&ClauseType::Op(ref name, ..) => name.clone(),
|
||||
&ClauseType::Named(ref name, ..) => name.clone(),
|
||||
&ClauseType::SetupCallCleanup => clause_name!("setup_call_cleanup"),
|
||||
&ClauseType::Sort => clause_name!("sort"),
|
||||
&ClauseType::Throw => clause_name!("throw")
|
||||
@@ -835,9 +843,9 @@ impl ClauseType {
|
||||
("sort", 2) => ClauseType::Sort,
|
||||
("throw", 1) => ClauseType::Throw,
|
||||
_ => if let Some(fixity) = fixity {
|
||||
ClauseType::Op(name, fixity)
|
||||
ClauseType::Op(name, fixity, CodeIndex::default())
|
||||
} else {
|
||||
ClauseType::Named(name)
|
||||
ClauseType::Named(name, CodeIndex::default())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1385,6 +1393,21 @@ impl HeapCellValue {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CodeIndex(pub Rc<Cell<usize>>, pub ClauseName);
|
||||
|
||||
impl CodeIndex {
|
||||
pub fn is_undefined(&self) -> bool {
|
||||
self.0.get() == 0 && self.1 == clause_name!("")
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(usize, ClauseName)> for CodeIndex {
|
||||
fn from(value: (usize, ClauseName)) -> Self {
|
||||
CodeIndex(Rc::new(Cell::new(value.0)), value.1)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum CodePtr {
|
||||
DirEntry(usize, ClauseName), // offset, resident module name.
|
||||
@@ -1414,6 +1437,12 @@ impl PartialOrd<CodePtr> for CodePtr {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CodeIndex {
|
||||
fn default() -> Self {
|
||||
CodeIndex(Rc::new(Cell::new(0)), clause_name!(""))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CodePtr {
|
||||
fn default() -> Self {
|
||||
CodePtr::TopLevel(0, 0)
|
||||
@@ -1541,9 +1570,9 @@ impl<'a> TermIterState<'a> {
|
||||
TermIterState::AnonVar(lvl),
|
||||
&Term::Clause(ref cell, ref name, ref subterms, fixity) => {
|
||||
let ct = if let Some(fixity) = fixity {
|
||||
ClauseType::Op(name.clone(), fixity)
|
||||
ClauseType::Op(name.clone(), fixity, CodeIndex::default())
|
||||
} else {
|
||||
ClauseType::Named(name.clone())
|
||||
ClauseType::Named(name.clone(), CodeIndex::default())
|
||||
};
|
||||
|
||||
TermIterState::Clause(lvl, 0, cell, ct, subterms)
|
||||
|
||||
@@ -688,62 +688,64 @@ pub fn build_code_and_op_dirs() -> (CodeDir, OpDir)
|
||||
// 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), (0, builtin.clone()));
|
||||
code_dir.insert((clause_name!("call"), arity), CodeIndex::from((0, 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), (62, builtin.clone()));
|
||||
code_dir.insert((clause_name!("duplicate_term"), 2), (71, builtin.clone()));
|
||||
code_dir.insert((clause_name!("catch"), 3), (5, builtin.clone()));
|
||||
code_dir.insert((clause_name!("throw"), 1), (59, builtin.clone()));
|
||||
code_dir.insert((clause_name!("="), 2), (73, builtin.clone()));
|
||||
code_dir.insert((clause_name!("true"), 0), (75, builtin.clone()));
|
||||
code_dir.insert((clause_name!("atomic"), 1), CodeIndex::from((1, builtin.clone())));
|
||||
code_dir.insert((clause_name!("var"), 1), CodeIndex::from((3, builtin.clone())));
|
||||
code_dir.insert((clause_name!("false"), 0), CodeIndex::from((61, builtin.clone())));
|
||||
code_dir.insert((clause_name!("\\+"), 1), CodeIndex::from((62, builtin.clone())));
|
||||
code_dir.insert((clause_name!("duplicate_term"), 2), CodeIndex::from((71, builtin.clone())));
|
||||
code_dir.insert((clause_name!("catch"), 3), CodeIndex::from((5, builtin.clone())));
|
||||
code_dir.insert((clause_name!("throw"), 1), CodeIndex::from((59, builtin.clone())));
|
||||
code_dir.insert((clause_name!("="), 2), CodeIndex::from((73, builtin.clone())));
|
||||
code_dir.insert((clause_name!("true"), 0), CodeIndex::from((75, builtin.clone())));
|
||||
|
||||
code_dir.insert((clause_name!(","), 2), (76, builtin.clone()));
|
||||
code_dir.insert((clause_name!(";"), 2), (120, builtin.clone()));
|
||||
code_dir.insert((clause_name!("->"), 2), (138, builtin.clone()));
|
||||
code_dir.insert((clause_name!(","), 2), CodeIndex::from((76, builtin.clone())));
|
||||
code_dir.insert((clause_name!(";"), 2), CodeIndex::from((120, builtin.clone())));
|
||||
code_dir.insert((clause_name!("->"), 2), CodeIndex::from((138, builtin.clone())));
|
||||
|
||||
code_dir.insert((clause_name!("functor"), 3), (146, builtin.clone()));
|
||||
code_dir.insert((clause_name!("arg"), 3), (150, builtin.clone()));
|
||||
code_dir.insert((clause_name!("integer"), 1), (147, builtin.clone()));
|
||||
code_dir.insert((clause_name!("display"), 1), (192, builtin.clone()));
|
||||
code_dir.insert((clause_name!("functor"), 3), CodeIndex::from((146, builtin.clone())));
|
||||
code_dir.insert((clause_name!("arg"), 3), CodeIndex::from((150, builtin.clone())));
|
||||
code_dir.insert((clause_name!("integer"), 1), CodeIndex::from((147, builtin.clone())));
|
||||
code_dir.insert((clause_name!("display"), 1), CodeIndex::from((192, builtin.clone())));
|
||||
|
||||
code_dir.insert((clause_name!("is"), 2), (194, builtin.clone()));
|
||||
code_dir.insert((clause_name!(">"), 2), (196, builtin.clone()));
|
||||
code_dir.insert((clause_name!("<"), 2), (198, builtin.clone()));
|
||||
code_dir.insert((clause_name!(">="), 2), (200, builtin.clone()));
|
||||
code_dir.insert((clause_name!("=<"), 2), (202, builtin.clone()));
|
||||
code_dir.insert((clause_name!("=\\="), 2), (204, builtin.clone()));
|
||||
code_dir.insert((clause_name!("=:="), 2), (206, builtin.clone()));
|
||||
code_dir.insert((clause_name!("=.."), 2), (208, builtin.clone()));
|
||||
code_dir.insert((clause_name!("is"), 2), CodeIndex::from((194, builtin.clone())));
|
||||
code_dir.insert((clause_name!(">"), 2), CodeIndex::from((196, builtin.clone())));
|
||||
code_dir.insert((clause_name!("<"), 2), CodeIndex::from((198, builtin.clone())));
|
||||
code_dir.insert((clause_name!(">="), 2), CodeIndex::from((200, builtin.clone())));
|
||||
code_dir.insert((clause_name!("=<"), 2), CodeIndex::from((202, builtin.clone())));
|
||||
code_dir.insert((clause_name!("=\\="), 2), CodeIndex::from((204, builtin.clone())));
|
||||
code_dir.insert((clause_name!("=:="), 2), CodeIndex::from((206, builtin.clone())));
|
||||
code_dir.insert((clause_name!("=.."), 2), CodeIndex::from((208, builtin.clone())));
|
||||
|
||||
code_dir.insert((clause_name!("length"), 2), (261, builtin.clone()));
|
||||
code_dir.insert((clause_name!("setup_call_cleanup"), 3), (294, builtin.clone()));
|
||||
code_dir.insert((clause_name!("call_with_inference_limit"), 3), (393, builtin.clone()));
|
||||
code_dir.insert((clause_name!("length"), 2), CodeIndex::from((261, builtin.clone())));
|
||||
code_dir.insert((clause_name!("setup_call_cleanup"), 3),
|
||||
CodeIndex::from((294, builtin.clone())));
|
||||
code_dir.insert((clause_name!("call_with_inference_limit"), 3),
|
||||
CodeIndex::from((393, builtin.clone())));
|
||||
|
||||
code_dir.insert((clause_name!("compound"), 1), (372, builtin.clone()));
|
||||
code_dir.insert((clause_name!("rational"), 1), (374, builtin.clone()));
|
||||
code_dir.insert((clause_name!("string"), 1), (376, builtin.clone()));
|
||||
code_dir.insert((clause_name!("float"), 1), (378, builtin.clone()));
|
||||
code_dir.insert((clause_name!("nonvar"), 1), (380, builtin.clone()));
|
||||
code_dir.insert((clause_name!("compound"), 1), CodeIndex::from((372, builtin.clone())));
|
||||
code_dir.insert((clause_name!("rational"), 1), CodeIndex::from((374, builtin.clone())));
|
||||
code_dir.insert((clause_name!("string"), 1), CodeIndex::from((376, builtin.clone())));
|
||||
code_dir.insert((clause_name!("float"), 1), CodeIndex::from((378, builtin.clone())));
|
||||
code_dir.insert((clause_name!("nonvar"), 1), CodeIndex::from((380, builtin.clone())));
|
||||
|
||||
code_dir.insert((clause_name!("ground"), 1), (384, builtin.clone()));
|
||||
code_dir.insert((clause_name!("=="), 2), (385, builtin.clone()));
|
||||
code_dir.insert((clause_name!("\\=="), 2), (386, builtin.clone()));
|
||||
code_dir.insert((clause_name!("@>="), 2), (387, builtin.clone()));
|
||||
code_dir.insert((clause_name!("@=<"), 2), (388, builtin.clone()));
|
||||
code_dir.insert((clause_name!("@>"), 2), (389, builtin.clone()));
|
||||
code_dir.insert((clause_name!("@<"), 2), (390, builtin.clone()));
|
||||
code_dir.insert((clause_name!("=@="), 2), (391, builtin.clone()));
|
||||
code_dir.insert((clause_name!("\\=@="), 2), (392, builtin.clone()));
|
||||
code_dir.insert((clause_name!("compare"), 3), (464, builtin.clone()));
|
||||
code_dir.insert((clause_name!("atom"), 1), (465, builtin.clone()));
|
||||
code_dir.insert((clause_name!("sort"), 2), (467, builtin.clone()));
|
||||
code_dir.insert((clause_name!("keysort"), 2), (468, builtin.clone()));
|
||||
code_dir.insert((clause_name!("acyclic_term"), 1), (469, builtin.clone()));
|
||||
code_dir.insert((clause_name!("cyclic_term"), 1), (470, builtin.clone()));
|
||||
code_dir.insert((clause_name!("ground"), 1), CodeIndex::from((384, builtin.clone())));
|
||||
code_dir.insert((clause_name!("=="), 2), CodeIndex::from((385, builtin.clone())));
|
||||
code_dir.insert((clause_name!("\\=="), 2), CodeIndex::from((386, builtin.clone())));
|
||||
code_dir.insert((clause_name!("@>="), 2), CodeIndex::from((387, builtin.clone())));
|
||||
code_dir.insert((clause_name!("@=<"), 2), CodeIndex::from((388, builtin.clone())));
|
||||
code_dir.insert((clause_name!("@>"), 2), CodeIndex::from((389, builtin.clone())));
|
||||
code_dir.insert((clause_name!("@<"), 2), CodeIndex::from((390, builtin.clone())));
|
||||
code_dir.insert((clause_name!("=@="), 2), CodeIndex::from((391, builtin.clone())));
|
||||
code_dir.insert((clause_name!("\\=@="), 2), CodeIndex::from((392, builtin.clone())));
|
||||
code_dir.insert((clause_name!("compare"), 3), CodeIndex::from((464, builtin.clone())));
|
||||
code_dir.insert((clause_name!("atom"), 1), CodeIndex::from((465, builtin.clone())));
|
||||
code_dir.insert((clause_name!("sort"), 2), CodeIndex::from((467, builtin.clone())));
|
||||
code_dir.insert((clause_name!("keysort"), 2), CodeIndex::from((468, builtin.clone())));
|
||||
code_dir.insert((clause_name!("acyclic_term"), 1), CodeIndex::from((469, builtin.clone())));
|
||||
code_dir.insert((clause_name!("cyclic_term"), 1), CodeIndex::from((470, builtin.clone())));
|
||||
|
||||
(code_dir, op_dir)
|
||||
}
|
||||
|
||||
116
src/prolog/io.rs
116
src/prolog/io.rs
@@ -103,6 +103,16 @@ impl fmt::Display for CompareTermQT {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ClauseType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&ClauseType::Named(ref name, ref idx) | &ClauseType::Op(ref name, _, ref idx) =>
|
||||
write!(f, "{}:{}/{}", idx.1, name, idx.0.get()),
|
||||
ref ct =>
|
||||
write!(f, "{}", ct.name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ControlInstruction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
@@ -110,9 +120,9 @@ impl fmt::Display for ControlInstruction {
|
||||
&ControlInstruction::Allocate(num_cells) =>
|
||||
write!(f, "allocate {}", num_cells),
|
||||
&ControlInstruction::CallClause(ref ct, arity, pvs, true) =>
|
||||
write!(f, "execute {}/{}, {}", ct.name(), arity, pvs),
|
||||
write!(f, "execute {}/{}, {}", ct, arity, pvs),
|
||||
&ControlInstruction::CallClause(ref ct, arity, pvs, false) =>
|
||||
write!(f, "call {}/{}, {}", ct.name(), arity, pvs),
|
||||
write!(f, "call {}/{}, {}", ct, arity, pvs),
|
||||
&ControlInstruction::CheckCpExecute =>
|
||||
write!(f, "check_cp_execute"),
|
||||
&ControlInstruction::Deallocate =>
|
||||
@@ -162,7 +172,7 @@ impl fmt::Display for BuiltInInstruction {
|
||||
&BuiltInInstruction::CompareNumber(cmp, ref at_1, ref at_2) =>
|
||||
write!(f, "number_test {}, {}, {} ", cmp, at_1, at_2),
|
||||
&BuiltInInstruction::DefaultRetryMeElse(o) =>
|
||||
write!(f, "default_retry_me_else {}", o),
|
||||
write!(f, "default_retry_me_else {}", o),
|
||||
&BuiltInInstruction::DefaultSetCutPoint(r) =>
|
||||
write!(f, "default_set_cp {}", r),
|
||||
&BuiltInInstruction::DefaultTrustMe =>
|
||||
@@ -421,6 +431,58 @@ pub fn read() -> Input {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait TLInfo {
|
||||
fn update_entry_index(&self, &ClauseName, usize, CodeIndex, &mut CodeIndex, usize);
|
||||
|
||||
// give the correct CodePtr offsets to CallClause's whose types are
|
||||
// Named and Op. Enable late binding by setting to the default.
|
||||
fn label_clauses(&self, code_size: usize, code_dir: &mut CodeDir, code: &mut Code)
|
||||
{
|
||||
for line in code.iter_mut() {
|
||||
if let &mut Line::Control(ControlInstruction::CallClause(ref mut ct, a1, ..)) = line {
|
||||
match ct {
|
||||
&mut ClauseType::Named(ref n1, ref mut cp)
|
||||
| &mut ClauseType::Op(ref n1, _, ref mut cp) => {
|
||||
let entry = code_dir.entry((n1.clone(), a1)).or_insert(CodeIndex::default());
|
||||
self.update_entry_index(n1, a1, entry.clone(), cp, code_size);
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DeclInfo { name: ClauseName, arity: usize, module_name: ClauseName }
|
||||
|
||||
impl TLInfo for DeclInfo {
|
||||
fn update_entry_index(&self, n1: &ClauseName, a1: usize, mut entry: CodeIndex,
|
||||
cp: &mut CodeIndex, code_size: usize)
|
||||
{
|
||||
let (name, arity) = (self.name.clone(), self.arity);
|
||||
|
||||
if entry.0.get() == 0 {
|
||||
if &name == n1 && arity == a1 {
|
||||
// *entry = default(); // implement logical view update semantics.
|
||||
entry.0.set(code_size);
|
||||
}
|
||||
}
|
||||
|
||||
entry.1 = self.module_name.clone();
|
||||
*cp = entry;
|
||||
}
|
||||
}
|
||||
|
||||
struct QueryInfo {}
|
||||
|
||||
impl TLInfo for QueryInfo {
|
||||
fn update_entry_index(&self, _: &ClauseName, _: usize, entry: CodeIndex,
|
||||
cp: &mut CodeIndex, _: usize)
|
||||
{
|
||||
*cp = entry;
|
||||
}
|
||||
}
|
||||
|
||||
// throw errors if declaration or query found.
|
||||
fn compile_relation(tl: &TopLevel) -> Result<Code, ParserError>
|
||||
{
|
||||
@@ -438,9 +500,9 @@ fn compile_relation(tl: &TopLevel) -> Result<Code, ParserError>
|
||||
}
|
||||
}
|
||||
|
||||
// set first jmp_by_call or jmp_by_index instruction to code.len() - idx,
|
||||
// where idx is the place it occurs. It only does this to the *first* uninitialized
|
||||
// jmp index it encounters, then returns.
|
||||
// set first jmp_by_call or jmp_by_index instruction to code.len() -
|
||||
// idx, where idx is the place it occurs. It only does this to the
|
||||
// *first* uninitialized jmp index it encounters, then returns.
|
||||
fn set_first_index(code: &mut Code)
|
||||
{
|
||||
let code_len = code.len();
|
||||
@@ -466,7 +528,8 @@ fn compile_appendix(code: &mut Code, queue: Vec<TopLevel>) -> Result<(), ParserE
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_query(terms: Vec<QueryTerm>, queue: Vec<TopLevel>)
|
||||
fn compile_query(terms: Vec<QueryTerm>, queue: Vec<TopLevel>, code_size: usize,
|
||||
code_dir: &mut CodeDir)
|
||||
-> Result<(Code, AllocVarDict), ParserError>
|
||||
{
|
||||
let mut cg = CodeGenerator::<DebrayAllocator>::new();
|
||||
@@ -474,6 +537,9 @@ fn compile_query(terms: Vec<QueryTerm>, queue: Vec<TopLevel>)
|
||||
|
||||
compile_appendix(&mut code, queue)?;
|
||||
|
||||
let query_info = QueryInfo {};
|
||||
query_info.label_clauses(code_size, code_dir, &mut code);
|
||||
|
||||
Ok((code, cg.take_vars()))
|
||||
}
|
||||
|
||||
@@ -491,15 +557,22 @@ fn compile_decl(wam: &mut Machine, tl: TopLevel, queue: Vec<TopLevel>) -> EvalSe
|
||||
TopLevel::Declaration(_) =>
|
||||
EvalSession::from(ParserError::InvalidModuleDecl),
|
||||
_ => {
|
||||
let name = try_eval_session!(if let Some(name) = tl.name() {
|
||||
Ok(name)
|
||||
} else {
|
||||
Err(EvalError::NamelessEntry)
|
||||
});
|
||||
|
||||
let mut code = try_eval_session!(compile_relation(&tl));
|
||||
try_eval_session!(compile_appendix(&mut code, queue));
|
||||
|
||||
let decl_info = DeclInfo { name: name.clone(), arity: tl.arity(),
|
||||
module_name: clause_name!("user") };
|
||||
|
||||
decl_info.label_clauses(wam.code_size(), &mut wam.code_dir, &mut code);
|
||||
|
||||
if !code.is_empty() {
|
||||
if let Some(name) = tl.name() {
|
||||
wam.add_user_code(name, tl.arity(), code, tl.as_predicate().unwrap())
|
||||
} else {
|
||||
EvalSession::from(EvalError::NamelessEntry)
|
||||
}
|
||||
wam.add_user_code(name, tl.arity(), code, tl.as_predicate().unwrap())
|
||||
} else {
|
||||
EvalSession::from(EvalError::ImpermissibleEntry(String::from("no code generated.")))
|
||||
}
|
||||
@@ -511,7 +584,7 @@ pub fn compile_packet(wam: &mut Machine, tl: TopLevelPacket) -> EvalSession
|
||||
{
|
||||
match tl {
|
||||
TopLevelPacket::Query(terms, queue) =>
|
||||
match compile_query(terms, queue) {
|
||||
match compile_query(terms, queue, wam.code_size(), &mut wam.code_dir) {
|
||||
Ok((mut code, vars)) => wam.submit_query(code, vars),
|
||||
Err(e) => EvalSession::from(e)
|
||||
},
|
||||
@@ -525,7 +598,7 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
|
||||
fn get_module_name(module: &Option<Module>) -> ClauseName {
|
||||
match module {
|
||||
&Some(ref module) => module.module_decl.name.clone(),
|
||||
_ => ClauseName::BuiltIn("builtin")
|
||||
_ => ClauseName::BuiltIn("user")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,8 +656,21 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
|
||||
|
||||
try_eval_session!(compile_appendix(&mut decl_code, queue));
|
||||
|
||||
let name = try_eval_session!(if let Some(name) = decl.name() {
|
||||
Ok(name)
|
||||
} else {
|
||||
Err(EvalError::NamelessEntry)
|
||||
});
|
||||
|
||||
let module_name = get_module_name(&module);
|
||||
|
||||
let decl_info = DeclInfo { name, arity: decl.arity(), module_name };
|
||||
decl_info.label_clauses(p, &mut code_dir, &mut decl_code);
|
||||
|
||||
code.extend(decl_code.into_iter());
|
||||
code_dir.insert((decl.name().unwrap(), decl.arity()), (p, get_module_name(&module)));
|
||||
|
||||
let index = CodeIndex::from((p, get_module_name(&module)));
|
||||
code_dir.insert((decl_info.name.clone(), decl_info.arity), index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,16 +28,12 @@ impl<'a> CodeDirs<'a> {
|
||||
let module_name = p.module_name();
|
||||
|
||||
match module_name {
|
||||
ClauseName::BuiltIn("user") | ClauseName::BuiltIn("builtin") =>
|
||||
self.code_dir,
|
||||
_ =>
|
||||
&self.modules.get(&module_name).unwrap().code_dir
|
||||
ClauseName::BuiltIn("user") | ClauseName::BuiltIn("builtin") => self.code_dir,
|
||||
_ => &self.modules.get(&module_name).unwrap().code_dir
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get(&self, name: ClauseName, arity: usize, p: &CodePtr)
|
||||
-> Option<(usize, ClauseName)>
|
||||
{
|
||||
pub(super) fn get(&self, name: ClauseName, arity: usize, p: &CodePtr) -> Option<CodeIndex> {
|
||||
let code_dir = self.get_current_code_dir(p);
|
||||
code_dir.get(&(name, arity)).cloned()
|
||||
}
|
||||
@@ -215,54 +211,46 @@ pub struct MachineState {
|
||||
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
|
||||
|
||||
pub(crate) trait CallPolicy: Any {
|
||||
fn context_call<'a>(&mut self, machine_st: &mut MachineState, code_dirs: CodeDirs<'a>,
|
||||
name: ClauseName, arity: usize, lco: bool)
|
||||
-> CallResult
|
||||
{
|
||||
if lco {
|
||||
self.try_execute(machine_st, code_dirs, name, arity)
|
||||
} else {
|
||||
self.try_call(machine_st, code_dirs, name, arity)
|
||||
}
|
||||
}
|
||||
|
||||
fn try_call<'a>(&mut self, machine_st: &mut MachineState, code_dirs: CodeDirs<'a>,
|
||||
name: ClauseName, arity: usize)
|
||||
fn context_call(&mut self, machine_st: &mut MachineState, arity: usize, idx: CodeIndex, lco: bool)
|
||||
-> CallResult
|
||||
{
|
||||
let compiled_tl_index = code_dirs.get(name, arity, &machine_st.p);
|
||||
if lco {
|
||||
self.try_execute(machine_st, arity, idx)
|
||||
} else {
|
||||
self.try_call(machine_st, arity, idx)
|
||||
}
|
||||
}
|
||||
|
||||
match compiled_tl_index {
|
||||
Some(compiled_tl_index) => {
|
||||
let module_name = compiled_tl_index.1.clone();
|
||||
fn try_call(&mut self, machine_st: &mut MachineState, arity: usize, idx: CodeIndex) -> CallResult
|
||||
{
|
||||
if idx.is_undefined() {
|
||||
machine_st.fail = true;
|
||||
} else {
|
||||
let compiled_tl_index = idx.0.get();
|
||||
let module_name = idx.1;
|
||||
|
||||
machine_st.cp = machine_st.p.clone() + 1;
|
||||
machine_st.num_of_args = arity;
|
||||
machine_st.b0 = machine_st.b;
|
||||
machine_st.p = CodePtr::DirEntry(compiled_tl_index.0, module_name);
|
||||
},
|
||||
None => machine_st.fail = true
|
||||
};
|
||||
machine_st.cp = machine_st.p.clone() + 1;
|
||||
machine_st.num_of_args = arity;
|
||||
machine_st.b0 = machine_st.b;
|
||||
machine_st.p = CodePtr::DirEntry(compiled_tl_index, module_name);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_execute<'a>(&mut self, machine_st: &mut MachineState, code_dirs: CodeDirs<'a>,
|
||||
name: ClauseName, arity: usize)
|
||||
fn try_execute<'a>(&mut self, machine_st: &mut MachineState, arity: usize, idx: CodeIndex)
|
||||
-> CallResult
|
||||
{
|
||||
let compiled_tl_index = code_dirs.get(name, arity, &machine_st.p);
|
||||
{
|
||||
if idx.is_undefined() {
|
||||
machine_st.fail = true;
|
||||
} else {
|
||||
let compiled_tl_index = idx.0.get();
|
||||
let module_name = idx.1;
|
||||
|
||||
match compiled_tl_index {
|
||||
Some(compiled_tl_index) => {
|
||||
let module_name = compiled_tl_index.1.clone();
|
||||
|
||||
machine_st.num_of_args = arity;
|
||||
machine_st.b0 = machine_st.b;
|
||||
machine_st.p = CodePtr::DirEntry(compiled_tl_index.0, module_name);
|
||||
},
|
||||
None => machine_st.fail = true
|
||||
};
|
||||
machine_st.num_of_args = arity;
|
||||
machine_st.b0 = machine_st.b;
|
||||
machine_st.p = CodePtr::DirEntry(compiled_tl_index, module_name);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -396,7 +384,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
{
|
||||
match ct {
|
||||
&ClauseType::AcyclicTerm => {
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
machine_st.fail = machine_st.is_cyclic_term(addr);
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
@@ -422,21 +410,26 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::CallN =>
|
||||
&ClauseType::CallN => {
|
||||
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
|
||||
self.context_call(machine_st, code_dirs, name, arity, lco)
|
||||
} else {
|
||||
Ok(())
|
||||
},
|
||||
if let Some(idx) = code_dirs.get(name, arity, &machine_st.p.clone()) {
|
||||
return self.context_call(machine_st, arity, idx, lco);
|
||||
} else {
|
||||
machine_st.fail = true;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::Compare => {
|
||||
let a1 = machine_st[temp_v!(1)].clone();
|
||||
let a2 = machine_st[temp_v!(2)].clone();
|
||||
let a3 = machine_st[temp_v!(3)].clone();
|
||||
|
||||
let c = Addr::Con(match machine_st.compare_term_test(&a2, &a3) {
|
||||
Ordering::Greater => atom!(">", machine_st.atom_tbl),
|
||||
Ordering::Equal => atom!("=", machine_st.atom_tbl),
|
||||
Ordering::Less => atom!("<", machine_st.atom_tbl)
|
||||
Ordering::Greater => atom!(">"),
|
||||
Ordering::Equal => atom!("="),
|
||||
Ordering::Less => atom!("<")
|
||||
});
|
||||
|
||||
machine_st.unify(a1, c);
|
||||
@@ -454,7 +447,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::CyclicTerm => {
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
machine_st.fail = !machine_st.is_cyclic_term(addr);
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
@@ -522,12 +515,12 @@ pub(crate) trait CallPolicy: Any {
|
||||
if !lco {
|
||||
machine_st.cp = machine_st.p.clone() + 1;
|
||||
}
|
||||
|
||||
|
||||
machine_st.goto_throw();
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::Named(ref name) | &ClauseType::Op(ref name, _) =>
|
||||
self.context_call(machine_st, code_dirs, name.clone(), arity, lco),
|
||||
&ClauseType::Named(_, ref idx) | &ClauseType::Op(_, _, ref idx) =>
|
||||
self.context_call(machine_st, arity, idx.clone(), lco),
|
||||
&ClauseType::CallWithInferenceLimit => {
|
||||
machine_st.goto_ptr(CodePtr::DirEntry(393, clause_name!("builtin")), 3, lco);
|
||||
Ok(())
|
||||
|
||||
@@ -909,11 +909,14 @@ impl MachineState {
|
||||
self.registers[arity - 1] = pred;
|
||||
|
||||
if let Some((name, arity)) = self.setup_call_n(arity - 1) {
|
||||
try_or_fail!(self, call_policy.try_execute(self, code_dirs, name, arity));
|
||||
if let Some(idx) = code_dirs.get(name, arity, &self.p.clone()) {
|
||||
try_or_fail!(self, call_policy.try_execute(self, arity, idx));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
|
||||
pub(super) fn goto_throw(&mut self) {
|
||||
|
||||
@@ -25,8 +25,8 @@ pub struct Machine {
|
||||
call_policy: Box<CallPolicy>,
|
||||
cut_policy: Box<CutPolicy>,
|
||||
code: Code,
|
||||
code_dir: CodeDir,
|
||||
pub op_dir: OpDir,
|
||||
pub(super) code_dir: CodeDir,
|
||||
pub(super) op_dir: OpDir,
|
||||
term_dir: TermDir,
|
||||
modules: HashMap<ClauseName, Module>,
|
||||
cached_query: Option<Code>
|
||||
@@ -87,7 +87,7 @@ impl Machine {
|
||||
let name = name.defrock_brackets();
|
||||
|
||||
match self.code_dir.get(&(name.clone(), arity)).cloned() {
|
||||
Some((_, ref mod_name)) if mod_name == &module_name => {
|
||||
Some(CodeIndex (_, ref mod_name)) if mod_name == &module_name => {
|
||||
self.code_dir.remove(&(name.clone(), arity));
|
||||
|
||||
// remove or respecify ops.
|
||||
@@ -179,7 +179,7 @@ impl Machine {
|
||||
-> EvalSession
|
||||
{
|
||||
match self.code_dir.get(&(name.clone(), arity)) {
|
||||
Some(&(_, ref mod_name)) if mod_name == &clause_name!("builtin") =>
|
||||
Some(&CodeIndex (_, ref mod_name)) if mod_name == &clause_name!("builtin") =>
|
||||
return EvalSession::from(EvalError::ImpermissibleEntry(format!("{}/{}", name, arity))),
|
||||
_ => {}
|
||||
};
|
||||
@@ -188,7 +188,12 @@ impl Machine {
|
||||
|
||||
self.code.extend(code.into_iter());
|
||||
self.term_dir.insert((name.clone(), arity), pred);
|
||||
self.code_dir.insert((name, arity), (offset, clause_name!("user")));
|
||||
|
||||
let entry = self.code_dir.entry((name, arity))
|
||||
.or_insert(CodeIndex::from((offset, clause_name!("user"))));
|
||||
|
||||
entry.0.set(offset);
|
||||
entry.1 = clause_name!("user");
|
||||
|
||||
EvalSession::EntrySuccess
|
||||
}
|
||||
|
||||
@@ -124,10 +124,14 @@ macro_rules! put_var {
|
||||
|
||||
macro_rules! put_structure {
|
||||
($atom:expr, $arity:expr, $r:expr, Some($fix:expr)) => (
|
||||
QueryInstruction::PutStructure(ClauseType::Op(clause_name!($atom), $fix), $arity, $r)
|
||||
QueryInstruction::PutStructure(ClauseType::Op(clause_name!($atom), $fix, CodeIndex::default()),
|
||||
$arity,
|
||||
$r)
|
||||
);
|
||||
($atom:expr, $arity:expr, $r:expr, None) => (
|
||||
QueryInstruction::PutStructure(ClauseType::Named(clause_name!($atom)), $arity, $r)
|
||||
QueryInstruction::PutStructure(ClauseType::Named(clause_name!($atom), CodeIndex::default()),
|
||||
$arity,
|
||||
$r)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -393,10 +397,14 @@ macro_rules! get_constant {
|
||||
|
||||
macro_rules! get_structure {
|
||||
($atom:expr, $arity:expr, $r:expr, Some($fix:expr)) => (
|
||||
FactInstruction::GetStructure(ClauseType::Op(clause_name!($atom), $fix), $arity, $r)
|
||||
FactInstruction::GetStructure(ClauseType::Op(clause_name!($atom), $fix, CodeIndex::default()),
|
||||
$arity,
|
||||
$r)
|
||||
);
|
||||
($atom:expr, $arity:expr, $r:expr, None) => (
|
||||
FactInstruction::GetStructure(ClauseType::Named(clause_name!($atom)), $arity, $r)
|
||||
FactInstruction::GetStructure(ClauseType::Named(clause_name!($atom), CodeIndex::default()),
|
||||
$arity,
|
||||
$r)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Submodule src/prolog/parser updated: a61db9f45e...2dfd48a1ef
Reference in New Issue
Block a user