add provisional functor and arg support, and give ';' and '->' their true semantics
This commit is contained in:
@@ -324,6 +324,7 @@ pub enum InlinedQueryTerm {
|
||||
CompareNumber(CompareNumberQT, Vec<Box<Term>>),
|
||||
IsAtomic(Vec<Box<Term>>),
|
||||
IsVar(Vec<Box<Term>>),
|
||||
IsInteger(Vec<Box<Term>>)
|
||||
}
|
||||
|
||||
impl InlinedQueryTerm {
|
||||
@@ -331,6 +332,7 @@ impl InlinedQueryTerm {
|
||||
match self {
|
||||
&InlinedQueryTerm::CompareNumber(_, _) => 2,
|
||||
&InlinedQueryTerm::IsAtomic(_) => 1,
|
||||
&InlinedQueryTerm::IsInteger(_) => 1,
|
||||
&InlinedQueryTerm::IsVar(_) => 1,
|
||||
}
|
||||
}
|
||||
@@ -347,9 +349,11 @@ pub enum CompareNumberQT {
|
||||
}
|
||||
|
||||
pub enum QueryTerm {
|
||||
Arg(Vec<Box<Term>>),
|
||||
CallN(Vec<Box<Term>>),
|
||||
Catch(Vec<Box<Term>>),
|
||||
Cut,
|
||||
Functor(Vec<Box<Term>>),
|
||||
Inlined(InlinedQueryTerm),
|
||||
Is(Vec<Box<Term>>),
|
||||
Term(Term),
|
||||
@@ -359,8 +363,10 @@ pub enum QueryTerm {
|
||||
impl QueryTerm {
|
||||
pub fn arity(&self) -> usize {
|
||||
match self {
|
||||
&QueryTerm::Arg(_) => 3,
|
||||
&QueryTerm::Catch(_) => 3,
|
||||
&QueryTerm::Throw(_) => 1,
|
||||
&QueryTerm::Functor(_) => 3,
|
||||
&QueryTerm::Inlined(ref term) => term.arity(),
|
||||
&QueryTerm::Is(_) => 2,
|
||||
&QueryTerm::CallN(ref terms) => terms.len(),
|
||||
@@ -715,12 +721,14 @@ pub enum BuiltInInstruction {
|
||||
DuplicateTerm,
|
||||
EraseBall,
|
||||
Fail,
|
||||
GetArg,
|
||||
GetBall,
|
||||
GetCurrentBlock,
|
||||
GetCutPoint(RegType),
|
||||
InstallNewBlock,
|
||||
InternalCallN,
|
||||
IsAtomic(RegType),
|
||||
IsInteger(RegType),
|
||||
IsVar(RegType),
|
||||
ResetBlock,
|
||||
SetBall,
|
||||
@@ -732,6 +740,8 @@ pub enum BuiltInInstruction {
|
||||
|
||||
pub enum ControlInstruction {
|
||||
Allocate(usize), // num_frames.
|
||||
ArgCall,
|
||||
ArgExecute,
|
||||
Call(Atom, usize, usize), // name, arity, perm_vars after threshold.
|
||||
CallN(usize), // arity.
|
||||
CatchCall,
|
||||
@@ -739,6 +749,8 @@ pub enum ControlInstruction {
|
||||
Deallocate,
|
||||
Execute(Atom, usize),
|
||||
ExecuteN(usize),
|
||||
FunctorCall,
|
||||
FunctorExecute,
|
||||
Goto(usize, usize), // p, arity.
|
||||
IsCall(RegType, ArithmeticTerm),
|
||||
IsExecute(RegType, ArithmeticTerm),
|
||||
@@ -750,12 +762,16 @@ pub enum ControlInstruction {
|
||||
impl ControlInstruction {
|
||||
pub fn is_jump_instr(&self) -> bool {
|
||||
match self {
|
||||
&ControlInstruction::ArgCall => true,
|
||||
&ControlInstruction::ArgExecute => true,
|
||||
&ControlInstruction::Call(_, _, _) => true,
|
||||
&ControlInstruction::CatchCall => true,
|
||||
&ControlInstruction::CatchExecute => true,
|
||||
&ControlInstruction::Execute(_, _) => true,
|
||||
&ControlInstruction::CallN(_) => true,
|
||||
&ControlInstruction::ExecuteN(_) => true,
|
||||
&ControlInstruction::FunctorCall => true,
|
||||
&ControlInstruction::FunctorExecute => true,
|
||||
&ControlInstruction::ThrowCall => true,
|
||||
&ControlInstruction::ThrowExecute => true,
|
||||
&ControlInstruction::Goto(_, _) => true,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use prolog::ast::*;
|
||||
use prolog::num::bigint::{BigInt};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -105,14 +106,8 @@ fn get_builtins() -> Code {
|
||||
fact![get_value!(temp_v!(1), 2)], // =/2, 73.
|
||||
proceed!(),
|
||||
proceed!(), // true/0, 75.
|
||||
try_me_else!(2), // ';'/2, 76.
|
||||
execute_n!(1),
|
||||
trust_me!(),
|
||||
query![put_value!(temp_v!(2), 1)],
|
||||
execute_n!(1),
|
||||
get_cp!(temp_v!(3)), // ','/2, 81
|
||||
goto!(83, 3),
|
||||
try_me_else!(18), // ','/3, 83.
|
||||
get_cp!(temp_v!(3)), // ','/2, 76
|
||||
try_me_else!(18), // ','/3, 77.
|
||||
switch_on_term!(4, 1, 0, 0),
|
||||
indexed_try!(4),
|
||||
retry!(7),
|
||||
@@ -165,14 +160,116 @@ fn get_builtins() -> Code {
|
||||
query![put_value!(perm_v!(1), 1)],
|
||||
deallocate!(),
|
||||
execute_n!(1),
|
||||
allocate!(2), // (->)/2, 126.
|
||||
get_level!(),
|
||||
fact![get_var_in_fact!(perm_v!(2), 2)],
|
||||
get_cp!(temp_v!(3)), // ';'/2, 120.
|
||||
try_me_else!(12),
|
||||
switch_on_term!(4, 0, 0, 1),
|
||||
indexed_try!(3),
|
||||
trust!(5),
|
||||
try_me_else!(3),
|
||||
fact![get_structure!(String::from("->"), 2, temp_v!(1)),
|
||||
unify_variable!(temp_v!(1)),
|
||||
unify_variable!(temp_v!(2))],
|
||||
goto!(139, 3),
|
||||
trust_me!(),
|
||||
fact![get_structure!(String::from("->"), 2, temp_v!(1)),
|
||||
unify_void!(2)],
|
||||
query![put_value!(temp_v!(2), 1)],
|
||||
neck_cut!(),
|
||||
execute_n!(1),
|
||||
retry_me_else!(2),
|
||||
execute_n!(1),
|
||||
trust_me!(),
|
||||
query![put_value!(temp_v!(2), 1)],
|
||||
execute_n!(1),
|
||||
get_cp!(temp_v!(3)), // '->'/2, 138.
|
||||
allocate!(2), // '->'/3, 139.
|
||||
fact![get_var_in_fact!(perm_v!(1), 2),
|
||||
get_var_in_fact!(perm_v!(2), 3)], // cut point.
|
||||
call_n!(1),
|
||||
cut!(),
|
||||
query![put_value!(perm_v!(2), 1)],
|
||||
set_cp!(perm_v!(2)),
|
||||
query![put_unsafe_value!(1, 1)],
|
||||
deallocate!(),
|
||||
execute_n!(1)
|
||||
execute_n!(1),
|
||||
functor_execute!(), // functor/3, 146.
|
||||
is_integer!(temp_v!(1)), // integer/1, 147.
|
||||
proceed!(),
|
||||
get_arg!(), // get_arg/3, 149.
|
||||
try_me_else!(10), // arg/3, 150.
|
||||
allocate!(4),
|
||||
fact![get_var_in_fact!(perm_v!(1), 1),
|
||||
get_var_in_fact!(perm_v!(2), 2),
|
||||
get_var_in_fact!(perm_v!(4), 3)],
|
||||
is_var!(perm_v!(1)),
|
||||
neck_cut!(),
|
||||
query![put_value!(perm_v!(2), 1),
|
||||
put_var!(temp_v!(4), 2),
|
||||
put_var!(perm_v!(3), 3)],
|
||||
functor_call!(),
|
||||
query![put_value!(perm_v!(1), 1),
|
||||
put_constant!(Level::Shallow, integer!(1), temp_v!(2)),
|
||||
put_unsafe_value!(3, 3),
|
||||
put_value!(perm_v!(2), 4),
|
||||
put_value!(perm_v!(4), 5)],
|
||||
deallocate!(),
|
||||
goto!(173, 5), // goto arg_/3.
|
||||
retry_me_else!(10),
|
||||
allocate!(3),
|
||||
fact![get_var_in_fact!(perm_v!(1), 1),
|
||||
get_var_in_fact!(perm_v!(2), 2),
|
||||
get_var_in_fact!(perm_v!(3), 3)],
|
||||
is_integer!(perm_v!(1)),
|
||||
neck_cut!(),
|
||||
query![put_value!(perm_v!(2), 1),
|
||||
put_var!(temp_v!(4), 2),
|
||||
put_var!(temp_v!(3), 3)],
|
||||
functor_call!(),
|
||||
query![put_value!(perm_v!(1), 1),
|
||||
put_value!(perm_v!(2), 2),
|
||||
put_value!(perm_v!(3), 3)],
|
||||
deallocate!(),
|
||||
goto!(149, 3), // goto get_arg/3.
|
||||
trust_me!(),
|
||||
query![get_var_in_query!(temp_v!(4), 1),
|
||||
put_structure!(Level::Shallow,
|
||||
String::from("type_error"),
|
||||
1,
|
||||
temp_v!(1)),
|
||||
set_constant!(Constant::Atom(String::from("integer_expected")))],
|
||||
goto!(59, 1), // goto throw/1.
|
||||
try_me_else!(5), // arg_/3, 173.
|
||||
fact![get_value!(temp_v!(1), 2),
|
||||
get_value!(temp_v!(1), 3)],
|
||||
neck_cut!(),
|
||||
query![put_value!(temp_v!(4), 2),
|
||||
put_value!(temp_v!(5), 3)],
|
||||
goto!(149, 3), // goto get_arg/3.
|
||||
retry_me_else!(4),
|
||||
fact![get_value!(temp_v!(1), 2)],
|
||||
query![put_value!(temp_v!(4), 2),
|
||||
get_var_in_query!(temp_v!(6), 3),
|
||||
put_value!(temp_v!(5), 3)],
|
||||
goto!(149, 3), // goto get_arg/3
|
||||
trust_me!(),
|
||||
allocate!(5),
|
||||
fact![get_var_in_fact!(perm_v!(2), 1),
|
||||
get_var_in_fact!(perm_v!(4), 3),
|
||||
get_var_in_fact!(perm_v!(3), 4),
|
||||
get_var_in_fact!(perm_v!(5), 5)],
|
||||
compare_number_instr!(CompareNumberQT::LessThan,
|
||||
ArithmeticTerm::Reg(temp_v!(2)),
|
||||
ArithmeticTerm::Reg(perm_v!(4))),
|
||||
add!(ArithmeticTerm::Reg(temp_v!(2)),
|
||||
ArithmeticTerm::Integer(BigInt::from(1)),
|
||||
1),
|
||||
query![put_var!(perm_v!(1), 1)],
|
||||
is_call!(perm_v!(1), interm!(1)),
|
||||
query![put_value!(perm_v!(2), 1),
|
||||
put_unsafe_value!(1, 2),
|
||||
put_value!(perm_v!(4), 3),
|
||||
put_value!(perm_v!(3), 4),
|
||||
put_value!(perm_v!(5), 5)],
|
||||
deallocate!(),
|
||||
goto!(173, 3) // goto arg_/3.
|
||||
]
|
||||
}
|
||||
|
||||
@@ -237,9 +334,13 @@ pub fn build_code_dir() -> (Code, CodeDir, OpDir)
|
||||
code_dir.insert((String::from("="), 2), (PredicateKeyType::BuiltIn, 73));
|
||||
code_dir.insert((String::from("true"), 0), (PredicateKeyType::BuiltIn, 75));
|
||||
|
||||
code_dir.insert((String::from(";"), 2), (PredicateKeyType::BuiltIn, 76));
|
||||
code_dir.insert((String::from(","), 2), (PredicateKeyType::BuiltIn, 81));
|
||||
code_dir.insert((String::from("->"), 2), (PredicateKeyType::BuiltIn, 126));
|
||||
code_dir.insert((String::from(","), 2), (PredicateKeyType::BuiltIn, 76));
|
||||
code_dir.insert((String::from(";"), 2), (PredicateKeyType::BuiltIn, 120));
|
||||
code_dir.insert((String::from("->"), 2), (PredicateKeyType::BuiltIn, 138));
|
||||
|
||||
code_dir.insert((String::from("functor"), 3), (PredicateKeyType::BuiltIn, 146));
|
||||
code_dir.insert((String::from("arg"), 3), (PredicateKeyType::BuiltIn, 150));
|
||||
code_dir.insert((String::from("integer"), 1), (PredicateKeyType::BuiltIn, 147));
|
||||
|
||||
(builtin_code, code_dir, op_dir)
|
||||
}
|
||||
|
||||
@@ -236,12 +236,18 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize)
|
||||
{
|
||||
match qt {
|
||||
&QueryTerm::Arg(_) => {
|
||||
let call = ControlInstruction::ArgCall;
|
||||
code.push(Line::Control(call));
|
||||
},
|
||||
&QueryTerm::CallN(ref terms) => {
|
||||
let call = ControlInstruction::CallN(terms.len());
|
||||
code.push(Line::Control(call));
|
||||
},
|
||||
&QueryTerm::Catch(_) =>
|
||||
code.push(Line::Control(ControlInstruction::CatchCall)),
|
||||
&QueryTerm::Functor(_) =>
|
||||
code.push(Line::Control(ControlInstruction::FunctorCall)),
|
||||
&QueryTerm::Inlined(_) =>
|
||||
code.push(proceed!()),
|
||||
&QueryTerm::Term(Term::Constant(_, Constant::Atom(ref atom))) => {
|
||||
@@ -268,10 +274,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
swap(ctrl, &mut instr);
|
||||
|
||||
match instr {
|
||||
ControlInstruction::ArgCall =>
|
||||
*ctrl = ControlInstruction::ArgExecute,
|
||||
ControlInstruction::Call(name, arity, _) =>
|
||||
*ctrl = ControlInstruction::Execute(name, arity),
|
||||
ControlInstruction::CallN(arity) =>
|
||||
*ctrl = ControlInstruction::ExecuteN(arity),
|
||||
ControlInstruction::FunctorCall =>
|
||||
*ctrl = ControlInstruction::FunctorExecute,
|
||||
ControlInstruction::CatchCall =>
|
||||
*ctrl = ControlInstruction::CatchExecute,
|
||||
ControlInstruction::ThrowCall =>
|
||||
@@ -304,7 +314,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
code.push(compare_number_instr!(cmp,
|
||||
at_1.unwrap_or(interm!(1)),
|
||||
at_2.unwrap_or(interm!(2))));
|
||||
},
|
||||
},
|
||||
&InlinedQueryTerm::IsAtomic(ref inner_term) =>
|
||||
match inner_term[0].as_ref() {
|
||||
&Term::AnonVar | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
|
||||
@@ -318,6 +328,19 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
code.push(is_atomic!(r));
|
||||
}
|
||||
},
|
||||
&InlinedQueryTerm::IsInteger(ref inner_term) =>
|
||||
match inner_term[0].as_ref() {
|
||||
&Term::Constant(_, Constant::Integer(_)) => {
|
||||
code.push(succeed!());
|
||||
},
|
||||
&Term::Var(ref vr, ref name) => {
|
||||
let r = self.mark_non_callable(name, 1, term_loc, vr, code);
|
||||
code.push(is_integer!(r));
|
||||
},
|
||||
_ => {
|
||||
code.push(fail!());
|
||||
},
|
||||
},
|
||||
&InlinedQueryTerm::IsVar(ref inner_term) =>
|
||||
match inner_term[0].as_ref() {
|
||||
&Term::Constant(_, _) | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
|
||||
@@ -330,7 +353,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
let r = self.mark_non_callable(name, 1, term_loc, vr, code);
|
||||
code.push(is_var!(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -51,8 +51,26 @@ pub struct HeapCellViewer<'a> {
|
||||
state_stack: Vec<CellRef<'a>>
|
||||
}
|
||||
|
||||
impl<'a> HeapCellViewer<'a> {
|
||||
fn cell_ref_from_addr(&self, mut focus: &'a Addr) -> CellRef<'a> {
|
||||
impl<'a> HeapCellViewer<'a>
|
||||
{
|
||||
pub fn new(heap: &'a Heap, and_stack: &'a AndStack, addr: &'a Addr) -> Self
|
||||
{
|
||||
let mut viewer = HeapCellViewer {
|
||||
heap: heap,
|
||||
and_stack: and_stack,
|
||||
state_stack: vec![]
|
||||
};
|
||||
|
||||
let cell_ref = viewer.deref_cell(addr);
|
||||
let view = viewer.follow(cell_ref);
|
||||
|
||||
viewer.state_stack.push(CellRef::View(view));
|
||||
|
||||
viewer
|
||||
}
|
||||
|
||||
fn deref_cell(&self, mut focus: &'a Addr) -> CellRef<'a>
|
||||
{
|
||||
loop {
|
||||
match focus {
|
||||
&Addr::Con(ref c) =>
|
||||
@@ -75,22 +93,6 @@ impl<'a> HeapCellViewer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(heap: &'a Heap, and_stack: &'a AndStack, addr: &'a Addr) -> Self
|
||||
{
|
||||
let mut viewer = HeapCellViewer {
|
||||
heap: heap,
|
||||
and_stack: and_stack,
|
||||
state_stack: vec![]
|
||||
};
|
||||
|
||||
let cell_ref = viewer.cell_ref_from_addr(addr);
|
||||
let view = viewer.follow(cell_ref);
|
||||
|
||||
viewer.state_stack.push(CellRef::View(view));
|
||||
|
||||
viewer
|
||||
}
|
||||
|
||||
pub fn remove_token(&mut self, loc: usize) {
|
||||
self.state_stack[loc] = CellRef::TToken(TToken::Nothing);
|
||||
}
|
||||
@@ -143,21 +145,19 @@ impl<'a> HeapCellViewer<'a> {
|
||||
|
||||
return CellView::Str(arity, name);
|
||||
},
|
||||
&HeapCellValue::Ref(Ref::HeapCell(hc)) => {
|
||||
&HeapCellValue::Ref(Ref::HeapCell(hc)) =>
|
||||
if focus == hc {
|
||||
return CellView::HeapVar(hc);
|
||||
} else {
|
||||
focus = hc;
|
||||
}
|
||||
},
|
||||
&HeapCellValue::Ref(Ref::StackCell(fr, sc)) => {
|
||||
match self.cell_ref_from_addr(&self.and_stack[fr][sc]) {
|
||||
},
|
||||
&HeapCellValue::Ref(Ref::StackCell(fr, sc)) =>
|
||||
match self.deref_cell(&self.and_stack[fr][sc]) {
|
||||
CellRef::Lis(hc) => return self.handle_list(hc),
|
||||
CellRef::View(cell_view) => return cell_view,
|
||||
CellRef::Redirect(hc) => focus = hc,
|
||||
CellRef::TToken(token) => return CellView::TToken(token)
|
||||
};
|
||||
},
|
||||
},
|
||||
&HeapCellValue::Str(cell_num) =>
|
||||
focus = cell_num,
|
||||
}
|
||||
@@ -179,7 +179,6 @@ impl<'a> HeapCellViewer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a> Iterator for HeapCellViewer<'a> {
|
||||
type Item = CellView<'a>;
|
||||
|
||||
|
||||
@@ -98,6 +98,10 @@ impl fmt::Display for ControlInstruction {
|
||||
match self {
|
||||
&ControlInstruction::Allocate(num_cells) =>
|
||||
write!(f, "allocate {}", num_cells),
|
||||
&ControlInstruction::ArgCall =>
|
||||
write!(f, "arg_call"),
|
||||
&ControlInstruction::ArgExecute =>
|
||||
write!(f, "arg_execute"),
|
||||
&ControlInstruction::Call(ref name, arity, pvs) =>
|
||||
write!(f, "call {}/{}, {}", name, arity, pvs),
|
||||
&ControlInstruction::CallN(arity) =>
|
||||
@@ -108,6 +112,10 @@ impl fmt::Display for ControlInstruction {
|
||||
write!(f, "execute_catch"),
|
||||
&ControlInstruction::ExecuteN(arity) =>
|
||||
write!(f, "execute_N {}", arity),
|
||||
&ControlInstruction::FunctorCall =>
|
||||
write!(f, "functor_call"),
|
||||
&ControlInstruction::FunctorExecute =>
|
||||
write!(f, "functor_execute"),
|
||||
&ControlInstruction::Deallocate =>
|
||||
write!(f, "deallocate"),
|
||||
&ControlInstruction::Execute(ref name, arity) =>
|
||||
@@ -154,6 +162,8 @@ impl fmt::Display for BuiltInInstruction {
|
||||
write!(f, "erase_ball"),
|
||||
&BuiltInInstruction::Fail =>
|
||||
write!(f, "false"),
|
||||
&BuiltInInstruction::GetArg =>
|
||||
write!(f, "get_arg X1, X2, X3"),
|
||||
&BuiltInInstruction::GetBall =>
|
||||
write!(f, "get_ball X1"),
|
||||
&BuiltInInstruction::GetCurrentBlock =>
|
||||
@@ -166,6 +176,8 @@ impl fmt::Display for BuiltInInstruction {
|
||||
write!(f, "internal_call_N"),
|
||||
&BuiltInInstruction::IsAtomic(r) =>
|
||||
write!(f, "is_atomic {}", r),
|
||||
&BuiltInInstruction::IsInteger(r) =>
|
||||
write!(f, "is_integer {}", r),
|
||||
&BuiltInInstruction::IsVar(r) =>
|
||||
write!(f, "is_var {}", r),
|
||||
&BuiltInInstruction::ResetBlock =>
|
||||
@@ -386,7 +398,7 @@ pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'
|
||||
Ok(rule) => rule,
|
||||
Err(e) => return EvalSession::ParserError(e)
|
||||
};
|
||||
|
||||
|
||||
wam.add_rule(rule, compiled_rule)
|
||||
},
|
||||
&TopLevel::Query(ref query) => {
|
||||
|
||||
@@ -40,12 +40,18 @@ impl<'a> QueryIterator<'a> {
|
||||
let state = IteratorState::Clause(0, ClauseType::Catch, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Arg(ref terms)
|
||||
| &QueryTerm::Functor(ref terms) => {
|
||||
let state = IteratorState::Clause(0, ClauseType::Root, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Inlined(InlinedQueryTerm::CompareNumber(_, ref terms))
|
||||
| &QueryTerm::Is(ref terms) => {
|
||||
let state = IteratorState::Clause(0, ClauseType::Is, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
let state = IteratorState::Clause(0, ClauseType::Is, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Inlined(InlinedQueryTerm::IsAtomic(ref terms))
|
||||
| &QueryTerm::Inlined(InlinedQueryTerm::IsInteger(ref terms))
|
||||
| &QueryTerm::Inlined(InlinedQueryTerm::IsVar(ref terms)) =>
|
||||
Self::from_term(terms[0].as_ref()),
|
||||
&QueryTerm::Term(ref term) =>
|
||||
@@ -271,6 +277,12 @@ impl<'a> ChunkedIterator<'a>
|
||||
arity = child_terms.len();
|
||||
break;
|
||||
},
|
||||
&QueryTerm::Arg(_)
|
||||
| &QueryTerm::Functor(_) => {
|
||||
result.push(term);
|
||||
arity = 3;
|
||||
break;
|
||||
},
|
||||
&QueryTerm::Is(_) => {
|
||||
result.push(term);
|
||||
arity = 2;
|
||||
|
||||
@@ -1498,7 +1498,8 @@ impl MachineState {
|
||||
self.p = CodePtr::DirEntry(59);
|
||||
}
|
||||
|
||||
fn throw_exception(&mut self, hcv: Vec<HeapCellValue>) {
|
||||
fn throw_exception
|
||||
(&mut self, hcv: Vec<HeapCellValue>) {
|
||||
let h = self.heap.h;
|
||||
|
||||
self.registers[1] = Addr::HeapCell(h);
|
||||
@@ -1569,6 +1570,35 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_get_arg(&mut self) -> Result<(), Vec<HeapCellValue>>
|
||||
{
|
||||
let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
if let Addr::Con(Constant::Integer(i)) = a1 {
|
||||
let a2 = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||
|
||||
if let Addr::Str(o) = a2 {
|
||||
match self.heap[o].clone() {
|
||||
HeapCellValue::NamedStr(arity, _) =>
|
||||
match i.to_usize() {
|
||||
Some(i) if 1 <= i && i <= arity => {
|
||||
let a3 = self[temp_v!(3)].clone();
|
||||
let h_a = Addr::HeapCell(o + i);
|
||||
|
||||
self.unify(a3, h_a);
|
||||
},
|
||||
_ => self.fail = true
|
||||
},
|
||||
_ => self.fail = true
|
||||
};
|
||||
} else {
|
||||
return Err(functor!("type_error", 1, [atom!("compound_expected")]));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_built_in_instr(&mut self, code_dir: &CodeDir, instr: &BuiltInInstruction)
|
||||
{
|
||||
match instr {
|
||||
@@ -1605,6 +1635,12 @@ impl MachineState {
|
||||
|
||||
self.p += 1;
|
||||
},
|
||||
&BuiltInInstruction::GetArg =>
|
||||
try_or_fail!(self, {
|
||||
let val = self.try_get_arg();
|
||||
self.p = self.cp;
|
||||
val
|
||||
}),
|
||||
&BuiltInInstruction::GetCurrentBlock => {
|
||||
let c = Constant::Usize(self.block);
|
||||
let addr = self[temp_v!(1)].clone();
|
||||
@@ -1720,6 +1756,14 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&BuiltInInstruction::IsInteger(r) => {
|
||||
let d = self.store(self.deref(self[r].clone()));
|
||||
|
||||
match d {
|
||||
Addr::Con(Constant::Integer(_)) => self.p += 1,
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&BuiltInInstruction::IsVar(r) => {
|
||||
let d = self.store(self.deref(self[r].clone()));
|
||||
|
||||
@@ -1747,6 +1791,70 @@ impl MachineState {
|
||||
};
|
||||
}
|
||||
|
||||
fn try_functor(&mut self) -> Result<(), Vec<HeapCellValue>> {
|
||||
let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
match a1.clone() {
|
||||
Addr::Str(o) =>
|
||||
match self.heap[o].clone() {
|
||||
HeapCellValue::NamedStr(arity, name) => {
|
||||
let name = Addr::Con(Constant::Atom(name)); // A2
|
||||
let arity = Addr::Con(Constant::Integer(BigInt::from(arity))); // A3
|
||||
|
||||
let a2 = self[temp_v!(2)].clone();
|
||||
self.unify(a2, name);
|
||||
|
||||
if !self.fail {
|
||||
let a3 = self[temp_v!(3)].clone();
|
||||
self.unify(a3, arity);
|
||||
}
|
||||
},
|
||||
_ => self.fail = true
|
||||
},
|
||||
Addr::HeapCell(_) | Addr::StackCell(_, _) => {
|
||||
let name = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||
let arity = self.store(self.deref(self[temp_v!(3)].clone()));
|
||||
|
||||
if let Addr::Con(Constant::Atom(name)) = name {
|
||||
if let Addr::Con(Constant::Integer(arity)) = arity {
|
||||
let f_a = Addr::Str(self.heap.h);
|
||||
let arity = match arity.to_usize() {
|
||||
Some(arity) => arity,
|
||||
None => {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
self.heap.push(HeapCellValue::NamedStr(arity, name));
|
||||
|
||||
for _ in 0 .. arity {
|
||||
let h = self.heap.h;
|
||||
self.heap.push(HeapCellValue::Ref(Ref::HeapCell(h)));
|
||||
}
|
||||
|
||||
self.unify(a1, f_a);
|
||||
} else {
|
||||
return Err(functor!("instantiation_error", 0, []));
|
||||
}
|
||||
} else {
|
||||
return Err(functor!("instantiation_error", 0, []));
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
let a2 = self[temp_v!(2)].clone();
|
||||
self.unify(a1, a2);
|
||||
|
||||
if !self.fail {
|
||||
let a3 = self[temp_v!(3)].clone();
|
||||
self.unify(a3, Addr::Con(Constant::Integer(BigInt::from(0))));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_ctrl_instr(&mut self, code_dir: &CodeDir, instr: &ControlInstruction)
|
||||
{
|
||||
match instr {
|
||||
@@ -1779,6 +1887,17 @@ impl MachineState {
|
||||
self.and_stack.push(gi, self.e, self.cp, num_cells);
|
||||
self.e = self.and_stack.len() - 1;
|
||||
},
|
||||
&ControlInstruction::ArgCall => {
|
||||
self.cp = self.p + 1;
|
||||
self.num_of_args = 3;
|
||||
self.b0 = self.b;
|
||||
self.p = CodePtr::DirEntry(150);
|
||||
},
|
||||
&ControlInstruction::ArgExecute => {
|
||||
self.num_of_args = 3;
|
||||
self.b0 = self.b;
|
||||
self.p = CodePtr::DirEntry(150);
|
||||
},
|
||||
&ControlInstruction::Call(ref name, arity, _) =>
|
||||
self.try_call_predicate(code_dir, name.clone(), arity),
|
||||
&ControlInstruction::CatchCall => {
|
||||
@@ -1810,6 +1929,18 @@ impl MachineState {
|
||||
if let Some((name, arity)) = self.setup_call_n(arity) {
|
||||
self.try_execute_predicate(code_dir, name, arity);
|
||||
},
|
||||
&ControlInstruction::FunctorCall =>
|
||||
try_or_fail!(self, {
|
||||
let val = self.try_functor();
|
||||
self.p += 1;
|
||||
val
|
||||
}),
|
||||
&ControlInstruction::FunctorExecute =>
|
||||
try_or_fail!(self, {
|
||||
let val = self.try_functor();
|
||||
self.p = self.cp;
|
||||
val
|
||||
}),
|
||||
&ControlInstruction::Goto(p, arity) => {
|
||||
self.num_of_args = arity;
|
||||
self.b0 = self.b;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
macro_rules! internal_call_n {
|
||||
() => (
|
||||
Line::BuiltIn(BuiltInInstruction::InternalCallN)
|
||||
@@ -99,12 +100,24 @@ macro_rules! put_var {
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! put_structure {
|
||||
($lvl:expr, $name:expr, $arity:expr, $r:expr) => (
|
||||
QueryInstruction::PutStructure($lvl, $name, $arity, $r)
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! put_constant {
|
||||
($lvl:expr, $cons:expr, $r:expr) => (
|
||||
QueryInstruction::PutConstant($lvl, $cons, $r)
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! set_constant {
|
||||
($cons:expr) => (
|
||||
QueryInstruction::SetConstant($cons)
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! put_value {
|
||||
($r:expr, $arg:expr) => (
|
||||
QueryInstruction::PutValue($r, $arg)
|
||||
@@ -135,6 +148,12 @@ macro_rules! is_atomic {
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! is_integer {
|
||||
($reg:expr) => (
|
||||
Line::BuiltIn(BuiltInInstruction::IsInteger($reg))
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! is_var {
|
||||
($reg:expr) => (
|
||||
Line::BuiltIn(BuiltInInstruction::IsVar($reg))
|
||||
@@ -303,12 +322,30 @@ macro_rules! get_structure {
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! functor_call {
|
||||
() => (
|
||||
Line::Control(ControlInstruction::FunctorCall)
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! functor_execute {
|
||||
() => (
|
||||
Line::Control(ControlInstruction::FunctorExecute)
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! unify_variable {
|
||||
($r:expr) => (
|
||||
FactInstruction::UnifyVariable($r)
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! unify_void {
|
||||
($n:expr) => (
|
||||
FactInstruction::UnifyVoid($n)
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! set_cp {
|
||||
($r:expr) => (
|
||||
Line::BuiltIn(BuiltInInstruction::SetCutPoint($r))
|
||||
@@ -321,4 +358,20 @@ macro_rules! get_cp {
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! integer {
|
||||
($i:expr) => (
|
||||
Constant::Integer(BigInt::from($i))
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! add {
|
||||
($at_1:expr, $at_2:expr, $o:expr) => (
|
||||
Line::Arithmetic(ArithmeticInstruction::Add($at_1, $at_2, $o))
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! get_arg {
|
||||
() => (
|
||||
Line::BuiltIn(BuiltInInstruction::GetArg)
|
||||
)
|
||||
}
|
||||
|
||||
Submodule src/prolog/parser updated: 8723085780...f51fc401fa
Reference in New Issue
Block a user