add call support for numeric comparisons.
This commit is contained in:
@@ -742,11 +742,12 @@ pub enum BuiltInInstruction {
|
|||||||
GetBall,
|
GetBall,
|
||||||
GetCurrentBlock,
|
GetCurrentBlock,
|
||||||
GetCutPoint(RegType),
|
GetCutPoint(RegType),
|
||||||
|
DynamicCompareNumber(CompareNumberQT),
|
||||||
|
DynamicIs,
|
||||||
InstallNewBlock,
|
InstallNewBlock,
|
||||||
InternalCallN,
|
InternalCallN,
|
||||||
IsAtomic(RegType),
|
IsAtomic(RegType),
|
||||||
IsInteger(RegType),
|
IsInteger(RegType),
|
||||||
IsOnHeap,
|
|
||||||
IsVar(RegType),
|
IsVar(RegType),
|
||||||
ResetBlock,
|
ResetBlock,
|
||||||
SetBall,
|
SetBall,
|
||||||
|
|||||||
@@ -276,7 +276,19 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
|||||||
goto!(173, 3), // goto arg_/3.
|
goto!(173, 3), // goto arg_/3.
|
||||||
display!(), // display/1, 192.
|
display!(), // display/1, 192.
|
||||||
proceed!(),
|
proceed!(),
|
||||||
is_on_heap!(), // is/2, 194.
|
dynamic_is!(), // is/2, 194.
|
||||||
|
proceed!(),
|
||||||
|
dynamic_num_test!(cmp_gt!()), // >/2, 196.
|
||||||
|
proceed!(),
|
||||||
|
dynamic_num_test!(cmp_lt!()), // </2, 198.
|
||||||
|
proceed!(),
|
||||||
|
dynamic_num_test!(cmp_gte!()), // >=/2, 200.
|
||||||
|
proceed!(),
|
||||||
|
dynamic_num_test!(cmp_lte!()), // <=/2, 202.
|
||||||
|
proceed!(),
|
||||||
|
dynamic_num_test!(cmp_ne!()), // =\=, 204.
|
||||||
|
proceed!(),
|
||||||
|
dynamic_num_test!(cmp_eq!()), // =:=, 206.
|
||||||
proceed!()
|
proceed!()
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -350,7 +362,14 @@ pub fn build_code_dir(atom_tbl: TabledData<Atom>) -> (Code, CodeDir, OpDir)
|
|||||||
code_dir.insert((tabled_rc!("arg", atom_tbl), 3), (PredicateKeyType::BuiltIn, 150));
|
code_dir.insert((tabled_rc!("arg", atom_tbl), 3), (PredicateKeyType::BuiltIn, 150));
|
||||||
code_dir.insert((tabled_rc!("integer", atom_tbl), 1), (PredicateKeyType::BuiltIn, 147));
|
code_dir.insert((tabled_rc!("integer", atom_tbl), 1), (PredicateKeyType::BuiltIn, 147));
|
||||||
code_dir.insert((tabled_rc!("display", atom_tbl), 1), (PredicateKeyType::BuiltIn, 192));
|
code_dir.insert((tabled_rc!("display", atom_tbl), 1), (PredicateKeyType::BuiltIn, 192));
|
||||||
|
|
||||||
code_dir.insert((tabled_rc!("is", atom_tbl), 2), (PredicateKeyType::BuiltIn, 194));
|
code_dir.insert((tabled_rc!("is", atom_tbl), 2), (PredicateKeyType::BuiltIn, 194));
|
||||||
|
code_dir.insert((tabled_rc!(">", atom_tbl), 2), (PredicateKeyType::BuiltIn, 196));
|
||||||
|
code_dir.insert((tabled_rc!("<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 198));
|
||||||
|
code_dir.insert((tabled_rc!(">=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 200));
|
||||||
|
code_dir.insert((tabled_rc!("<=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 202));
|
||||||
|
code_dir.insert((tabled_rc!("=\\=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 204));
|
||||||
|
code_dir.insert((tabled_rc!("=:=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 206));
|
||||||
|
|
||||||
(builtin_code, code_dir, op_dir)
|
(builtin_code, code_dir, op_dir)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,6 +165,8 @@ impl fmt::Display for BuiltInInstruction {
|
|||||||
write!(f, "clean_up_block"),
|
write!(f, "clean_up_block"),
|
||||||
&BuiltInInstruction::CompareNumber(cmp, ref at_1, ref at_2) =>
|
&BuiltInInstruction::CompareNumber(cmp, ref at_1, ref at_2) =>
|
||||||
write!(f, "number_test {}, {}, {} ", cmp, at_1, at_2),
|
write!(f, "number_test {}, {}, {} ", cmp, at_1, at_2),
|
||||||
|
&BuiltInInstruction::DynamicCompareNumber(cmp) =>
|
||||||
|
write!(f, "dynamic_number_test {}", cmp),
|
||||||
&BuiltInInstruction::EraseBall =>
|
&BuiltInInstruction::EraseBall =>
|
||||||
write!(f, "erase_ball"),
|
write!(f, "erase_ball"),
|
||||||
&BuiltInInstruction::Fail =>
|
&BuiltInInstruction::Fail =>
|
||||||
@@ -185,8 +187,8 @@ impl fmt::Display for BuiltInInstruction {
|
|||||||
write!(f, "is_atomic {}", r),
|
write!(f, "is_atomic {}", r),
|
||||||
&BuiltInInstruction::IsInteger(r) =>
|
&BuiltInInstruction::IsInteger(r) =>
|
||||||
write!(f, "is_integer {}", r),
|
write!(f, "is_integer {}", r),
|
||||||
&BuiltInInstruction::IsOnHeap =>
|
&BuiltInInstruction::DynamicIs =>
|
||||||
write!(f, "call_is A1, A2"),
|
write!(f, "call_is"),
|
||||||
&BuiltInInstruction::IsVar(r) =>
|
&BuiltInInstruction::IsVar(r) =>
|
||||||
write!(f, "is_var {}", r),
|
write!(f, "is_var {}", r),
|
||||||
&BuiltInInstruction::ResetBlock =>
|
&BuiltInInstruction::ResetBlock =>
|
||||||
|
|||||||
@@ -497,12 +497,12 @@ impl MachineState {
|
|||||||
Rc::new(BigInt::from_signed_bytes_le(&f(&u_n1, &u_n2).to_bytes_le()))
|
Rc::new(BigInt::from_signed_bytes_le(&f(&u_n1, &u_n2).to_bytes_le()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn arith_eval_by_metacall(&self) -> Result<Number, Vec<HeapCellValue>>
|
fn arith_eval_by_metacall(&self, r: RegType) -> Result<Number, Vec<HeapCellValue>>
|
||||||
{
|
{
|
||||||
let instantiation_err = functor!(self.atom_tbl.clone(), "instantiation_error", 1,
|
let instantiation_err = functor!(self.atom_tbl.clone(), "instantiation_error", 1,
|
||||||
[heap_atom!("(is)/2", self.atom_tbl.clone())]);
|
[heap_atom!("(is)/2", self.atom_tbl.clone())]);
|
||||||
|
|
||||||
let a = self[temp_v!(2)].clone();
|
let a = self[r].clone();
|
||||||
|
|
||||||
if let &Addr::Con(Constant::Number(ref n)) = &a {
|
if let &Addr::Con(Constant::Number(ref n)) = &a {
|
||||||
return Ok(n.clone());
|
return Ok(n.clone());
|
||||||
@@ -1289,6 +1289,20 @@ impl MachineState {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compare_numbers(&mut self, cmp: CompareNumberQT, n1: Number, n2: Number) {
|
||||||
|
self.fail = match cmp {
|
||||||
|
CompareNumberQT::GreaterThan if !(n1.gt(n2)) => true,
|
||||||
|
CompareNumberQT::GreaterThanOrEqual if !(n1.gte(n2)) => true,
|
||||||
|
CompareNumberQT::LessThan if !(n1.lt(n2)) => true,
|
||||||
|
CompareNumberQT::LessThanOrEqual if !(n1.lte(n2)) => true,
|
||||||
|
CompareNumberQT::NotEqual if !(n1.ne(n2)) => true,
|
||||||
|
CompareNumberQT::Equal if !(n1.eq(n2)) => true,
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
|
||||||
|
self.p += 1;
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn execute_built_in_instr(&mut self, code_dir: &CodeDir, instr: &BuiltInInstruction)
|
pub(super) fn execute_built_in_instr(&mut self, code_dir: &CodeDir, instr: &BuiltInInstruction)
|
||||||
{
|
{
|
||||||
match instr {
|
match instr {
|
||||||
@@ -1296,16 +1310,19 @@ impl MachineState {
|
|||||||
let n1 = try_or_fail!(self, self.get_number(at_1));
|
let n1 = try_or_fail!(self, self.get_number(at_1));
|
||||||
let n2 = try_or_fail!(self, self.get_number(at_2));
|
let n2 = try_or_fail!(self, self.get_number(at_2));
|
||||||
|
|
||||||
self.fail = match cmp {
|
self.compare_numbers(cmp, n1, n2);
|
||||||
CompareNumberQT::GreaterThan if !(n1.gt(n2)) => true,
|
},
|
||||||
CompareNumberQT::GreaterThanOrEqual if !(n1.gte(n2)) => true,
|
&BuiltInInstruction::DynamicCompareNumber(cmp) => {
|
||||||
CompareNumberQT::LessThan if !(n1.lt(n2)) => true,
|
let n1 = try_or_fail!(self, self.arith_eval_by_metacall(temp_v!(1)));
|
||||||
CompareNumberQT::LessThanOrEqual if !(n1.lte(n2)) => true,
|
let n2 = try_or_fail!(self, self.arith_eval_by_metacall(temp_v!(2)));
|
||||||
CompareNumberQT::NotEqual if !(n1.ne(n2)) => true,
|
|
||||||
CompareNumberQT::Equal if !(n1.eq(n2)) => true,
|
|
||||||
_ => false
|
|
||||||
};
|
|
||||||
|
|
||||||
|
self.compare_numbers(cmp, n1, n2);
|
||||||
|
},
|
||||||
|
&BuiltInInstruction::DynamicIs => {
|
||||||
|
let a = self[temp_v!(1)].clone();
|
||||||
|
let result = try_or_fail!(self, self.arith_eval_by_metacall(temp_v!(2)));
|
||||||
|
|
||||||
|
self.unify(a, Addr::Con(Constant::Number(result)));
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
},
|
},
|
||||||
&BuiltInInstruction::GetArg =>
|
&BuiltInInstruction::GetArg =>
|
||||||
@@ -1352,14 +1369,7 @@ impl MachineState {
|
|||||||
self[r] = Addr::Con(c);
|
self[r] = Addr::Con(c);
|
||||||
|
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
},
|
},
|
||||||
&BuiltInInstruction::IsOnHeap => {
|
|
||||||
let a1 = self[temp_v!(1)].clone();
|
|
||||||
let result = try_or_fail!(self, self.arith_eval_by_metacall());
|
|
||||||
|
|
||||||
self.unify(a1, Addr::Con(Constant::Number(result)));
|
|
||||||
self.p += 1;
|
|
||||||
},
|
|
||||||
&BuiltInInstruction::SetBall => {
|
&BuiltInInstruction::SetBall => {
|
||||||
let addr = self[temp_v!(1)].clone();
|
let addr = self[temp_v!(1)].clone();
|
||||||
self.ball.0 = self.heap.h;
|
self.ball.0 = self.heap.h;
|
||||||
|
|||||||
@@ -418,8 +418,50 @@ macro_rules! display {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! is_on_heap {
|
macro_rules! dynamic_is {
|
||||||
() => (
|
() => (
|
||||||
Line::BuiltIn(BuiltInInstruction::IsOnHeap)
|
Line::BuiltIn(BuiltInInstruction::DynamicIs)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! dynamic_num_test {
|
||||||
|
($cmp:expr) => (
|
||||||
|
Line::BuiltIn(BuiltInInstruction::DynamicCompareNumber($cmp))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! cmp_gt {
|
||||||
|
() => (
|
||||||
|
CompareNumberQT::GreaterThan
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! cmp_lt {
|
||||||
|
() => (
|
||||||
|
CompareNumberQT::LessThan
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! cmp_gte {
|
||||||
|
() => (
|
||||||
|
CompareNumberQT::GreaterThanOrEqual
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! cmp_lte {
|
||||||
|
() => (
|
||||||
|
CompareNumberQT::LessThanOrEqual
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! cmp_ne {
|
||||||
|
() => (
|
||||||
|
CompareNumberQT::NotEqual
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! cmp_eq {
|
||||||
|
() => (
|
||||||
|
CompareNumberQT::Equal
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Submodule src/prolog/parser updated: 3b1dd579b4...87d3b043bb
Reference in New Issue
Block a user