porolog 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 255c18b94a31335781ec500cbec763b710def39e9b1c9e331b573e51b18da80e
4
- data.tar.gz: d676680c7eea7d2fd3df0b3708fd7f09977ed92472616cdf44b3db2eede37688
3
+ metadata.gz: 595dfcb99ad8db28a4aa8b5a71b0f63c4e417dd4b2036ec0e7559c7bf0523438
4
+ data.tar.gz: dc8d09f758aea19d636bd593e3e6a9a9283027e44424ad6cc88ce78445afec64
5
5
  SHA512:
6
- metadata.gz: 2f5018c1e104af58e1decd95f1d55647c6c51c7eb8bf38e3720feb4438d3c52fa24d9cfab000e5251d8160b2980d74234e56dd2c3f1a8991334e98276e519b44
7
- data.tar.gz: 1b4e60c16c278e5c4f3f276545fc0c1e330b895f01c916f053217dd72df1f5f198c3b8feed2a3c5460e1de3f3238da3b5d481e0405de272ee28142361d6adb88
6
+ metadata.gz: 88889f2063831ca8b5a6358e96727c1ad3805a5721d6b39e6b931af584ea24ac12b5dc89bdf18eeff81eed1e93e04b8637f27a1fe62db2a08d126e1e208a16e1
7
+ data.tar.gz: c564320bd055721a1de3a4af742c81f69c51574c88a84207373208870655452508aed97c21c567ba4a0205d4ae4944f9e824fc5b206043facf112f9c799150bc
data/README.md CHANGED
@@ -2,43 +2,72 @@
2
2
 
3
3
  Plain Old Ruby Objects Prolog
4
4
 
