rubylog 0.0.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. data/Gemfile +1 -1
  2. data/README.hu.rb +58 -0
  3. data/README.rdoc +248 -89
  4. data/Rakefile +6 -1
  5. data/VERSION +1 -1
  6. data/bin/rubylog +18 -0
  7. data/examples/dcg.rb +35 -0
  8. data/examples/dcg2.rb +42 -0
  9. data/examples/enumerators.rb +30 -0
  10. data/examples/factorial.rb +9 -8
  11. data/examples/hanoi.rb +24 -0
  12. data/examples/hello.rb +11 -5
  13. data/examples/parsing.rb +27 -0
  14. data/examples/primitives.rb +24 -0
  15. data/examples/theory.rb +22 -10
  16. data/lib/rubylog/builtins/default.rb +10 -0
  17. data/lib/rubylog/builtins/file_system.rb +15 -0
  18. data/lib/rubylog/builtins/logic.rb +109 -0
  19. data/lib/rubylog/builtins/reflection.rb +94 -0
  20. data/lib/rubylog/builtins/term.rb +47 -0
  21. data/lib/rubylog/dsl/array_splat.rb +25 -0
  22. data/lib/rubylog/dsl/primitives.rb +17 -0
  23. data/lib/rubylog/dsl/thats.rb +22 -0
  24. data/lib/rubylog/dsl/variables.rb +30 -0
  25. data/lib/rubylog/dsl.rb +35 -17
  26. data/lib/rubylog/errors.rb +19 -1
  27. data/lib/rubylog/interfaces/assertable.rb +16 -0
  28. data/lib/rubylog/interfaces/callable.rb +18 -0
  29. data/lib/rubylog/interfaces/composite_term.rb +47 -0
  30. data/lib/rubylog/interfaces/predicate.rb +8 -0
  31. data/lib/rubylog/interfaces/procedure.rb +60 -0
  32. data/lib/rubylog/interfaces/term.rb +41 -0
  33. data/lib/rubylog/mixins/array.rb +118 -0
  34. data/lib/{class.rb → rubylog/mixins/class.rb} +2 -2
  35. data/lib/rubylog/mixins/hash.rb +8 -0
  36. data/lib/rubylog/mixins/kernel.rb +5 -0
  37. data/lib/rubylog/mixins/method.rb +3 -0
  38. data/lib/rubylog/mixins/object.rb +8 -0
  39. data/lib/rubylog/mixins/proc.rb +37 -0
  40. data/lib/rubylog/mixins/string.rb +104 -0
  41. data/lib/rubylog/mixins/symbol.rb +44 -0
  42. data/lib/rubylog/simple_procedure.rb +8 -0
  43. data/lib/rubylog/{clause.rb → structure.rb} +32 -31
  44. data/lib/rubylog/theory.rb +368 -79
  45. data/lib/rubylog/variable.rb +102 -23
  46. data/lib/rubylog.rb +33 -25
  47. data/logic/builtins/file_system_logic.rb +23 -0
  48. data/logic/builtins/reflection_logic.rb +40 -0
  49. data/logic/dereference_logic.rb +23 -0
  50. data/logic/directory_structure_logic.rb +19 -0
  51. data/logic/dsl_logic.rb +29 -0
  52. data/logic/errors_logic.rb +9 -0
  53. data/logic/guard_logic.rb +115 -0
  54. data/logic/list_logic.rb +55 -0
  55. data/logic/map_logic.rb +15 -0
  56. data/logic/multitheory.rb +23 -0
  57. data/logic/recursion_logic.rb +12 -0
  58. data/logic/string_logic.rb +41 -0
  59. data/logic/thats_logic.rb +51 -0
  60. data/logic/variable_logic.rb +24 -0
  61. data/rubylog.gemspec +85 -46
  62. data/spec/bartak_guide_spec.rb +57 -62
  63. data/spec/builtins/all_spec.rb +99 -0
  64. data/spec/builtins/and_spec.rb +22 -0
  65. data/spec/builtins/array_spec.rb +16 -0
  66. data/spec/builtins/branch_or_spec.rb +27 -0
  67. data/spec/builtins/cut_spec.rb +44 -0
  68. data/spec/builtins/fail_spec.rb +5 -0
  69. data/spec/builtins/false_spec.rb +5 -0
  70. data/spec/builtins/in_spec.rb +38 -0
  71. data/spec/builtins/is_false_spec.rb +12 -0
  72. data/spec/builtins/is_spec.rb +26 -0
  73. data/spec/builtins/matches_spec.rb +23 -0
  74. data/spec/builtins/or_spec.rb +22 -0
  75. data/spec/{rubylog/builtins → builtins}/splits_to.rb +0 -0
  76. data/spec/builtins/then_spec.rb +27 -0
  77. data/spec/builtins/true_spec.rb +5 -0
  78. data/spec/clause_spec.rb +82 -0
  79. data/spec/compilation_spec.rb +61 -0
  80. data/spec/custom_classes_spec.rb +43 -0
  81. data/spec/dereference.rb +10 -0
  82. data/spec/{inriasuite.rb → inriasuite_spec.rb} +2 -9
  83. data/spec/queries_spec.rb +150 -0
  84. data/spec/recursion_spec.rb +4 -4
  85. data/spec/ruby_code_spec.rb +52 -0
  86. data/spec/rules_spec.rb +97 -0
  87. data/spec/spec_helper.rb +6 -2
  88. data/spec/theory_spec.rb +28 -0
  89. data/spec/unification_spec.rb +84 -0
  90. data/spec/variable_spec.rb +26 -0
  91. metadata +153 -180
  92. data/examples/4queens.rb +0 -10
  93. data/examples/calculation.rb +0 -12
  94. data/examples/concepts.rb +0 -46
  95. data/examples/fp.rb +0 -56
  96. data/examples/historia_de_espana.rb +0 -31
  97. data/examples/idea.rb +0 -143
  98. data/examples/lists.rb +0 -5
  99. data/examples/mechanika.rb +0 -409
  100. data/examples/parse.rb +0 -15
  101. data/lib/array.rb +0 -24
  102. data/lib/method.rb +0 -4
  103. data/lib/object.rb +0 -5
  104. data/lib/proc.rb +0 -4
  105. data/lib/rubylog/builtins.rb +0 -193
  106. data/lib/rubylog/callable.rb +0 -20
  107. data/lib/rubylog/composite_term.rb +0 -38
  108. data/lib/rubylog/dsl/constants.rb +0 -15
  109. data/lib/rubylog/dsl/first_order_functors.rb +0 -9
  110. data/lib/rubylog/dsl/global_functors.rb +0 -3
  111. data/lib/rubylog/dsl/second_order_functors.rb +0 -8
  112. data/lib/rubylog/internal_helpers.rb +0 -16
  113. data/lib/rubylog/predicate.rb +0 -34
  114. data/lib/rubylog/proc_method_additions.rb +0 -69
  115. data/lib/rubylog/term.rb +0 -20
  116. data/lib/rubylog/unifiable.rb +0 -19
  117. data/lib/symbol.rb +0 -35
  118. data/script/inriasuite2spec +0 -0
  119. data/script/inriasuite2spec.pl +0 -22
  120. data/spec/rubylog/clause_spec.rb +0 -81
  121. data/spec/rubylog/variable_spec.rb +0 -25
  122. data/spec/rubylog_spec.rb +0 -914
