* `nonvar/1`
* `once/1`
* `rational/1`
+* `read/1`
* `repeat/0`
* `reverse/2`
* `select/3`
&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] })
Is(RegType, ArithmeticTerm),
KeySort,
NotEq,
+ Read,
Sort,
}
&BuiltInClauseType::Is(..) => clause_name!("is"),
&BuiltInClauseType::KeySort => clause_name!("keysort"),
&BuiltInClauseType::NotEq => clause_name!("\\=="),
+ &BuiltInClauseType::Read => clause_name!("read"),
&BuiltInClauseType::Sort => clause_name!("sort"),
}
}
&BuiltInClauseType::Is(..) => 2,
&BuiltInClauseType::KeySort => 2,
&BuiltInClauseType::NotEq => 2,
+ &BuiltInClauseType::Read => 1,
&BuiltInClauseType::Sort => 2,
}
}
("keysort", 2) => Some(BuiltInClauseType::KeySort),
("\\==", 2) => Some(BuiltInClauseType::NotEq),
("sort", 2) => Some(BuiltInClauseType::Sort),
+ ("read", 1) => Some(BuiltInClauseType::Read),
_ => None
}
}
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)
&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())
}
}
}
use std::vec::Vec;
pub struct QueryIterator<'a> {
- state_stack: Vec<TermIterState<'a>>
+ state_stack: Vec<TermIterState<'a>>,
}
impl<'a> QueryIterator<'a> {
pub struct FactIterator<'a> {
state_queue: VecDeque<TermIterState<'a>>,
+ iterable_root: bool
}
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)],
vec![TermIterState::Var(Level::Root, cell, var.clone())]
};
- FactIterator { state_queue: VecDeque::from(states) }
+ FactIterator { state_queue: VecDeque::from(states), iterable_root }
}
}
}
match lvl {
- Level::Root => continue,
+ Level::Root if !self.iterable_root => continue,
_ => return Some(TermRef::Clause(lvl, cell, ct, child_terms))
};
},
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)
}
}
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;
}
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>
}
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,
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 {
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 {},
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()
}
},
&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),
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)
},
pub mod heap_print;
pub mod targets;
pub mod tabled_rc;
+pub mod read;
-Subproject commit 6a7545257bbfc660b37a0bc3d7a72edb244dda86
+Subproject commit 3fb28efa315852734613fcf34ee3467c5be8545c
--- /dev/null
+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
+ }
+}
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 {