From: Mark Thom Date: Tue, 9 Jan 2018 04:14:19 +0000 (-0700) Subject: add provisional functor and arg support, and give ';' and '->' their true semantics X-Git-Tag: v0.8.110~641 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=d49157bef656f4a51aeef7895e720d9825a79200;p=scryer-prolog.git add provisional functor and arg support, and give ';' and '->' their true semantics --- diff --git a/Cargo.lock b/Cargo.lock index 56e97a19..e6566fff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,20 +1,20 @@ [root] name = "rusty-wam" -version = "0.7.4" +version = "0.7.5" dependencies = [ - "lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aho-corasick" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -40,52 +40,57 @@ dependencies = [ [[package]] name = "lazy_static" -version = "0.2.10" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "1.0.2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", "num-rational 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-bigint" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-complex" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -94,7 +99,7 @@ name = "num-integer" version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -103,7 +108,7 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -111,15 +116,15 @@ name = "num-rational" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -127,7 +132,7 @@ name = "ordered-float" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -137,12 +142,12 @@ version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -150,18 +155,18 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -180,17 +185,17 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "thread_local" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -221,29 +226,30 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" +"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159" "checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82" -"checksum lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "236eb37a62591d4a41a89b7763d7de3e06ca02d5ab2815446a8bae5d2f8c2d57" -"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" -"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" -"checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525" -"checksum num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "8fd0f8dbb4c0960998958a796281d88c16fbe68d87b1baa6f31e2979e81fd0bd" -"checksum num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "503e668405c5492d67cf662a81e05be40efe2e6bcf10f7794a07bd9865e704e6" +"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" +"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0" +"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4083e14b542ea3eb9b5f33ff48bd373a92d78687e74f4cc0a30caeb754f0ca" +"checksum num-bigint 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "bdc1494b5912f088f260b775799468d9b9209ac60885d8186a547a0476289e23" +"checksum num-complex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "58de7b4bf7cf5dbecb635a5797d489864eadd03b107930cbccf9e0fd7428b47c" "checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba" "checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01" "checksum num-rational 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "0c7cb72a95250d8a370105c828f388932373e0e94414919891a0f945222310fe" -"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" +"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" "checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f" "checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd" -"checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" +"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" +"checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" +"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" diff --git a/Cargo.toml b/Cargo.toml index 7d3168db..08e048a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rusty-wam" -version = "0.7.4" +version = "0.7.5" authors = ["Mark Thom"] [dependencies] diff --git a/README.md b/README.md index 3e972087..b43ed20a 100644 --- a/README.md +++ b/README.md @@ -76,13 +76,14 @@ The following predicates are built-in to rusty-wam. * `is/2` works for `(+)/2`, `(-)/{1,2}`, `(*)/2`, `(//)/2`, `(div)/2`, `(/)/2`, `(rdiv)/2`, `(xor)/2`, `(rem)/2`, `(mod)/2`, `(/\)/2`, `(\/)/2`, `(>>)/2`, `(<<)/2`. * Comparison operators: `>`, `<`, `=<`, `>=`, `=:=`, `=\=`. +* `(\+)/1` +* `(=)/2` * `atomic/1` * `call/N` (1 <= N <= 63) * `catch/3` * `duplicate_term/2` * `false/0` -* `(\+)/1` -* `(=)/2` +* `integer/1` * `throw/1` * `true/0` * `var/1` diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index 12d8bf95..2a570a1d 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -324,6 +324,7 @@ pub enum InlinedQueryTerm { CompareNumber(CompareNumberQT, Vec>), IsAtomic(Vec>), IsVar(Vec>), + IsInteger(Vec>) } impl InlinedQueryTerm { @@ -331,6 +332,7 @@ impl InlinedQueryTerm { match self { &InlinedQueryTerm::CompareNumber(_, _) => 2, &InlinedQueryTerm::IsAtomic(_) => 1, + &InlinedQueryTerm::IsInteger(_) => 1, &InlinedQueryTerm::IsVar(_) => 1, } } @@ -347,9 +349,11 @@ pub enum CompareNumberQT { } pub enum QueryTerm { + Arg(Vec>), CallN(Vec>), Catch(Vec>), Cut, + Functor(Vec>), Inlined(InlinedQueryTerm), Is(Vec>), Term(Term), @@ -359,8 +363,10 @@ pub enum QueryTerm { impl QueryTerm { pub fn arity(&self) -> usize { match self { + &QueryTerm::Arg(_) => 3, &QueryTerm::Catch(_) => 3, &QueryTerm::Throw(_) => 1, + &QueryTerm::Functor(_) => 3, &QueryTerm::Inlined(ref term) => term.arity(), &QueryTerm::Is(_) => 2, &QueryTerm::CallN(ref terms) => terms.len(), @@ -715,12 +721,14 @@ pub enum BuiltInInstruction { DuplicateTerm, EraseBall, Fail, + GetArg, GetBall, GetCurrentBlock, GetCutPoint(RegType), InstallNewBlock, InternalCallN, IsAtomic(RegType), + IsInteger(RegType), IsVar(RegType), ResetBlock, SetBall, @@ -732,6 +740,8 @@ pub enum BuiltInInstruction { pub enum ControlInstruction { Allocate(usize), // num_frames. + ArgCall, + ArgExecute, Call(Atom, usize, usize), // name, arity, perm_vars after threshold. CallN(usize), // arity. CatchCall, @@ -739,6 +749,8 @@ pub enum ControlInstruction { Deallocate, Execute(Atom, usize), ExecuteN(usize), + FunctorCall, + FunctorExecute, Goto(usize, usize), // p, arity. IsCall(RegType, ArithmeticTerm), IsExecute(RegType, ArithmeticTerm), @@ -750,12 +762,16 @@ pub enum ControlInstruction { impl ControlInstruction { pub fn is_jump_instr(&self) -> bool { match self { + &ControlInstruction::ArgCall => true, + &ControlInstruction::ArgExecute => true, &ControlInstruction::Call(_, _, _) => true, &ControlInstruction::CatchCall => true, &ControlInstruction::CatchExecute => true, &ControlInstruction::Execute(_, _) => true, &ControlInstruction::CallN(_) => true, &ControlInstruction::ExecuteN(_) => true, + &ControlInstruction::FunctorCall => true, + &ControlInstruction::FunctorExecute => true, &ControlInstruction::ThrowCall => true, &ControlInstruction::ThrowExecute => true, &ControlInstruction::Goto(_, _) => true, diff --git a/src/prolog/builtins.rs b/src/prolog/builtins.rs index 2b99e3f8..34fa430e 100644 --- a/src/prolog/builtins.rs +++ b/src/prolog/builtins.rs @@ -1,4 +1,5 @@ use prolog::ast::*; +use prolog::num::bigint::{BigInt}; use std::collections::HashMap; @@ -105,14 +106,8 @@ fn get_builtins() -> Code { fact![get_value!(temp_v!(1), 2)], // =/2, 73. proceed!(), proceed!(), // true/0, 75. - try_me_else!(2), // ';'/2, 76. - execute_n!(1), - trust_me!(), - query![put_value!(temp_v!(2), 1)], - execute_n!(1), - get_cp!(temp_v!(3)), // ','/2, 81 - goto!(83, 3), - try_me_else!(18), // ','/3, 83. + get_cp!(temp_v!(3)), // ','/2, 76 + try_me_else!(18), // ','/3, 77. switch_on_term!(4, 1, 0, 0), indexed_try!(4), retry!(7), @@ -165,14 +160,116 @@ fn get_builtins() -> Code { query![put_value!(perm_v!(1), 1)], deallocate!(), execute_n!(1), - allocate!(2), // (->)/2, 126. - get_level!(), - fact![get_var_in_fact!(perm_v!(2), 2)], + get_cp!(temp_v!(3)), // ';'/2, 120. + try_me_else!(12), + switch_on_term!(4, 0, 0, 1), + indexed_try!(3), + trust!(5), + try_me_else!(3), + fact![get_structure!(String::from("->"), 2, temp_v!(1)), + unify_variable!(temp_v!(1)), + unify_variable!(temp_v!(2))], + goto!(139, 3), + trust_me!(), + fact![get_structure!(String::from("->"), 2, temp_v!(1)), + unify_void!(2)], + query![put_value!(temp_v!(2), 1)], + neck_cut!(), + execute_n!(1), + retry_me_else!(2), + execute_n!(1), + trust_me!(), + query![put_value!(temp_v!(2), 1)], + execute_n!(1), + get_cp!(temp_v!(3)), // '->'/2, 138. + allocate!(2), // '->'/3, 139. + fact![get_var_in_fact!(perm_v!(1), 2), + get_var_in_fact!(perm_v!(2), 3)], // cut point. call_n!(1), - cut!(), - query![put_value!(perm_v!(2), 1)], + set_cp!(perm_v!(2)), + query![put_unsafe_value!(1, 1)], deallocate!(), - execute_n!(1) + execute_n!(1), + functor_execute!(), // functor/3, 146. + is_integer!(temp_v!(1)), // integer/1, 147. + proceed!(), + get_arg!(), // get_arg/3, 149. + try_me_else!(10), // arg/3, 150. + allocate!(4), + fact![get_var_in_fact!(perm_v!(1), 1), + get_var_in_fact!(perm_v!(2), 2), + get_var_in_fact!(perm_v!(4), 3)], + is_var!(perm_v!(1)), + neck_cut!(), + query![put_value!(perm_v!(2), 1), + put_var!(temp_v!(4), 2), + put_var!(perm_v!(3), 3)], + functor_call!(), + query![put_value!(perm_v!(1), 1), + put_constant!(Level::Shallow, integer!(1), temp_v!(2)), + put_unsafe_value!(3, 3), + put_value!(perm_v!(2), 4), + put_value!(perm_v!(4), 5)], + deallocate!(), + goto!(173, 5), // goto arg_/3. + retry_me_else!(10), + allocate!(3), + fact![get_var_in_fact!(perm_v!(1), 1), + get_var_in_fact!(perm_v!(2), 2), + get_var_in_fact!(perm_v!(3), 3)], + is_integer!(perm_v!(1)), + neck_cut!(), + query![put_value!(perm_v!(2), 1), + put_var!(temp_v!(4), 2), + put_var!(temp_v!(3), 3)], + functor_call!(), + query![put_value!(perm_v!(1), 1), + put_value!(perm_v!(2), 2), + put_value!(perm_v!(3), 3)], + deallocate!(), + goto!(149, 3), // goto get_arg/3. + trust_me!(), + query![get_var_in_query!(temp_v!(4), 1), + put_structure!(Level::Shallow, + String::from("type_error"), + 1, + temp_v!(1)), + set_constant!(Constant::Atom(String::from("integer_expected")))], + goto!(59, 1), // goto throw/1. + try_me_else!(5), // arg_/3, 173. + fact![get_value!(temp_v!(1), 2), + get_value!(temp_v!(1), 3)], + neck_cut!(), + query![put_value!(temp_v!(4), 2), + put_value!(temp_v!(5), 3)], + goto!(149, 3), // goto get_arg/3. + retry_me_else!(4), + fact![get_value!(temp_v!(1), 2)], + query![put_value!(temp_v!(4), 2), + get_var_in_query!(temp_v!(6), 3), + put_value!(temp_v!(5), 3)], + goto!(149, 3), // goto get_arg/3 + trust_me!(), + allocate!(5), + fact![get_var_in_fact!(perm_v!(2), 1), + get_var_in_fact!(perm_v!(4), 3), + get_var_in_fact!(perm_v!(3), 4), + get_var_in_fact!(perm_v!(5), 5)], + compare_number_instr!(CompareNumberQT::LessThan, + ArithmeticTerm::Reg(temp_v!(2)), + ArithmeticTerm::Reg(perm_v!(4))), + add!(ArithmeticTerm::Reg(temp_v!(2)), + ArithmeticTerm::Integer(BigInt::from(1)), + 1), + query![put_var!(perm_v!(1), 1)], + is_call!(perm_v!(1), interm!(1)), + query![put_value!(perm_v!(2), 1), + put_unsafe_value!(1, 2), + put_value!(perm_v!(4), 3), + put_value!(perm_v!(3), 4), + put_value!(perm_v!(5), 5)], + deallocate!(), + goto!(173, 3) // goto arg_/3. ] } @@ -237,9 +334,13 @@ pub fn build_code_dir() -> (Code, CodeDir, OpDir) code_dir.insert((String::from("="), 2), (PredicateKeyType::BuiltIn, 73)); code_dir.insert((String::from("true"), 0), (PredicateKeyType::BuiltIn, 75)); - code_dir.insert((String::from(";"), 2), (PredicateKeyType::BuiltIn, 76)); - code_dir.insert((String::from(","), 2), (PredicateKeyType::BuiltIn, 81)); - code_dir.insert((String::from("->"), 2), (PredicateKeyType::BuiltIn, 126)); + code_dir.insert((String::from(","), 2), (PredicateKeyType::BuiltIn, 76)); + code_dir.insert((String::from(";"), 2), (PredicateKeyType::BuiltIn, 120)); + code_dir.insert((String::from("->"), 2), (PredicateKeyType::BuiltIn, 138)); + + code_dir.insert((String::from("functor"), 3), (PredicateKeyType::BuiltIn, 146)); + code_dir.insert((String::from("arg"), 3), (PredicateKeyType::BuiltIn, 150)); + code_dir.insert((String::from("integer"), 1), (PredicateKeyType::BuiltIn, 147)); (builtin_code, code_dir, op_dir) } diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index 1a8bc30b..d3eeab24 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -236,12 +236,18 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize) { match qt { + &QueryTerm::Arg(_) => { + let call = ControlInstruction::ArgCall; + code.push(Line::Control(call)); + }, &QueryTerm::CallN(ref terms) => { let call = ControlInstruction::CallN(terms.len()); code.push(Line::Control(call)); }, &QueryTerm::Catch(_) => code.push(Line::Control(ControlInstruction::CatchCall)), + &QueryTerm::Functor(_) => + code.push(Line::Control(ControlInstruction::FunctorCall)), &QueryTerm::Inlined(_) => code.push(proceed!()), &QueryTerm::Term(Term::Constant(_, Constant::Atom(ref atom))) => { @@ -268,10 +274,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> swap(ctrl, &mut instr); match instr { + ControlInstruction::ArgCall => + *ctrl = ControlInstruction::ArgExecute, ControlInstruction::Call(name, arity, _) => *ctrl = ControlInstruction::Execute(name, arity), ControlInstruction::CallN(arity) => *ctrl = ControlInstruction::ExecuteN(arity), + ControlInstruction::FunctorCall => + *ctrl = ControlInstruction::FunctorExecute, ControlInstruction::CatchCall => *ctrl = ControlInstruction::CatchExecute, ControlInstruction::ThrowCall => @@ -304,7 +314,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> code.push(compare_number_instr!(cmp, at_1.unwrap_or(interm!(1)), at_2.unwrap_or(interm!(2)))); - }, + }, &InlinedQueryTerm::IsAtomic(ref inner_term) => match inner_term[0].as_ref() { &Term::AnonVar | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => { @@ -318,6 +328,19 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> code.push(is_atomic!(r)); } }, + &InlinedQueryTerm::IsInteger(ref inner_term) => + match inner_term[0].as_ref() { + &Term::Constant(_, Constant::Integer(_)) => { + code.push(succeed!()); + }, + &Term::Var(ref vr, ref name) => { + let r = self.mark_non_callable(name, 1, term_loc, vr, code); + code.push(is_integer!(r)); + }, + _ => { + code.push(fail!()); + }, + }, &InlinedQueryTerm::IsVar(ref inner_term) => match inner_term[0].as_ref() { &Term::Constant(_, _) | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => { @@ -330,7 +353,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> let r = self.mark_non_callable(name, 1, term_loc, vr, code); code.push(is_var!(r)); } - } + } } Ok(()) diff --git a/src/prolog/heapview.rs b/src/prolog/heapview.rs index c11103db..52ed0747 100644 --- a/src/prolog/heapview.rs +++ b/src/prolog/heapview.rs @@ -51,8 +51,26 @@ pub struct HeapCellViewer<'a> { state_stack: Vec> } -impl<'a> HeapCellViewer<'a> { - fn cell_ref_from_addr(&self, mut focus: &'a Addr) -> CellRef<'a> { +impl<'a> HeapCellViewer<'a> +{ + pub fn new(heap: &'a Heap, and_stack: &'a AndStack, addr: &'a Addr) -> Self + { + let mut viewer = HeapCellViewer { + heap: heap, + and_stack: and_stack, + state_stack: vec![] + }; + + let cell_ref = viewer.deref_cell(addr); + let view = viewer.follow(cell_ref); + + viewer.state_stack.push(CellRef::View(view)); + + viewer + } + + fn deref_cell(&self, mut focus: &'a Addr) -> CellRef<'a> + { loop { match focus { &Addr::Con(ref c) => @@ -75,22 +93,6 @@ impl<'a> HeapCellViewer<'a> { } } - pub fn new(heap: &'a Heap, and_stack: &'a AndStack, addr: &'a Addr) -> Self - { - let mut viewer = HeapCellViewer { - heap: heap, - and_stack: and_stack, - state_stack: vec![] - }; - - let cell_ref = viewer.cell_ref_from_addr(addr); - let view = viewer.follow(cell_ref); - - viewer.state_stack.push(CellRef::View(view)); - - viewer - } - pub fn remove_token(&mut self, loc: usize) { self.state_stack[loc] = CellRef::TToken(TToken::Nothing); } @@ -143,21 +145,19 @@ impl<'a> HeapCellViewer<'a> { return CellView::Str(arity, name); }, - &HeapCellValue::Ref(Ref::HeapCell(hc)) => { + &HeapCellValue::Ref(Ref::HeapCell(hc)) => if focus == hc { return CellView::HeapVar(hc); } else { focus = hc; - } - }, - &HeapCellValue::Ref(Ref::StackCell(fr, sc)) => { - match self.cell_ref_from_addr(&self.and_stack[fr][sc]) { + }, + &HeapCellValue::Ref(Ref::StackCell(fr, sc)) => + match self.deref_cell(&self.and_stack[fr][sc]) { CellRef::Lis(hc) => return self.handle_list(hc), CellRef::View(cell_view) => return cell_view, CellRef::Redirect(hc) => focus = hc, CellRef::TToken(token) => return CellView::TToken(token) - }; - }, + }, &HeapCellValue::Str(cell_num) => focus = cell_num, } @@ -179,7 +179,6 @@ impl<'a> HeapCellViewer<'a> { } } - impl<'a> Iterator for HeapCellViewer<'a> { type Item = CellView<'a>; diff --git a/src/prolog/io.rs b/src/prolog/io.rs index 3774520f..e1a6915c 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -98,6 +98,10 @@ impl fmt::Display for ControlInstruction { match self { &ControlInstruction::Allocate(num_cells) => write!(f, "allocate {}", num_cells), + &ControlInstruction::ArgCall => + write!(f, "arg_call"), + &ControlInstruction::ArgExecute => + write!(f, "arg_execute"), &ControlInstruction::Call(ref name, arity, pvs) => write!(f, "call {}/{}, {}", name, arity, pvs), &ControlInstruction::CallN(arity) => @@ -108,6 +112,10 @@ impl fmt::Display for ControlInstruction { write!(f, "execute_catch"), &ControlInstruction::ExecuteN(arity) => write!(f, "execute_N {}", arity), + &ControlInstruction::FunctorCall => + write!(f, "functor_call"), + &ControlInstruction::FunctorExecute => + write!(f, "functor_execute"), &ControlInstruction::Deallocate => write!(f, "deallocate"), &ControlInstruction::Execute(ref name, arity) => @@ -154,6 +162,8 @@ impl fmt::Display for BuiltInInstruction { write!(f, "erase_ball"), &BuiltInInstruction::Fail => write!(f, "false"), + &BuiltInInstruction::GetArg => + write!(f, "get_arg X1, X2, X3"), &BuiltInInstruction::GetBall => write!(f, "get_ball X1"), &BuiltInInstruction::GetCurrentBlock => @@ -166,6 +176,8 @@ impl fmt::Display for BuiltInInstruction { write!(f, "internal_call_N"), &BuiltInInstruction::IsAtomic(r) => write!(f, "is_atomic {}", r), + &BuiltInInstruction::IsInteger(r) => + write!(f, "is_integer {}", r), &BuiltInInstruction::IsVar(r) => write!(f, "is_var {}", r), &BuiltInInstruction::ResetBlock => @@ -386,7 +398,7 @@ pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<' Ok(rule) => rule, Err(e) => return EvalSession::ParserError(e) }; - + wam.add_rule(rule, compiled_rule) }, &TopLevel::Query(ref query) => { diff --git a/src/prolog/iterators.rs b/src/prolog/iterators.rs index 62002207..e5cf2d35 100644 --- a/src/prolog/iterators.rs +++ b/src/prolog/iterators.rs @@ -40,12 +40,18 @@ impl<'a> QueryIterator<'a> { let state = IteratorState::Clause(0, ClauseType::Catch, terms); QueryIterator { state_stack: vec![state] } }, + &QueryTerm::Arg(ref terms) + | &QueryTerm::Functor(ref terms) => { + let state = IteratorState::Clause(0, ClauseType::Root, terms); + QueryIterator { state_stack: vec![state] } + }, &QueryTerm::Inlined(InlinedQueryTerm::CompareNumber(_, ref terms)) | &QueryTerm::Is(ref terms) => { - let state = IteratorState::Clause(0, ClauseType::Is, terms); - QueryIterator { state_stack: vec![state] } - }, + let state = IteratorState::Clause(0, ClauseType::Is, terms); + QueryIterator { state_stack: vec![state] } + }, &QueryTerm::Inlined(InlinedQueryTerm::IsAtomic(ref terms)) + | &QueryTerm::Inlined(InlinedQueryTerm::IsInteger(ref terms)) | &QueryTerm::Inlined(InlinedQueryTerm::IsVar(ref terms)) => Self::from_term(terms[0].as_ref()), &QueryTerm::Term(ref term) => @@ -271,6 +277,12 @@ impl<'a> ChunkedIterator<'a> arity = child_terms.len(); break; }, + &QueryTerm::Arg(_) + | &QueryTerm::Functor(_) => { + result.push(term); + arity = 3; + break; + }, &QueryTerm::Is(_) => { result.push(term); arity = 2; diff --git a/src/prolog/machine.rs b/src/prolog/machine.rs index 014d2078..35a36276 100644 --- a/src/prolog/machine.rs +++ b/src/prolog/machine.rs @@ -1498,7 +1498,8 @@ impl MachineState { self.p = CodePtr::DirEntry(59); } - fn throw_exception(&mut self, hcv: Vec) { + fn throw_exception + (&mut self, hcv: Vec) { let h = self.heap.h; self.registers[1] = Addr::HeapCell(h); @@ -1569,6 +1570,35 @@ impl MachineState { } } + fn try_get_arg(&mut self) -> Result<(), Vec> + { + let a1 = self.store(self.deref(self[temp_v!(1)].clone())); + + if let Addr::Con(Constant::Integer(i)) = a1 { + let a2 = self.store(self.deref(self[temp_v!(2)].clone())); + + if let Addr::Str(o) = a2 { + match self.heap[o].clone() { + HeapCellValue::NamedStr(arity, _) => + match i.to_usize() { + Some(i) if 1 <= i && i <= arity => { + let a3 = self[temp_v!(3)].clone(); + let h_a = Addr::HeapCell(o + i); + + self.unify(a3, h_a); + }, + _ => self.fail = true + }, + _ => self.fail = true + }; + } else { + return Err(functor!("type_error", 1, [atom!("compound_expected")])); + } + } + + Ok(()) + } + fn execute_built_in_instr(&mut self, code_dir: &CodeDir, instr: &BuiltInInstruction) { match instr { @@ -1605,6 +1635,12 @@ impl MachineState { self.p += 1; }, + &BuiltInInstruction::GetArg => + try_or_fail!(self, { + let val = self.try_get_arg(); + self.p = self.cp; + val + }), &BuiltInInstruction::GetCurrentBlock => { let c = Constant::Usize(self.block); let addr = self[temp_v!(1)].clone(); @@ -1720,6 +1756,14 @@ impl MachineState { _ => self.fail = true }; }, + &BuiltInInstruction::IsInteger(r) => { + let d = self.store(self.deref(self[r].clone())); + + match d { + Addr::Con(Constant::Integer(_)) => self.p += 1, + _ => self.fail = true + }; + }, &BuiltInInstruction::IsVar(r) => { let d = self.store(self.deref(self[r].clone())); @@ -1747,6 +1791,70 @@ impl MachineState { }; } + fn try_functor(&mut self) -> Result<(), Vec> { + let a1 = self.store(self.deref(self[temp_v!(1)].clone())); + + match a1.clone() { + Addr::Str(o) => + match self.heap[o].clone() { + HeapCellValue::NamedStr(arity, name) => { + let name = Addr::Con(Constant::Atom(name)); // A2 + let arity = Addr::Con(Constant::Integer(BigInt::from(arity))); // A3 + + let a2 = self[temp_v!(2)].clone(); + self.unify(a2, name); + + if !self.fail { + let a3 = self[temp_v!(3)].clone(); + self.unify(a3, arity); + } + }, + _ => self.fail = true + }, + Addr::HeapCell(_) | Addr::StackCell(_, _) => { + let name = self.store(self.deref(self[temp_v!(2)].clone())); + let arity = self.store(self.deref(self[temp_v!(3)].clone())); + + if let Addr::Con(Constant::Atom(name)) = name { + if let Addr::Con(Constant::Integer(arity)) = arity { + let f_a = Addr::Str(self.heap.h); + let arity = match arity.to_usize() { + Some(arity) => arity, + None => { + self.fail = true; + return Ok(()); + } + }; + + self.heap.push(HeapCellValue::NamedStr(arity, name)); + + for _ in 0 .. arity { + let h = self.heap.h; + self.heap.push(HeapCellValue::Ref(Ref::HeapCell(h))); + } + + self.unify(a1, f_a); + } else { + return Err(functor!("instantiation_error", 0, [])); + } + } else { + return Err(functor!("instantiation_error", 0, [])); + } + }, + _ => { + let a2 = self[temp_v!(2)].clone(); + self.unify(a1, a2); + + if !self.fail { + let a3 = self[temp_v!(3)].clone(); + self.unify(a3, Addr::Con(Constant::Integer(BigInt::from(0)))); + } + } + }; + + Ok(()) + } + fn execute_ctrl_instr(&mut self, code_dir: &CodeDir, instr: &ControlInstruction) { match instr { @@ -1779,6 +1887,17 @@ impl MachineState { self.and_stack.push(gi, self.e, self.cp, num_cells); self.e = self.and_stack.len() - 1; }, + &ControlInstruction::ArgCall => { + self.cp = self.p + 1; + self.num_of_args = 3; + self.b0 = self.b; + self.p = CodePtr::DirEntry(150); + }, + &ControlInstruction::ArgExecute => { + self.num_of_args = 3; + self.b0 = self.b; + self.p = CodePtr::DirEntry(150); + }, &ControlInstruction::Call(ref name, arity, _) => self.try_call_predicate(code_dir, name.clone(), arity), &ControlInstruction::CatchCall => { @@ -1810,6 +1929,18 @@ impl MachineState { if let Some((name, arity)) = self.setup_call_n(arity) { self.try_execute_predicate(code_dir, name, arity); }, + &ControlInstruction::FunctorCall => + try_or_fail!(self, { + let val = self.try_functor(); + self.p += 1; + val + }), + &ControlInstruction::FunctorExecute => + try_or_fail!(self, { + let val = self.try_functor(); + self.p = self.cp; + val + }), &ControlInstruction::Goto(p, arity) => { self.num_of_args = arity; self.b0 = self.b; diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index 4474dd62..0cad85cc 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -1,3 +1,4 @@ + macro_rules! internal_call_n { () => ( Line::BuiltIn(BuiltInInstruction::InternalCallN) @@ -99,12 +100,24 @@ macro_rules! put_var { ) } +macro_rules! put_structure { + ($lvl:expr, $name:expr, $arity:expr, $r:expr) => ( + QueryInstruction::PutStructure($lvl, $name, $arity, $r) + ) +} + macro_rules! put_constant { ($lvl:expr, $cons:expr, $r:expr) => ( QueryInstruction::PutConstant($lvl, $cons, $r) ) } +macro_rules! set_constant { + ($cons:expr) => ( + QueryInstruction::SetConstant($cons) + ) +} + macro_rules! put_value { ($r:expr, $arg:expr) => ( QueryInstruction::PutValue($r, $arg) @@ -135,6 +148,12 @@ macro_rules! is_atomic { ) } +macro_rules! is_integer { + ($reg:expr) => ( + Line::BuiltIn(BuiltInInstruction::IsInteger($reg)) + ) +} + macro_rules! is_var { ($reg:expr) => ( Line::BuiltIn(BuiltInInstruction::IsVar($reg)) @@ -303,12 +322,30 @@ macro_rules! get_structure { ) } +macro_rules! functor_call { + () => ( + Line::Control(ControlInstruction::FunctorCall) + ) +} + +macro_rules! functor_execute { + () => ( + Line::Control(ControlInstruction::FunctorExecute) + ) +} + macro_rules! unify_variable { ($r:expr) => ( FactInstruction::UnifyVariable($r) ) } +macro_rules! unify_void { + ($n:expr) => ( + FactInstruction::UnifyVoid($n) + ) +} + macro_rules! set_cp { ($r:expr) => ( Line::BuiltIn(BuiltInInstruction::SetCutPoint($r)) @@ -321,4 +358,20 @@ macro_rules! get_cp { ) } +macro_rules! integer { + ($i:expr) => ( + Constant::Integer(BigInt::from($i)) + ) +} + +macro_rules! add { + ($at_1:expr, $at_2:expr, $o:expr) => ( + Line::Arithmetic(ArithmeticInstruction::Add($at_1, $at_2, $o)) + ) +} +macro_rules! get_arg { + () => ( + Line::BuiltIn(BuiltInInstruction::GetArg) + ) +} diff --git a/src/prolog/parser b/src/prolog/parser index 87230857..f51fc401 160000 --- a/src/prolog/parser +++ b/src/prolog/parser @@ -1 +1 @@ -Subproject commit 87230857805adcfff30c8f0257179e87c531fb21 +Subproject commit f51fc401fa86fa90136c05e83dee5a5b85e579be