rubylog 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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