5
+ [![Gem Version](https://badge.fury.io/rb/porolog.svg)](https://badge.fury.io/rb/porolog)
6
+ [![Build Status](https://travis-ci.com/wizardofosmium/porolog.svg?branch=master)](https://travis-ci.com/wizardofosmium/porolog)
7
+
5
8
  ## Introduction
6
9
 
7
- porolog is a Prolog implementation using plain old Ruby objects with the aim that
10
+ `porolog` is a Prolog implementation using plain old Ruby objects with the aim that
8
11
  logic queries can be called within a regular Ruby program. The goal was not to
9
12
  implement a Prolog interpreter that is just implement in Ruby, but rather that
10
13
  a logic engine could be embedded in a larger program.
11
14
 
15
+ The need that this gem aims to meet is to have a Ruby program interact with a Prolog
16
+ program using native Ruby objects (POROs); hence the name Porolog.
12
17
  The goal was to implement a minimal logic engine in the style of Prolog where
13
18
  Ruby objects could be passed in and Ruby objects were passed back.
14
19
 
20
+ ## Dependencies
21
+
22
+ The aim of `porolog` is to provide a logic engine with a minimal footprint.
23
+ Thus `porolog` has no dependencies.
24
+
15
25
  ## Installation
16
26
 
17
- gem install porolog
27
+ ```bash
28
+ gem install porolog
29
+ ```
18
30
 
19
31
  ## Usage
20
32
 
33
+ `porolog` is used by:
34
+
35
+ * requiring the library within a Ruby program
36
+ * defining facts and rules
37
+ * solving goals
38
+
39
+ It is entirely possible to create a Ruby program that is effectively just a Prolog program.
40
+
21
41
  ### Basic Usage
22
42
 
23
- require 'porolog'
43
+ Using `porolog` involves creating logic from facts and rules.
44
+ An example, of the most basic usage uses just facts.
24
45
 
25
- prime = Predicate.new :prime
46
+ ```ruby
47
+ require 'porolog'
26
48
 
27
- prime.(2).fact!
28
- prime.(3).fact!
29
- prime.(5).fact!
30
- prime.(7).fact!
49
+ prime = Porolog::Predicate.new :prime
31
50
 
32
- solutions = prime.(:X).solve
51
+ prime.(2).fact!
52
+ prime.(3).fact!
53
+ prime.(5).fact!
54
+ prime.(7).fact!
33
55
 
34
- solutions.each do |solution|
35
- puts "#{solution[:X]} is prime"
36
- end
56
+ solutions = prime.(:X).solve
37
57
 
58
+ solutions.each do |solution|
59
+ puts "#{solution[:X]} is prime"
60
+ end
61
+ ```
38
62
 
39
63
  ### Common Usage
40
64
 
41
- require 'porolog'
65
+ Common usage is expected to be including Porolog in a class and encapsulating the engine defined.
66
+
67
+ ```ruby
68
+ require 'porolog'
69
+
70
+ class Numbers
42
71
 
43
72
  include Porolog
44
73
 
@@ -49,70 +78,88 @@ Ruby objects could be passed in and Ruby objects were passed back.
49
78
  prime(5).fact!
50
79
  prime(7).fact!
51
80
 
52
- solutions = prime(:X).solve
81
+ def show_primes
82
+ solutions = prime(:X).solve
53
83
 
54
- solutions.each do |solution|
55
- puts "#{solution[:X]} is prime"
84
+ solutions.each do |solution|
85
+ puts "#{solution[:X]} is prime"
86
+ end
56
87
  end
57
88
 
58
- ### Scope Usage
59
-
60
- The Scope class enables you to have multiple logic programs embedded in the same
61
- Ruby program. A Scope object defines a scope for the predicates of a logic programme.
62
-
63
- require 'porolog'
64
-
65
- # -- Prime Numbers Predicate --
66
- prime = prime1 = Predicate.new :prime, :numbers
67
-
68
- prime.(2).fact!
69
- prime.(3).fact!
70
- prime.(5).fact!
71
- prime.(7).fact!
72
- prime.(11).fact!
73
-
74
- # -- Pump Predicate --
75
- prime = prime2 = Predicate.new :prime, :pumps
76
-
77
- prime.('pump A').fact!
78
- prime.('pump B').fact!
79
- prime.('pump C').fact!
80
- prime.('pump D').fact!
81
-
82
- assert_equal [:default,:numbers,:pumps], Scope.scopes
89
+ def primes
90
+ prime(:X).solve_for(:X)
91
+ end
83
92
 
84
- assert_scope Scope[:default], :default, []
85
- assert_scope Scope[:numbers], :first, [prime1]
86
- assert_scope Scope[:pumps], :second, [prime2]
93
+ end
94
+ ```
87
95
 
88
- assert_equal :prime, prime1.name
89
- assert_equal :prime, prime2.name
96
+ ### Scope and Predicate Usage
90
97
 
91
- solutions = [
92
- { X: 2 },
93
- { X: 3 },
94
- { X: 5 },
95
- { X: 7 },
96
- { X: 11 },
97
- ]
98
- assert_equal solutions, prime1.(:X).solve
98
+ A Predicate represents a Prolog predicate. They form the basis for rules and queries.
99
99
 
100
- solutions = [
101
- { X: 'pump A' },
102
- { X: 'pump B' },
103
- { X: 'pump C' },
104
- { X: 'pump D' },
105
- ]
106
- assert_equal solutions, prime2.(:X).solve
100
+ The Scope class enables you to have multiple logic programs embedded in the same
101
+ Ruby program. A Scope object defines a scope for the predicates of a logic programme.
107
102
 
103
+ ```ruby
104
+ require 'porolog'
105
+
106
+ # -- Prime Numbers Predicate --
107
+ prime = prime1 = Porolog::Predicate.new :prime, :numbers
108
+
109
+ prime.(2).fact!
110
+ prime.(3).fact!
111
+ prime.(5).fact!
112
+ prime.(7).fact!
113
+ prime.(11).fact!
114
+
115
+ # -- Pump Predicate --
116
+ prime = prime2 = Porolog::Predicate.new :prime, :pumps
117
+
118
+ prime.('pump A').fact!
119
+ prime.('pump B').fact!
120
+ prime.('pump C').fact!
121
+ prime.('pump D').fact!
122
+
123
+ # -- Assertions --
124
+ assert_equal [:default,:numbers,:pumps], Scope.scopes
125
+
126
+ assert_scope Porolog::Scope[:default], :default, []
127
+ assert_scope Porolog::Scope[:numbers], :first, [prime1]
128
+ assert_scope Porolog::Scope[:pumps], :second, [prime2]
129
+
130
+ assert_equal :prime, prime1.name
131
+ assert_equal :prime, prime2.name
132
+
133
+ solutions = [
134
+ { X: 2 },
135
+ { X: 3 },
136
+ { X: 5 },
137
+ { X: 7 },
138
+ { X: 11 },
139
+ ]
140
+ assert_equal solutions, prime1.(:X).solve
141
+
142
+ solutions = [
143
+ { X: 'pump A' },
144
+ { X: 'pump B' },
145
+ { X: 'pump C' },
146
+ { X: 'pump D' },
147
+ ]
148
+ assert_equal solutions, prime2.(:X).solve
149
+ ```
108
150
 
109
151
  ## Testing
110
152
 
111
- rake test
153
+ ```bash
154
+ rake test
155
+ ```
112
156
 
113
157
  or
114
158
 
115
- rake scope_test
159
+ ```bash
160
+ rake scope_test
161
+ rake predicate_test
162
+ ```
116
163
 
117
164
  ## Author
118
165
 
@@ -0,0 +1,103 @@
1
+ #
2
+ # lib/porolog/predicate.rb - Plain Old Ruby Objects Prolog Engine -- Predicate
3
+ #
4
+ # Luis Esteban 2 May 2018
5
+ # created
6
+ #
7
+
8
+ # Porolog::Predicate
9
+ #
10
+ # A Porolog::Predicate corresponds to a Prolog predicate.
11
+ # It contains rules (Porolog::Rule) and belongs to a Porolog::Scope.
12
+ # When provided with arguments, it produces a Porolog::Arguments.
13
+ #
14
+
15
+ module Porolog
16
+
17
+ class Predicate
18
+
19
+ class PredicateError < PorologError ; end
20
+ class NameError < PredicateError ; end
21
+
22
+ attr_reader :name, :rules
23
+
24
+ @@current_scope = Scope[:default]
25
+ @builtin_predicate_ids = {}
26
+
27
+ def self.scope(scope_name = nil)
28
+ if scope_name
29
+ @@current_scope = Scope[scope_name] || Scope.new(scope_name)
30
+ else
31
+ @@current_scope
32
+ end
33
+ end
34
+
35
+ def self.scope=(scope_name)
36
+ if scope_name
37
+ @@current_scope = Scope[scope_name] || Scope.new(scope_name)
38
+ end
39
+ end
40
+
41
+ def self.reset
42
+ scope(:default)
43
+ @builtin_predicate_ids = {}
44
+ end
45
+
46
+ def self.[](name)
47
+ @@current_scope[name]
48
+ end
49
+
50
+ reset
51
+
52
+ def initialize(name, scope_name = Predicate.scope.name)
53
+ @name = name.to_sym
54
+ @rules = []
55
+
56
+ raise NameError.new("Cannot name a predicate 'predicate'") if @name == :predicate
57
+
58
+ scope = Scope[scope_name] || Scope.new(scope_name)
59
+ scope[@name] = self
60
+ end
61
+
62
+ def self.new(*args)
63
+ name, _ = *args
64
+ scope[name.to_sym] || super
65
+ end
66
+
67
+ def call(*args)
68
+ Arguments.new(self,args)
69
+ end
70
+
71
+ def arguments(*args)
72
+ Arguments.new(self,args)
73
+ end
74
+
75
+ def <<(rule)
76
+ @rules << rule
77
+ end
78
+
79
+ def inspect
80
+ lines = []
81
+
82
+ if @rules.size == 1
83
+ lines << "#{@name}:-#{@rules.first.inspect}"
84
+ else
85
+ lines << "#{@name}:-"
86
+ @rules.each do |rule|
87
+ lines << rule.inspect
88
+ end
89
+ end
90
+
91
+ lines.join("\n")
92
+ end
93
+
94
+ def self.builtin(key)
95
+ @builtin_predicate_ids[key] ||= 0
96
+ @builtin_predicate_ids[key] += 1
97
+
98
+ self.new("_#{key}_#{@builtin_predicate_ids[key]}")
99
+ end
100
+
101
+ end
102
+
103
+ end
data/lib/porolog/scope.rb CHANGED
@@ -54,8 +54,7 @@ module Porolog
54
54
  end
55
55
 
56
56
  def []=(name,predicate)
57
- # TODO: Uncomment when Porolog::Predicate has been added.
58
- #raise NotPredicateError.new("#{predicate.inspect} is not a Predicate") unless predicate.is_a?(Predicate)
57
+ raise NotPredicateError.new("#{predicate.inspect} is not a Predicate") unless predicate.is_a?(Predicate)
59
58
  @predicates[name.to_sym] = predicate
60
59
  end
61
60
 
data/lib/porolog.rb CHANGED
@@ -7,10 +7,28 @@
7
7
 
8
8
  module Porolog
9
9
 
10
- VERSION = '0.0.1'
11
- VERSION_DATE = '2018-05-02'
12
-
10
+ VERSION = '0.0.2'
11
+ VERSION_DATE = '2019-04-20'
12
+
13
+ def predicate(*names)
14
+ names = [names].flatten
15
+
16
+ predicates = names.map{|name|
17
+ method = name.to_sym
18
+ predicate = Predicate.new(name)
19
+ Object.class_eval{
20
+ define_method(method){|*args|
21
+ predicate.(*args)
22
+ }
23
+ }
24
+ predicate
25
+ }
26
+
27
+ predicates.size > 1 && predicates || predicates.first
28
+ end
29
+
13
30
  end
14
31
 
15
32
  require_relative 'porolog/error'
16
33
  require_relative 'porolog/scope'
34
+ require_relative 'porolog/predicate'
@@ -0,0 +1,335 @@
1
+ #
2
+ # test/porolog/predicate_test.rb - Test Suite for Porolog::Predicate
3
+ #
4
+ # Luis Esteban 2 May 2018
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
+ describe 'Predicate' do
17
+
18
+ it 'should default to creating predicates in the default scope' do
19
+ assert_equal :default, Predicate.scope.name
20
+
21
+ test = Predicate.new 'test'
22
+
23
+ assert_includes Scope[:default].predicates, test
24
+ end
25
+
26
+ describe '.scope' do
27
+
28
+ it 'should return the current scope for new predicates' do
29
+ assert_equal Scope[:default], Predicate.scope
30
+
31
+ alpha = Predicate.new 'alpha', :new_scope
32
+
33
+ assert_equal Scope[:default], Predicate.scope
34
+
35
+ Predicate.scope :new_scope
36
+
37
+ assert_equal Scope[:new_scope], Predicate.scope
38
+
39
+ bravo = Predicate.new 'bravo'
40
+
41
+ assert_equal [], Scope[:default ].predicates
42
+ assert_equal [alpha,bravo], Scope[:new_scope].predicates
43
+ end
44
+
45
+ it 'should allow predicate scope to be created and set' do
46
+ Predicate.scope :internal
47
+ assert_equal :internal, Predicate.scope.name
48
+
49
+ Predicate.new 'alpha'
50
+
51
+ Predicate.scope :external
52
+ assert_equal :external, Predicate.scope.name
53
+
54
+ Predicate.new 'bravo'
55
+
56
+ Predicate.scope :internal
57
+ assert_equal :internal, Predicate.scope.name
58
+
59
+ Predicate.new 'carly'
60
+ Predicate.new 'delta', :external
61
+
62
+ assert_equal :internal, Predicate.scope.name
63
+
64
+ assert_equal [:alpha,:carly], Scope[:internal].predicates.map(&:name)
65
+ assert_equal [:bravo,:delta], Scope[:external].predicates.map(&:name)
66
+ end
67
+
68
+ end
69
+
70
+ describe '.scope=' do
71
+
72
+ it 'should also allow predicate scope to be assigned' do
73
+ Predicate.scope = :internal
74
+ assert_equal :internal, Predicate.scope.name
75
+
76
+ alpha = Predicate.new 'alpha'
77
+
78
+ Predicate.scope = :external
79
+ assert_equal :external, Predicate.scope.name
80
+
81
+ bravo = Predicate.new 'bravo'
82
+
83
+ Predicate.scope = :internal
84
+ assert_equal :internal, Predicate.scope.name
85
+
86
+ carly = Predicate.new 'carly'
87
+ delta = Predicate.new 'delta', :external
88
+
89
+ assert_equal :internal, Predicate.scope.name
90
+
91
+ assert_equal [alpha,carly], Scope[:internal].predicates
92
+ assert_equal [bravo,delta], Scope[:external].predicates
93
+ end
94
+
95
+ end
96
+
97
+ describe '.reset' do
98
+
99
+ it 'should revert to the default scope when reset' do
100
+ Predicate.scope = :other
101
+ assert_equal :other, Predicate.scope.name
102
+
103
+ Predicate.reset
104
+ assert_equal :default, Predicate.scope.name
105
+
106
+ Predicate.scope :temporary
107
+
108
+ alpha = Predicate.new :alpha
109
+
110
+ assert_equal :temporary, Predicate.scope.name
111
+ assert_equal [alpha], Predicate.scope.predicates
112
+
113
+ Predicate.reset
114
+
115
+ bravo = Predicate.new :bravo
116
+
117
+ assert_equal :default, Predicate.scope.name
118
+ assert_equal [bravo], Predicate.scope.predicates
119
+ end
120
+
121
+ end
122
+
123
+ describe '.[]' do
124
+
125
+ it 'should return a predicate by name' do
126
+ alpha = Predicate.new :alpha
127
+
128
+ assert_equal alpha, Predicate[:alpha]
129
+ end
130
+
131
+ end
132
+
133
+ describe '.new' do
134
+
135
+ it 'should create a new predicate' do
136
+ alpha = Predicate.new :alpha
137
+
138
+ assert_instance_of Predicate, alpha
139
+ end
140
+
141
+ it 'should not create a predicate if a predicate with the same name already exists in the scope but instead return the existing one' do
142
+ predicate1 = Predicate.new 'predicate1', :left
143
+ predicate2 = Predicate.new 'predicate1', :right
144
+
145
+ refute_equal predicate1, predicate2
146
+
147
+ Predicate.scope :left
148
+ predicate3 = Predicate.new :predicate1
149
+
150
+ assert_equal predicate1, predicate3
151
+ end
152
+
153
+ end
154
+
155
+ describe '#initialize' do
156
+
157
+ it 'can create predicates in different scopes' do
158
+ left = Scope.new :left
159
+ #right = Scope.new :right # Not explicitly creating scope :right
160
+
161
+ assert_equal left, Predicate.scope(:left)
162
+ assert_equal :left, Predicate.scope.name
163
+
164
+ left_test = Predicate.new 'left_test'
165
+
166
+ assert_equal :left, Predicate.scope.name
167
+ refute_empty left.predicates
168
+ assert_includes left.predicates, left_test
169
+
170
+ right_test = Predicate.new 'right_test', :right
171
+
172
+ assert_includes Scope[:right].predicates, right_test
173
+ assert_equal :left, Predicate.scope.name
174
+
175
+ assert_equal [left_test], Scope[:left ].predicates
176
+ assert_equal [right_test], Scope[:right].predicates
177
+ end
178
+
179
+ it 'should not create a Predicate named "predicate"' do
180
+ assert_raises Porolog::Predicate::NameError do
181
+ predicate :predicate
182
+ end
183
+ assert_raises Porolog::Predicate::NameError do
184
+ predicate 'predicate'
185
+ end
186
+ assert_raises Porolog::Predicate::NameError do
187
+ Predicate.new :predicate
188
+ end
189
+ assert_raises Porolog::Predicate::NameError do
190
+ Predicate.new 'predicate'
191
+ end
192
+ end
193
+
194
+ end
195
+
196
+ describe '#call' do
197
+
198
+ it 'should create an Arguments when "called"' do
199
+ skip 'until Arguments added'
200
+
201
+ p = Predicate.new :p
202
+
203
+ arguments = p.(1,2,3)
204
+
205
+ assert_instance_of Arguments, arguments
206
+ assert_equal [1,2,3], arguments.arguments
207
+ assert_equal 'p(1,2,3)', arguments.inspect
208
+ end
209
+
210
+ end
211
+
212
+ describe '#arguments' do
213
+
214
+ it 'should provide a convenience method to create an Arguments' do
215
+ skip 'until Arguments added'
216
+
217
+ p = Predicate.new :p
218
+
219
+ arguments = p.arguments(1,2,3)
220
+
221
+ assert_instance_of Arguments, arguments
222
+ assert_equal [1,2,3], arguments.arguments
223
+ assert_equal 'p(1,2,3)', arguments.inspect
224
+ end
225
+
226
+ end
227
+
228
+ describe '#name' do
229
+
230
+ it 'should create predicates with a name attribute, which is converted to a Symbol' do
231
+ test_predicate = Predicate.new('test_predicate_name')
232
+
233
+ assert_respond_to test_predicate, :name
234
+ assert_equal :test_predicate_name, test_predicate.name
235
+ end
236
+
237
+ end
238
+
239
+ describe '#rules' do
240
+
241
+ it 'should create predicates with an empty set of rules' do
242
+ test_predicate = Predicate.new('test_predicate_name')
243
+
244
+ assert_respond_to test_predicate, :rules
245
+ assert_equal [], test_predicate.rules
246
+ end
247
+
248
+ it 'should add new facts to a predicate' do
249
+ skip 'until Arguments added'
250
+
251
+ alpha = Predicate.new 'alpha'
252
+
253
+ alpha.('p','q').fact!
254
+
255
+ assert_equal 1, alpha.rules.size
256
+ assert_equal true, alpha.rules.first.definition
257
+ assert_equal ' alpha("p","q"):- true', alpha.rules.first.inspect
258
+ assert_equal 'alpha:- alpha("p","q"):- true', alpha.inspect
259
+
260
+ assert_predicate alpha, :alpha, [alpha.rules.first]
261
+ end
262
+
263
+ it 'should add new falicies to a predicate' do
264
+ skip 'until Arguments added'
265
+
266
+ alpha = Predicate.new 'alpha'
267
+
268
+ alpha.('p','q').falicy!
269
+
270
+ assert_equal 1, alpha.rules.size
271
+ assert_equal false, alpha.rules.first.definition
272
+ assert_equal ' alpha("p","q"):- false', alpha.rules.first.inspect
273
+ assert_equal 'alpha:- alpha("p","q"):- false', alpha.inspect
274
+
275
+ assert_predicate alpha, :alpha, [alpha.rules.first]
276
+ end
277
+
278
+ end
279
+
280
+ describe '#inspect' do
281
+
282
+ it 'should return a summary of the predicate' do
283
+ skip 'until Arguments added'
284
+
285
+ alpha = Predicate.new 'alpha'
286
+ assert_equal 'alpha:-', alpha.inspect
287
+
288
+ alpha.(:x,:y) << [
289
+ alpha.(:x,:y),
290
+ alpha.(:y,:x),
291
+ :CUT
292
+ ]
293
+ assert_equal 'alpha:- alpha(:x,:y):- [alpha(:x,:y), alpha(:y,:x), :CUT]', alpha.inspect
294
+ end
295
+
296
+ end
297
+
298
+ describe '#<<' do
299
+
300
+ it 'should add new rules to a predicate' do
301
+ skip 'until Arguments added'
302
+
303
+ alpha = Predicate.new 'alpha'
304
+
305
+ alpha.(:P,:Q) << [
306
+ alpha.(:P,:Q),
307
+ alpha.(:Q,:P),
308
+ ]
309
+ alpha.(:P,:Q) << [
310
+ alpha.(:P,:P),
311
+ alpha.(:Q,:Q),
312
+ ]
313
+
314
+ assert_equal 2, alpha.rules.size
315
+ assert_instance_of Array, alpha.rules.first.definition
316
+ assert_equal 2, alpha.rules.first.definition.size
317
+
318
+ assert_arguments alpha.rules.first.definition[0], :alpha, [:P,:Q]
319
+ assert_arguments alpha.rules.first.definition[1], :alpha, [:Q,:P]
320
+
321
+ assert_equal ' alpha(:P,:Q):- [alpha(:P,:Q), alpha(:Q,:P)]', alpha.rules.first.inspect
322
+ assert_equal [
323
+ 'alpha:-',
324
+ ' alpha(:P,:Q):- [alpha(:P,:Q), alpha(:Q,:P)]',
325
+ ' alpha(:P,:Q):- [alpha(:P,:P), alpha(:Q,:Q)]',
326
+ ].join("\n"), alpha.inspect
327
+
328
+ assert_predicate alpha, :alpha, [alpha.rules.first,alpha.rules.second]
329
+ end
330
+
331
+ end
332
+
333
+ end
334
+
335
+ end
@@ -23,7 +23,7 @@ describe 'Porolog' do
23
23
  end
24
24
 
25
25
  it 'should allow predicates with the same name to coexist in different scopes' do
26
- skip 'until Predicate added'
26
+ skip 'until Arguments added'
27
27
 
28
28
  prime = prime1 = Predicate.new :prime, :first
29
29
 
@@ -82,8 +82,6 @@ describe 'Porolog' do
82
82
  describe '.reset' do
83
83
 
84
84
  it 'should clear all scopes' do
85
- skip 'until Predicate added'
86
-
87
85
  delta = Predicate.new :delta
88
86
 
89
87
  Scope.new :alpha
@@ -111,8 +109,6 @@ describe 'Porolog' do
111
109
  end
112
110
 
113
111
  it 'should clear all scopes and start with a default scope when reset' do
114
- skip 'until Predicate added'
115
-
116
112
  test_predicate0 = Predicate.new 'test_predicate0'
117
113
  test_predicate11 = Predicate.new 'test_predicate11', :scope1
118
114
  test_predicate12 = Predicate.new 'test_predicate12', :scope1
@@ -201,8 +197,6 @@ describe 'Porolog' do
201
197
  describe '#predicates' do
202
198
 
203
199
  it 'should provide access to all the predicates of a scope' do
204
- skip 'until Predicate added'
205
-
206
200
  test_predicate1 = Predicate.new 'test_predicate1', :test
207
201
  test_predicate2 = Predicate.new 'test_predicate2', :test
208
202
 
@@ -215,8 +209,6 @@ describe 'Porolog' do
215
209
  describe '#[]' do
216
210
 
217
211
  it 'should provide access to a predicate of a scope by its name' do
218
- skip 'until Predicate added'
219
-
220
212
  test_predicate3 = Predicate.new 'test_predicate3', :test
221
213
  test_predicate4 = Predicate.new 'test_predicate4', :test
222
214
 
@@ -236,8 +228,6 @@ describe 'Porolog' do
236
228
  describe '#[]=' do
237
229
 
238
230
  it 'should raise an error when trying to put anthing but a Predicate in a Scope' do
239
- skip 'until Predicate added'
240
-
241
231
  error = assert_raises(Porolog::Scope::NotPredicateError){
242
232
  scope = Scope.new :scope
243
233
 
@@ -247,8 +237,6 @@ describe 'Porolog' do
247
237
  end
248
238
 
249
239
  it 'should allow an existing predicate to be assigned to a scope' do
250
- skip 'until Predicate added'
251
-
252
240
  test_predicate = Predicate.new 'test_predicate', :test
253
241
 
254
242
  scope = Scope.new :scope
data/test/test_helper.rb CHANGED
@@ -12,6 +12,7 @@ include Porolog
12
12
 
13
13
  def reset
14
14
  Scope.reset
15
+ Predicate.reset
15
16
  end
16
17
 
17
18
  def assert_scope(scope, name, predicates)
@@ -19,3 +20,9 @@ def assert_scope(scope, name, predicates)
19
20
  assert_equal name, scope.name
20
21
  assert_equal predicates, scope.predicates
21
22
  end
23
+
24
+ def assert_predicate(predicate, name, rules)
25
+ assert_instance_of Predicate, predicate
26
+ assert_equal name, predicate.name
27
+ assert_equal rules, predicate.rules
28
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: porolog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luis Esteban
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-02 00:00:00.000000000 Z
11
+ date: 2019-04-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Implements a Prolog inference engine using Plain Old Ruby Objects
14
14
  email:
@@ -22,10 +22,12 @@ files:
22
22
  - bin/porolog
23
23
  - lib/porolog.rb
24
24
  - lib/porolog/error.rb
25
+ - lib/porolog/predicate.rb
25
26
  - lib/porolog/scope.rb
27
+ - test/porolog/predicate_test.rb
26
28
  - test/porolog/scope_test.rb
27
29
  - test/test_helper.rb
28
- homepage: http://rubygems.org/gems/porolog
30
+ homepage: https://github.com/wizardofosmium/porolog
29
31
  licenses:
30
32
  - Unlicense
31
33
  metadata: {}
@@ -51,4 +53,5 @@ specification_version: 4
51
53
  summary: Prolog using Plain Old Ruby Objects
52
54
  test_files:
53
55
  - test/test_helper.rb
56
+ - test/porolog/predicate_test.rb
54
57
  - test/porolog/scope_test.rb