add wam_instructions/2 to render predicate instructions as lists of functors
This commit is contained in:
@@ -74,6 +74,12 @@ impl Heap {
|
||||
self.push(HeapCellValue::Addr(Addr::Con(Constant::EmptyList)));
|
||||
head_addr
|
||||
}
|
||||
|
||||
pub fn extend<Iter: Iterator<Item=HeapCellValue>>(&mut self, iter: Iter) {
|
||||
for hcv in iter {
|
||||
self.push(hcv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Heap {
|
||||
|
||||
@@ -5,7 +5,7 @@ use prolog::machine::machine_indices::*;
|
||||
use prolog::machine::machine_state::*;
|
||||
use prolog::rug::Integer;
|
||||
|
||||
pub(super) type MachineStub = Vec<HeapCellValue>;
|
||||
pub(crate) type MachineStub = Vec<HeapCellValue>;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum ErrorProvenance {
|
||||
|
||||
@@ -10,6 +10,7 @@ use prolog::heap_print::*;
|
||||
use prolog::instructions::*;
|
||||
use prolog::machine::attributed_variables::*;
|
||||
use prolog::machine::and_stack::*;
|
||||
use prolog::machine::code_repo::CodeRepo;
|
||||
use prolog::machine::copier::*;
|
||||
use prolog::machine::heap::*;
|
||||
use prolog::machine::or_stack::*;
|
||||
@@ -2975,6 +2976,7 @@ impl MachineState {
|
||||
}
|
||||
|
||||
fn handle_call_clause(&mut self, indices: &mut IndexStore,
|
||||
code_repo: &CodeRepo,
|
||||
call_policy: &mut Box<CallPolicy>,
|
||||
cut_policy: &mut Box<CutPolicy>,
|
||||
parsing_stream: &mut PrologStream,
|
||||
@@ -3010,22 +3012,25 @@ impl MachineState {
|
||||
try_or_fail!(self, call_policy.context_call(self, name.clone(), arity, idx.clone(),
|
||||
indices)),
|
||||
&ClauseType::System(ref ct) =>
|
||||
try_or_fail!(self, self.system_call(ct, indices, call_policy, cut_policy,
|
||||
try_or_fail!(self, self.system_call(ct, code_repo, indices, call_policy, cut_policy,
|
||||
parsing_stream))
|
||||
};
|
||||
}
|
||||
|
||||
pub(super) fn execute_ctrl_instr(&mut self, indices: &mut IndexStore,
|
||||
call_policy: &mut Box<CallPolicy>,
|
||||
cut_policy: &mut Box<CutPolicy>,
|
||||
parsing_stream: &mut PrologStream,
|
||||
instr: &ControlInstruction)
|
||||
pub(super)
|
||||
fn execute_ctrl_instr(&mut self,
|
||||
indices: &mut IndexStore,
|
||||
code_repo: &CodeRepo,
|
||||
call_policy: &mut Box<CallPolicy>,
|
||||
cut_policy: &mut Box<CutPolicy>,
|
||||
parsing_stream: &mut PrologStream,
|
||||
instr: &ControlInstruction)
|
||||
{
|
||||
match instr {
|
||||
&ControlInstruction::Allocate(num_cells) =>
|
||||
self.allocate(num_cells),
|
||||
&ControlInstruction::CallClause(ref ct, arity, _, lco, use_default_cp) =>
|
||||
self.handle_call_clause(indices, call_policy, cut_policy,
|
||||
self.handle_call_clause(indices, code_repo, call_policy, cut_policy,
|
||||
parsing_stream, ct, arity, lco,
|
||||
use_default_cp),
|
||||
&ControlInstruction::Deallocate => self.deallocate(),
|
||||
|
||||
@@ -688,7 +688,7 @@ impl MachineState {
|
||||
}
|
||||
|
||||
fn dispatch_instr(&mut self, instr: &Line, indices: &mut IndexStore, policies: &mut MachinePolicies,
|
||||
prolog_stream: &mut PrologStream)
|
||||
code_repo: &CodeRepo, prolog_stream: &mut PrologStream)
|
||||
{
|
||||
match instr {
|
||||
&Line::Arithmetic(ref arith_instr) =>
|
||||
@@ -698,7 +698,7 @@ impl MachineState {
|
||||
&Line::Cut(ref cut_instr) =>
|
||||
self.execute_cut_instr(cut_instr, &mut policies.cut_policy),
|
||||
&Line::Control(ref control_instr) =>
|
||||
self.execute_ctrl_instr(indices, &mut policies.call_policy,
|
||||
self.execute_ctrl_instr(indices, code_repo, &mut policies.call_policy,
|
||||
&mut policies.cut_policy, prolog_stream,
|
||||
control_instr),
|
||||
&Line::Fact(ref fact_instr) => {
|
||||
@@ -724,7 +724,7 @@ impl MachineState {
|
||||
None => return
|
||||
};
|
||||
|
||||
self.dispatch_instr(instr.as_ref(), indices, policies, prolog_stream);
|
||||
self.dispatch_instr(instr.as_ref(), indices, policies, code_repo, prolog_stream);
|
||||
}
|
||||
|
||||
fn backtrack(&mut self)
|
||||
@@ -793,7 +793,7 @@ impl MachineState {
|
||||
None => return false
|
||||
};
|
||||
|
||||
self.dispatch_instr(instr.as_ref(), indices, policies, prolog_stream);
|
||||
self.dispatch_instr(instr.as_ref(), indices, policies, code_repo, prolog_stream);
|
||||
|
||||
if self.fail {
|
||||
self.backtrack();
|
||||
|
||||
@@ -6,6 +6,8 @@ use prolog_parser::tabled_rc::*;
|
||||
use prolog::clause_types::*;
|
||||
use prolog::forms::*;
|
||||
use prolog::heap_print::*;
|
||||
use prolog::instructions::*;
|
||||
use prolog::machine::code_repo::CodeRepo;
|
||||
use prolog::machine::copier::*;
|
||||
use prolog::machine::machine_errors::*;
|
||||
use prolog::machine::machine_indices::*;
|
||||
@@ -15,7 +17,7 @@ use prolog::ordered_float::OrderedFloat;
|
||||
use prolog::read::{PrologStream, readline};
|
||||
use prolog::rug::Integer;
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
use std::io::{stdout, Write};
|
||||
use std::iter::once;
|
||||
use std::mem;
|
||||
@@ -34,6 +36,21 @@ impl BrentAlgState {
|
||||
}
|
||||
}
|
||||
|
||||
fn scan_for_trust_me(code: &Code, jmp_offsets: &mut VecDeque<usize>, after_idx: &mut usize) {
|
||||
for (idx, instr) in code[*after_idx ..].iter().enumerate() {
|
||||
match instr {
|
||||
&Line::Choice(ChoiceInstruction::TrustMe)
|
||||
| &Line::IndexedChoice(IndexedChoiceInstruction::Trust(..)) => {
|
||||
*after_idx += idx;
|
||||
return;
|
||||
},
|
||||
&Line::Control(ControlInstruction::JmpBy(_, offset, ..)) =>
|
||||
jmp_offsets.push_back(*after_idx + idx + offset),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_builtin_predicate(name: &ClauseName) -> bool {
|
||||
let in_builtins = name.owning_module().as_str() == "builtins";
|
||||
let hidden_name = name.as_str().starts_with("$");
|
||||
@@ -385,13 +402,61 @@ impl MachineState {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn system_call(&mut self,
|
||||
ct: &SystemClauseType,
|
||||
indices: &mut IndexStore,
|
||||
call_policy: &mut Box<CallPolicy>,
|
||||
cut_policy: &mut Box<CutPolicy>,
|
||||
current_input_stream: &mut PrologStream)
|
||||
-> CallResult
|
||||
fn create_instruction_functors(&mut self, code: &Code, first_idx: usize) -> Vec<Addr>
|
||||
{
|
||||
let mut queue = VecDeque::new();
|
||||
let mut functors = vec![];
|
||||
let mut h = self.heap.h;
|
||||
|
||||
queue.push_back(first_idx);
|
||||
|
||||
while let Some(first_idx) = queue.pop_front() {
|
||||
let mut last_idx = first_idx;
|
||||
|
||||
loop {
|
||||
match &code[last_idx] {
|
||||
&Line::Choice(ChoiceInstruction::TryMeElse(..))
|
||||
| &Line::IndexedChoice(IndexedChoiceInstruction::Try(..)) => {
|
||||
last_idx += 1;
|
||||
scan_for_trust_me(code, &mut queue, &mut last_idx);
|
||||
},
|
||||
&Line::Control(ControlInstruction::JmpBy(_, offset, _, false)) => {
|
||||
queue.push_back(last_idx + offset);
|
||||
last_idx += 1;
|
||||
},
|
||||
&Line::Control(ControlInstruction::JmpBy(_, offset, _, true)) => {
|
||||
queue.push_back(last_idx + offset);
|
||||
break;
|
||||
},
|
||||
&Line::Control(ControlInstruction::Proceed)
|
||||
| &Line::Control(ControlInstruction::CallClause(_, _, _, true, _)) =>
|
||||
break,
|
||||
_ =>
|
||||
last_idx += 1
|
||||
};
|
||||
}
|
||||
|
||||
for instr in &code[first_idx .. last_idx + 1] {
|
||||
let section = instr.to_functor(h);
|
||||
functors.push(Addr::HeapCell(h));
|
||||
|
||||
h += section.len();
|
||||
self.heap.extend(section.into_iter());
|
||||
}
|
||||
}
|
||||
|
||||
functors
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn system_call(&mut self,
|
||||
ct: &SystemClauseType,
|
||||
code_repo: &CodeRepo,
|
||||
indices: &mut IndexStore,
|
||||
call_policy: &mut Box<CallPolicy>,
|
||||
cut_policy: &mut Box<CutPolicy>,
|
||||
current_input_stream: &mut PrologStream)
|
||||
-> CallResult
|
||||
{
|
||||
match ct {
|
||||
&SystemClauseType::AbolishClause => {
|
||||
@@ -1640,6 +1705,55 @@ impl MachineState {
|
||||
self.unwind_stack(),
|
||||
&SystemClauseType::Variant =>
|
||||
self.fail = self.structural_eq_test(),
|
||||
&SystemClauseType::WAMInstructions => {
|
||||
let name = self[temp_v!(1)].clone();
|
||||
let arity = self[temp_v!(2)].clone();
|
||||
|
||||
let name = match self.store(self.deref(name)) {
|
||||
Addr::Con(Constant::Atom(name, _)) => name,
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
let arity = match self.store(self.deref(arity)) {
|
||||
Addr::Con(Constant::Integer(n)) => n,
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
let first_idx = match indices.code_dir.get(&(name.clone(), arity.to_usize().unwrap()))
|
||||
{
|
||||
Some(ref idx) =>
|
||||
if let Some(idx) = idx.local() {
|
||||
idx
|
||||
} else {
|
||||
let arity = arity.to_usize().unwrap();
|
||||
let stub = MachineError::functor_stub(name.clone(), arity);
|
||||
let h = self.heap.h;
|
||||
|
||||
let err = MachineError::existence_error(h, ExistenceError::Procedure(name, arity));
|
||||
let err = self.error_form(err, stub);
|
||||
|
||||
self.throw_exception(err);
|
||||
return Ok(());
|
||||
},
|
||||
None => {
|
||||
let arity = arity.to_usize().unwrap();
|
||||
let stub = MachineError::functor_stub(name.clone(), arity);
|
||||
let h = self.heap.h;
|
||||
|
||||
let err = MachineError::existence_error(h, ExistenceError::Procedure(name, arity));
|
||||
let err = self.error_form(err, stub);
|
||||
|
||||
self.throw_exception(err);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
let functors = self.create_instruction_functors(&code_repo.code, first_idx);
|
||||
let listing = Addr::HeapCell(self.heap.to_list(functors.into_iter()));
|
||||
let listing_var = self[temp_v!(3)].clone();
|
||||
|
||||
self.unify(listing, listing_var);
|
||||
},
|
||||
&SystemClauseType::WriteTerm => {
|
||||
let addr = self[temp_v!(1)].clone();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user