properly handle undefined predicates declared dynamic
This commit is contained in:
@@ -325,13 +325,13 @@ fn compile_into_module_impl<R: Read>(
|
|||||||
let module_code =
|
let module_code =
|
||||||
compiler.generate_code(results.worker_results, wam, &mut indices.code_dir, 0)?;
|
compiler.generate_code(results.worker_results, wam, &mut indices.code_dir, 0)?;
|
||||||
|
|
||||||
let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len());
|
let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len(), module_name.clone());
|
||||||
clause_code_generator.generate_clause_code(results.dynamic_clause_map, wam)?;
|
clause_code_generator.generate_clause_code(&results.dynamic_clause_map, wam)?;
|
||||||
|
|
||||||
update_module_indices(wam, module_name, indices);
|
update_module_indices(wam, module_name, indices);
|
||||||
|
|
||||||
wam.code_repo.code.extend(module_code.into_iter());
|
wam.code_repo.code.extend(module_code.into_iter());
|
||||||
clause_code_generator.add_clause_code(wam);
|
clause_code_generator.add_clause_code(wam, results.dynamic_clause_map);
|
||||||
|
|
||||||
Ok(compiler.drop_expansions(wam.machine_flags(), &mut wam.code_repo))
|
Ok(compiler.drop_expansions(wam.machine_flags(), &mut wam.code_repo))
|
||||||
}
|
}
|
||||||
@@ -347,22 +347,24 @@ pub struct GatherResult {
|
|||||||
pub struct ClauseCodeGenerator {
|
pub struct ClauseCodeGenerator {
|
||||||
len_offset: usize,
|
len_offset: usize,
|
||||||
code: Code,
|
code: Code,
|
||||||
|
module_name: ClauseName,
|
||||||
pi_to_loc: IndexMap<PredicateKey, usize>,
|
pi_to_loc: IndexMap<PredicateKey, usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClauseCodeGenerator {
|
impl ClauseCodeGenerator {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new(len_offset: usize) -> Self {
|
fn new(len_offset: usize, module_name: ClauseName) -> Self {
|
||||||
ClauseCodeGenerator {
|
ClauseCodeGenerator {
|
||||||
len_offset,
|
len_offset,
|
||||||
code: vec![],
|
code: vec![],
|
||||||
|
module_name,
|
||||||
pi_to_loc: IndexMap::new(),
|
pi_to_loc: IndexMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_clause_code(
|
fn generate_clause_code(
|
||||||
&mut self,
|
&mut self,
|
||||||
dynamic_clause_map: DynamicClauseMap,
|
dynamic_clause_map: &DynamicClauseMap,
|
||||||
wam: &Machine,
|
wam: &Machine,
|
||||||
) -> Result<(), SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
for ((name, arity), heads_and_tails) in dynamic_clause_map {
|
for ((name, arity), heads_and_tails) in dynamic_clause_map {
|
||||||
@@ -372,12 +374,12 @@ impl ClauseCodeGenerator {
|
|||||||
|
|
||||||
let predicate = Predicate(
|
let predicate = Predicate(
|
||||||
heads_and_tails
|
heads_and_tails
|
||||||
.into_iter()
|
.iter()
|
||||||
.map(|(head, tail)| {
|
.map(|(head, tail)| {
|
||||||
let clause = Term::Clause(
|
let clause = Term::Clause(
|
||||||
Cell::default(),
|
Cell::default(),
|
||||||
clause_name!("clause"),
|
clause_name!("clause"),
|
||||||
vec![Box::new(head), Box::new(tail)],
|
vec![Box::new(head.clone()), Box::new(tail.clone())],
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
PredicateClause::Fact(clause)
|
PredicateClause::Fact(clause)
|
||||||
@@ -391,16 +393,24 @@ impl ClauseCodeGenerator {
|
|||||||
|
|
||||||
compile_appendix(&mut decl_code, &VecDeque::new(), false, wam.machine_flags())?;
|
compile_appendix(&mut decl_code, &VecDeque::new(), false, wam.machine_flags())?;
|
||||||
|
|
||||||
self.pi_to_loc.insert((name, arity), p);
|
self.pi_to_loc.insert((name.clone(), *arity), p);
|
||||||
self.code.extend(decl_code.into_iter());
|
self.code.extend(decl_code.into_iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_clause_code(self, wam: &mut Machine) {
|
fn add_clause_code(self, wam: &mut Machine, dynamic_code_dir: DynamicClauseMap)
|
||||||
|
{
|
||||||
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());
|
||||||
|
wam.indices.code_dir.entry((name, arity))
|
||||||
|
.or_insert(CodeIndex::dynamic_undefined(self.module_name.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
@@ -457,11 +467,11 @@ fn add_non_module_code(
|
|||||||
) -> Result<(), SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
wam.check_toplevel_code(&indices)?;
|
wam.check_toplevel_code(&indices)?;
|
||||||
|
|
||||||
let mut clause_code_generator = ClauseCodeGenerator::new(code.len());
|
let mut clause_code_generator = ClauseCodeGenerator::new(code.len(), clause_name!("user"));
|
||||||
clause_code_generator.generate_clause_code(dynamic_clause_map, wam)?;
|
clause_code_generator.generate_clause_code(&dynamic_clause_map, wam)?;
|
||||||
|
|
||||||
add_toplevel_code(wam, code, indices);
|
add_toplevel_code(wam, code, indices);
|
||||||
clause_code_generator.add_clause_code(wam);
|
clause_code_generator.add_clause_code(wam, dynamic_clause_map);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -818,6 +828,9 @@ impl ListingCompiler {
|
|||||||
.dynamic_clause_map
|
.dynamic_clause_map
|
||||||
.entry((name.clone(), arity))
|
.entry((name.clone(), arity))
|
||||||
.or_insert(vec![]);
|
.or_insert(vec![]);
|
||||||
|
|
||||||
|
indices.code_dir.insert((name.clone(), arity),
|
||||||
|
CodeIndex::dynamic_undefined(self.get_module_name()));
|
||||||
}
|
}
|
||||||
&Declaration::Hook(hook, _, ref queue) if self.module.is_none() => worker
|
&Declaration::Hook(hook, _, ref queue) if self.module.is_none() => worker
|
||||||
.term_stream
|
.term_stream
|
||||||
@@ -929,17 +942,18 @@ fn compile_work_impl(
|
|||||||
|
|
||||||
if let Some(module) = compiler.module.take() {
|
if let Some(module) = compiler.module.take() {
|
||||||
let mut clause_code_generator =
|
let mut clause_code_generator =
|
||||||
ClauseCodeGenerator::new(module_code.len() + toplvl_code.len());
|
ClauseCodeGenerator::new(module_code.len() + toplvl_code.len(),
|
||||||
|
module.module_decl.name.clone());
|
||||||
|
|
||||||
try_eval_session!(wam.check_toplevel_code(&results.toplevel_indices));
|
try_eval_session!(wam.check_toplevel_code(&results.toplevel_indices));
|
||||||
try_eval_session!(
|
try_eval_session!(
|
||||||
clause_code_generator.generate_clause_code(results.dynamic_clause_map, wam)
|
clause_code_generator.generate_clause_code(&results.dynamic_clause_map, wam)
|
||||||
);
|
);
|
||||||
|
|
||||||
add_module_code(wam, module, module_code, indices);
|
add_module_code(wam, module, module_code, indices);
|
||||||
add_toplevel_code(wam, toplvl_code, results.toplevel_indices);
|
add_toplevel_code(wam, toplvl_code, results.toplevel_indices);
|
||||||
|
|
||||||
clause_code_generator.add_clause_code(wam);
|
clause_code_generator.add_clause_code(wam, results.dynamic_clause_map);
|
||||||
} else {
|
} else {
|
||||||
try_eval_session!(add_non_module_code(
|
try_eval_session!(add_non_module_code(
|
||||||
wam,
|
wam,
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ impl Machine {
|
|||||||
let (name, arity) = self.get_predicate_key(name, arity);
|
let (name, arity) = self.get_predicate_key(name, arity);
|
||||||
|
|
||||||
if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) {
|
if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) {
|
||||||
set_code_index!(idx, IndexPtr::Undefined, clause_name!("user"));
|
set_code_index!(idx, IndexPtr::DynamicUndefined, clause_name!("user"));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.indices.remove_code_index((name.clone(), arity));
|
self.indices.remove_code_index((name.clone(), arity));
|
||||||
@@ -106,7 +106,7 @@ impl Machine {
|
|||||||
|
|
||||||
if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) {
|
if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) {
|
||||||
if idx.module_name() == module_name {
|
if idx.module_name() == module_name {
|
||||||
set_code_index!(idx, IndexPtr::Undefined, clause_name!("user"));
|
set_code_index!(idx, IndexPtr::DynamicUndefined, clause_name!("user"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,11 +208,6 @@ impl Machine {
|
|||||||
let mut addrs = VecDeque::from(addrs);
|
let mut addrs = VecDeque::from(addrs);
|
||||||
addrs.remove(index);
|
addrs.remove(index);
|
||||||
|
|
||||||
if addrs.is_empty() {
|
|
||||||
self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2), temp_v!(5));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||||
}
|
}
|
||||||
Err(err) => return self.machine_st.throw_exception(err),
|
Err(err) => return self.machine_st.throw_exception(err),
|
||||||
@@ -242,11 +237,6 @@ impl Machine {
|
|||||||
let mut addrs = VecDeque::from(addrs);
|
let mut addrs = VecDeque::from(addrs);
|
||||||
addrs.remove(index);
|
addrs.remove(index);
|
||||||
|
|
||||||
if addrs.is_empty() {
|
|
||||||
self.abolish_dynamic_clause(temp_v!(1), temp_v!(2));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||||
}
|
}
|
||||||
Err(err) => return self.machine_st.throw_exception(err),
|
Err(err) => return self.machine_st.throw_exception(err),
|
||||||
|
|||||||
@@ -206,6 +206,7 @@ impl HeapCellValue {
|
|||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub enum IndexPtr {
|
pub enum IndexPtr {
|
||||||
|
DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
|
||||||
Undefined,
|
Undefined,
|
||||||
Index(usize),
|
Index(usize),
|
||||||
}
|
}
|
||||||
@@ -218,13 +219,20 @@ impl CodeIndex {
|
|||||||
pub fn is_undefined(&self) -> bool {
|
pub fn is_undefined(&self) -> bool {
|
||||||
let index_ptr = &self.0.borrow().0;
|
let index_ptr = &self.0.borrow().0;
|
||||||
|
|
||||||
if let &IndexPtr::Undefined = index_ptr {
|
match index_ptr {
|
||||||
true
|
&IndexPtr::Undefined | &IndexPtr::DynamicUndefined => true,
|
||||||
} else {
|
_ => false
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn dynamic_undefined(module_name: ClauseName) -> Self {
|
||||||
|
CodeIndex(Rc::new(RefCell::new((
|
||||||
|
IndexPtr::DynamicUndefined,
|
||||||
|
module_name
|
||||||
|
))))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn module_name(&self) -> ClauseName {
|
pub fn module_name(&self) -> ClauseName {
|
||||||
self.0.borrow().1.clone()
|
self.0.borrow().1.clone()
|
||||||
|
|||||||
@@ -325,14 +325,21 @@ impl MachineState {
|
|||||||
let (name, arity) = key;
|
let (name, arity) = key;
|
||||||
|
|
||||||
if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone()) {
|
if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone()) {
|
||||||
if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 {
|
match idx.0.borrow().0 {
|
||||||
if last_call {
|
IndexPtr::Index(compiled_tl_index) => {
|
||||||
self.execute_at_index(arity, compiled_tl_index);
|
if last_call {
|
||||||
} else {
|
self.execute_at_index(arity, compiled_tl_index);
|
||||||
self.call_at_index(arity, compiled_tl_index);
|
} else {
|
||||||
}
|
self.call_at_index(arity, compiled_tl_index);
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
}
|
||||||
|
IndexPtr::DynamicUndefined => {
|
||||||
|
self.fail = true;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -586,7 +593,10 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
indices: &IndexStore,
|
indices: &IndexStore,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
match idx.0.borrow().0 {
|
match idx.0.borrow().0 {
|
||||||
IndexPtr::Undefined => return try_in_situ(machine_st, name, arity, indices, false),
|
IndexPtr::DynamicUndefined =>
|
||||||
|
machine_st.fail = true,
|
||||||
|
IndexPtr::Undefined =>
|
||||||
|
return try_in_situ(machine_st, name, arity, indices, false),
|
||||||
IndexPtr::Index(compiled_tl_index) => {
|
IndexPtr::Index(compiled_tl_index) => {
|
||||||
machine_st.call_at_index(arity, compiled_tl_index)
|
machine_st.call_at_index(arity, compiled_tl_index)
|
||||||
}
|
}
|
||||||
@@ -604,7 +614,10 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
indices: &IndexStore,
|
indices: &IndexStore,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
match idx.0.borrow().0 {
|
match idx.0.borrow().0 {
|
||||||
IndexPtr::Undefined => return try_in_situ(machine_st, name, arity, indices, true),
|
IndexPtr::DynamicUndefined =>
|
||||||
|
machine_st.fail = true,
|
||||||
|
IndexPtr::Undefined =>
|
||||||
|
return try_in_situ(machine_st, name, arity, indices, true),
|
||||||
IndexPtr::Index(compiled_tl_index) => {
|
IndexPtr::Index(compiled_tl_index) => {
|
||||||
machine_st.execute_at_index(arity, compiled_tl_index)
|
machine_st.execute_at_index(arity, compiled_tl_index)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ use std::collections::VecDeque;
|
|||||||
|
|
||||||
// Module's and related types are defined in forms.
|
// Module's and related types are defined in forms.
|
||||||
impl Module {
|
impl Module {
|
||||||
pub fn new(module_decl: ModuleDecl, atom_tbl: TabledData<Atom>) -> Self {
|
pub fn new(module_decl: ModuleDecl, atom_tbl: TabledData<Atom>) -> Self
|
||||||
|
{
|
||||||
Module {
|
Module {
|
||||||
module_decl,
|
module_decl,
|
||||||
atom_tbl,
|
atom_tbl,
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ impl fmt::Display for REPLCodePtr {
|
|||||||
impl fmt::Display for IndexPtr {
|
impl fmt::Display for IndexPtr {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
&IndexPtr::DynamicUndefined => write!(f, "undefined"),
|
||||||
&IndexPtr::Undefined => write!(f, "undefined"),
|
&IndexPtr::Undefined => write!(f, "undefined"),
|
||||||
&IndexPtr::Index(i) => write!(f, "{}", i),
|
&IndexPtr::Index(i) => write!(f, "{}", i),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user