data/lib/rubylog.rb CHANGED
@@ -1,39 +1,47 @@
1
- # rubylog.rb -- Prolog workalike for Ruby
1
+ # rubylog -- Prolog workalike for Ruby
2
2
  # github.com/cie/rubylog
3
+ module Rubylog
4
+ end
3
5
 
4
6
  # rtl
5
7
  require 'set'
6
8
 
9
+ dir = File.dirname(__FILE__) + "/"
10
+
7
11
  # interfaces
8
- require 'rubylog/term.rb'
9
- require 'rubylog/callable.rb'
10
- require 'rubylog/unifiable.rb'
11
- require 'rubylog/composite_term.rb'
12
+ require dir+'rubylog/interfaces/term'
13
+ require dir+'rubylog/interfaces/callable'
14
+ require dir+'rubylog/interfaces/assertable'
15
+ require dir+'rubylog/interfaces/composite_term'
16
+ require dir+'rubylog/interfaces/predicate'
17
+ require dir+'rubylog/interfaces/procedure'
12
18
 
13
19
  # helpers
14
- require 'rubylog/dsl.rb'
15
- require 'rubylog/dsl/constants.rb'
16
- require 'rubylog/dsl/first_order_functors.rb'
17
- require 'rubylog/dsl/global_functors.rb'
18
- require 'rubylog/dsl/second_order_functors.rb'
19
- require 'rubylog/proc_method_additions.rb'
20
- require 'rubylog/internal_helpers.rb'
20
+ require dir+'rubylog/dsl'
21
+ require dir+'rubylog/dsl/variables'
22
+ require dir+'rubylog/dsl/primitives'
23
+ require dir+'rubylog/dsl/array_splat'
24
+ require dir+'rubylog/dsl/thats'
25
+ require dir+'rubylog/errors'
21
26
 
