refine is/2 compilation so errors are thrown when expected without needlessly allocating (#1974, #1984)
This commit is contained in:
@@ -99,6 +99,8 @@ enum BuiltInClauseType {
|
|||||||
Ground,
|
Ground,
|
||||||
#[strum_discriminants(strum(props(Arity = "2", Name = "is")))]
|
#[strum_discriminants(strum(props(Arity = "2", Name = "is")))]
|
||||||
Is(RegType, ArithmeticTerm),
|
Is(RegType, ArithmeticTerm),
|
||||||
|
#[strum_discriminants(strum(props(Arity = "1", Name = "$get_number")))]
|
||||||
|
GetNumber(ArithmeticTerm),
|
||||||
#[strum_discriminants(strum(props(Arity = "2", Name = "keysort")))]
|
#[strum_discriminants(strum(props(Arity = "2", Name = "keysort")))]
|
||||||
KeySort,
|
KeySort,
|
||||||
#[strum_discriminants(strum(props(Arity = "2", Name = "sort")))]
|
#[strum_discriminants(strum(props(Arity = "2", Name = "sort")))]
|
||||||
@@ -1553,7 +1555,8 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::CallFunctor |
|
&Instruction::CallFunctor |
|
||||||
&Instruction::CallGround |
|
&Instruction::CallGround |
|
||||||
&Instruction::CallKeySort |
|
&Instruction::CallKeySort |
|
||||||
&Instruction::CallSort => {
|
&Instruction::CallSort |
|
||||||
|
&Instruction::CallGetNumber(_) => {
|
||||||
let (name, arity) = self.to_name_and_arity();
|
let (name, arity) = self.to_name_and_arity();
|
||||||
functor!(atom!("call"), [atom(name), fixnum(arity)])
|
functor!(atom!("call"), [atom(name), fixnum(arity)])
|
||||||
}
|
}
|
||||||
@@ -1578,7 +1581,8 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::ExecuteGround |
|
&Instruction::ExecuteGround |
|
||||||
&Instruction::ExecuteIs(..) |
|
&Instruction::ExecuteIs(..) |
|
||||||
&Instruction::ExecuteKeySort |
|
&Instruction::ExecuteKeySort |
|
||||||
&Instruction::ExecuteSort => {
|
&Instruction::ExecuteSort |
|
||||||
|
&Instruction::ExecuteGetNumber(_) => {
|
||||||
let (name, arity) = self.to_name_and_arity();
|
let (name, arity) = self.to_name_and_arity();
|
||||||
functor!(atom!("execute"), [atom(name), fixnum(arity)])
|
functor!(atom!("execute"), [atom(name), fixnum(arity)])
|
||||||
}
|
}
|
||||||
@@ -1603,7 +1607,8 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::DefaultCallGround |
|
&Instruction::DefaultCallGround |
|
||||||
&Instruction::DefaultCallIs(..) |
|
&Instruction::DefaultCallIs(..) |
|
||||||
&Instruction::DefaultCallKeySort |
|
&Instruction::DefaultCallKeySort |
|
||||||
&Instruction::DefaultCallSort => {
|
&Instruction::DefaultCallSort |
|
||||||
|
&Instruction::DefaultCallGetNumber(_) => {
|
||||||
let (name, arity) = self.to_name_and_arity();
|
let (name, arity) = self.to_name_and_arity();
|
||||||
functor!(atom!("call_default"), [atom(name), fixnum(arity)])
|
functor!(atom!("call_default"), [atom(name), fixnum(arity)])
|
||||||
}
|
}
|
||||||
@@ -1628,7 +1633,8 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::DefaultExecuteGround |
|
&Instruction::DefaultExecuteGround |
|
||||||
&Instruction::DefaultExecuteIs(..) |
|
&Instruction::DefaultExecuteIs(..) |
|
||||||
&Instruction::DefaultExecuteKeySort |
|
&Instruction::DefaultExecuteKeySort |
|
||||||
&Instruction::DefaultExecuteSort => {
|
&Instruction::DefaultExecuteSort |
|
||||||
|
&Instruction::DefaultExecuteGetNumber(_) => {
|
||||||
let (name, arity) = self.to_name_and_arity();
|
let (name, arity) = self.to_name_and_arity();
|
||||||
functor!(atom!("execute_default"), [atom(name), fixnum(arity)])
|
functor!(atom!("execute_default"), [atom(name), fixnum(arity)])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -814,19 +814,34 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
self.marker.mark_safe_var_unconditionally(var_num);
|
self.marker.mark_safe_var_unconditionally(var_num);
|
||||||
|
compile_expr!(self, &terms[1], term_loc, code)
|
||||||
} else {
|
} else {
|
||||||
if self.marker.in_tail_position {
|
if let Term::Var(ref vr, ref var) = &terms[1] {
|
||||||
if self.marker.var_data.allocates {
|
let var_num = var.to_var_num().unwrap();
|
||||||
code.push_back(instr!("deallocate"));
|
|
||||||
}
|
|
||||||
|
|
||||||
code.push_back(instr!("proceed"));
|
// if var is an anonymous variable, insert
|
||||||
|
// is/2 call so that an instantiation error is
|
||||||
|
// thrown when the predicate is run.
|
||||||
|
if self.marker.var_data.records[var_num].num_occurrences > 1 {
|
||||||
|
self.marker.mark_var::<QueryInstruction>(
|
||||||
|
var_num,
|
||||||
|
Level::Shallow,
|
||||||
|
vr,
|
||||||
|
term_loc,
|
||||||
|
code,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.marker.mark_safe_var_unconditionally(var_num);
|
||||||
|
|
||||||
|
let at = ArithmeticTerm::Reg(vr.get().norm());
|
||||||
|
self.add_call(code, instr!("$get_number", at), call_policy);
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
compile_expr!(self, &terms[1], term_loc, code)
|
||||||
}
|
}
|
||||||
|
|
||||||
compile_expr!(self, &terms[1], term_loc, code)
|
|
||||||
}
|
}
|
||||||
&Term::Literal(_, c @ Literal::Integer(_) |
|
&Term::Literal(_, c @ Literal::Integer(_) |
|
||||||
c @ Literal::Float(_) |
|
c @ Literal::Float(_) |
|
||||||
|
|||||||
@@ -1497,6 +1497,14 @@ impl Machine {
|
|||||||
try_or_throw!(self.machine_st, self.machine_st.is(r, at));
|
try_or_throw!(self.machine_st, self.machine_st.is(r, at));
|
||||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||||
}
|
}
|
||||||
|
Instruction::DefaultCallGetNumber(at) => {
|
||||||
|
try_or_throw!(self.machine_st, self.machine_st.get_number(at));
|
||||||
|
step_or_fail!(self, self.machine_st.p += 1);
|
||||||
|
}
|
||||||
|
Instruction::DefaultExecuteGetNumber(at) => {
|
||||||
|
try_or_throw!(self.machine_st, self.machine_st.get_number(at));
|
||||||
|
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||||
|
}
|
||||||
&Instruction::CallAcyclicTerm => {
|
&Instruction::CallAcyclicTerm => {
|
||||||
let addr = self.machine_st.registers[1];
|
let addr = self.machine_st.registers[1];
|
||||||
|
|
||||||
@@ -1965,6 +1973,34 @@ impl Machine {
|
|||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Instruction::CallGetNumber(at) => {
|
||||||
|
try_or_throw!(self.machine_st, self.machine_st.get_number(at));
|
||||||
|
|
||||||
|
if self.machine_st.fail {
|
||||||
|
self.machine_st.backtrack();
|
||||||
|
} else {
|
||||||
|
try_or_throw!(
|
||||||
|
self.machine_st,
|
||||||
|
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||||
|
);
|
||||||
|
|
||||||
|
self.machine_st.p += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Instruction::ExecuteGetNumber(at) => {
|
||||||
|
try_or_throw!(self.machine_st, self.machine_st.get_number(at));
|
||||||
|
|
||||||
|
if self.machine_st.fail {
|
||||||
|
self.machine_st.backtrack();
|
||||||
|
} else {
|
||||||
|
try_or_throw!(
|
||||||
|
self.machine_st,
|
||||||
|
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||||
|
);
|
||||||
|
|
||||||
|
self.machine_st.p = self.machine_st.cp;
|
||||||
|
}
|
||||||
|
}
|
||||||
&Instruction::CallN(arity) => {
|
&Instruction::CallN(arity) => {
|
||||||
let pred = self.machine_st.registers[1];
|
let pred = self.machine_st.registers[1];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user