porolog 0.0.4 → 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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +30 -5
  3. data/Rakefile +7 -2
  4. data/bin/porolog +58 -1
  5. data/coverage/badge.svg +1 -1
  6. data/coverage/index.html +76733 -2638
  7. data/doc/Array.html +1066 -0
  8. data/doc/Object.html +674 -0
  9. data/doc/Porolog.html +4153 -74
  10. data/doc/Symbol.html +501 -0
  11. data/doc/_index.html +280 -6
  12. data/doc/class_list.html +1 -1
  13. data/doc/file.README.html +34 -39
  14. data/doc/index.html +34 -39
  15. data/doc/method_list.html +1337 -57
  16. data/doc/top-level-namespace.html +4 -2
  17. data/lib/porolog.rb +1144 -4
  18. data/lib/porolog/arguments.rb +28 -24
  19. data/lib/porolog/core_ext.rb +188 -0
  20. data/lib/porolog/error.rb +9 -0
  21. data/lib/porolog/goal.rb +357 -0
  22. data/lib/porolog/instantiation.rb +346 -0
  23. data/lib/porolog/predicate.rb +74 -31
  24. data/lib/porolog/predicate/builtin.rb +825 -0
  25. data/lib/porolog/rule.rb +162 -0
  26. data/lib/porolog/scope.rb +4 -4
  27. data/lib/porolog/tail.rb +57 -0
  28. data/lib/porolog/value.rb +105 -0
  29. data/lib/porolog/variable.rb +325 -0
  30. data/test/porolog/arguments_test.rb +244 -195
  31. data/test/porolog/core_ext_test.rb +290 -0
  32. data/test/porolog/goal_test.rb +891 -0
  33. data/test/porolog/instantiation_test.rb +910 -0
  34. data/test/porolog/porolog_test.rb +2376 -13
  35. data/test/porolog/predicate/builtin_test.rb +1340 -0
  36. data/test/porolog/predicate_test.rb +84 -30
  37. data/test/porolog/rule_test.rb +527 -0
  38. data/test/porolog/scope_test.rb +0 -2
  39. data/test/porolog/tail_test.rb +127 -0
  40. data/test/porolog/value_test.rb +315 -0
  41. data/test/porolog/variable_test.rb +1614 -0
  42. data/test/samples_test.rb +277 -0
  43. data/test/test_helper.rb +115 -0
  44. metadata +34 -7
