preliminary read support

This commit is contained in:
Mark Thom
2018-07-25 17:12:07 -06:00
parent 82ff377585
commit 38dcd6113e
11 changed files with 167 additions and 23 deletions

View File

@@ -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] })

View File

@@ -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())
}
}
}

View File

@@ -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)
}
}

View File

@@ -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()
}

View File

@@ -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),

View File

@@ -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)
},

View File

@@ -26,3 +26,4 @@ pub mod parser;
pub mod heap_print;
pub mod targets;
pub mod tabled_rc;
pub mod read;

120
src/prolog/read.rs Normal file
View 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
}
}

View File

@@ -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 {