add call support for numeric comparisons.

This commit is contained in:
Mark Thom
2018-01-19 19:39:46 -07:00
parent f9b53856ac
commit f28b975343
6 changed files with 101 additions and 27 deletions

View File

@@ -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,

View File

@@ -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)
} }

View File

@@ -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 =>

View File

@@ -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 =>
@@ -1353,13 +1370,6 @@ impl MachineState {
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;

View File

@@ -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
) )
} }