@@ -0,0 +1,277 @@
1
+ #
2
+ # test/samples_test.rb - Test Suite for Porolog::Predicate
3
+ #
4
+ # Luis Esteban 13 July 2020
5
+ # created
6
+ #
7
+
8
+ require_relative 'test_helper'
9
+
10
+ describe 'Porolog' do
11
+
12
+ before(:all) do
13
+ reset
14
+ end
15
+
16
+ it 'implements delete first predicate' do
17
+ predicate :delete
18
+
19
+ delete(:X, [:X]/:T, :T).fact!
20
+
21
+ assert_solutions delete(9, [1,2,3,4], [2,3,4]), []
22
+ assert_solutions delete(1, [1,2,3,4], [2,3,4]), [{}]
23
+
24
+ assert_solutions delete(:Removed, [1,2,3,4], [2,3,4]), [{ Removed: 1 }]
25
+ assert_solutions delete(1, :Original, [2,3,4]), [{ Original: [1,2,3,4] }]
26
+ assert_solutions delete(1, [1,2,3,4], :Result), [{ Result: [2,3,4] }]
27
+ assert_solutions delete(1, [:First,2,3,4], [2,3,4]), [{ First: 1 }]
28
+ assert_solutions delete(1, [1,:Second,3,4], [2,3,4]), [{ Second: 2 }]
29
+ assert_solutions delete(1, [1,2,:Third,4], [2,3,4]), [{ Third: 3 }]
30
+ assert_solutions delete(1, [1,2,3,4], [:Second,3,4]), [{ Second: 2 }]
31
+ assert_solutions delete(1, [1,2,3,4], [:A, :B, :C]), [{ A: 2, B: 3, C: 4 }]
32
+ assert_solutions delete(1, [:A,2,3,:D], [:B,3,4]), [{ A: 1, B: 2, D: 4 }]
33
+ end
34
+
35
+ it 'implements the delete predicate' do
36
+ builtin :write
37
+ predicate :delete
38
+
39
+ delete(:X, [:X]/:T, :T).fact!
40
+ delete(:X, [:H]/:T, [:H]/:NT) << [
41
+ delete(:X, :T, :NT),
42
+ ]
43
+
44
+ assert_solutions delete(1, [1,2,3,4], [1,2,4]), [], goals: 9
45
+ assert_solutions delete(3, [1,2,3,4], [1,2,4]), [{}]
46
+ assert_solutions delete(4, [1,2,3,4], [1,2,3]), [{}]
47
+ assert_solutions delete(4, [1,2,3,4], [1,2,:X]), [{ X: 3 }]
48
+
49
+ assert_solutions delete(:Removed, [1,2,3,4], [1,2,4]), [
50
+ { Removed: 3 }
51
+ ]
52
+
53
+ assert_solutions delete(:Removed, [1,2,3,4], [1,2,3]), [
54
+ { Removed: 4 }
55
+ ]
56
+
57
+ assert_solutions delete(3, :Original, [1,2,4]), [
58
+ { Original: [3, 1, 2, 4] },
59
+ { Original: [1, 3, 2, 4] },
60
+ { Original: [1, 2, 3, 4] },
61
+ { Original: [1, 2, 4, 3] },
62
+ ]
63
+
64
+ assert_solutions delete(:X, [1,2,3,4], :L), [
65
+ { X: 1, L: [2, 3, 4] },
66
+ { X: 2, L: [1, 3, 4] },
67
+ { X: 3, L: [1, 2, 4] },
68
+ { X: 4, L: [1, 2, 3] },
69
+ ]
70
+
71
+ assert_solutions delete(:X, [1,2,3,4], [:A,:B,:C]), [
72
+ { X: 1, A: 2, B: 3, C: 4 },
73
+ { X: 2, A: 1, B: 3, C: 4 },
74
+ { X: 3, A: 1, B: 2, C: 4 },
75
+ { X: 4, A: 1, B: 2, C: 3 },
76
+ ]
77
+ end
78
+
79
+ it 'implements the permutation predicate' do
80
+ warn name
81
+ predicate :delete, :permutation
82
+
83
+ permutation([],[]).fact!
84
+ permutation(:List, [:H]/:Permutation) << [
85
+ delete(:H, :List, :Rest),
86
+ permutation(:Rest, :Permutation)
87
+ ]
88
+
89
+ delete(:X, [:X]/:T, :T).fact!
90
+ delete(:X, [:H]/:T, [:H]/:NT) << [
91
+ delete(:X, :T, :NT),
92
+ ]
93
+
94
+ assert_solutions permutation([1,2,3,4], [1,2,3,4]), [{}]
95
+ assert_solutions permutation([3,2,1,4], [1,2,3,4]), [{}]
96
+ assert_solutions permutation([3,2,:A,4], [1,2,3,4]), [
97
+ { A: 1 }
98
+ ]
99
+ assert_solutions permutation([3,2,:A,:B], [1,2,3,4]), [
100
+ { A: 1, B: 4 },
101
+ { A: 4, B: 1 },
102
+ ]
103
+ assert_solutions permutation([3,2,:A,4], [1,2,:C,4]), [
104
+ { A: 1, C: 3 }
105
+ ]
106
+ assert_solutions permutation([2,3,1], :L), [
107
+ { L: [2, 3, 1] },
108
+ { L: [2, 1, 3] },
109
+ { L: [3, 2, 1] },
110
+ { L: [3, 1, 2] },
111
+ { L: [1, 2, 3] },
112
+ { L: [1, 3, 2] }
113
+ ]
114
+ end
115
+
116
+ it 'solves the Einstein / Zebra riddle' do
117
+ warn name
118
+ builtin :is, :member, :is_noteq
119
+ predicate :same, :not_same, :left, :beside, :houses
120
+
121
+ same(:X,:X).fact!
122
+
123
+ not_same(:X,:X).cut_falicy!
124
+ not_same(:X,:Y).fact!
125
+
126
+ (1..5).to_a.each_cons(2) do |left, right|
127
+ left(left,right).fact!
128
+ beside(left,right).fact!
129
+ beside(right,left).fact!
130
+ end
131
+
132
+ HOUSES = [1, 2, 3, 4, 5 ]
133
+
134
+ PEOPLE = [:Brit, :Dane, :Swede, :German, :Norwegian]
135
+ SMOKES = [:Blend, :Pallmall, :Dunhill, :Winfield, :Rothmans ]
136
+ PETS = [:Dog, :Cats, :Fish, :Birds, :Horses ]
137
+ COLOURS = [:Red, :Blue, :Green, :White, :Yellow ]
138
+ DRINKS = [:Tea, :Beer, :Milk, :Water, :Coffee ]
139
+
140
+ FISH_INDEX = PETS.index(:Fish)
141
+
142
+ houses(:People, :Smokes, :Pets, :Colours, :Drinks) << [
143
+ same(:Milk, 3), # 8. The man living in the house right in the center drinks milk.
144
+ same(:Norwegian, 1), # 9. The Norwegian lives in the first house.
145
+ left(:Green, :White), # 4. The green house is on the left of the white house.
146
+ beside(:Norwegian, :Blue), # 14. The Norwegian lives next to the blue house.
147
+ not_same(:Blue, :White),
148
+ beside(:Blend, :Water), # 15. The man who smokes Blend has a neighbour who drinks water.
149
+ not_same(:Milk, :Water),
150
+ beside(:Horses, :Dunhill), # 11. The man who keeps horses lives next to the man who smokes Dunhill.
151
+ same(:Yellow, :Dunhill), # 7. The owner of the yellow house smokes Dunhill.
152
+ same(:Green, :Coffee), # 5. The green house owner drinks coffee.
153
+ not_same(:Milk, :Coffee),
154
+ not_same(:Water, :Coffee),
155
+ is_noteq(:Red, HOUSES, :Green, :White, :Blue, :Yellow),
156
+ same(:Brit, :Red), # 1. The Brit lives in a red house.
157
+ not_same(:Brit, :Norwegian),
158
+ beside(:Blend, :Cats), # 10. The man who smokes Blend lives next to the one who keeps cats.
159
+ not_same(:Horses, :Cats),
160
+ is_noteq(:Tea, HOUSES, :Coffee, :Milk, :Water),
161
+ same(:Dane, :Tea), # 3. The Dane drinks tea.
162
+ is_noteq(:Beer, HOUSES, :Tea, :Coffee, :Milk, :Water),
163
+ same(:Winfield, :Beer), # 12. The owner who smokes Winfield drinks beer.
164
+ is_noteq(:German, HOUSES, :Norwegian, :Dane, :Brit),
165
+ is_noteq(:Swede, HOUSES, :German, :Norwegian, :Dane, :Brit),
166
+ same(:Swede, :Dog), # 2. The Swede keeps a dog.
167
+ is_noteq(:Pallmall, HOUSES, :Dunhill, :Blend, :Winfield),
168
+ is_noteq(:Rothmans, HOUSES, :Pallmall, :Dunhill, :Blend, :Winfield),
169
+ same(:Pallmall, :Birds), # 6. The person who smokes Pall Mall keeps birds.
170
+ same(:German, :Rothmans), # 13. The German smokes Rothmans.
171
+ is_noteq(:Fish, HOUSES, :Dog, :Birds, :Cats, :Horses),
172
+
173
+ same(:People, PEOPLE),
174
+ same(:Smokes, SMOKES),
175
+ same(:Pets, PETS),
176
+ same(:Colours, COLOURS),
177
+ same(:Drinks, DRINKS),
178
+ ]
179
+
180
+ solutions = assert_solutions houses(:People, :Smokes, :Pets, :Colours, :Drinks), [
181
+ {
182
+ People: [3, 2, 5, 4, 1],
183
+ Smokes: [2, 3, 1, 5, 4],
184
+ Pets: [5, 1, 4, 3, 2],
185
+ Colours: [3, 2, 4, 5, 1],
186
+ Drinks: [2, 5, 3, 1, 4]
187
+ }
188
+ ], goals: 1873
189
+
190
+ solution = solutions.first
191
+
192
+ assert_equal :German, PEOPLE[solution[:People].index(solution[:Pets][FISH_INDEX])]
193
+
194
+ def house_details(solution, h)
195
+ [
196
+ PEOPLE[solution[:People].index(h)],
197
+ SMOKES[solution[:Smokes].index(h)],
198
+ PETS[solution[:Pets].index(h)],
199
+ COLOURS[solution[:Colours].index(h)],
200
+ DRINKS[solution[:Drinks].index(h)]
201
+ ]
202
+ end
203
+
204
+ assert_equal [:Norwegian, :Dunhill, :Cats, :Yellow, :Water ], house_details(solution, 1)
205
+ assert_equal [:Dane, :Blend, :Horses, :Blue, :Tea ], house_details(solution, 2)
206
+ assert_equal [:Brit, :Pallmall, :Birds, :Red, :Milk ], house_details(solution, 3)
207
+ assert_equal [:German, :Rothmans, :Fish, :Green, :Coffee], house_details(solution, 4)
208
+ assert_equal [:Swede, :Winfield, :Dog, :White, :Beer ], house_details(solution, 5)
209
+ end
210
+
211
+ it 'instantiates lists using member and length builtin predicates' do
212
+ builtin :member, :length
213
+ predicate :lists
214
+
215
+ lists(:L) << [
216
+ member(:N,[1,2,3,4,5]),
217
+ length(:L, :N),
218
+ member(:N, :L)
219
+ ]
220
+
221
+ assert_solutions lists(:L), [
222
+ { L: [1] },
223
+ { L: [2, nil] },
224
+ { L: [nil, 2] },
225
+ { L: [3, nil, nil] },
226
+ { L: [nil, 3, nil] },
227
+ { L: [nil, nil, 3] },
228
+ { L: [4, nil, nil, nil] },
229
+ { L: [nil, 4, nil, nil] },
230
+ { L: [nil, nil, 4, nil] },
231
+ { L: [nil, nil, nil, 4] },
232
+ { L: [5, nil, nil, nil, nil] },
233
+ { L: [nil, 5, nil, nil, nil] },
234
+ { L: [nil, nil, 5, nil, nil] },
235
+ { L: [nil, nil, nil, 5, nil] },
236
+ { L: [nil, nil, nil, nil, 5] },
237
+ ], goals: 13
238
+ end
239
+
240
+ it 'implements a prime number search' do
241
+ builtin :gtr, :is, :noteq, :between
242
+ predicate :prime, :search_prime
243
+
244
+ prime(2).fact!
245
+ prime(3).fact!
246
+ prime(:X) << [
247
+ between(:X, 4, 20000),
248
+ is(:X_mod_2, :X){|x| x % 2 },
249
+ noteq(:X_mod_2, 0),
250
+ search_prime(:X, 3),
251
+ ]
252
+
253
+ search_prime(:X, :N) << [
254
+ is(:N_squared, :N){|n| n ** 2 },
255
+ gtr(:N_squared, :X),
256
+ :CUT
257
+ ]
258
+
259
+ search_prime(:X, :N) << [
260
+ is(:X_mod_N, :X, :N){|x,n| x % n },
261
+ noteq(:X_mod_N, 0),
262
+ is(:M, :N){|n| n + 2 },
263
+ :CUT,
264
+ search_prime(:X, :M),
265
+ ]
266
+
267
+ known_primes = [
268
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
269
+ 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
270
+ 211, 223, 227, 229
271
+ ]
272
+
273
+ assert_equal known_primes, prime(:number).solve_for(:number, max_solutions: 50)
274
+ assert_equal 3016, Goal.goal_count
275
+ end
276
+
277
+ end
@@ -17,6 +17,8 @@ SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
17
17
 
