porolog 0.0.1 → 0.0.2

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.
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