22
27
  # classes
23
- require 'rubylog/errors.rb'
24
- require 'rubylog/predicate.rb'
25
- require 'rubylog/theory.rb'
26
- require 'rubylog/variable.rb'
28
+ require dir+'rubylog/theory'
29
+ require dir+'rubylog/simple_procedure'
30
+ require dir+'rubylog/variable'
31
+ require dir+'rubylog/structure'
27
32
 
28
33
  # builtins
29
- require 'rubylog/builtins.rb'
34
+ require dir+'rubylog/builtins/default'
35
+
36
+ # mixins
37
+ require dir+'rubylog/mixins/array'
38
+ require dir+'rubylog/mixins/class'
39
+ require dir+'rubylog/mixins/hash'
40
+ require dir+'rubylog/mixins/kernel'
41
+ require dir+'rubylog/mixins/method'
42
+ require dir+'rubylog/mixins/object'
43
+ require dir+'rubylog/mixins/proc'
44
+ require dir+'rubylog/mixins/string'
45
+ require dir+'rubylog/mixins/symbol'
30
46
 
31
- require 'rubylog/clause.rb'
32
- require 'array.rb'
33
- require 'symbol.rb'
34
- require 'proc.rb'
35
- require 'object.rb'
36
- require 'class.rb'
37
- require 'method.rb'
38
47
 