18
18
  # -- Testing --
19
19
  require 'minitest/autorun'
20
+ require 'mocha/minitest'
21
+ require 'spy/integration'
20
22
  require 'porolog'
21
23
 
22
24
  include Porolog
@@ -27,6 +29,10 @@ def reset
27
29
  Scope.reset
28
30
  Predicate.reset
29
31
  Arguments.reset
32
+ Rule.reset
33
+ Goal.reset
34
+ Instantiation.reset
35
+ Porolog::ANONYMOUS[0] = '_a'
30
36
  end
31
37
 
32
38
  def assert_Scope(scope, name, predicates)
@@ -46,3 +52,112 @@ def assert_Arguments(arguments, predicate, args)
46
52
  assert_equal predicate, arguments.predicate.name
47
53
  assert_equal args, arguments.arguments
48
54
  end
55
+
56
+ def assert_Rule(rule, predicate, arguments, definition)
57
+ assert_instance_of Rule, rule
58
+ assert_equal predicate, rule.arguments.predicate.name
59
+ assert_equal arguments, rule.arguments.arguments
60
+ assert_equal definition, rule.definition
61
+ end
62
+
63
+ def assert_Goal(goal, predicate, arguments)#, definition)
64
+ assert_instance_of Goal, goal
65
+ assert_equal predicate, goal.arguments.predicate.name
66
+ assert_equal goal.variablise(arguments), goal.arguments.arguments
67
+ # TODO: add definition
68
+ #assert_equal definition, goal.definition
69
+ end
70
+
71
+ def assert_Goal_variables(goal, hash, str)
72
+ assert_instance_of Goal, goal
73
+ assert_equal hash, goal.variables
74
+ assert_equal str, goal.inspect_variables
75
+ end
76
+
77
+ def assert_Value(value, value_value, goal)
78
+ assert_instance_of Value, value
79
+ assert_equal value_value, value.value
80
+ assert_equal goal, value.goal
81
+ end
82
+
83
+ def assert_Variable(variable, name, goal, instantiations, values)
84
+ assert_instance_of Variable, variable
85
+ assert_equal name, variable.name
86
+ assert_equal goal, variable.goal
87
+ assert_equal instantiations, variable.instantiations
88
+ assert_equal values, variable.values
89
+ end
90
+
91
+ def assert_Instantiation(instantiation, variable1, variable2, index1, index2)
92
+ assert_instance_of Instantiation, instantiation
93
+ assert_includes [Variable,Value], variable1.class
94
+ assert_includes [Variable,Value], variable2.class
95
+ assert_equal variable1, instantiation.variable1
96
+ assert_equal variable2, instantiation.variable2
97
+ if index1
98
+ assert_equal index1, instantiation.index1
99
+ else
100
+ assert_nil instantiation.index1
101
+ end
102
+ if index2
103
+ assert_equal index2, instantiation.index2
104
+ else
105
+ assert_nil instantiation.index2
106
+ end
107
+ end
108
+
109
+ def assert_Tail(tail, inspect)
110
+ assert_instance_of Tail, tail
111
+ assert_equal inspect, tail.inspect
112
+ end
113
+
114
+ def assert_Array_with_Tail(array, head, inspect)
115
+ assert_instance_of Array, array
116
+ assert_equal head.size + 1, array.size
117
+ assert_equal head, array[0...head.size]
118
+ assert_Tail array.last, inspect
119
+ end
120
+
121
+ def expect_unify_arrays_with_calls(no_tails, some_tails, all_tails)
122
+ expects(:unify_arrays_with_no_tails ).times(no_tails)
123
+ expects(:unify_arrays_with_some_tails).times(some_tails)
124
+ expects(:unify_arrays_with_all_tails ).times(all_tails)
125
+ end
126
+
127
+ def assert_Unify_arrays(arrays, goals, merged, unifications = [])
128
+ result_merged, result_unifications = unify_arrays(*arrays, *goals)
129
+
130
+ unifications = unifications.map{|v1,v2,g1,g2|
131
+ assert_instance_of Goal, g1
132
+ assert_instance_of Goal, g2
133
+ [g1.variablise(v1), g2.variablise(v2), g1, g2]
134
+ }
135
+
136
+ assert_equal merged, result_merged
137
+ assert_equal unifications, result_unifications
138
+ end
139
+
140
+ def refute_Unify_arrays(arrays, goals, log = [])
141
+ result = unify_arrays(*arrays, *goals)
142
+
143
+ assert_nil result
144
+
145
+ goals.each do |goal|
146
+ assert_equal log, goal.log
147
+ end
148
+ end
149
+
150
+
151
+ def new_goal(predicate_name, *arguments_list)
152
+ predicate = Predicate.new(predicate_name)
153
+ arguments = predicate.arguments(*arguments_list)
154
+ arguments.goal
155
+ end
156
+
157
+ def assert_solutions(arguments, expected_solutions, goals: nil)
158
+ solutions = arguments.solve
159
+
160
+ assert_equal expected_solutions, solutions
161
+ assert_equal goals, Goal.goal_count if goals
162
+ solutions
163
+ end
metadata CHANGED
@@ -1,17 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: porolog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luis Esteban
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-21 00:00:00.000000000 Z
11
+ date: 2020-08-02 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Implements a Prolog inference engine using Plain Old Ruby Objects (work
14
- in progress)
13
+ description: Implements a Prolog inference engine using Plain Old Ruby Objects
15
14
  email:
