From: Mark Thom Date: Sat, 20 Jan 2018 02:39:46 +0000 (-0700) Subject: add call support for numeric comparisons. X-Git-Tag: v0.8.110~613 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=f28b975343ef9a0763d6fdc1aa1ece8f7ebb6bd5;p=scryer-prolog.git add call support for numeric comparisons. --- diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index 1c244325..a9dc647c 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -742,11 +742,12 @@ pub enum BuiltInInstruction { GetBall, GetCurrentBlock, GetCutPoint(RegType), + DynamicCompareNumber(CompareNumberQT), + DynamicIs, InstallNewBlock, InternalCallN, IsAtomic(RegType), - IsInteger(RegType), - IsOnHeap, + IsInteger(RegType), IsVar(RegType), ResetBlock, SetBall, diff --git a/src/prolog/builtins.rs b/src/prolog/builtins.rs index 119a1184..58e37a25 100644 --- a/src/prolog/builtins.rs +++ b/src/prolog/builtins.rs @@ -276,7 +276,19 @@ fn get_builtins(atom_tbl: TabledData) -> Code { goto!(173, 3), // goto arg_/3. display!(), // display/1, 192. 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, 200. + proceed!(), + dynamic_num_test!(cmp_lte!()), // <=/2, 202. + proceed!(), + dynamic_num_test!(cmp_ne!()), // =\=, 204. + proceed!(), + dynamic_num_test!(cmp_eq!()), // =:=, 206. proceed!() ] } @@ -350,7 +362,14 @@ pub fn build_code_dir(atom_tbl: TabledData) -> (Code, CodeDir, OpDir) 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!("display", atom_tbl), 1), (PredicateKeyType::BuiltIn, 192)); + 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) } diff --git a/src/prolog/io.rs b/src/prolog/io.rs index fc1f9eeb..1e56aee4 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -165,6 +165,8 @@ impl fmt::Display for BuiltInInstruction { write!(f, "clean_up_block"), &BuiltInInstruction::CompareNumber(cmp, ref at_1, ref at_2) => write!(f, "number_test {}, {}, {} ", cmp, at_1, at_2), + &BuiltInInstruction::DynamicCompareNumber(cmp) => + write!(f, "dynamic_number_test {}", cmp), &BuiltInInstruction::EraseBall => write!(f, "erase_ball"), &BuiltInInstruction::Fail => @@ -185,8 +187,8 @@ impl fmt::Display for BuiltInInstruction { write!(f, "is_atomic {}", r), &BuiltInInstruction::IsInteger(r) => write!(f, "is_integer {}", r), - &BuiltInInstruction::IsOnHeap => - write!(f, "call_is A1, A2"), + &BuiltInInstruction::DynamicIs => + write!(f, "call_is"), &BuiltInInstruction::IsVar(r) => write!(f, "is_var {}", r), &BuiltInInstruction::ResetBlock => diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 3b286b94..d50a1c00 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -497,12 +497,12 @@ impl MachineState { Rc::new(BigInt::from_signed_bytes_le(&f(&u_n1, &u_n2).to_bytes_le())) } - fn arith_eval_by_metacall(&self) -> Result> + fn arith_eval_by_metacall(&self, r: RegType) -> Result> { let instantiation_err = functor!(self.atom_tbl.clone(), "instantiation_error", 1, [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 { return Ok(n.clone()); @@ -1289,6 +1289,20 @@ impl MachineState { 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) { match instr { @@ -1296,16 +1310,19 @@ impl MachineState { let n1 = try_or_fail!(self, self.get_number(at_1)); let n2 = try_or_fail!(self, self.get_number(at_2)); - 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.compare_numbers(cmp, n1, n2); + }, + &BuiltInInstruction::DynamicCompareNumber(cmp) => { + let n1 = try_or_fail!(self, self.arith_eval_by_metacall(temp_v!(1))); + let n2 = try_or_fail!(self, self.arith_eval_by_metacall(temp_v!(2))); + 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; }, &BuiltInInstruction::GetArg => @@ -1352,14 +1369,7 @@ impl MachineState { self[r] = Addr::Con(c); 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 => { let addr = self[temp_v!(1)].clone(); self.ball.0 = self.heap.h; diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index 94d4cdca..6ad024a5 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -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 ) } diff --git a/src/prolog/parser b/src/prolog/parser index 3b1dd579..87d3b043 160000 --- a/src/prolog/parser +++ b/src/prolog/parser @@ -1 +1 @@ -Subproject commit 3b1dd579b411a440cc4b475471231fb6f9f2ada9 +Subproject commit 87d3b043bb178fb10818cd7cd34dd8c47651621d