From 9d5f897fed530c1fc7a6cc1be283e166cd57f8cf Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 5 Feb 2018 20:10:41 -0700 Subject: [PATCH] add more type predicates. --- README.md | 5 ++ src/prolog/ast.rs | 21 ++++++-- src/prolog/builtins.rs | 19 ++++++- src/prolog/codegen.rs | 65 ++++++++++++++++++++++++ src/prolog/io.rs | 12 ++++- src/prolog/iterators.rs | 7 ++- src/prolog/machine/machine_state_impl.rs | 40 +++++++++++++++ src/prolog/macros.rs | 31 +++++++++++ src/prolog/parser | 2 +- src/tests.rs | 38 ++++++++++++++ 10 files changed, 232 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3e609d35..1fbeb7ca 100644 --- a/README.md +++ b/README.md @@ -88,19 +88,24 @@ The following predicates are built-in to rusty-wam. * `between/3` * `call/1..63` * `catch/3` +* `compound/1` * `display/1` * `duplicate_term/2` * `false/0` +* `float/1` * `functor/3` * `integer/1` * `length/2` * `maplist/1..8` * `member/2` * `memberchk/2` +* `nonvar/1` * `once/1` +* `rational/1` * `reverse/2` * `select/3` * `setup_call_cleanup/3` +* `string/1` * `throw/1` * `true/0` * `var/1` diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index dc31d649..386c83b5 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -341,8 +341,13 @@ pub enum Term { pub enum InlinedQueryTerm { CompareNumber(CompareNumberQT, Vec>), IsAtomic(Vec>), - IsVar(Vec>), - IsInteger(Vec>) + IsCompound(Vec>), + IsInteger(Vec>), + IsRational(Vec>), + IsString(Vec>), + IsFloat(Vec>), + IsNonVar(Vec>), + IsVar(Vec>), } impl InlinedQueryTerm { @@ -350,6 +355,11 @@ impl InlinedQueryTerm { match self { &InlinedQueryTerm::CompareNumber(_, _) => 2, &InlinedQueryTerm::IsAtomic(_) => 1, + &InlinedQueryTerm::IsCompound(_) => 1, + &InlinedQueryTerm::IsFloat(_) => 1, + &InlinedQueryTerm::IsRational(_) => 1, + &InlinedQueryTerm::IsString(_) => 1, + &InlinedQueryTerm::IsNonVar(_) => 1, &InlinedQueryTerm::IsInteger(_) => 1, &InlinedQueryTerm::IsVar(_) => 1, } @@ -800,7 +810,12 @@ pub enum BuiltInInstruction { InstallNewBlock, InternalCallN, IsAtomic(RegType), - IsInteger(RegType), + IsCompound(RegType), + IsFloat(RegType), + IsInteger(RegType), + IsNonVar(RegType), + IsRational(RegType), + IsString(RegType), IsVar(RegType), ResetBlock, SetBall, diff --git a/src/prolog/builtins.rs b/src/prolog/builtins.rs index c9555b26..5d2c89bd 100644 --- a/src/prolog/builtins.rs +++ b/src/prolog/builtins.rs @@ -524,7 +524,17 @@ fn get_builtins(atom_tbl: TabledData) -> Code { reset_block!(), cut!(perm_v!(1)), deallocate!(), - proceed!() + proceed!(), + is_compound!(temp_v!(1)), // compound/1, 370. + proceed!(), + is_rational!(temp_v!(1)), // rational/1, 372. + proceed!(), + is_string!(temp_v!(1)), // string/1, 374. + proceed!(), + is_float!(temp_v!(1)), // float/1, 376. + proceed!(), + is_nonvar!(temp_v!(1)), // nonvar/1, 378. + proceed!(), ] } @@ -611,6 +621,11 @@ pub fn build_code_dir(atom_tbl: TabledData) -> (Code, CodeDir, OpDir) code_dir.insert((tabled_rc!("length", atom_tbl), 2), (PredicateKeyType::BuiltIn, 261)); code_dir.insert((tabled_rc!("setup_call_cleanup", atom_tbl), 3), (PredicateKeyType::BuiltIn, 294)); - + code_dir.insert((tabled_rc!("compound", atom_tbl), 1), (PredicateKeyType::BuiltIn, 370)); + code_dir.insert((tabled_rc!("rational", atom_tbl), 1), (PredicateKeyType::BuiltIn, 372)); + code_dir.insert((tabled_rc!("string", atom_tbl), 1), (PredicateKeyType::BuiltIn, 374)); + code_dir.insert((tabled_rc!("float", atom_tbl), 1), (PredicateKeyType::BuiltIn, 376)); + code_dir.insert((tabled_rc!("nonvar", atom_tbl), 1), (PredicateKeyType::BuiltIn, 378)); + (builtin_code, code_dir, op_dir) } diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index ac6ce83e..8e5f0c41 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -350,6 +350,71 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> code.push(is_atomic!(r)); } }, + &InlinedQueryTerm::IsCompound(ref inner_term) => + match inner_term[0].as_ref() { + &Term::Clause(..) => { + code.push(succeed!()); + }, + &Term::Var(ref vr, ref name) => { + let r = self.mark_non_callable(name, 1, term_loc, vr, code); + code.push(is_compound!(r)); + }, + _ => { + code.push(fail!()); + } + }, + &InlinedQueryTerm::IsRational(ref inner_term) => + match inner_term[0].as_ref() { + &Term::Constant(_, Constant::Number(Number::Rational(_))) => { + code.push(succeed!()); + }, + &Term::Var(ref vr, ref name) => { + let r = self.mark_non_callable(name, 1, term_loc, vr, code); + code.push(is_rational!(r)); + }, + _ => { + code.push(fail!()); + } + }, + &InlinedQueryTerm::IsFloat(ref inner_term) => + match inner_term[0].as_ref() { + &Term::Constant(_, Constant::Number(Number::Float(_))) => { + code.push(succeed!()); + }, + &Term::Var(ref vr, ref name) => { + let r = self.mark_non_callable(name, 1, term_loc, vr, code); + code.push(is_float!(r)); + }, + _ => { + code.push(fail!()); + } + }, + &InlinedQueryTerm::IsString(ref inner_term) => + match inner_term[0].as_ref() { + &Term::Constant(_, Constant::String(_)) => { + code.push(succeed!()); + }, + &Term::Var(ref vr, ref name) => { + let r = self.mark_non_callable(name, 1, term_loc, vr, code); + code.push(is_string!(r)); + }, + _ => { + code.push(fail!()); + } + }, + &InlinedQueryTerm::IsNonVar(ref inner_term) => + match inner_term[0].as_ref() { + &Term::AnonVar => { + code.push(fail!()); + }, + &Term::Var(ref vr, ref name) => { + let r = self.mark_non_callable(name, 1, term_loc, vr, code); + code.push(is_nonvar!(r)); + }, + _ => { + code.push(succeed!()); + } + }, &InlinedQueryTerm::IsInteger(ref inner_term) => match inner_term[0].as_ref() { &Term::Constant(_, Constant::Number(Number::Integer(_))) => { diff --git a/src/prolog/io.rs b/src/prolog/io.rs index 5d467db6..3119ad2d 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -201,8 +201,18 @@ impl fmt::Display for BuiltInInstruction { write!(f, "internal_call_N"), &BuiltInInstruction::IsAtomic(r) => write!(f, "is_atomic {}", r), + &BuiltInInstruction::IsCompound(r) => + write!(f, "is_compound {}", r), + &BuiltInInstruction::IsFloat(r) => + write!(f, "is_float {}", r), + &BuiltInInstruction::IsRational(r) => + write!(f, "is_rational {}", r), + &BuiltInInstruction::IsNonVar(r) => + write!(f, "is_non_var {}", r), + &BuiltInInstruction::IsString(r) => + write!(f, "is_string {}", r), &BuiltInInstruction::IsInteger(r) => - write!(f, "is_integer {}", r), + write!(f, "is_integer {}", r), &BuiltInInstruction::DynamicIs => write!(f, "call_is"), &BuiltInInstruction::IsVar(r) => diff --git a/src/prolog/iterators.rs b/src/prolog/iterators.rs index 80146fc1..ab63e2dd 100644 --- a/src/prolog/iterators.rs +++ b/src/prolog/iterators.rs @@ -67,7 +67,12 @@ impl<'a> QueryIterator<'a> { }, &QueryTerm::Inlined(InlinedQueryTerm::IsAtomic(ref terms)) | &QueryTerm::Inlined(InlinedQueryTerm::IsInteger(ref terms)) - | &QueryTerm::Inlined(InlinedQueryTerm::IsVar(ref terms)) => + | &QueryTerm::Inlined(InlinedQueryTerm::IsVar(ref terms)) + | &QueryTerm::Inlined(InlinedQueryTerm::IsNonVar(ref terms)) + | &QueryTerm::Inlined(InlinedQueryTerm::IsFloat(ref terms)) + | &QueryTerm::Inlined(InlinedQueryTerm::IsRational(ref terms)) + | &QueryTerm::Inlined(InlinedQueryTerm::IsCompound(ref terms)) + | &QueryTerm::Inlined(InlinedQueryTerm::IsString(ref terms)) => Self::from_term(terms[0].as_ref()), &QueryTerm::Term(ref term) => Self::from_term(term), diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 9ff12250..57c1f094 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -1283,6 +1283,46 @@ impl MachineState { _ => self.fail = true }; }, + &BuiltInInstruction::IsCompound(r) => { + let d = self.store(self.deref(self[r].clone())); + + match d { + Addr::Str(_) => self.p += 1, + _ => self.fail = true + }; + }, + &BuiltInInstruction::IsFloat(r) => { + let d = self.store(self.deref(self[r].clone())); + + match d { + Addr::Con(Constant::Number(Number::Float(_))) => self.p += 1, + _ => self.fail = true + }; + }, + &BuiltInInstruction::IsRational(r) => { + let d = self.store(self.deref(self[r].clone())); + + match d { + Addr::Con(Constant::Number(Number::Rational(_))) => self.p += 1, + _ => self.fail = true + }; + }, + &BuiltInInstruction::IsString(r) => { + let d = self.store(self.deref(self[r].clone())); + + match d { + Addr::Con(Constant::String(_)) => self.p += 1, + _ => self.fail = true + }; + }, + &BuiltInInstruction::IsNonVar(r) => { + let d = self.store(self.deref(self[r].clone())); + + match d { + Addr::HeapCell(_) | Addr::StackCell(..) => self.fail = true, + _ => self.p += 1 + }; + }, &BuiltInInstruction::IsVar(r) => { let d = self.store(self.deref(self[r].clone())); diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index 2195a245..2220a669 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -168,6 +168,37 @@ macro_rules! is_integer { ) } +macro_rules! is_compound { + ($r:expr) => ( + Line::BuiltIn(BuiltInInstruction::IsCompound($r)) + ) +} + +macro_rules! is_float { + ($r:expr) => ( + Line::BuiltIn(BuiltInInstruction::IsFloat($r)) + ) +} + +macro_rules! is_rational { + ($r:expr) => ( + Line::BuiltIn(BuiltInInstruction::IsRational($r)) + ) +} + + +macro_rules! is_nonvar { + ($r:expr) => ( + Line::BuiltIn(BuiltInInstruction::IsNonVar($r)) + ) +} + +macro_rules! is_string { + ($r:expr) => ( + Line::BuiltIn(BuiltInInstruction::IsString($r)) + ) +} + macro_rules! is_var { ($reg:expr) => ( Line::BuiltIn(BuiltInInstruction::IsVar($reg)) diff --git a/src/prolog/parser b/src/prolog/parser index 87d0d493..7687a367 160000 --- a/src/prolog/parser +++ b/src/prolog/parser @@ -1 +1 @@ -Subproject commit 87d0d493e69e5cde80f454d21f8caa33cbffca3e +Subproject commit 7687a367636a79972788b2633de8fbba7778eb10 diff --git a/src/tests.rs b/src/tests.rs index bf0df94b..64c7573f 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1290,6 +1290,44 @@ fn test_queries_on_builtins() assert_prolog_failure!(&mut wam, "?- duplicate_term(g(X), f(X))."); assert_prolog_success!(&mut wam, "?- duplicate_term(f(X), f(X)).", [["X = _1"]]); + + assert_prolog_success!(&mut wam, "?- float(3.14159269)."); + assert_prolog_failure!(&mut wam, "?- float(3)."); + assert_prolog_failure!(&mut wam, "?- float(\"sdfsa\")."); + assert_prolog_failure!(&mut wam, "?- float(atom)."); + assert_prolog_failure!(&mut wam, "?- float(structure(functor))."); + assert_prolog_failure!(&mut wam, "?- float([1,2,3])."); + assert_prolog_failure!(&mut wam, "?- X is 3 rdiv 4, float(X)."); + + assert_prolog_success!(&mut wam, "?- X is 3 rdiv 4, rational(X)."); + assert_prolog_failure!(&mut wam, "?- rational(3)."); + assert_prolog_failure!(&mut wam, "?- rational(\"sdfsa\")."); + assert_prolog_failure!(&mut wam, "?- rational(atom)."); + assert_prolog_failure!(&mut wam, "?- rational(structure(functor))."); + assert_prolog_failure!(&mut wam, "?- rational([1,2,3])."); + + assert_prolog_success!(&mut wam, "?- compound(functor(compound))."); + assert_prolog_failure!(&mut wam, "?- compound(3.14159269)."); + assert_prolog_failure!(&mut wam, "?- compound(3)."); + assert_prolog_failure!(&mut wam, "?- compound(\"sdfsa\")."); + assert_prolog_failure!(&mut wam, "?- compound(atom)."); + assert_prolog_failure!(&mut wam, "?- compound([1,2,3])."); + + assert_prolog_failure!(&mut wam, "?- string(functor(string))."); + assert_prolog_failure!(&mut wam, "?- string(3.14159269)."); + assert_prolog_failure!(&mut wam, "?- string(3)."); + assert_prolog_success!(&mut wam, "?- string(\"sdfsa\")."); + assert_prolog_failure!(&mut wam, "?- string(atom)."); + assert_prolog_failure!(&mut wam, "?- string([1,2,3])."); + + assert_prolog_success!(&mut wam, "?- X = nonvar, nonvar(X)."); + assert_prolog_failure!(&mut wam, "?- nonvar(X)."); + assert_prolog_success!(&mut wam, "?- nonvar(functor(nonvar))."); + assert_prolog_success!(&mut wam, "?- nonvar(3.14159269)."); + assert_prolog_success!(&mut wam, "?- nonvar(3)."); + assert_prolog_success!(&mut wam, "?- nonvar(\"sdfsa\")."); + assert_prolog_success!(&mut wam, "?- nonvar(atom)."); + assert_prolog_success!(&mut wam, "?- nonvar([1,2,3])."); } #[test] -- 2.54.0