16
15
  - luis.esteban.consulting@gmail.com
17
16
  executables: []
@@ -23,7 +22,10 @@ files:
23
22
  - bin/porolog
24
23
  - coverage/badge.svg
25
24
  - coverage/index.html
25
+ - doc/Array.html
26
+ - doc/Object.html
26
27
  - doc/Porolog.html
28
+ - doc/Symbol.html
27
29
  - doc/_index.html
28
30
  - doc/class_list.html
29
31
  - doc/file.README.html
@@ -34,13 +36,30 @@ files:
34
36
  - doc/top-level-namespace.html
35
37
  - lib/porolog.rb
36
38
  - lib/porolog/arguments.rb
39
+ - lib/porolog/core_ext.rb
37
40
  - lib/porolog/error.rb
41
+ - lib/porolog/goal.rb
42
+ - lib/porolog/instantiation.rb
38
43
  - lib/porolog/predicate.rb
44
+ - lib/porolog/predicate/builtin.rb
45
+ - lib/porolog/rule.rb
39
46
  - lib/porolog/scope.rb
47
+ - lib/porolog/tail.rb
48
+ - lib/porolog/value.rb
49
+ - lib/porolog/variable.rb
40
50
  - test/porolog/arguments_test.rb
51
+ - test/porolog/core_ext_test.rb
52
+ - test/porolog/goal_test.rb
53
+ - test/porolog/instantiation_test.rb
41
54
  - test/porolog/porolog_test.rb