39
- Rubylog::Theory.new!
@@ -0,0 +1,23 @@
1
+ require "./lib/rubylog/builtins/file_system"
2
+
3
+ theory do
4
+ check "lib".dirname_in(".")
5
+ check "lib".filename_in(".").false
6
+ check "README.rdoc".filename_in(".")
7
+ check "README.rdoc".dirname_in(".").false
8
+ check (Dir.pwd+"/lib").dir_in(".")
9
+ check (Dir.pwd+"/lib").file_in(".").false
10
+ check (Dir.pwd+"/README.rdoc").file_in(".")
11
+ check (Dir.pwd+"/README.rdoc").dir_in(".").false
12
+ check (Dir.pwd+"/lib/rubylog.rb").file_in("lib")
13
+ check (Dir.pwd+"/lib/rubylog").dir_in("lib")
14
+ check "rubylog.rb".filename_in("lib")
15
+ check "rubylog".dirname_in("lib")
16
+
17
+
18
+ # this is removed in favor of string unification
19
+ #check "rubylog.rb".filename("rubylog", "rb")
20
+ #check A.filename("rubylog", "rb").and A.is "rubylog.rb"
21
+ #check "rubylog.rb".filename(F, "rb").and F.is "rubylog"
22
+ #check "rubylog.rb".filename("rubylog", E).and E.is "rb"
23
+ end
@@ -0,0 +1,40 @@
1
+ require "./lib/rubylog/builtins/reflection.rb"
2
+
3
+ theory do
4
+ functor_for String, :likes, :drinks
5
+
6
+ # fact
7
+ "John".likes! "beer"
8
+ check "John".likes("beer").fact
9
+ check { A.likes(B).fact.map{A.likes(B)} == ["John".likes("beer")] }
10
+
11
+ # follows_from
12
+ A.drinks(B).if A.likes(B)
13
+ check A.drinks(B).follows_from A.likes(B)
14
+ check {A.drinks(B).follows_from(K).map{K} == [A.likes(B)] }
15
+
16
+ # structure
17
+ check A.likes(B).structure(:likes, [A,B])
18
+ check { A.likes(B).structure(X,Y).map{[X,Y]} == [[:likes, [A,B]]] }
19
+
20
+ # structures with variable functor and partial argument list
21
+ check { K.structure(:drinks, ["John", "beer"]).map{K} == ["John".drinks("beer")] }
22
+ check { K.structure(A,[*B]).
23
+ and(A.is(:drinks)).
24
+ and(B.is(["John","beer"])).
25
+ map{K} == ["John".drinks("beer")] }
26
+
27
+ # variable
28
+ # Removed because of the "every built-in prediate is pure logical" principle
29
+ #check A.variable("A")
30
+ #check A.variable("B").false
31
+ #check { A.variable(B).map{B} == ["A"] }
32
+ # You can use the fact that automatic variable resolution yields nil if the
33
+ # variable is undefined:
34
+ #
35
+ # check A.is(ANY).and{ A }.false
36
+ # check A.is(ANY).and{ not A }
37
+ #
38
+
39
+
40
+ end
@@ -0,0 +1,23 @@
1
+ theory do
2
+ functor_for Integer, :divides
3
+
4
+ check { A.is_a? Rubylog::Variable }
5
+ check { A.rubylog_deep_dereference == A }
6
+
7
+ a = A
8
+ check { a.rubylog_deep_dereference.equal? a }
9
+
10
+ a.rubylog_unify(4) do
11
+ check { a.rubylog_deep_dereference == 4 }
12
+ check { [1,a].rubylog_deep_dereference == [1,4] }
13
+ check { a.divides(16).rubylog_deep_dereference == 4.divides(16) }
14
+ end
15
+
16
+ b = []
17
+ check { not b.rubylog_deep_dereference.equal? b }
18
+
19
+ c = Object.new
20
+ check { c.rubylog_deep_dereference.equal? c }
21
+ end
22
+
23
+
@@ -0,0 +1,19 @@
1
+ require "./lib/rubylog/builtins/file_system"
2
+
3
+ theory do
4
+ subject String
5
+ functor :dir, :contains
6
+ check_discontiguous false
7
+
8
+ ".git".dir!.contains! "Git repository"
9
+ "bin".dir!.contains! "executables"
10
+ "examples".dir!.contains! "examples and ideas for different applications of Rubylog"
11
+ "lib".dir!.contains! "source code of Rubylog"
12
+ "spec".dir!.contains! "functional tests written in RSpec"
13
+ "logic".dir!.contains! "integration tests written in Rubylog"
14
+
15
+ gitignore = File.readlines(".gitignore").map{|l| l.chop}
16
+ check X.in(Y.dir.map{Y}).iff(X.in(Y.dirname_in(".").and(Y.not_in(gitignore)).map{Y}))
17
+
18
+ end
19
+
@@ -0,0 +1,29 @@
1
+ theory do
2
+
3
+ # prefix functors
4
+
5
+ prefix_functor :we_have
6
+ we_have! :weapons
7
+ we_have! :sunglasses
8
+ we_have! :rustling_leather_coats
9
+
10
+ check we_have :sunglasses
11
+ check { we_have? :rustling_leather_coats }
12
+
13
+
14
+ # built-in prefix functors
15
+
16
+ check all X.is(4).and(Y.is(X)), Y.is(4)
17
+ check any X.is(4)
18
+ check one(X.in([1,2,3])) { X % 2 == 0 }
19
+ check none X.in([1,2,3]), X.is(5)
20
+
21
+ check { all?(X.is(4)) { X < 5 } }
22
+
23
+ # variables
24
+ check A.is(ANY).and{ A == nil }
25
+ check A.is(4) .and{ A == 4 }
26
+ check B.is(4) .and{ A.is_a? Rubylog::Variable }
27
+ check B.is(ANY).and{ A.is_a? Rubylog::Variable }
28
+
29
+ end
@@ -0,0 +1,9 @@
1
+ theory do
2
+ functor_for String, :happy, :has
3
+
4
+ # syntax error
5
+ check { begin "John".happy.if; rescue Rubylog::SyntaxError; true else false end }
6
+ check { begin "John".happy.if!; rescue Rubylog::SyntaxError; true else false end }
7
+ check { begin "John".happy.unless; rescue Rubylog::SyntaxError; true else false end }
8
+
9
+ end
@@ -0,0 +1,115 @@
1
+ theory do
2
+
3
+ # class guard
4
+ functor_for Numeric, :divides
5
+ A[Integer].divides(B[Integer]).if { B % A == 0 }
6
+ A[Float].divides!(B[Float])
7
+ check 2.divides(10)
8
+ check 2.divides(9).false
9
+ check 2.divides(1).false
10
+ check 2.divides(0)
11
+ check 2.12.divides(4.5)
12
+ check -0.31.divides(-1.5)
13
+ check 0.3.divides(3).false
14
+ check 2.0.divides(10).false
15
+ check 2.divides(10.0).false
16
+ check 2.divides(9.0).false
17
+
18
+ # union of guards at compile
19
+ functor_for Numeric, :small
20
+ A[0...100].small.if ANY.is A[Integer]
21
+ check 0.small
22
+ check 10.small
23
+ check -1.small.false
24
+ check 0.0.small.false
25
+ check 99.small
26
+ check 99.0.small.false
27
+ check 99.9.small.false
28
+ check 100.small.false
29
+ check 100.0.small.false
30
+
31
+ # union of guards at compile (dont-care)
32
+ functor_for Numeric, :small
33
+ A[0...100].small.if A.is ANY[Integer]
34
+ check 0.small
35
+ check 10.small
36
+ check -1.small.false
37
+ check 0.0.small.false
38
+ check 99.small
39
+ check 99.0.small.false
40
+ check 99.9.small.false
41
+ check 100.small.false
42
+ check 100.0.small.false
43
+
44
+ # union of guards at unification
45
+ self[[:small,1]].clear
46
+ functor_for Numeric, :small
47
+ A[0...100].small.if A.is B[Integer]
48
+ check 0.small
49
+ check 10.small
50
+ check -1.small.false
51
+ check 0.0.small.false
52
+ check 99.small
53
+ check 99.0.small.false
54
+ check 99.9.small.false
55
+ check 100.small.false
56
+ check 100.0.small.false
57
+
58
+ # union of guards at unification (reversed)
59
+ self[[:small,1]].clear
60
+ functor_for Numeric, :small
61
+ A[0...100].small.if B[Integer].is A
62
+ check 0.small
63
+ check 10.small
64
+ check -1.small.false
65
+ check 0.0.small.false
66
+ check 99.small
67
+ check 99.0.small.false
68
+ check 99.9.small.false
69
+ check 100.small.false
70
+ check 100.0.small.false
71
+
72
+
73
+ # proc guards
74
+ functor_for Numeric, :big
75
+ A[proc{|a|a > 20}].big!
76
+ check -100.big.false
77
+ check 0.big.false
78
+ check 10.big.false
79
+ check 20.big.false
80
+ check 21.big
81
+ check 200.big
82
+
83
+ # hash guards
84
+ functor_for String, :char
85
+ S[length: 1].char!
86
+ check "a".char
87
+ check " ".char
88
+ check "".char.false
89
+ check "af".char.false
90
+ check "Hello".char.false
91
+
92
+ # list hash guards
93
+ functor_for String, :capitalized
94
+ S[[:[],0] => /[A-Z]/].capitalized!
95
+ check "a".capitalized.false
96
+ check " ".capitalized.false
97
+ check "".capitalized.false
98
+ check "af".capitalized.false
99
+ check "A".capitalized
100
+ check "Hello".capitalized
101
+
102
+
103
+ # chained hash guards
104
+ functor_for String, :funny
105
+ S[upcase: {[:[],1..-2] => "ELL"}].funny!
106
+ check "hello".funny
107
+ check "Bell!".funny
108
+ check "BELL!".funny
109
+ check "DELL".funny.false
110
+ check "help!".funny.false
111
+ check "hello!".funny.false
112
+
113
+
114
+
115
+ end
@@ -0,0 +1,55 @@
1
+ theory do
2
+ check [1,2,3].is [1,2,3]
3
+ check {[1,2,3].is([A,B,C]).map{[A,B,C]} == [[1,2,3]]}
4
+ check [].is []
5
+
6
+ check [1,2,3].is_not [1,2,4]
7
+ check [1,2,3].is_not [1,2]
8
+ check [1,2,3].is_not [1,ANY]
9
+ check [1,2,3].is [1,2,ANY]
10
+
11
+ # splats
12
+ check { [1,2,3].is([1,*A]).map{A} == [[2,3]] }
13
+ check [].is_not [A,*ANY]
14
+ check [].is [*ANY]
15
+ check [2].is [2, *ANY]
16
+ check [2, *ANY].is [2]
17
+ check [1,2].is([A,*B]).and A.is(1).and B.is([2])
18
+
19
+ # [*A] = [*B]
20
+ check {[*A].is([*B]).and A.is([1,2]).map{B} == [[1,2]]}
21
+ check [*A].is [*B]
22
+ check { [*A].is([*B]).each { } } # no infinite recursion
23
+
24
+
25
+ # append
26
+ check {[1,2,3].is([*A,*B]).map{[A,B]} == [[[],[1,2,3]],[[1],[2,3]],[[1,2],[3]],[[1,2,3],[]]] }
27
+ check [1,2,3].is [Rubylog::DSL::ArraySplat.new([1,2]),*ANY]
28
+ check [1,2,3].is [Rubylog::DSL::ArraySplat.new([1,2,3]),*ANY]
29
+ check [1,2,3].is_not [Rubylog::DSL::ArraySplat.new([1,2,3,B]),*ANY]
30
+
31
+ # member
32
+ check [1,2,3].is [*ANY,2,*ANY]
33
+ check X.is([1,2,3]).and A.in(X).all X.is [*ANY,A,*ANY]
34
+
35
+ # palindromes
36
+ functor_for Array, :palindrome
37
+ [].palindrome!
38
+ [ANY].palindrome!
39
+ [A,*X,A].palindrome.if X.palindrome
40
+ check X.in([[], [1], [1,1], [1,2,1], [1,2,2,1], [1,2,3,2,1], [1,2,3,3,2,1]]).all X.palindrome
41
+ check X.in([[1,2], [1,3,4,1], [2,2,5]]).none X.palindrome
42
+
43
+ # legacy syntax
44
+ check { [1,2,3].is([1]+A).map{A} == [[2,3]] }
45
+ check [].is_not [A]+ANY
46
+ check [].is []+ANY
47
+ check [2].is [2]+ANY
48
+ check(([2]+ANY).is [2])
49
+ check [1,2].is([A]+B).and A.is(1).and B.is([2])
50
+ check {([]+A).is([]+B).and A.is([1,2]).map{B} == [[1,2]]}
51
+ check(([]+A).is([]+B))
52
+ check {([]+A).is([]+B).each { } }
53
+ check {[1,2,3].is([]+A+B).map{[A,B]} == [[[],[1,2,3]],[[1],[2,3]],[[1,2],[3]],[[1,2,3],[]]] }
54
+ check X.is([1,2,3]).and A.in(X).all X.is []+ANY+[A]+ANY
55
+ end
@@ -0,0 +1,15 @@
1
+ theory "Rubylog::MapLogic" do
2
+ functor :likes
3
+ subject Symbol
4
+
5
+ # inriausite^findall
6
+ check S.is{X.is(1).or(X.is(2)).map{X}}.and{S == [1,2]}
7
+ check S.is{X.is(:john).map{X.likes(Y)}}.and{S == [:john.likes(Y)]}
8
+ check G.is(:fail.or :fail).and L.is{G.map{X}}.and{L == []}
9
+ check S.is{X.is(1).or(X.is(1)).map{X}}.and{S == [1,1]}
10
+ check [1,2].is{X.is(2).or(X.is(1)).map{X}}.false
11
+ check [X,Y].is{A.is(1).or(A.is(2)).map{A}}.and{X == 1}.and{Y == 2}
12
+ (S.is {Goal.map{X}}).solve and check :fail rescue NoMethodError
13
+ (S.is {4.map{X}}).solve and check :fail rescue NoMethodError
14
+ end
15
+
@@ -0,0 +1,23 @@
1
+ load "lib/rubylog/theory.rb"
2
+ A = theory do
3
+ functor_for Symbol, :good
4
+
5
+ :x.good!
6
+ end
7
+
8
+ B = theory do
9
+ :y.good!
10
+ end
11
+
12
+ theory do
13
+ multitheory [:good,1]
14
+
15
+ check { self[[:good,1]].multitheory? }
16
+
17
+ include A
18
+ include B
19
+
20
+ check { self[[:good,1]].multitheory? }
21
+
22
+ check {X.good.map{X} == [:x,:y]}
23
+ end
@@ -0,0 +1,12 @@
1
+ theory do
2
+ functor_for Integer, :factorial
3
+ 0.factorial! 1
4
+ N.factorial(K).if proc{N > 0}.and N1.is {N-1} .and N1.factorial(K1).and K.is{ N*K1 }
5
+
6
+ check 0.factorial 1
7
+ check 1.factorial 1
8
+ check 2.factorial 2
9
+ check 3.factorial 6
10
+ check 4.factorial 24
11
+ check 7.factorial 5040
12
+ end
@@ -0,0 +1,41 @@
1
+ theory do
2
+ check "asdf".is "asdf"
3
+ check { "abc#{S}def" =~ /abc.S\[\].def/ }
4
+ check { "abc#{S[length: 1]}def" =~ /abc.S\[\d+\].def/ }
5
+ check { "h#{S}o".is("hello").map{S} == ["ell"] }
6
+ check { "#{Base}.#{Ext}".is("hello.rb").map{Base} == ["hello"] }
7
+
8
+ check { "#{Base}.#{Ext}".is("hello.rb").map{Ext} == ["rb"] }
9
+ check { "h#{S}o".is("auto").map{S} == [] }
10
+
11
+ # backtracked matches
12
+ check { "abc".is("#{A}#{B}").map{"#{A}:#{B}"} == [":abc","a:bc","ab:c","abc:"] }
13
+ check { "www.google.com".is("#{A}.#{B}").map{[A,B]} == [["www", "google.com"],["www.google", "com"]] }
14
+ check { "a".is("#{A}#{B}#{C}").map{"#{A}:#{B}:#{C}"} == ["::a",":a:","a::"] }
15
+ check { "ab".is("#{A}#{B}#{C}").map{"#{A}:#{B}:#{C}"} == %w(::ab :a:b :ab: a::b a:b: ab::) }
16
+
17
+ # guards
18
+ check { "abc".is("#{A[/\A.\z/]}#{B}").map{"#{A}:#{B}"} == ["a:bc"] }
19
+ check { "abc".is("#{A[length: 1]}#{B}").map{"#{A}:#{B}"} == ["a:bc"] }
20
+
21
+
22
+ # palindromes
23
+ functor_for String, :palindrome
24
+
25
+ S[empty?: true].palindrome!
26
+ S[length: 1].palindrome!
27
+ S[lambda{|s|s.length > 1}].palindrome.if S.is("#{A[length: 1]}#{B}#{A}").and B.palindrome
28
+
29
+ check "".palindrome
30
+ check "dd".palindrome
31
+ check "aba".palindrome
32
+ check "faaf".palindrome
33
+ check "ffaaff".palindrome
34
+ check "rererer".palindrome
35
+ check "lol".palindrome
36
+ check "ji".palindrome.false
37
+ check "doo".palindrome.false
38
+ check "taaaz".palindrome.false
39
+ check "faad".palindrome.false
40
+ check "rerere".palindrome.false
41
+ end
@@ -0,0 +1,51 @@
1
+ require "./lib/rubylog/builtins/file_system"
2
+
3
+ theory do
4
+ functor_for Integer, :factorial
5
+
6
+ # one level
7
+ check 4.is(ANY[Integer,thats < 10])
8
+ check 4.is(ANY[Integer,thats < 5])
9
+ check 4.is(ANY[Integer,thats < 4]).false
10
+ check 4.is(ANY[Integer,thats < 2]).false
11
+
12
+ # question mark
13
+ check "".is(ANY[thats.empty?])
14
+ check "a".is(ANY[thats.empty?]).false
15
+
16
+ # two levels
17
+ check "hello".is(ANYTHING[thats.reverse == "olleh"])
18
+ check "hello".is(ANYTHING[thats.reverse == "olle"]).false
19
+
20
+ # four levels
21
+ check "hello".is(ANY[thats.upcase.partition("E")[0] == "H"])
22
+ check "hello".is(ANY[thats.upcase.partition("E")[1] == "E"])
23
+ check "hello".is(ANY[thats.upcase.partition("E")[2] == "LLO"])
24
+ check "hello".is(ANY[thats.upcase.partition("E")[1] == "H"]).false
25
+ check "hello".is(ANY[thats.upcase.partition("E")[0] == "h"]).false
26
+ check "hello".is(ANY[thats.upcase.partition("L")[0] == "H"]).false
27
+ check "hello".is(ANY[thats.upcase.partition("e")[0] == "H"]).false
28
+
29
+ # files
30
+ check { "#{S[String, thats.start_with?(".")]}".filename_in(".").map{S}.include? ".gitignore" }
31
+ check { not "#{S[String, thats.start_with?(".")]}".filename_in(".").map{S}.include? "lib" }
32
+ check { "#{S[/\A(.*)\.rb/]}".filename_in("lib").map{S} == ["rubylog.rb"] }
33
+
34
+ # factorial
35
+ 0.factorial! 1
36
+ K[thats > 0].factorial(N).if K0.is{K-1}.and K0.factorial(N0).and N.is{N0*K}
37
+
38
+ # palindrome
39
+ functor_for String, :palindrome
40
+ S[String, thats.length <= 1].palindrome!
41
+ "#{A[thats.length == 1]}#{B}#{A}".palindrome.if B.palindrome
42
+
43
+ check "a".palindrome
44
+ check "aa".palindrome
45
+ check "aga".palindrome
46
+ check "aaa".palindrome
47
+ check "avava".palindrome
48
+ check "ab".palindrome.false
49
+ check "abb".palindrome.false
50
+ check "abab".palindrome.false
51
+ end
@@ -0,0 +1,24 @@
1
+ theory do
2
+ # dont-care variables case insensitive ANY* and _*
3
+ check 3.is(ANY).and 3.is(ANY)
4
+ check 3.is(ANY).and 4.is(ANY)
5
+ check 3.is(ANYTHING).and 3.is(ANYTHING)
6
+ check 3.is(ANYTHING).and 4.is(ANYTHING)
7
+ check 3.is(Anything).and 3.is(Anything)
8
+ check 3.is(Anything).and 4.is(Anything)
9
+ check 3.is(Rubylog::Variable.new(:_var1)).and(3.is(Rubylog::Variable.new(:_var1)))
10
+ check 3.is(Rubylog::Variable.new(:_var1)).and(4.is(Rubylog::Variable.new(:_var1)))
11
+ check 3.is(Rubylog::Variable.new(:var1 )).and(3.is(Rubylog::Variable.new(:var1 )))
12
+ check 3.is(Rubylog::Variable.new(:var1 )).and(4.is(Rubylog::Variable.new(:var1 ))).false
13
+
14
+ # dont-care variables support recursion
15
+ functor_for Integer, :factorial
16
+ 0.factorial! 1
17
+ N.factorial(K).if proc{N > 0}.and N1.is {N-1} .and N1.factorial(K1).and K.is{ N*K1 }.and K.is(ANY1).and N.is(ANY2)
18
+ check 0.factorial 1
19
+ check 1.factorial 1
20
+ check 2.factorial 2
21
+ check 3.factorial 6
22
+ check 4.factorial 24
23
+ check 7.factorial 5040
24
+ end