compile special instructions for partial strings when recognized
This commit is contained in:
@@ -163,40 +163,49 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
||||
target.push(Target::to_void(1));
|
||||
}
|
||||
|
||||
fn subterm_to_instr<Target>(
|
||||
fn deep_var_instr<Target: CompilationTarget<'a>>(
|
||||
&mut self,
|
||||
cell: &'a Cell<VarReg>,
|
||||
var: &'a Rc<Var>,
|
||||
term_loc: GenContext,
|
||||
is_exposed: bool,
|
||||
target: &mut Vec<Target>,
|
||||
) {
|
||||
if is_exposed || self.get_var_count(var.as_ref()) > 1 {
|
||||
self.marker.mark_var(var.clone(), Level::Deep, cell, term_loc, target);
|
||||
} else {
|
||||
Self::add_or_increment_void_instr(target);
|
||||
}
|
||||
}
|
||||
|
||||
fn subterm_to_instr<Target: CompilationTarget<'a>>(
|
||||
&mut self,
|
||||
subterm: &'a Term,
|
||||
term_loc: GenContext,
|
||||
is_exposed: bool,
|
||||
target: &mut Vec<Target>,
|
||||
) where
|
||||
Target: CompilationTarget<'a>,
|
||||
{
|
||||
) {
|
||||
match subterm {
|
||||
&Term::AnonVar if is_exposed => {
|
||||
self.marker.mark_anon_var(Level::Deep, term_loc, target)
|
||||
self.marker.mark_anon_var(Level::Deep, term_loc, target);
|
||||
}
|
||||
&Term::AnonVar => {
|
||||
Self::add_or_increment_void_instr(target);
|
||||
}
|
||||
&Term::AnonVar => Self::add_or_increment_void_instr(target),
|
||||
&Term::Cons(ref cell, _, _) | &Term::Clause(ref cell, _, _, _) => {
|
||||
self.marker
|
||||
.mark_non_var(Level::Deep, term_loc, cell, target);
|
||||
self.marker.mark_non_var(Level::Deep, term_loc, cell, target);
|
||||
target.push(Target::clause_arg_to_instr(cell.get()));
|
||||
}
|
||||
&Term::Constant(_, ref constant) => {
|
||||
target.push(Target::constant_subterm(constant.clone()))
|
||||
target.push(Target::constant_subterm(constant.clone()));
|
||||
}
|
||||
&Term::Var(ref cell, ref var) => {
|
||||
if is_exposed || self.get_var_count(var) > 1 {
|
||||
self.marker
|
||||
.mark_var(var.clone(), Level::Deep, cell, term_loc, target);
|
||||
} else {
|
||||
Self::add_or_increment_void_instr(target);
|
||||
}
|
||||
self.deep_var_instr(cell, var, term_loc, is_exposed, target);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn compile_target<Target, Iter>(
|
||||
fn compile_target<Target, Iter>(
|
||||
&mut self,
|
||||
iter: Iter,
|
||||
term_loc: GenContext,
|
||||
@@ -210,6 +219,13 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
||||
|
||||
for term in iter {
|
||||
match term {
|
||||
TermRef::AnonVar(lvl @ Level::Shallow) => {
|
||||
if let GenContext::Head = term_loc {
|
||||
self.marker.advance_arg();
|
||||
} else {
|
||||
self.marker.mark_anon_var(lvl, term_loc, &mut target);
|
||||
}
|
||||
}
|
||||
TermRef::Clause(lvl, cell, ct, terms) => {
|
||||
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
|
||||
target.push(Target::to_structure(ct, terms.len(), cell.get()));
|
||||
@@ -225,15 +241,22 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
||||
self.subterm_to_instr(head, term_loc, is_exposed, &mut target);
|
||||
self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
|
||||
}
|
||||
TermRef::Constant(lvl @ Level::Shallow, cell, Constant::String(ref string)) => {
|
||||
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
|
||||
target.push(Target::to_pstr(lvl, string.to_string(), cell.get(), false));
|
||||
}
|
||||
TermRef::Constant(lvl @ Level::Shallow, cell, constant) => {
|
||||
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
|
||||
target.push(Target::to_constant(lvl, constant.clone(), cell.get()));
|
||||
}
|
||||
TermRef::AnonVar(lvl @ Level::Shallow) => {
|
||||
if let GenContext::Head = term_loc {
|
||||
self.marker.advance_arg();
|
||||
TermRef::PartialString(lvl, cell, string, tail) => {
|
||||
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
|
||||
|
||||
if let Some(tail) = tail {
|
||||
target.push(Target::to_pstr(lvl, string, cell.get(), true));
|
||||
self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
|
||||
} else {
|
||||
self.marker.mark_anon_var(lvl, term_loc, &mut target);
|
||||
target.push(Target::to_pstr(lvl, string, cell.get(), false));
|
||||
}
|
||||
}
|
||||
TermRef::Var(lvl @ Level::Shallow, cell, ref var) if var.as_str() == "!" => {
|
||||
@@ -252,14 +275,13 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
||||
}
|
||||
}
|
||||
|
||||
self.marker
|
||||
.mark_var(var.clone(), lvl, cell, term_loc, &mut target);
|
||||
self.marker.mark_var(var.clone(), lvl, cell, term_loc, &mut target);
|
||||
}
|
||||
TermRef::Var(lvl @ Level::Shallow, cell, var) => {
|
||||
self.marker
|
||||
.mark_var(var.clone(), lvl, cell, term_loc, &mut target)
|
||||
self.marker.mark_var(var.clone(), lvl, cell, term_loc, &mut target);
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -578,7 +578,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, left_directed_op));
|
||||
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
|
||||
} else {
|
||||
// if is_infix!(spec.assoc())
|
||||
match ct.name().as_str() {
|
||||
"|" => {
|
||||
self.format_bar_separator_op(iter, max_depth, ct.name(), spec);
|
||||
@@ -1031,8 +1030,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
mut max_depth: usize,
|
||||
h: usize,
|
||||
n: usize,
|
||||
)
|
||||
{
|
||||
) {
|
||||
iter.stack().pop();
|
||||
iter.stack().pop();
|
||||
|
||||
@@ -1044,24 +1042,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
let mut heap_pstr_iter =
|
||||
self.machine_st.heap_pstr_iter(Addr::PStrLocation(h, n));
|
||||
|
||||
let mut buf = String::new();
|
||||
let buf = heap_pstr_iter.to_string();
|
||||
let end_addr = heap_pstr_iter.focus();
|
||||
|
||||
while let Some(Some(c)) = heap_pstr_iter.next() {
|
||||
buf.push(c);
|
||||
}
|
||||
|
||||
let end_addr =
|
||||
if let &HeapCellValue::PartialString(_, has_tail) = &self.machine_st.heap[h] {
|
||||
if has_tail {
|
||||
self.machine_st.store(self.machine_st.deref(heap_pstr_iter.focus()))
|
||||
} else {
|
||||
Addr::EmptyList
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
if let Addr::EmptyList = end_addr {
|
||||
if Addr::EmptyList == end_addr {
|
||||
if !self.machine_st.flags.double_quotes.is_codes() {
|
||||
self.push_char('"');
|
||||
|
||||
|
||||
@@ -225,7 +225,7 @@ fn arith_instr_unary_functor(
|
||||
t: usize,
|
||||
) -> MachineStub {
|
||||
let at_stub = at.into_functor();
|
||||
|
||||
|
||||
functor!(
|
||||
name,
|
||||
[aux(h, 0), integer(t)],
|
||||
@@ -244,7 +244,7 @@ fn arith_instr_bin_functor(
|
||||
let at_2_stub = at_2.into_functor();
|
||||
|
||||
functor!(
|
||||
name,
|
||||
name,
|
||||
[aux(h, 0), aux(h, 1), integer(t)],
|
||||
[at_1_stub, at_2_stub]
|
||||
)
|
||||
@@ -313,7 +313,7 @@ impl ArithmeticInstruction {
|
||||
&ArithmeticInstruction::Gcd(ref at_1, ref at_2, t) => {
|
||||
arith_instr_bin_functor(h, "gcd", at_1, at_2, t)
|
||||
}
|
||||
&ArithmeticInstruction::Sign(ref at, t) => {
|
||||
&ArithmeticInstruction::Sign(ref at, t) => {
|
||||
arith_instr_unary_functor(h, "sign", at, t)
|
||||
}
|
||||
&ArithmeticInstruction::Cos(ref at, t) => {
|
||||
@@ -463,6 +463,7 @@ impl IndexingInstruction {
|
||||
pub enum FactInstruction {
|
||||
GetConstant(Level, Constant, RegType),
|
||||
GetList(Level, RegType),
|
||||
GetPartialString(Level, String, RegType, bool),
|
||||
GetStructure(ClauseType, usize, RegType),
|
||||
GetValue(RegType, usize),
|
||||
GetVariable(RegType, usize),
|
||||
@@ -479,7 +480,7 @@ impl FactInstruction {
|
||||
&FactInstruction::GetConstant(lvl, ref c, r) => {
|
||||
let lvl_stub = lvl.into_functor();
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
|
||||
functor!(
|
||||
"get_constant",
|
||||
[aux(h, 0), constant(h, c), aux(h, 1)],
|
||||
@@ -496,6 +497,16 @@ impl FactInstruction {
|
||||
[lvl_stub, rt_stub]
|
||||
)
|
||||
}
|
||||
&FactInstruction::GetPartialString(lvl, ref s, r, has_tail) => {
|
||||
let lvl_stub = lvl.into_functor();
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
functor!(
|
||||
"get_partial_string",
|
||||
[aux(h, 0), string(h, s), aux(h, 1), boolean(has_tail)],
|
||||
[lvl_stub, rt_stub]
|
||||
)
|
||||
}
|
||||
&FactInstruction::GetStructure(ref ct, arity, r) => {
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
@@ -528,7 +539,7 @@ impl FactInstruction {
|
||||
}
|
||||
&FactInstruction::UnifyLocalValue(r) => {
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
|
||||
functor!(
|
||||
"unify_local_value",
|
||||
[aux(h, 0)],
|
||||
@@ -546,7 +557,7 @@ impl FactInstruction {
|
||||
}
|
||||
&FactInstruction::UnifyValue(r) => {
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
|
||||
functor!(
|
||||
"unify_value",
|
||||
[aux(h, 0)],
|
||||
@@ -565,6 +576,7 @@ pub enum QueryInstruction {
|
||||
GetVariable(RegType, usize),
|
||||
PutConstant(Level, Constant, RegType),
|
||||
PutList(Level, RegType),
|
||||
PutPartialString(Level, String, RegType, bool),
|
||||
PutStructure(ClauseType, usize, RegType),
|
||||
PutUnsafeValue(usize, usize),
|
||||
PutValue(RegType, usize),
|
||||
@@ -596,13 +608,23 @@ impl QueryInstruction {
|
||||
&QueryInstruction::PutList(lvl, r) => {
|
||||
let lvl_stub = lvl.into_functor();
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
|
||||
functor!(
|
||||
"put_list",
|
||||
[aux(h, 0), aux(h, 1)],
|
||||
[lvl_stub, rt_stub]
|
||||
)
|
||||
}
|
||||
&QueryInstruction::PutPartialString(lvl, ref s, r, has_tail) => {
|
||||
let lvl_stub = lvl.into_functor();
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
functor!(
|
||||
"put_partial_string",
|
||||
[aux(h, 0), string(h, s), aux(h, 1), boolean(has_tail)],
|
||||
[lvl_stub, rt_stub]
|
||||
)
|
||||
}
|
||||
&QueryInstruction::PutStructure(ref ct, arity, r) => {
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
@@ -616,7 +638,7 @@ impl QueryInstruction {
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
functor!(
|
||||
"put_value",
|
||||
"put_value",
|
||||
[aux(h, 0), integer(arg)],
|
||||
[rt_stub]
|
||||
)
|
||||
@@ -644,7 +666,7 @@ impl QueryInstruction {
|
||||
}
|
||||
&QueryInstruction::SetLocalValue(r) => {
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
|
||||
functor!(
|
||||
"set_local_value",
|
||||
[aux(h, 0)],
|
||||
|
||||
@@ -16,6 +16,7 @@ pub enum TermRef<'a> {
|
||||
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
||||
Constant(Level, &'a Cell<RegType>, &'a Constant),
|
||||
Clause(Level, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
|
||||
PartialString(Level, &'a Cell<RegType>, String, Option<&'a Term>),
|
||||
Var(Level, &'a Cell<VarReg>, Rc<Var>),
|
||||
}
|
||||
|
||||
@@ -27,6 +28,7 @@ impl<'a> TermRef<'a> {
|
||||
| TermRef::Constant(lvl, ..)
|
||||
| TermRef::Var(lvl, ..)
|
||||
| TermRef::Clause(lvl, ..) => lvl,
|
||||
| TermRef::PartialString(lvl, ..) => lvl,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,13 +45,63 @@ pub enum TermIterState<'a> {
|
||||
),
|
||||
InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
||||
FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
||||
PartialString(Level, &'a Cell<RegType>, String, Option<&'a Term>),
|
||||
Var(Level, &'a Cell<VarReg>, Rc<Var>),
|
||||
}
|
||||
|
||||
fn is_partial_string<'a>(
|
||||
head: &'a Term,
|
||||
mut tail: &'a Term,
|
||||
) -> Option<(String, Option<&'a Term>)>
|
||||
{
|
||||
let mut string =
|
||||
match head {
|
||||
&Term::Constant(_, Constant::Atom(ref atom, _)) if atom.is_char() => {
|
||||
atom.as_str().chars().next().unwrap().to_string()
|
||||
}
|
||||
&Term::Constant(_, Constant::Char(c)) => {
|
||||
c.to_string()
|
||||
}
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
while let Term::Cons(_, ref head, ref succ) = tail {
|
||||
match head.as_ref() {
|
||||
&Term::Constant(_, Constant::Atom(ref atom, _)) if atom.is_char() => {
|
||||
string.push(atom.as_str().chars().next().unwrap());
|
||||
}
|
||||
&Term::Constant(_, Constant::Char(c)) => {
|
||||
string.push(c);
|
||||
}
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
tail = succ.as_ref();
|
||||
}
|
||||
|
||||
match tail {
|
||||
Term::AnonVar | Term::Var(..) => {
|
||||
return Some((string, Some(tail)));
|
||||
}
|
||||
Term::Constant(_, Constant::EmptyList) => {
|
||||
return Some((string, None));
|
||||
}
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TermIterState<'a> {
|
||||
pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
|
||||
match term {
|
||||
&Term::AnonVar => TermIterState::AnonVar(lvl),
|
||||
&Term::AnonVar => {
|
||||
TermIterState::AnonVar(lvl)
|
||||
}
|
||||
&Term::Clause(ref cell, ref name, ref subterms, ref spec) => {
|
||||
let ct = if let Some(spec) = spec {
|
||||
ClauseType::Op(name.clone(), spec.clone(), CodeIndex::default())
|
||||
@@ -62,8 +114,12 @@ impl<'a> TermIterState<'a> {
|
||||
&Term::Cons(ref cell, ref head, ref tail) => {
|
||||
TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref())
|
||||
}
|
||||
&Term::Constant(ref cell, ref constant) => TermIterState::Constant(lvl, cell, constant),
|
||||
&Term::Var(ref cell, ref var) => TermIterState::Var(lvl, cell, var.clone()),
|
||||
&Term::Constant(ref cell, ref constant) => {
|
||||
TermIterState::Constant(lvl, cell, constant)
|
||||
}
|
||||
&Term::Var(ref cell, ref var) => {
|
||||
TermIterState::Var(lvl, cell, var.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,7 +184,7 @@ impl<'a> QueryIterator<'a> {
|
||||
QueryIterator {
|
||||
state_stack: vec![state],
|
||||
}
|
||||
}
|
||||
}
|
||||
&QueryTerm::Clause(ref cell, ref ct, ref terms, _) => {
|
||||
let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms);
|
||||
QueryIterator {
|
||||
@@ -169,7 +225,9 @@ impl<'a> Iterator for QueryIterator<'a> {
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let Some(iter_state) = self.state_stack.pop() {
|
||||
match iter_state {
|
||||
TermIterState::AnonVar(lvl) => return Some(TermRef::AnonVar(lvl)),
|
||||
TermIterState::AnonVar(lvl) => {
|
||||
return Some(TermRef::AnonVar(lvl));
|
||||
}
|
||||
TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => {
|
||||
if child_num == child_terms.len() {
|
||||
match ct {
|
||||
@@ -182,7 +240,9 @@ impl<'a> Iterator for QueryIterator<'a> {
|
||||
lvl => Some(TermRef::Clause(lvl, cell, ct, child_terms)),
|
||||
}
|
||||
}
|
||||
_ => return None,
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
self.state_stack.push(TermIterState::Clause(
|
||||
@@ -192,23 +252,41 @@ impl<'a> Iterator for QueryIterator<'a> {
|
||||
ct,
|
||||
child_terms,
|
||||
));
|
||||
|
||||
self.push_subterm(lvl.child_level(), child_terms[child_num].as_ref());
|
||||
}
|
||||
}
|
||||
TermIterState::InitialCons(lvl, cell, head, tail) => {
|
||||
self.state_stack
|
||||
.push(TermIterState::FinalCons(lvl, cell, head, tail));
|
||||
if let Some((string, tail)) = is_partial_string(head, tail) {
|
||||
self.state_stack.push(TermIterState::PartialString(
|
||||
lvl,
|
||||
cell,
|
||||
string,
|
||||
tail,
|
||||
));
|
||||
|
||||
self.push_subterm(lvl.child_level(), tail);
|
||||
self.push_subterm(lvl.child_level(), head);
|
||||
if let Some(tail) = tail {
|
||||
self.push_subterm(lvl.child_level(), tail);
|
||||
}
|
||||
} else {
|
||||
self.state_stack.push(TermIterState::FinalCons(lvl, cell, head, tail));
|
||||
|
||||
self.push_subterm(lvl.child_level(), tail);
|
||||
self.push_subterm(lvl.child_level(), head);
|
||||
}
|
||||
}
|
||||
TermIterState::PartialString(lvl, cell, string, tail) => {
|
||||
return Some(TermRef::PartialString(lvl, cell, string, tail));
|
||||
}
|
||||
TermIterState::FinalCons(lvl, cell, head, tail) => {
|
||||
return Some(TermRef::Cons(lvl, cell, head, tail))
|
||||
return Some(TermRef::Cons(lvl, cell, head, tail));
|
||||
}
|
||||
TermIterState::Constant(lvl, cell, constant) => {
|
||||
return Some(TermRef::Constant(lvl, cell, constant))
|
||||
return Some(TermRef::Constant(lvl, cell, constant));
|
||||
}
|
||||
TermIterState::Var(lvl, cell, var) => {
|
||||
return Some(TermRef::Var(lvl, cell, var));
|
||||
}
|
||||
TermIterState::Var(lvl, cell, var) => return Some(TermRef::Var(lvl, cell, var)),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -223,8 +301,7 @@ pub struct FactIterator<'a> {
|
||||
|
||||
impl<'a> FactIterator<'a> {
|
||||
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
|
||||
self.state_queue
|
||||
.push_back(TermIterState::subterm_to_state(lvl, term));
|
||||
self.state_queue.push_back(TermIterState::subterm_to_state(lvl, term));
|
||||
}
|
||||
|
||||
pub fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self {
|
||||
@@ -241,7 +318,9 @@ impl<'a> FactIterator<'a> {
|
||||
|
||||
fn new(term: &'a Term, iterable_root: bool) -> Self {
|
||||
let states = match term {
|
||||
&Term::AnonVar => vec![TermIterState::AnonVar(Level::Root)],
|
||||
&Term::AnonVar => {
|
||||
vec![TermIterState::AnonVar(Level::Root)]
|
||||
}
|
||||
&Term::Clause(ref cell, ref name, ref terms, ref fixity) => {
|
||||
let ct = ClauseType::from(name.clone(), terms.len(), fixity.clone());
|
||||
vec![TermIterState::Clause(Level::Root, 0, cell, ct, terms)]
|
||||
@@ -273,7 +352,9 @@ impl<'a> Iterator for FactIterator<'a> {
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let Some(state) = self.state_queue.pop_front() {
|
||||
match state {
|
||||
TermIterState::AnonVar(lvl) => return Some(TermRef::AnonVar(lvl)),
|
||||
TermIterState::AnonVar(lvl) => {
|
||||
return Some(TermRef::AnonVar(lvl));
|
||||
}
|
||||
TermIterState::Clause(lvl, _, cell, ct, child_terms) => {
|
||||
for child_term in child_terms {
|
||||
self.push_subterm(lvl.child_level(), child_term);
|
||||
@@ -285,16 +366,27 @@ impl<'a> Iterator for FactIterator<'a> {
|
||||
};
|
||||
}
|
||||
TermIterState::InitialCons(lvl, cell, head, tail) => {
|
||||
self.push_subterm(Level::Deep, head);
|
||||
self.push_subterm(Level::Deep, tail);
|
||||
if let Some((string, tail)) = is_partial_string(head, tail) {
|
||||
if let Some(tail) = tail {
|
||||
self.push_subterm(Level::Deep, tail);
|
||||
}
|
||||
|
||||
return Some(TermRef::Cons(lvl, cell, head, tail));
|
||||
return Some(TermRef::PartialString(lvl, cell, string, tail));
|
||||
} else {
|
||||
self.push_subterm(Level::Deep, head);
|
||||
self.push_subterm(Level::Deep, tail);
|
||||
|
||||
return Some(TermRef::Cons(lvl, cell, head, tail));
|
||||
}
|
||||
}
|
||||
TermIterState::Constant(lvl, cell, constant) => {
|
||||
return Some(TermRef::Constant(lvl, cell, constant))
|
||||
}
|
||||
TermIterState::Var(lvl, cell, var) => return Some(TermRef::Var(lvl, cell, var)),
|
||||
_ => {}
|
||||
TermIterState::Var(lvl, cell, var) => {
|
||||
return Some(TermRef::Var(lvl, cell, var));
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ impl CodeRepo {
|
||||
_ => {
|
||||
in_situ_code_dir.insert((name, arity), p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut cg = CodeGenerator::<DebrayAllocator>::new(non_counted_bt);
|
||||
let mut decl_code = cg.compile_predicate(&decl.0)?;
|
||||
|
||||
@@ -179,12 +179,23 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pop(&mut self) {
|
||||
pub(crate)
|
||||
fn put_complete_string(&mut self, s: &str) -> Addr {
|
||||
let addr = self.allocate_pstr(s);
|
||||
self.pop();
|
||||
|
||||
let h = self.h();
|
||||
|
||||
if h > 0 {
|
||||
self.truncate(h - 1);
|
||||
match &mut self[h - 1] {
|
||||
&mut HeapCellValue::PartialString(_, ref mut has_tail) => {
|
||||
*has_tail = false;
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
addr
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -219,21 +230,7 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
if s.is_empty() {
|
||||
Addr::EmptyList
|
||||
} else {
|
||||
let addr = self.allocate_pstr(&s);
|
||||
self.pop();
|
||||
|
||||
let h = self.h();
|
||||
|
||||
match &mut self[h - 1] {
|
||||
&mut HeapCellValue::PartialString(_, ref mut has_tail) => {
|
||||
*has_tail = false;
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
addr
|
||||
self.put_complete_string(&s)
|
||||
}
|
||||
}
|
||||
Constant::Usize(n) => {
|
||||
@@ -242,6 +239,16 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn pop(&mut self) {
|
||||
let h = self.h();
|
||||
|
||||
if h > 0 {
|
||||
self.truncate(h - 1);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn push(&mut self, val: HeapCellValue) -> usize {
|
||||
|
||||
@@ -274,16 +274,10 @@ impl Addr {
|
||||
let mut heap_pstr_iter =
|
||||
machine_st.heap_pstr_iter(Addr::PStrLocation(h, n));
|
||||
|
||||
let mut buf = String::new();
|
||||
let buf = heap_pstr_iter.to_string();
|
||||
let end_addr = heap_pstr_iter.focus();
|
||||
|
||||
while let Some(Some(c)) = heap_pstr_iter.next() {
|
||||
buf.push(c);
|
||||
}
|
||||
|
||||
let end_addr =
|
||||
machine_st.store(machine_st.deref(heap_pstr_iter.focus()));
|
||||
|
||||
if let Addr::EmptyList = end_addr {
|
||||
if end_addr == Addr::EmptyList {
|
||||
Some(Constant::String(Rc::new(buf)))
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -21,8 +21,7 @@ use std::io::Write;
|
||||
use std::mem;
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
||||
pub(crate)
|
||||
struct HeapPStrIter<'a> {
|
||||
pub(crate) struct HeapPStrIter<'a> {
|
||||
focus: Addr,
|
||||
machine_st: &'a MachineState,
|
||||
seen: IndexSet<Addr>,
|
||||
@@ -41,12 +40,44 @@ impl<'a> HeapPStrIter<'a> {
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn focus(&'a self) -> Addr {
|
||||
self.focus
|
||||
self.machine_st.store(self.machine_st.deref(self.focus))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn to_string(&mut self) -> String {
|
||||
let mut buf = String::new();
|
||||
|
||||
while let Some(iteratee) = self.next() {
|
||||
match iteratee {
|
||||
PStrIteratee::Char(c) => {
|
||||
buf.push(c);
|
||||
}
|
||||
PStrIteratee::PStrSegment(h, n) => {
|
||||
match &self.machine_st.heap[h] {
|
||||
HeapCellValue::PartialString(ref pstr, _) => {
|
||||
buf += pstr.as_str_from(n);
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(crate) enum PStrIteratee {
|
||||
Char(char),
|
||||
PStrSegment(usize, usize),
|
||||
}
|
||||
|
||||
impl<'a> Iterator for HeapPStrIter<'a> {
|
||||
type Item = Option<char>;
|
||||
type Item = PStrIteratee;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let addr = self.machine_st.store(self.machine_st.deref(self.focus));
|
||||
@@ -59,13 +90,14 @@ impl<'a> Iterator for HeapPStrIter<'a> {
|
||||
|
||||
match addr {
|
||||
Addr::PStrLocation(h, n) => {
|
||||
if let &HeapCellValue::PartialString(ref pstr, _) = &self.machine_st.heap[h] {
|
||||
if let Some(c) = pstr.range_from(n ..).next() {
|
||||
self.focus = Addr::PStrLocation(h, n + c.len_utf8());
|
||||
return Some(Some(c));
|
||||
if let &HeapCellValue::PartialString(_, has_tail) = &self.machine_st.heap[h] {
|
||||
self.focus = if has_tail {
|
||||
Addr::HeapCell(h + 1)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
Addr::EmptyList
|
||||
};
|
||||
|
||||
return Some(PStrIteratee::PStrSegment(h, n));
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
@@ -73,16 +105,36 @@ impl<'a> Iterator for HeapPStrIter<'a> {
|
||||
Addr::Lis(l) => {
|
||||
let addr = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l)));
|
||||
|
||||
if let Addr::Char(c) = addr {
|
||||
let opt_c = match addr {
|
||||
Addr::Con(h) if self.machine_st.heap.atom_at(h) => {
|
||||
if let HeapCellValue::Atom(ref atom, _) = &self.machine_st.heap[h] {
|
||||
if atom.is_char() {
|
||||
Some(atom.as_str().chars().next().unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
Addr::Char(c) => {
|
||||
Some(c)
|
||||
}
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(c) = opt_c {
|
||||
self.focus = Addr::HeapCell(l + 1);
|
||||
return Some(Some(c));
|
||||
return Some(PStrIteratee::Char(c));
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Addr::EmptyList => {
|
||||
self.focus = Addr::EmptyList;
|
||||
return Some(None);
|
||||
return None;
|
||||
}
|
||||
_ => {
|
||||
return None;
|
||||
@@ -93,24 +145,51 @@ impl<'a> Iterator for HeapPStrIter<'a> {
|
||||
|
||||
#[inline]
|
||||
pub(super)
|
||||
fn compare_pstr<'a>(
|
||||
pstr_iter: HeapPStrIter<'a>,
|
||||
mut c_iter: impl Iterator<Item = char>,
|
||||
) -> bool {
|
||||
for opt_c in pstr_iter {
|
||||
match opt_c {
|
||||
Some(_) => {
|
||||
if opt_c != c_iter.next() {
|
||||
return false;
|
||||
fn compare_pstr_to_string<'a>(
|
||||
heap_pstr_iter: &mut HeapPStrIter<'a>,
|
||||
s: &String,
|
||||
) -> Option<usize> {
|
||||
let mut s_offset = 0;
|
||||
|
||||
while let Some(iteratee) = heap_pstr_iter.next() {
|
||||
match iteratee {
|
||||
PStrIteratee::Char(c1) => {
|
||||
if let Some(c2) = s[s_offset ..].chars().next() {
|
||||
if c1 != c2 {
|
||||
return None;
|
||||
} else {
|
||||
s_offset += c1.len_utf8();
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
return c_iter.next().is_none();
|
||||
PStrIteratee::PStrSegment(h, n) => {
|
||||
match heap_pstr_iter.machine_st.heap[h] {
|
||||
HeapCellValue::PartialString(ref pstr, _) => {
|
||||
let t = pstr.as_str_from(n);
|
||||
|
||||
if s[s_offset ..].starts_with(t) {
|
||||
s_offset += t.len();
|
||||
} else if t.starts_with(&s[s_offset ..]) {
|
||||
heap_pstr_iter.focus =
|
||||
Addr::PStrLocation(h, n + s[s_offset ..].len());
|
||||
|
||||
s_offset += s[s_offset ..].len();
|
||||
return Some(s_offset);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
Some(s_offset)
|
||||
}
|
||||
|
||||
pub struct Ball {
|
||||
|
||||
@@ -688,8 +688,8 @@ impl MachineState {
|
||||
HeapPtr::HeapCell(ref mut h) => {
|
||||
*h += rhs;
|
||||
}
|
||||
&mut HeapPtr::PStrChar(h, ref mut n)
|
||||
| &mut HeapPtr::PStrLocation(h, ref mut n) => {
|
||||
&mut HeapPtr::PStrChar(h, ref mut n) |
|
||||
&mut HeapPtr::PStrLocation(h, ref mut n) => {
|
||||
match &self.heap[h] {
|
||||
HeapCellValue::PartialString(ref pstr, _) => {
|
||||
for c in pstr.range_from(*n ..).take(rhs) {
|
||||
@@ -768,13 +768,94 @@ impl MachineState {
|
||||
self.trail.truncate(self.tr);
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn match_partial_string(&mut self, addr: Addr, string: &String, has_tail: bool) {
|
||||
let mut heap_pstr_iter = self.heap_pstr_iter(addr);
|
||||
|
||||
match compare_pstr_to_string(&mut heap_pstr_iter, string) {
|
||||
Some(prefix_len) if prefix_len == string.len() => {
|
||||
let focus = heap_pstr_iter.focus();
|
||||
|
||||
match focus {
|
||||
Addr::PStrLocation(h, n) => {
|
||||
if has_tail {
|
||||
self.s = HeapPtr::PStrLocation(h, n);
|
||||
self.mode = MachineMode::Read;
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
addr => {
|
||||
if has_tail {
|
||||
let h = self.heap.h();
|
||||
|
||||
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
|
||||
self.bind(Ref::HeapCell(h), addr);
|
||||
|
||||
self.s = HeapPtr::HeapCell(h);
|
||||
self.mode = MachineMode::Read;
|
||||
} else {
|
||||
if let Some(var) = addr.as_var() {
|
||||
self.bind(var, Addr::EmptyList);
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(prefix_len) => {
|
||||
match heap_pstr_iter.focus() {
|
||||
addr @ Addr::AttrVar(_) |
|
||||
addr @ Addr::StackCell(..) |
|
||||
addr @ Addr::HeapCell(_) => {
|
||||
let h = self.heap.h();
|
||||
|
||||
let pstr_addr =
|
||||
if has_tail {
|
||||
self.s = HeapPtr::HeapCell(h+1);
|
||||
self.mode = MachineMode::Read;
|
||||
|
||||
self.heap.allocate_pstr(&string[prefix_len ..])
|
||||
} else {
|
||||
self.heap.put_complete_string(&string[prefix_len ..])
|
||||
};
|
||||
|
||||
self.bind(addr.as_var().unwrap(), pstr_addr);
|
||||
}
|
||||
Addr::Lis(l) if !self.flags.double_quotes.is_atom() => {
|
||||
let h = self.heap.h();
|
||||
|
||||
let pstr_addr =
|
||||
if has_tail {
|
||||
self.s = HeapPtr::HeapCell(h+1);
|
||||
self.mode = MachineMode::Read;
|
||||
|
||||
self.heap.allocate_pstr(&string[prefix_len ..])
|
||||
} else {
|
||||
self.heap.put_complete_string(&string[prefix_len ..])
|
||||
};
|
||||
|
||||
self.unify(Addr::Lis(l), pstr_addr);
|
||||
}
|
||||
_ => {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn write_constant_to_var(&mut self, addr: Addr, c: &Constant) {
|
||||
match self.store(self.deref(addr)) {
|
||||
Addr::Con(c1) => {
|
||||
self.fail = match &self.heap[c1] {
|
||||
match &self.heap[c1] {
|
||||
HeapCellValue::Atom(ref n1, _) => {
|
||||
match c {
|
||||
self.fail = match c {
|
||||
Constant::Atom(ref n2, _) => {
|
||||
n1 != n2
|
||||
}
|
||||
@@ -784,10 +865,10 @@ impl MachineState {
|
||||
_ => {
|
||||
true
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
HeapCellValue::Integer(ref n1) => {
|
||||
match c {
|
||||
self.fail = match c {
|
||||
Constant::Fixnum(n2) => {
|
||||
n1.to_isize() != Some(*n2)
|
||||
}
|
||||
@@ -800,10 +881,10 @@ impl MachineState {
|
||||
_ => {
|
||||
true
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
HeapCellValue::Rational(ref r1) => {
|
||||
if let Constant::Rational(ref r2) = c {
|
||||
self.fail = if let Constant::Rational(ref r2) = c {
|
||||
r1 != r2
|
||||
} else {
|
||||
true
|
||||
@@ -811,10 +892,13 @@ impl MachineState {
|
||||
}
|
||||
HeapCellValue::PartialString(..) => {
|
||||
if let Constant::String(ref s2) = c {
|
||||
let iter = self.heap_pstr_iter(Addr::PStrLocation(c1, 0));
|
||||
!compare_pstr(iter, s2.chars())
|
||||
self.match_partial_string(
|
||||
Addr::PStrLocation(c1, 0),
|
||||
&s2,
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
true
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@@ -846,11 +930,14 @@ impl MachineState {
|
||||
self.unify(Addr::Lis(l), addr);
|
||||
}
|
||||
Addr::PStrLocation(h, n) => {
|
||||
self.fail = if let Constant::String(ref s2) = c {
|
||||
let iter = self.heap_pstr_iter(Addr::PStrLocation(h, n));
|
||||
!compare_pstr(iter, s2.chars())
|
||||
if let Constant::String(ref s2) = c {
|
||||
self.match_partial_string(
|
||||
Addr::PStrLocation(h, n),
|
||||
&s2,
|
||||
false,
|
||||
)
|
||||
} else {
|
||||
true
|
||||
self.fail = true;
|
||||
};
|
||||
}
|
||||
Addr::Stream(_) => {
|
||||
@@ -1154,9 +1241,9 @@ impl MachineState {
|
||||
self.s = HeapPtr::PStrChar(h, n);
|
||||
self.mode = MachineMode::Read;
|
||||
}
|
||||
addr @ Addr::AttrVar(_)
|
||||
| addr @ Addr::StackCell(..)
|
||||
| addr @ Addr::HeapCell(_) => {
|
||||
addr @ Addr::AttrVar(_) |
|
||||
addr @ Addr::StackCell(..) |
|
||||
addr @ Addr::HeapCell(_) => {
|
||||
let h = self.heap.h();
|
||||
|
||||
self.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
||||
@@ -1168,9 +1255,15 @@ impl MachineState {
|
||||
self.s = HeapPtr::HeapCell(a);
|
||||
self.mode = MachineMode::Read;
|
||||
}
|
||||
_ => self.fail = true,
|
||||
_ => {
|
||||
self.fail = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
&FactInstruction::GetPartialString(_, ref string, reg, has_tail) => {
|
||||
let addr = self.store(self.deref(self[reg]));
|
||||
self.match_partial_string(addr, string, has_tail);
|
||||
}
|
||||
&FactInstruction::GetStructure(ref ct, arity, reg) => {
|
||||
let addr = self.deref(self[reg]);
|
||||
|
||||
@@ -1191,14 +1284,15 @@ impl MachineState {
|
||||
let h = self.heap.h();
|
||||
|
||||
self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1)));
|
||||
self.heap
|
||||
.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
|
||||
self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
|
||||
|
||||
self.bind(addr.as_var().unwrap(), Addr::HeapCell(h));
|
||||
|
||||
self.mode = MachineMode::Write;
|
||||
}
|
||||
_ => self.fail = true,
|
||||
_ => {
|
||||
self.fail = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
&FactInstruction::GetVariable(norm, arg) => {
|
||||
@@ -1214,7 +1308,9 @@ impl MachineState {
|
||||
match self.mode {
|
||||
MachineMode::Read => {
|
||||
let addr = self.s.read(&self.heap);
|
||||
|
||||
self.write_constant_to_var(addr, c);
|
||||
self.increment_s_ptr(1);
|
||||
}
|
||||
MachineMode::Write => {
|
||||
let addr = self.heap.put_constant(c.clone());
|
||||
@@ -1224,12 +1320,13 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.increment_s_ptr(1);
|
||||
}
|
||||
&FactInstruction::UnifyVariable(reg) => {
|
||||
match self.mode {
|
||||
MachineMode::Read => self[reg] = self.s.read(&self.heap),
|
||||
MachineMode::Read => {
|
||||
self[reg] = self.s.read(&self.heap);
|
||||
self.increment_s_ptr(1);
|
||||
}
|
||||
MachineMode::Write => {
|
||||
let h = self.heap.h();
|
||||
|
||||
@@ -1237,14 +1334,14 @@ impl MachineState {
|
||||
self[reg] = Addr::HeapCell(h);
|
||||
}
|
||||
};
|
||||
|
||||
self.increment_s_ptr(1);
|
||||
}
|
||||
&FactInstruction::UnifyLocalValue(reg) => {
|
||||
match self.mode {
|
||||
MachineMode::Read => {
|
||||
let reg_addr = self[reg];
|
||||
|
||||
self.unify(reg_addr, self.s.read(&self.heap));
|
||||
self.increment_s_ptr(1);
|
||||
}
|
||||
MachineMode::Write => {
|
||||
let addr = self.deref(self[reg]);
|
||||
@@ -1265,26 +1362,26 @@ impl MachineState {
|
||||
self.bind(Ref::HeapCell(h), addr);
|
||||
}
|
||||
};
|
||||
|
||||
self.increment_s_ptr(1);
|
||||
}
|
||||
&FactInstruction::UnifyValue(reg) => {
|
||||
match self.mode {
|
||||
MachineMode::Read => {
|
||||
let reg_addr = self[reg];
|
||||
|
||||
self.unify(reg_addr, self.s.read(&self.heap));
|
||||
self.increment_s_ptr(1);
|
||||
}
|
||||
MachineMode::Write => {
|
||||
let heap_val = self.store(self[reg]);
|
||||
self.heap.push(HeapCellValue::Addr(heap_val));
|
||||
}
|
||||
};
|
||||
|
||||
self.increment_s_ptr(1);
|
||||
}
|
||||
&FactInstruction::UnifyVoid(n) => {
|
||||
match self.mode {
|
||||
MachineMode::Read => self.increment_s_ptr(n),
|
||||
MachineMode::Read => {
|
||||
self.increment_s_ptr(n);
|
||||
}
|
||||
MachineMode::Write => {
|
||||
let h = self.heap.h();
|
||||
|
||||
@@ -1394,6 +1491,18 @@ impl MachineState {
|
||||
&QueryInstruction::PutList(_, reg) => {
|
||||
self[reg] = Addr::Lis(self.heap.h());
|
||||
}
|
||||
&QueryInstruction::PutPartialString(_, ref string, reg, has_tail) => {
|
||||
let pstr_addr =
|
||||
if has_tail {
|
||||
let pstr_addr = self.heap.allocate_pstr(&string);
|
||||
self.heap.pop(); // the tail will be added by the next instruction.
|
||||
pstr_addr
|
||||
} else {
|
||||
self.heap.put_complete_string(&string)
|
||||
};
|
||||
|
||||
self[reg] = pstr_addr;
|
||||
}
|
||||
&QueryInstruction::PutStructure(ref ct, arity, reg) => {
|
||||
let h = self.heap.h();
|
||||
|
||||
@@ -1466,7 +1575,7 @@ impl MachineState {
|
||||
&QueryInstruction::SetVoid(n) => {
|
||||
let h = self.heap.h();
|
||||
|
||||
for i in h..h + n {
|
||||
for i in h .. h + n {
|
||||
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -840,27 +840,33 @@ impl MachineState {
|
||||
current_output_stream: &mut Stream,
|
||||
) {
|
||||
match instr {
|
||||
&Line::Arithmetic(ref arith_instr) => self.execute_arith_instr(arith_instr),
|
||||
&Line::Arithmetic(ref arith_instr) => {
|
||||
self.execute_arith_instr(arith_instr)
|
||||
}
|
||||
&Line::Choice(ref choice_instr) => {
|
||||
self.execute_choice_instr(choice_instr, &mut policies.call_policy)
|
||||
}
|
||||
&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,
|
||||
code_repo,
|
||||
&mut policies.call_policy,
|
||||
&mut policies.cut_policy,
|
||||
current_input_stream,
|
||||
current_output_stream,
|
||||
control_instr,
|
||||
),
|
||||
&Line::Control(ref control_instr) => {
|
||||
self.execute_ctrl_instr(
|
||||
indices,
|
||||
code_repo,
|
||||
&mut policies.call_policy,
|
||||
&mut policies.cut_policy,
|
||||
current_input_stream,
|
||||
current_output_stream,
|
||||
control_instr,
|
||||
)
|
||||
}
|
||||
&Line::Fact(ref fact_instr) => {
|
||||
self.execute_fact_instr(&fact_instr);
|
||||
self.p += 1;
|
||||
}
|
||||
&Line::Indexing(ref indexing_instr) => self.execute_indexing_instr(&indexing_instr),
|
||||
&Line::Indexing(ref indexing_instr) => {
|
||||
self.execute_indexing_instr(&indexing_instr)
|
||||
}
|
||||
&Line::IndexedChoice(ref choice_instr) => {
|
||||
self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy)
|
||||
}
|
||||
|
||||
@@ -164,7 +164,12 @@ impl PartialString {
|
||||
|
||||
pub(super)
|
||||
fn clone_from_offset(&self, n: usize) -> Self {
|
||||
let len = if self.len > n { self.len - n } else { 0 };
|
||||
let len =
|
||||
if self.len - '\u{0}'.len_utf8() > n {
|
||||
self.len - n - '\u{0}'.len_utf8()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let mut pstr = PartialString {
|
||||
buf: ptr::null_mut(),
|
||||
@@ -216,4 +221,18 @@ impl PartialString {
|
||||
ptr::read((self.buf as usize + end_n) as *const u8) == 0u8
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_str_from(&self, n: usize) -> &str {
|
||||
unsafe {
|
||||
let slice = slice::from_raw_parts(
|
||||
self.buf,
|
||||
self.len - '\u{0}'.len_utf8(),
|
||||
);
|
||||
|
||||
let s = str::from_utf8(slice).unwrap();
|
||||
|
||||
&s[n ..]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1093,8 +1093,9 @@ impl RelationWorker {
|
||||
Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num))
|
||||
}
|
||||
}
|
||||
term =>
|
||||
Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num)),
|
||||
term => {
|
||||
Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1132,8 +1133,7 @@ impl RelationWorker {
|
||||
|
||||
fn absorb(&mut self, other: RelationWorker) {
|
||||
self.queue.extend(other.queue.into_iter());
|
||||
self.dynamic_clauses
|
||||
.extend(other.dynamic_clauses.into_iter());
|
||||
self.dynamic_clauses.extend(other.dynamic_clauses.into_iter());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,21 @@ macro_rules! functor_term {
|
||||
(atom($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
||||
HeapCellValue::Atom(clause_name!($e), None)
|
||||
);
|
||||
(string($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => ({
|
||||
let len: usize = $aux_lens.iter().sum();
|
||||
let h = len + $arity + 1 + $addendum.h() + $h;
|
||||
|
||||
$addendum.put_complete_string(&$e);
|
||||
|
||||
HeapCellValue::Addr(Addr::PStrLocation(h, 0))
|
||||
});
|
||||
(boolean($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => ({
|
||||
if $e {
|
||||
functor_term!(atom("true"), $arity, $aux_lens, $addendum)
|
||||
} else {
|
||||
functor_term!(atom("false"), $arity, $aux_lens, $addendum)
|
||||
}
|
||||
});
|
||||
($e:expr, $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||
$e
|
||||
);
|
||||
@@ -154,7 +169,7 @@ macro_rules! from_constant {
|
||||
let len: usize = $aux_lens.iter().sum();
|
||||
let h = len + $arity + 1 + $addendum.h() + $over_h;
|
||||
|
||||
$addendum.put_constant(Constant::String(s.clone()));
|
||||
$addendum.put_complete_string(&s);
|
||||
|
||||
HeapCellValue::Addr(Addr::PStrLocation(h, 0))
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ use prolog_parser::tabled_rc::TabledData;
|
||||
|
||||
use crate::prolog::forms::*;
|
||||
use crate::prolog::iterators::*;
|
||||
use crate::prolog::machine::heap::Heap;
|
||||
use crate::prolog::machine::machine_indices::*;
|
||||
use crate::prolog::machine::machine_state::MachineState;
|
||||
use crate::prolog::machine::streams::Stream;
|
||||
@@ -13,25 +12,6 @@ use std::collections::VecDeque;
|
||||
|
||||
type SubtermDeque = VecDeque<(usize, usize)>;
|
||||
|
||||
impl<'a> TermRef<'a> {
|
||||
fn as_addr(&self, heap: &mut Heap, h: usize) -> Addr {
|
||||
match self {
|
||||
&TermRef::AnonVar(_) | &TermRef::Var(..) => {
|
||||
Addr::HeapCell(h)
|
||||
}
|
||||
&TermRef::Cons(..) => {
|
||||
Addr::HeapCell(h)
|
||||
}
|
||||
&TermRef::Constant(_, _, c) => {
|
||||
heap.put_constant(c.clone())
|
||||
}
|
||||
&TermRef::Clause(..) => {
|
||||
Addr::Str(h)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type PrologStream = ParsingStream<Stream>;
|
||||
|
||||
pub mod readline {
|
||||
@@ -102,7 +82,6 @@ pub mod readline {
|
||||
result => {
|
||||
result
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,24 +107,17 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
fn push_stub_addr(machine_st: &mut MachineState) {
|
||||
let h = machine_st.heap.h();
|
||||
machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult {
|
||||
let term_writer = TermWriter::new(machine_st);
|
||||
term_writer.write_term_to_heap(term)
|
||||
}
|
||||
|
||||
fn modify_head_of_queue(
|
||||
machine_st: &mut MachineState,
|
||||
queue: &mut SubtermDeque,
|
||||
term: TermRef,
|
||||
h: usize,
|
||||
) {
|
||||
if let Some((arity, site_h)) = queue.pop_front() {
|
||||
machine_st.heap[site_h] = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
|
||||
|
||||
if arity > 1 {
|
||||
queue.push_front((arity - 1, site_h + 1));
|
||||
}
|
||||
}
|
||||
struct TermWriter<'a> {
|
||||
machine_st: &'a mut MachineState,
|
||||
queue: SubtermDeque,
|
||||
var_dict: HeapVarDict,
|
||||
}
|
||||
|
||||
pub struct TermWriteResult {
|
||||
@@ -153,79 +125,168 @@ pub struct TermWriteResult {
|
||||
pub(crate) var_dict: HeapVarDict,
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult {
|
||||
let heap_loc = machine_st.heap.h();
|
||||
|
||||
let mut queue = SubtermDeque::new();
|
||||
let mut var_dict = HeapVarDict::new();
|
||||
|
||||
for term in breadth_first_iter(term, true) {
|
||||
let h = machine_st.heap.h();
|
||||
|
||||
match &term {
|
||||
&TermRef::Cons(lvl, ..) => {
|
||||
queue.push_back((2, h + 1));
|
||||
machine_st.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
||||
|
||||
push_stub_addr(machine_st);
|
||||
push_stub_addr(machine_st);
|
||||
|
||||
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.spec());
|
||||
|
||||
machine_st.heap.push(named);
|
||||
|
||||
for _ in 0..subterms.len() {
|
||||
push_stub_addr(machine_st);
|
||||
}
|
||||
|
||||
if let Level::Root = lvl {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
&TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..)
|
||||
| &TermRef::Var(Level::Root, ..) => {
|
||||
let addr = term.as_addr(&mut machine_st.heap, h);
|
||||
|
||||
if !addr.is_heap_bound() {
|
||||
machine_st.heap.push(HeapCellValue::Addr(addr));
|
||||
}
|
||||
}
|
||||
&TermRef::AnonVar(_) => {
|
||||
if let Some((arity, site_h)) = queue.pop_front() {
|
||||
if arity > 1 {
|
||||
queue.push_front((arity - 1, site_h + 1));
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
&TermRef::Var(_, _, ref var) => {
|
||||
if let Some((arity, site_h)) = queue.pop_front() {
|
||||
if let Some(addr) = var_dict.get(var).cloned() {
|
||||
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;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
modify_head_of_queue(machine_st, &mut queue, term, h);
|
||||
impl<'a> TermWriter<'a> {
|
||||
#[inline]
|
||||
fn new(machine_st: &'a mut MachineState) -> Self {
|
||||
TermWriter {
|
||||
machine_st,
|
||||
queue: SubtermDeque::new(),
|
||||
var_dict: HeapVarDict::new(),
|
||||
}
|
||||
}
|
||||
|
||||
TermWriteResult { heap_loc, var_dict }
|
||||
#[inline]
|
||||
fn modify_head_of_queue(&mut self, term: &TermRef<'a>, h: usize) {
|
||||
if let Some((arity, site_h)) = self.queue.pop_front() {
|
||||
self.machine_st.heap[site_h] =
|
||||
HeapCellValue::Addr(self.term_as_addr(term, h));
|
||||
|
||||
if arity > 1 {
|
||||
self.queue.push_front((arity - 1, site_h + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn push_stub_addr(&mut self) {
|
||||
let h = self.machine_st.heap.h();
|
||||
self.machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
|
||||
}
|
||||
|
||||
fn term_as_addr(&mut self, term: &TermRef<'a>, h: usize) -> Addr {
|
||||
match term {
|
||||
&TermRef::AnonVar(_) | &TermRef::Var(..) => {
|
||||
Addr::HeapCell(h)
|
||||
}
|
||||
&TermRef::Cons(..) => {
|
||||
Addr::HeapCell(h)
|
||||
}
|
||||
&TermRef::Constant(_, _, c) => {
|
||||
self.machine_st.heap.put_constant(c.clone())
|
||||
}
|
||||
&TermRef::Clause(..) => {
|
||||
Addr::Str(h)
|
||||
}
|
||||
&TermRef::PartialString(..) => {//_, _, ref pstr, tail) => {
|
||||
Addr::PStrLocation(h, 0)
|
||||
/*
|
||||
match tail {
|
||||
Term::AnonVar => {
|
||||
let h = self.machine_st.heap.h();
|
||||
self.machine_st.heap.allocate_pstr(pstr);
|
||||
|
||||
Addr::PStrLocation(h, 0)
|
||||
}
|
||||
Term::Constant(_, Constant::EmptyList) => {
|
||||
self.machine_st.heap.put_complete_string(pstr)
|
||||
}
|
||||
Term::Var(_, ref var) => {
|
||||
let h = self.machine_st.heap.h();
|
||||
|
||||
self.machine_st.heap.allocate_pstr(pstr);
|
||||
let tail_h = self.machine_st.heap.h() - 1;
|
||||
|
||||
if let Some(addr) = self.var_dict.get(var) {
|
||||
self.machine_st.heap[tail_h] = HeapCellValue::Addr(*addr);
|
||||
} else {
|
||||
self.var_dict.insert(var.clone(), Addr::HeapCell(tail_h));
|
||||
}
|
||||
|
||||
Addr::PStrLocation(h, 0)
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_term_to_heap(mut self, term: &'a Term) -> TermWriteResult {
|
||||
let heap_loc = self.machine_st.heap.h();
|
||||
|
||||
for term in breadth_first_iter(term, true) {
|
||||
let h = self.machine_st.heap.h();
|
||||
|
||||
match &term {
|
||||
&TermRef::Cons(lvl, ..) => {
|
||||
self.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) => {
|
||||
self.queue.push_back((subterms.len(), h + 1));
|
||||
let named = HeapCellValue::NamedStr(subterms.len(), ct.name(), ct.spec());
|
||||
|
||||
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::Constant(Level::Root, ..) |
|
||||
&TermRef::Var(Level::Root, ..) => {
|
||||
let addr = self.term_as_addr(&term, h);
|
||||
|
||||
if !addr.is_heap_bound() {
|
||||
self.machine_st.heap.push(HeapCellValue::Addr(addr));
|
||||
}
|
||||
}
|
||||
&TermRef::AnonVar(_) => {
|
||||
if let Some((arity, site_h)) = self.queue.pop_front() {
|
||||
if arity > 1 {
|
||||
self.queue.push_front((arity - 1, site_h + 1));
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
&TermRef::PartialString(lvl, _, ref pstr, tail) => {
|
||||
if tail.is_some() {
|
||||
self.machine_st.heap.allocate_pstr(&pstr);
|
||||
} else {
|
||||
self.machine_st.heap.put_complete_string(&pstr);
|
||||
}
|
||||
|
||||
if let Level::Root = lvl {
|
||||
} else if tail.is_some() {
|
||||
let h = self.machine_st.heap.h();
|
||||
self.queue.push_back((1, h - 1));
|
||||
}
|
||||
}
|
||||
&TermRef::Var(_, _, ref var) => {
|
||||
if let Some((arity, site_h)) = self.queue.pop_front() {
|
||||
if let Some(addr) = self.var_dict.get(var).cloned() {
|
||||
self.machine_st.heap[site_h] = HeapCellValue::Addr(addr);
|
||||
} else {
|
||||
self.var_dict.insert(var.clone(), Addr::HeapCell(site_h));
|
||||
}
|
||||
|
||||
if arity > 1 {
|
||||
self.queue.push_front((arity - 1, site_h + 1));
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
};
|
||||
|
||||
self.modify_head_of_queue(&term, h);
|
||||
}
|
||||
|
||||
TermWriteResult { heap_loc, var_dict: self.var_dict }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ pub trait CompilationTarget<'a> {
|
||||
fn to_void(_: usize) -> Self;
|
||||
fn is_void_instr(&self) -> bool;
|
||||
|
||||
fn to_pstr(lvl: Level, string: String, r: RegType, has_tail: bool) -> Self;
|
||||
|
||||
fn incr_void_instr(&mut self);
|
||||
|
||||
fn constant_subterm(_: Constant) -> Self;
|
||||
@@ -62,6 +64,10 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_pstr(lvl: Level, string: String, r: RegType, has_tail: bool) -> Self {
|
||||
FactInstruction::GetPartialString(lvl, string, r, has_tail)
|
||||
}
|
||||
|
||||
fn incr_void_instr(&mut self) {
|
||||
match self {
|
||||
&mut FactInstruction::UnifyVoid(ref mut incr) => *incr += 1,
|
||||
@@ -117,6 +123,10 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
|
||||
QueryInstruction::PutList(lvl, reg)
|
||||
}
|
||||
|
||||
fn to_pstr(lvl: Level, string: String, r: RegType, has_tail: bool) -> Self {
|
||||
QueryInstruction::PutPartialString(lvl, string, r, has_tail)
|
||||
}
|
||||
|
||||
fn to_void(subterms: usize) -> Self {
|
||||
QueryInstruction::SetVoid(subterms)
|
||||
}
|
||||
|
||||
@@ -27,14 +27,14 @@ impl fmt::Display for REPLCodePtr {
|
||||
match self {
|
||||
REPLCodePtr::CompileBatch =>
|
||||
write!(f, "REPLCodePtr::CompileBatch"),
|
||||
REPLCodePtr::UseModule =>
|
||||
write!(f, "REPLCodePtr::UseModule"),
|
||||
REPLCodePtr::UseQualifiedModule =>
|
||||
write!(f, "REPLCodePtr::UseQualifiedModule"),
|
||||
REPLCodePtr::UseModuleFromFile =>
|
||||
write!(f, "REPLCodePtr::UseModuleFromFile"),
|
||||
REPLCodePtr::UseQualifiedModuleFromFile =>
|
||||
write!(f, "REPLCodePtr::UseQualifiedModuleFromFile")
|
||||
REPLCodePtr::UseModule =>
|
||||
write!(f, "REPLCodePtr::UseModule"),
|
||||
REPLCodePtr::UseQualifiedModule =>
|
||||
write!(f, "REPLCodePtr::UseQualifiedModule"),
|
||||
REPLCodePtr::UseModuleFromFile =>
|
||||
write!(f, "REPLCodePtr::UseModuleFromFile"),
|
||||
REPLCodePtr::UseQualifiedModuleFromFile =>
|
||||
write!(f, "REPLCodePtr::UseQualifiedModuleFromFile")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,13 @@ impl fmt::Display for FactInstruction {
|
||||
&FactInstruction::GetConstant(lvl, ref constant, ref r) => {
|
||||
write!(f, "get_constant {}, {}{}", constant, lvl, r.reg_num())
|
||||
}
|
||||
&FactInstruction::GetList(lvl, ref r) => write!(f, "get_list {}{}", lvl, r.reg_num()),
|
||||
&FactInstruction::GetList(lvl, ref r) => {
|
||||
write!(f, "get_list {}{}", lvl, r.reg_num())
|
||||
}
|
||||
&FactInstruction::GetPartialString(lvl, ref s, r, has_tail) => {
|
||||
write!(f, "get_partial_string({}, {}, {}, {})",
|
||||
lvl, s, r, has_tail)
|
||||
}
|
||||
&FactInstruction::GetStructure(ref ct, ref arity, ref r) => {
|
||||
write!(f, "get_structure {}/{}, {}", ct.name(), arity, r)
|
||||
}
|
||||
@@ -86,7 +92,13 @@ impl fmt::Display for QueryInstruction {
|
||||
&QueryInstruction::PutConstant(lvl, ref constant, ref r) => {
|
||||
write!(f, "put_constant {}, {}{}", constant, lvl, r.reg_num())
|
||||
}
|
||||
&QueryInstruction::PutList(lvl, ref r) => write!(f, "put_list {}{}", lvl, r.reg_num()),
|
||||
&QueryInstruction::PutList(lvl, ref r) => {
|
||||
write!(f, "put_list {}{}", lvl, r.reg_num())
|
||||
}
|
||||
&QueryInstruction::PutPartialString(lvl, ref s, r, has_tail) => {
|
||||
write!(f, "put_partial_string({}, {}, {}, {})",
|
||||
lvl, s, r, has_tail)
|
||||
}
|
||||
&QueryInstruction::PutStructure(ref ct, ref arity, ref r) => {
|
||||
write!(f, "put_structure {}/{}, {}", ct.name(), arity, r)
|
||||
}
|
||||
@@ -159,9 +171,12 @@ impl fmt::Display for HeapCellValue {
|
||||
write!(f, "{}/{}", name.as_str(), arity)
|
||||
}
|
||||
&HeapCellValue::PartialString(ref pstr, has_tail) => {
|
||||
write!(f, "pstr ( buf: 0x{:x}, has_tail({}) )",
|
||||
(pstr as *const _) as usize,
|
||||
has_tail)
|
||||
write!(
|
||||
f,
|
||||
"pstr ( buf: \"{}\", has_tail({}) )",
|
||||
pstr.as_str_from(0),
|
||||
has_tail,
|
||||
)
|
||||
}
|
||||
&HeapCellValue::Stream(ref stream) => {
|
||||
write!(f, "$stream({})", stream.as_ptr() as usize)
|
||||
|
||||
Reference in New Issue
Block a user