55
+ - test/porolog/predicate/builtin_test.rb
42
56
  - test/porolog/predicate_test.rb
57
+ - test/porolog/rule_test.rb
43
58
  - test/porolog/scope_test.rb
59
+ - test/porolog/tail_test.rb
60
+ - test/porolog/value_test.rb
61
+ - test/porolog/variable_test.rb
62
+ - test/samples_test.rb
44
63
  - test/test_helper.rb
45
64
  homepage: https://github.com/wizardofosmium/porolog
46
65
  licenses:
@@ -61,14 +80,22 @@ required_rubygems_version: !ruby/object:Gem::Requirement
61
80
  - !ruby/object:Gem::Version
62
81
  version: '0'
63
82
  requirements: []
64
- rubyforge_project:
65
- rubygems_version: 2.7.6
83
+ rubygems_version: 3.0.3
66
84
  signing_key:
67
85
  specification_version: 4
68
- summary: Prolog using Plain Old Ruby Objects (work in progress)
86
+ summary: Prolog using Plain Old Ruby Objects
69
87
  test_files:
70
88
  - test/test_helper.rb
89
+ - test/porolog/instantiation_test.rb
90
+ - test/porolog/predicate/builtin_test.rb
91
+ - test/porolog/variable_test.rb
92
+ - test/porolog/tail_test.rb
71
93
  - test/porolog/porolog_test.rb
94
+ - test/porolog/goal_test.rb
95
+ - test/porolog/core_ext_test.rb
96
+ - test/porolog/rule_test.rb
97
+ - test/porolog/value_test.rb
72
98
  - test/porolog/predicate_test.rb
73
99
  - test/porolog/arguments_test.rb
74
100
  - test/porolog/scope_test.rb
101
+ - test/samples_test.rb