}
}
- pub fn arity(&self) -> usize {
- match self {
- &InlinedClauseType::CompareNumber(..) => 2,
- &InlinedClauseType::IsAtom(..) => 1,
- &InlinedClauseType::IsAtomic(..) => 1,
- &InlinedClauseType::IsCompound(..) => 1,
- &InlinedClauseType::IsInteger (..) => 1,
- &InlinedClauseType::IsRational(..) => 1,
- &InlinedClauseType::IsString(..) => 1,
- &InlinedClauseType::IsFloat (..) => 1,
- &InlinedClauseType::IsNonVar(..) => 1,
- &InlinedClauseType::IsVar(..) => 1
- }
- }
-
pub fn from(name: &str, arity: usize) -> Option<Self> {
let r1 = temp_v!(1);
let r2 = temp_v!(2);
}
impl SystemClauseType {
- pub fn arity(&self) -> usize {
- match self {
- &SystemClauseType::InstallCleaner => 1,
- &SystemClauseType::InstallInferenceCounter => 3,
- &SystemClauseType::RemoveCallPolicyCheck => 1,
- &SystemClauseType::RemoveInferenceCounter => 2,
- &SystemClauseType::RestoreCutPolicy => 0,
- &SystemClauseType::SetCutPoint(_) => 1,
- &SystemClauseType::GetArg => 3,
- &SystemClauseType::InferenceLevel => 2,
- &SystemClauseType::CleanUpBlock => 1,
- &SystemClauseType::EraseBall => 0,
- &SystemClauseType::Fail => 0,
- &SystemClauseType::GetBall => 1,
- &SystemClauseType::GetCurrentBlock => 1,
- &SystemClauseType::GetCutPoint => 1,
- &SystemClauseType::InstallNewBlock => 1,
- &SystemClauseType::ResetBlock => 1,
- &SystemClauseType::SetBall => 1,
- &SystemClauseType::SkipMaxList => 4,
- &SystemClauseType::Succeed => 0,
- &SystemClauseType::UnwindStack => 0
- }
- }
-
pub fn fixity(&self) -> Option<Fixity> {
None
}
Str(usize)
}
+impl PartialEq<Ref> for Addr {
+ fn eq(&self, r: &Ref) -> bool {
+ self.as_var() == Some(*r)
+ }
+}
+
+// for use in MachineState::bind.
+impl PartialOrd<Ref> for Addr {
+ fn partial_cmp(&self, r: &Ref) -> Option<Ordering> {
+ match self {
+ &Addr::StackCell(fr, sc) =>
+ match *r {
+ Ref::HeapCell(_) => Some(Ordering::Greater),
+ Ref::StackCell(fr1, sc1) =>
+ if fr1 < fr || (fr1 == fr && sc1 < sc) {
+ Some(Ordering::Greater)
+ } else if fr1 == fr && sc1 == sc {
+ Some(Ordering::Equal)
+ } else {
+ Some(Ordering::Less)
+ }
+ },
+ &Addr::HeapCell(h) =>
+ match r {
+ Ref::StackCell(..) => Some(Ordering::Less),
+ Ref::HeapCell(h1) => h.partial_cmp(h1)
+ },
+ _ => None
+ }
+ }
+}
+
impl Addr {
pub fn is_ref(&self) -> bool {
match self {
pub fn is_protected(&self, e: usize) -> bool {
match self {
- &Addr::StackCell(fr, _) if fr > e => false,
+ &Addr::StackCell(addr, _) if addr >= e => false,
_ => true
}
}
StackCell(usize, usize)
}
+impl Ref {
+ pub fn as_addr(self) -> Addr {
+ match self {
+ Ref::HeapCell(h) => Addr::HeapCell(h),
+ Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc)
+ }
+ }
+}
+
#[derive(Clone, PartialEq)]
pub enum HeapCellValue {
Addr(Addr),
pub struct ConjunctInfo<'a> {
pub perm_vs: VariableFixtures<'a>,
pub num_of_chunks: usize,
- pub has_deep_cut: bool
+ pub has_deep_cut: bool,
}
impl<'a> ConjunctInfo<'a>
// from 7.12.2 b) of 13211-1:1995
#[derive(Clone, Copy)]
pub enum ValidType {
- Atom,
- Atomic,
- Byte,
+// Atom,
+// Atomic,
+// Byte,
Callable,
- Character,
+// Character,
Compound,
- Evaluable,
- InByte,
- InCharacter,
+// Evaluable,
+// InByte,
+// InCharacter,
Integer,
List,
- Number,
+// Number,
Pair,
- PredicateIndicator,
- Variable
+// PredicateIndicator,
+// Variable
}
impl ValidType {
pub fn as_str(self) -> &'static str {
match self {
- ValidType::Atom => "atom",
- ValidType::Atomic => "atomic",
- ValidType::Byte => "byte",
+// ValidType::Atom => "atom",
+// ValidType::Atomic => "atomic",
+// ValidType::Byte => "byte",
ValidType::Callable => "callable",
- ValidType::Character => "character",
+// ValidType::Character => "character",
ValidType::Compound => "compound",
- ValidType::Evaluable => "evaluable",
- ValidType::InByte => "in_byte",
- ValidType::InCharacter => "in_character",
+// ValidType::Evaluable => "evaluable",
+// ValidType::InByte => "in_byte",
+// ValidType::InCharacter => "in_character",
ValidType::Integer => "integer",
ValidType::List => "list",
- ValidType::Number => "number",
+// ValidType::Number => "number",
ValidType::Pair => "pair",
- ValidType::PredicateIndicator => "predicate_indicator",
- ValidType::Variable => "variable"
+// ValidType::PredicateIndicator => "predicate_indicator",
+// ValidType::Variable => "variable"
}
}
}
// from 7.12.2 f) of 13211-1:1995
#[derive(Clone, Copy)]
pub enum RepFlag {
- Character,
- CharacterCode,
- InCharacterCode,
+// Character,
+// CharacterCode,
+// InCharacterCode,
MaxArity,
- MaxInteger,
- MinInteger
+// MaxInteger,
+// MinInteger
}
impl RepFlag {
pub fn as_str(self) -> &'static str {
match self {
- RepFlag::Character => "character",
- RepFlag::CharacterCode => "character_code",
- RepFlag::InCharacterCode => "in_character_code",
+// RepFlag::Character => "character",
+// RepFlag::CharacterCode => "character_code",
+// RepFlag::InCharacterCode => "in_character_code",
RepFlag::MaxArity => "max_arity",
- RepFlag::MaxInteger => "max_integer",
- RepFlag::MinInteger => "min_integer"
+// RepFlag::MaxInteger => "max_integer",
+// RepFlag::MinInteger => "min_integer"
}
}
}
// from 7.12.2 g) of 13211-1:1995
#[derive(Clone, Copy)]
pub enum EvalError {
- FloatOverflow,
- IntOverflow,
- Undefined,
- Underflow,
+// FloatOverflow,
+// IntOverflow,
+// Undefined,
+// Underflow,
ZeroDivisor
}
impl EvalError {
pub fn as_str(self) -> &'static str {
match self {
- EvalError::FloatOverflow => "float_overflow",
- EvalError::IntOverflow => "int_overflow",
- EvalError::Undefined => "undefined",
- EvalError::Underflow => "underflow",
+// EvalError::FloatOverflow => "float_overflow",
+// EvalError::IntOverflow => "int_overflow",
+// EvalError::Undefined => "undefined",
+// EvalError::Underflow => "underflow",
EvalError::ZeroDivisor => "zero_divisor"
}
}
pub(super) block: usize, // an offset into the OR stack.
pub(super) ball: Ball,
pub(super) interms: Vec<Number>, // intermediate numbers.
+ pub(super) last_call: bool
}
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
let b = machine_st.b - 1;
let n = machine_st.or_stack[b].num_args();
- for i in 1 .. n + 1 {
- let addr = machine_st.store(machine_st.deref(machine_st.or_stack[b][i].clone()));
+ for i in 1 .. n + 1 {
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
}
}
fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize,
- idx: CodeIndex, lco: bool)
+ idx: CodeIndex)
-> CallResult
{
- if lco {
+ if machine_st.last_call {
self.try_execute(machine_st, name, arity, idx)
} else {
self.try_call(machine_st, name, arity, idx)
Ok(())
}
- fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, lco: bool)
+ fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType)
-> CallResult
{
match ct {
&BuiltInClauseType::AcyclicTerm => {
let addr = machine_st[temp_v!(1)].clone();
machine_st.fail = machine_st.is_cyclic_term(addr);
- return_from_clause!(lco, machine_st)
+ return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::Compare => {
let a1 = machine_st[temp_v!(1)].clone();
});
machine_st.unify(a1, c);
- return_from_clause!(lco, machine_st)
+ return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::CompareTerm(qt) => {
match qt {
_ => machine_st.compare_term(qt)
};
- return_from_clause!(lco, machine_st)
+ return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::CyclicTerm => {
let addr = machine_st[temp_v!(1)].clone();
machine_st.fail = !machine_st.is_cyclic_term(addr);
- return_from_clause!(lco, machine_st)
+ return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::Display => {
let output = machine_st.print_term(machine_st[temp_v!(1)].clone(),
PrinterOutputter::new());
println!("{}", output.result());
- return_from_clause!(lco, machine_st)
+ return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::DuplicateTerm => {
machine_st.duplicate_term();
- return_from_clause!(lco, machine_st)
+ return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::Eq => {
machine_st.fail = machine_st.eq_test();
- return_from_clause!(lco, machine_st)
+ return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::Ground => {
machine_st.fail = machine_st.ground_test();
- return_from_clause!(lco, machine_st)
+ return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::Functor => {
machine_st.try_functor()?;
- return_from_clause!(lco, machine_st)
+ return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::NotEq => {
machine_st.fail = !machine_st.eq_test();
- return_from_clause!(lco, machine_st)
+ return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::Sort => {
machine_st.check_sort_errors()?;
let r2 = machine_st[temp_v!(2)].clone();
machine_st.unify(r2, heap_addr);
- return_from_clause!(lco, machine_st)
+ return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::KeySort => {
machine_st.check_keysort_errors()?;
let r2 = machine_st[temp_v!(2)].clone();
machine_st.unify(r2, heap_addr);
- return_from_clause!(lco, machine_st)
+ return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::Is => {
let a = machine_st[temp_v!(1)].clone();
let result = machine_st.arith_eval_by_metacall(temp_v!(2))?;
machine_st.unify(a, Addr::Con(Constant::Number(result)));
- machine_st.p += 1; // TODO: change this!!
-
- Ok(())
+ return_from_clause!(machine_st.last_call, machine_st)
},
}
}
- fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize,
- code_dirs: CodeDirs<'a>, lco: bool)
+ fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, code_dirs: CodeDirs<'a>)
-> CallResult
{
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
machine_st.execute_inlined(&inlined),
ClauseType::Op(..) | ClauseType::Named(..) =>
if let Some(idx) = code_dirs.get(name.clone(), arity, user) {
- self.context_call(machine_st, name, arity, idx, lco)?;
+ self.context_call(machine_st, name, arity, idx)?;
} else {
return Err(machine_st.existence_error(name, arity));
},
- ClauseType::System(ct) =>
+ ClauseType::System(_) =>
return Err(machine_st.type_error(ValidType::Callable,
Addr::Con(Constant::Atom(name))))
};
impl CallPolicy for CallWithInferenceLimitCallPolicy {
fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName,
- arity: usize, idx: CodeIndex, lco: bool)
+ arity: usize, idx: CodeIndex)
-> CallResult
{
- self.prev_policy.context_call(machine_st, name, arity, idx, lco)?;
+ self.prev_policy.context_call(machine_st, name, arity, idx)?;
self.increment()
}
self.increment()
}
- fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, lco: bool)
+ fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType)
-> CallResult
{
- self.prev_policy.call_builtin(machine_st, ct, lco)?;
+ self.prev_policy.call_builtin(machine_st, ct)?;
self.increment()
}
- fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, code_dirs: CodeDirs<'a>,
- lco: bool)
+ fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, code_dirs: CodeDirs<'a>)
-> CallResult
{
- self.prev_policy.call_n(machine_st, arity, code_dirs, lco)?;
+ self.prev_policy.call_n(machine_st, arity, code_dirs)?;
self.increment()
}
}
hb: 0,
block: 0,
ball: Ball::new(),
- interms: vec![Number::default(); 256]
+ interms: vec![Number::default(); 256],
+ last_call: false
}
}
}
pub(super) fn bind(&mut self, r1: Ref, a2: Addr) {
- let t2 = self.store(a2);
+ let t1 = self.store(r1.as_addr());
+ let t2 = self.store(a2.clone());
- match r1 {
- Ref::StackCell(fr, sc) =>
- self.and_stack[fr][sc] = t2,
- Ref::HeapCell(hc) =>
- self.heap[hc] = HeapCellValue::Addr(t2)
- };
+ if t1.is_ref() && (!t2.is_ref() || a2 < r1) {
+ match r1 {
+ Ref::StackCell(fr, sc) =>
+ self.and_stack[fr][sc] = t2,
+ Ref::HeapCell(h) =>
+ self.heap[h] = HeapCellValue::Addr(t2)
+ };
- self.trail(r1);
+ self.trail(r1);
+ } else {
+ match a2.as_var() {
+ Some(Ref::StackCell(fr, sc)) => {
+ self.and_stack[fr][sc] = t1;
+ self.trail(Ref::StackCell(fr, sc));
+ },
+ Some(Ref::HeapCell(h)) => {
+ self.heap[h] = HeapCellValue::Addr(t1);
+ self.trail(Ref::HeapCell(h));
+ },
+ None => {}
+ }
+ }
}
pub(super)
self.write_constant_to_var(addr, c.clone());
},
&FactInstruction::GetList(_, reg) => {
- let addr = self.deref(self[reg].clone());
+ let addr = self.store(self.deref(self[reg].clone()));
- match self.store(addr.clone()) {
+ match addr {
Addr::HeapCell(hc) => {
let h = self.heap.h;
self.registers[arg] = self.heap[h].as_addr(h);
}
},
- &QueryInstruction::PutValue(norm, arg) => {
- let addr = self.store(self.deref(self[norm].clone()));
- self.registers[arg] = self[norm].clone();
- },
+ &QueryInstruction::PutValue(norm, arg) =>
+ self.registers[arg] = self[norm].clone(),
&QueryInstruction::PutVariable(norm, arg) => {
match norm {
RegType::Perm(n) => {
match instr {
&ControlInstruction::Allocate(num_cells) =>
self.allocate(num_cells),
- &ControlInstruction::CallClause(ClauseType::CallN, arity, _, lco) =>
- try_or_fail!(self, call_policy.call_n(self, arity, code_dirs, lco)),
- &ControlInstruction::CallClause(ClauseType::BuiltIn(ref ct), _, _, lco) =>
- try_or_fail!(self, call_policy.call_builtin(self, ct, lco)),
+ &ControlInstruction::CallClause(ClauseType::CallN, arity, _, lco) => {
+ self.last_call = lco;
+ try_or_fail!(self, call_policy.call_n(self, arity, code_dirs));
+ },
+ &ControlInstruction::CallClause(ClauseType::BuiltIn(ref ct), _, _, lco) => {
+ self.last_call = lco;
+ try_or_fail!(self, call_policy.call_builtin(self, ct));
+ },
&ControlInstruction::CallClause(ClauseType::Inlined(ref ct), ..) =>
self.execute_inlined(ct),
&ControlInstruction::CallClause(ClauseType::Named(ref name, ref idx), arity, _, lco)
- | &ControlInstruction::CallClause(ClauseType::Op(ref name, _, ref idx), arity, _, lco) =>
- try_or_fail!(self, call_policy.context_call(self, name.clone(), arity, idx.clone(),
- lco)),
- &ControlInstruction::CallClause(ClauseType::System(ref ct), arity, _, lco) => {
+ | &ControlInstruction::CallClause(ClauseType::Op(ref name, _, ref idx), arity, _, lco) => {
+ self.last_call = lco;
+ try_or_fail!(self, call_policy.context_call(self, name.clone(), arity, idx.clone()));
+ },
+ &ControlInstruction::CallClause(ClauseType::System(ref ct), _, _, lco) => {
+ self.last_call = lco;
try_or_fail!(self, self.system_call(ct, call_policy, cut_policy));
- if lco {
+ if self.last_call {
self.p = CodePtr::Local(self.cp.clone());
} else {
self.p += 1;
self.fail = true;
},
&ControlInstruction::IsClause(lco, r, ref at) => {
+ self.last_call = lco;
+
let a1 = self[r].clone();
let a2 = try_or_fail!(self, self.get_number(at));
self.unify(a1, Addr::Con(Constant::Number(a2)));
- try_or_fail!(self, return_from_clause!(lco, self));
+ try_or_fail!(self, return_from_clause!(self.last_call, self));
},
&ControlInstruction::JmpBy(arity, offset, _, lco) => {
if !lco {
CodePtr::Local(LocalCodePtr::DirEntry(p, _)) =>
Some(self.code[p].clone()),
CodePtr::BuiltInClause(built_in, _) =>
- Some(call_clause!(ClauseType::BuiltIn(built_in), built_in.arity(), 0)),
+ Some(call_clause!(ClauseType::BuiltIn(built_in), built_in.arity(),
+ 0, self.ms.last_call)),
CodePtr::CallN(arity, _) =>
- Some(call_clause!(ClauseType::CallN, arity, 0))
+ Some(call_clause!(ClauseType::CallN, arity, 0, self.ms.last_call))
}
}
macro_rules! call_clause {
($ct:expr, $arity:expr, $pvs:expr) => (
Line::Control(ControlInstruction::CallClause($ct, $arity, $pvs, false))
- )
+ );
+ ($ct:expr, $arity:expr, $pvs:expr, $lco:expr) => (
+ Line::Control(ControlInstruction::CallClause($ct, $arity, $pvs, $lco))
+ )
}
macro_rules! proceed {
}
macro_rules! is_call {
- ($r:expr, $at:expr) => (
+ ($r:expr, $at:expr) => (
Line::Control(ControlInstruction::IsClause(false, $r, $at))
-
)
}