preliminary read support
This commit is contained in:
@@ -31,7 +31,7 @@ impl<'a> ArithInstructionIterator<'a> {
|
||||
&Term::Cons(_, _, _) =>
|
||||
return Err(ArithmeticError::InvalidTerm),
|
||||
&Term::Var(ref cell, ref var) =>
|
||||
TermIterState::Var(Level::Shallow, cell, (*var).clone())
|
||||
TermIterState::Var(Level::Shallow, cell, var.clone())
|
||||
};
|
||||
|
||||
Ok(ArithInstructionIterator { state_stack: vec![state] })
|
||||
|
||||
@@ -803,6 +803,7 @@ pub enum BuiltInClauseType {
|
||||
Is(RegType, ArithmeticTerm),
|
||||
KeySort,
|
||||
NotEq,
|
||||
Read,
|
||||
Sort,
|
||||
}
|
||||
|
||||
@@ -906,6 +907,7 @@ impl BuiltInClauseType {
|
||||
&BuiltInClauseType::Is(..) => clause_name!("is"),
|
||||
&BuiltInClauseType::KeySort => clause_name!("keysort"),
|
||||
&BuiltInClauseType::NotEq => clause_name!("\\=="),
|
||||
&BuiltInClauseType::Read => clause_name!("read"),
|
||||
&BuiltInClauseType::Sort => clause_name!("sort"),
|
||||
}
|
||||
}
|
||||
@@ -925,6 +927,7 @@ impl BuiltInClauseType {
|
||||
&BuiltInClauseType::Is(..) => 2,
|
||||
&BuiltInClauseType::KeySort => 2,
|
||||
&BuiltInClauseType::NotEq => 2,
|
||||
&BuiltInClauseType::Read => 1,
|
||||
&BuiltInClauseType::Sort => 2,
|
||||
}
|
||||
}
|
||||
@@ -950,6 +953,7 @@ impl BuiltInClauseType {
|
||||
("keysort", 2) => Some(BuiltInClauseType::KeySort),
|
||||
("\\==", 2) => Some(BuiltInClauseType::NotEq),
|
||||
("sort", 2) => Some(BuiltInClauseType::Sort),
|
||||
("read", 1) => Some(BuiltInClauseType::Read),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
@@ -1015,7 +1019,7 @@ pub enum TermRef<'a> {
|
||||
Var(Level, &'a Cell<VarReg>, Rc<Var>)
|
||||
}
|
||||
|
||||
impl<'a> TermRef<'a> {
|
||||
impl<'a> TermRef<'a> {
|
||||
pub fn level(self) -> Level {
|
||||
match self {
|
||||
TermRef::AnonVar(lvl)
|
||||
@@ -1796,7 +1800,7 @@ impl<'a> TermIterState<'a> {
|
||||
&Term::Constant(ref cell, ref constant) =>
|
||||
TermIterState::Constant(lvl, cell, constant),
|
||||
&Term::Var(ref cell, ref var) =>
|
||||
TermIterState::Var(lvl, cell, (*var).clone())
|
||||
TermIterState::Var(lvl, cell, var.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::rc::Rc;
|
||||
use std::vec::Vec;
|
||||
|
||||
pub struct QueryIterator<'a> {
|
||||
state_stack: Vec<TermIterState<'a>>
|
||||
state_stack: Vec<TermIterState<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> QueryIterator<'a> {
|
||||
@@ -120,6 +120,7 @@ impl<'a> Iterator for QueryIterator<'a> {
|
||||
|
||||
pub struct FactIterator<'a> {
|
||||
state_queue: VecDeque<TermIterState<'a>>,
|
||||
iterable_root: bool
|
||||
}
|
||||
|
||||
impl<'a> FactIterator<'a> {
|
||||
@@ -132,10 +133,10 @@ impl<'a> FactIterator<'a> {
|
||||
.map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref()))
|
||||
.collect();
|
||||
|
||||
FactIterator { state_queue }
|
||||
FactIterator { state_queue, iterable_root: false }
|
||||
}
|
||||
|
||||
fn new(term: &'a Term) -> Self {
|
||||
fn new(term: &'a Term, iterable_root: bool) -> Self {
|
||||
let states = match term {
|
||||
&Term::AnonVar =>
|
||||
vec![TermIterState::AnonVar(Level::Root)],
|
||||
@@ -151,7 +152,7 @@ impl<'a> FactIterator<'a> {
|
||||
vec![TermIterState::Var(Level::Root, cell, var.clone())]
|
||||
};
|
||||
|
||||
FactIterator { state_queue: VecDeque::from(states) }
|
||||
FactIterator { state_queue: VecDeque::from(states), iterable_root }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +170,7 @@ impl<'a> Iterator for FactIterator<'a> {
|
||||
}
|
||||
|
||||
match lvl {
|
||||
Level::Root => continue,
|
||||
Level::Root if !self.iterable_root => continue,
|
||||
_ => return Some(TermRef::Clause(lvl, cell, ct, child_terms))
|
||||
};
|
||||
},
|
||||
@@ -196,8 +197,8 @@ impl Term {
|
||||
QueryIterator::from_term(self)
|
||||
}
|
||||
|
||||
pub fn breadth_first_iter(&self) -> FactIterator {
|
||||
FactIterator::new(self)
|
||||
pub fn breadth_first_iter(&self, iterable_root: bool) -> FactIterator {
|
||||
FactIterator::new(self, iterable_root)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ use prolog::heap_print::*;
|
||||
use prolog::machine::machine_errors::*;
|
||||
use prolog::num::{BigInt, BigUint, Zero, One};
|
||||
use prolog::or_stack::*;
|
||||
use prolog::read::*;
|
||||
use prolog::tabled_rc::*;
|
||||
|
||||
use downcast::Any;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::mem::swap;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::rc::Rc;
|
||||
@@ -32,13 +32,14 @@ impl Ball {
|
||||
}
|
||||
|
||||
pub(crate) struct CodeDirs<'a> {
|
||||
code_dir: &'a CodeDir,
|
||||
modules: &'a ModuleDir
|
||||
pub code_dir: &'a CodeDir,
|
||||
pub op_dir: &'a OpDir,
|
||||
pub modules: &'a ModuleDir
|
||||
}
|
||||
|
||||
impl<'a> CodeDirs<'a> {
|
||||
pub(super) fn new(code_dir: &'a CodeDir, modules: &'a HashMap<ClauseName, Module>) -> Self {
|
||||
CodeDirs { code_dir, modules }
|
||||
pub(super) fn new(code_dir: &'a CodeDir, op_dir: &'a OpDir, modules: &'a ModuleDir) -> Self {
|
||||
CodeDirs { code_dir, op_dir, modules }
|
||||
}
|
||||
|
||||
pub(super) fn get(&self, name: ClauseName, arity: usize, in_mod: ClauseName) -> Option<CodeIndex>
|
||||
@@ -202,7 +203,7 @@ pub(super) enum MachineMode {
|
||||
}
|
||||
|
||||
pub struct MachineState {
|
||||
pub(super) atom_tbl: TabledData<Atom>,
|
||||
pub(crate) atom_tbl: TabledData<Atom>,
|
||||
pub(super) s: usize,
|
||||
pub(super) p: CodePtr,
|
||||
pub(super) b: usize,
|
||||
@@ -449,7 +450,8 @@ pub(crate) trait CallPolicy: Any {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType)
|
||||
fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType,
|
||||
code_dirs: CodeDirs<'a>)
|
||||
-> CallResult
|
||||
{
|
||||
match ct {
|
||||
@@ -492,6 +494,19 @@ pub(crate) trait CallPolicy: Any {
|
||||
machine_st.fail = !machine_st.is_cyclic_term(addr);
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
&BuiltInClauseType::Read => {
|
||||
let mut reader = Reader::new(machine_st);
|
||||
|
||||
match reader.read_stdin(code_dirs.op_dir) {
|
||||
Ok(offset) => {
|
||||
let addr = reader.machine_st[temp_v!(1)].clone();
|
||||
reader.machine_st.unify(addr, Addr::HeapCell(offset));
|
||||
},
|
||||
Err(err) => println!("{:?}", err)
|
||||
};
|
||||
|
||||
return_from_clause!(reader.machine_st.last_call, reader.machine_st)
|
||||
},
|
||||
&BuiltInClauseType::Writeq => {
|
||||
let output = machine_st.print_term(machine_st[temp_v!(1)].clone(),
|
||||
WriteqFormatter {},
|
||||
@@ -645,10 +660,11 @@ impl CallPolicy for CallWithInferenceLimitCallPolicy {
|
||||
self.increment()
|
||||
}
|
||||
|
||||
fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType)
|
||||
fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType,
|
||||
code_dirs: CodeDirs<'a>)
|
||||
-> CallResult
|
||||
{
|
||||
self.prev_policy.call_builtin(machine_st, ct)?;
|
||||
self.prev_policy.call_builtin(machine_st, ct, code_dirs)?;
|
||||
self.increment()
|
||||
}
|
||||
|
||||
|
||||
@@ -1825,7 +1825,7 @@ impl MachineState {
|
||||
},
|
||||
&ControlInstruction::CallClause(ClauseType::BuiltIn(ref ct), _, _, lco) => {
|
||||
self.last_call = lco;
|
||||
try_or_fail!(self, call_policy.call_builtin(self, ct));
|
||||
try_or_fail!(self, call_policy.call_builtin(self, ct, code_dirs));
|
||||
},
|
||||
&ControlInstruction::CallClause(ClauseType::Inlined(ref ct), ..) =>
|
||||
self.execute_inlined(ct),
|
||||
|
||||
@@ -298,7 +298,8 @@ impl Machine {
|
||||
Line::Cut(ref cut_instr) =>
|
||||
self.ms.execute_cut_instr(cut_instr, &mut self.cut_policy),
|
||||
Line::Control(ref control_instr) => {
|
||||
let code_dirs = CodeDirs::new(&self.code_dir, &self.modules);
|
||||
let code_dirs = CodeDirs::new(&self.code_dir, &self.op_dir,
|
||||
&self.modules);
|
||||
self.ms.execute_ctrl_instr(code_dirs, &mut self.call_policy,
|
||||
&mut self.cut_policy, control_instr)
|
||||
},
|
||||
|
||||
@@ -26,3 +26,4 @@ pub mod parser;
|
||||
pub mod heap_print;
|
||||
pub mod targets;
|
||||
pub mod tabled_rc;
|
||||
pub mod read;
|
||||
|
||||
Submodule src/prolog/parser updated: 6a7545257b...3fb28efa31
120
src/prolog/read.rs
Normal file
120
src/prolog/read.rs
Normal file
@@ -0,0 +1,120 @@
|
||||
use prolog::ast::*;
|
||||
use prolog::machine::machine_state::*;
|
||||
use prolog::parser::parser::*;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::io::stdin;
|
||||
|
||||
pub struct Reader<'a> {
|
||||
pub machine_st: &'a mut MachineState,
|
||||
}
|
||||
|
||||
type SubtermDeque = VecDeque<(usize, usize)>;
|
||||
|
||||
impl<'a> TermRef<'a> {
|
||||
fn as_addr(&self, h: usize) -> Addr {
|
||||
match self {
|
||||
&TermRef::AnonVar(_) | &TermRef::Var(..) => Addr::HeapCell(h),
|
||||
&TermRef::Cons(..) => Addr::HeapCell(h),
|
||||
&TermRef::Constant(_, _, c) => Addr::Con(c.clone()),
|
||||
&TermRef::Clause(..) => Addr::Str(h),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Reader<'a> {
|
||||
pub fn new(machine_st: &'a mut MachineState) -> Self {
|
||||
Reader { machine_st }
|
||||
}
|
||||
|
||||
pub fn read_stdin(&mut self, op_dir: &'a OpDir) -> Result<usize, ParserError> {
|
||||
let mut buffer = String::new();
|
||||
|
||||
let stdin = stdin();
|
||||
stdin.read_line(&mut buffer).unwrap();
|
||||
|
||||
let mut parser = Parser::new(buffer.as_bytes(), self.machine_st.atom_tbl.clone());
|
||||
Ok(self.write_term_to_heap(parser.read_term(op_dir)?))
|
||||
}
|
||||
|
||||
fn push_stub_addr(&mut self) {
|
||||
let h = self.machine_st.heap.h;
|
||||
self.machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
|
||||
}
|
||||
|
||||
fn modify_head_of_queue(&mut self, queue: &mut SubtermDeque, term: TermRef, h: usize) {
|
||||
if let Some((arity, site_h)) = queue.pop_front() {
|
||||
self.machine_st.heap[site_h] = HeapCellValue::Addr(term.as_addr(h));
|
||||
|
||||
if arity > 1 {
|
||||
queue.push_front((arity - 1, site_h + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_term_to_heap(&mut self, term: Term) -> usize {
|
||||
let h = self.machine_st.heap.h;
|
||||
|
||||
let mut queue = SubtermDeque::new();
|
||||
let mut var_dict = HeapVarDict::new();
|
||||
|
||||
for term in term.breadth_first_iter(true) {
|
||||
let h = self.machine_st.heap.h;
|
||||
|
||||
match &term {
|
||||
&TermRef::Cons(lvl, ..) => {
|
||||
queue.push_back((2, h+1));
|
||||
self.machine_st.heap.push(HeapCellValue::Addr(Addr::Lis(h+1)));
|
||||
|
||||
self.push_stub_addr();
|
||||
self.push_stub_addr();
|
||||
|
||||
if let Level::Root = lvl {
|
||||
continue;
|
||||
}
|
||||
},
|
||||
&TermRef::Clause(lvl, _, ref ct, subterms) => {
|
||||
queue.push_back((subterms.len(), h+1));
|
||||
let named = HeapCellValue::NamedStr(subterms.len(), ct.name(),
|
||||
ct.fixity());
|
||||
|
||||
self.machine_st.heap.push(named);
|
||||
|
||||
for _ in 0 .. subterms.len() {
|
||||
self.push_stub_addr();
|
||||
}
|
||||
|
||||
if let Level::Root = lvl {
|
||||
continue;
|
||||
}
|
||||
},
|
||||
&TermRef::AnonVar(Level::Root)
|
||||
| &TermRef::Var(Level::Root, ..)
|
||||
| &TermRef::Constant(Level::Root, ..) =>
|
||||
self.machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h))),
|
||||
&TermRef::AnonVar(_) =>
|
||||
continue,
|
||||
&TermRef::Var(_, _, ref var) => {
|
||||
if let Some((arity, site_h)) = queue.pop_front() {
|
||||
if let Some(addr) = var_dict.get(var).cloned() {
|
||||
self.machine_st.heap[site_h] = HeapCellValue::Addr(addr);
|
||||
} else {
|
||||
var_dict.insert(var.clone(), Addr::HeapCell(site_h));
|
||||
}
|
||||
|
||||
if arity > 1 {
|
||||
queue.push_front((arity - 1, site_h + 1));
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
|
||||
self.modify_head_of_queue(&mut queue, term, h);
|
||||
}
|
||||
|
||||
h
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
|
||||
type Iterator = FactIterator<'a>;
|
||||
|
||||
fn iter(term: &'a Term) -> Self::Iterator {
|
||||
term.breadth_first_iter()
|
||||
term.breadth_first_iter(false) // do not iterate over the root clause if one exists.
|
||||
}
|
||||
|
||||
fn to_constant(lvl: Level, constant: Constant, reg: RegType) -> Self {
|
||||
|
||||
Reference in New Issue
Block a user