rbprolog 0.0.2 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 53b585062269fdd1b34299a6062ed17d194a24a0
4
- data.tar.gz: 189dee03f4f9bf9d6af6ad3ab04a1b1a6f6b8b1a
3
+ metadata.gz: dda78e71e7f2217c87e9a9c52e81be412f3adc15
4
+ data.tar.gz: 281cf156ef8af5401c8f6365bd7e10f7345d093e
5
5
  SHA512:
6
- metadata.gz: f268165d241aeaf52c27044b3a69c89a92ae4ad5380e1274189d01b6efbab70d117719ec7dd3c9ccf710fd353d64d17a7f0fa9437549cffc5461537029163965
7
- data.tar.gz: d615a690017127e4a957412ce550b2beaf832f3a97d0ccb48a80c810b5672ee1b37bd5ea431fbbdc646ada966daaf8583b2043468cb8f17f9f5d87b25adf4048
6
+ metadata.gz: 70aab09d55abbe7a3ce29d0ceabd55dd149ed3cae2395dd16a038c17de64ec15ebcd7a3f3ddfed2fd4d73dab2a92d9304206ade6bf0aa900d9d010e9718337eb
7
+ data.tar.gz: 441e56975d5aecb431d0aa39801734052949e88a0ea4806d1d7b8a7f0d19ec32c99700d85ab19a0767dd5c2034d7e9342616f504013cd2fb9ce825608aa14093
@@ -2,6 +2,11 @@ module Rbprolog
2
2
  class Context
3
3
  attr_accessor :binds
4
4
 
5
+ def initialize
6
+ @scopes = []
7
+ @binds = {}
8
+ end
9
+
5
10
  def match?(v1, v2)
6
11
  v1 = deduce(v1)
7
12
  Var === v1 || Var === v2 || v1 == v2
@@ -16,10 +21,18 @@ module Rbprolog
16
21
  end
17
22
  end
18
23
 
24
+ def [](sym)
25
+ @binds[sym]
26
+ end
27
+
28
+ def []=(sym, value)
29
+ @binds[sym] = value
30
+ end
31
+
19
32
  def deduce(v)
20
33
  if Var === v
21
34
  unless @binds[v.sym]
22
- @stacks.last << v.sym
35
+ @scopes.last << v.sym
23
36
  @binds[v.sym] = Var.new(v.sym)
24
37
  end
25
38
 
@@ -30,16 +43,13 @@ module Rbprolog
30
43
  end
31
44
 
32
45
  def scope(predicate, &block)
33
- @stacks ||= []
34
- @stacks.push([])
35
-
36
- @binds ||= {}
46
+ @scopes.push([])
37
47
 
38
48
  mirror = @binds.clone
39
49
 
40
- result = yield
50
+ result = yield predicate.args.map {|arg| self.deduce(arg)}
41
51
 
42
- @stacks.pop.each {|bind| @binds.delete bind}
52
+ @scopes.pop.each {|bind| @binds.delete bind}
43
53
  @binds.merge!(mirror)
44
54
 
45
55
  result
@@ -1,35 +1,24 @@
1
1
  module Rbprolog
2
2
  class Deduction
3
- include Enumerable
4
-
5
3
  attr_accessor :args, :sym
6
4
 
7
- def initialize(logic, sym, *args)
8
- @logic = logic
5
+ def initialize(sym, *args)
9
6
  @sym = sym
10
-
11
7
  @args = args
12
8
  end
13
9
 
14
- def each
15
- each_deduce(Context.new, @logic.rules, []) do |hash|
16
- yield hash
17
- end
18
- end
19
-
20
10
  def each_deduce(context, rules, id)
21
- print "#{"\t" * id.size}#{id.join('.')} #{@sym}?(#{@args.map(&:to_s).join(', ')})"
11
+ print "#{"\t" * id.size}#{id.join('.')} #{@sym}?(#{@args.join(', ')})"
22
12
 
23
- rules.select {|rule| rule.sym == @sym}.each_with_index do |rule, i|
24
- context.scope(self) do
25
- puts " => #{@sym}?(#{@args.map {|arg| context.deduce(arg).to_s}.join(', ')})" if i == 0
13
+ rules.select {|rule| rule.sym == @sym}.each_with_index do |rule, rule_index|
14
+ context.scope(self) do |scoped_args|
15
+ puts " => #{@sym}?(#{scoped_args.join(', ')})" if rule_index == 0
26
16
 
27
- rule.each_deduce(rules, *@args.map {|arg| context.deduce(arg)}, id + [i]) do |hash|
17
+ rule.each_match(rules, *scoped_args, id + [rule_index]) do |hash|
28
18
  context.scope(self) do
29
19
  rule.args.each_with_index do |rule_arg, rule_arg_index|
30
- deduced_arg = context.deduce(@args[rule_arg_index])
31
- if Var === deduced_arg
32
- context.binds[deduced_arg.sym] = Var === rule_arg ? hash[rule_arg.sym] : rule_arg
20
+ if Var === scoped_args[rule_arg_index]
21
+ context[scoped_args[rule_arg_index].sym] = Var === rule_arg ? hash[rule_arg.sym] : rule_arg
33
22
  end
34
23
  end
35
24
 
data/lib/rbprolog/rule.rb CHANGED
@@ -10,13 +10,13 @@ module Rbprolog
10
10
  @deductions = [deductions].flatten
11
11
  end
12
12
 
13
- def each_deduce(rules, *args, id)
14
- print "#{"\t" * id.size}#{id.join('.')} #{@sym}(#{@args.map(&:to_s).join(', ')}).deduce(#{args.map(&:to_s).join(', ')})"
13
+ def each_match(rules, *args, id)
14
+ print "#{"\t" * id.size}#{id.join('.')} #{@sym}(#{@args.join(', ')}).deduce(#{args.join(', ')})"
15
15
 
16
16
  context = Context.new
17
- context.scope(self) do
17
+ context.scope(self) do |scoped_args|
18
18
  if self.match!(context, args)
19
- puts " => #{@sym}(#{@args.map {|arg| context.deduce(arg).to_s}.join(', ')})" #{context.to_s} #{context.binds.inspect}"
19
+ puts " => #{@sym}(#{@args.map {|arg| context.deduce(arg)}.join(', ')})"
20
20
  deduce_deductions(context, rules, *@deductions, id) do
21
21
  yield context.binds
22
22
  end
@@ -41,17 +41,17 @@ module Rbprolog
41
41
  if deductions.empty?
42
42
  yield
43
43
  else
44
- predicate = deductions.shift
45
- if Deduction === predicate
46
- predicate.each_deduce(context, rules, id + [@deductions.size - deductions.size - 1]) do |hash|
44
+ deduction = deductions.shift
45
+ if Deduction === deduction
46
+ deduction.each_deduce(context, rules, id + [@deductions.size - deductions.size - 1]) do |hash|
47
47
  deduce_deductions(context, rules, *deductions, id, &block)
48
48
  end
49
49
  else
50
50
  @logic.send(:define_singleton_method, :const_missing) do |sym|
51
- context.binds[sym]
51
+ context[sym]
52
52
  end
53
53
 
54
- predicate.call && deduce_deductions(context, rules, *deductions, id, &block)
54
+ deduction.call && deduce_deductions(context, rules, *deductions, id, &block)
55
55
  end
56
56
 
57
57
  end
@@ -1,3 +1,3 @@
1
1
  module Rbprolog
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/rbprolog.rb CHANGED
@@ -7,18 +7,23 @@ require_relative 'rbprolog/var'
7
7
  module Rbprolog
8
8
  def self.included(mod)
9
9
  class << mod
10
- attr_accessor :rules, :syms
11
-
12
10
  include ClassMethods
11
+ attr_accessor :rules, :syms
13
12
  end
14
13
  end
15
14
 
16
- def initialize(&block)
17
- instance_eval(&block) if block
15
+ def initialize(string = nil, &block)
16
+ if string || block
17
+ self.extend(Rbprolog)
18
+
19
+ self.singleton_class.keywords(*self.class.syms)
20
+ self.singleton_class.class_eval(string) if string
21
+ self.singleton_class.class_eval(&block) if block
22
+ end
18
23
  end
19
24
 
20
25
  def rules
21
- self.class.rules + (@rules || [])
26
+ self.class.rules + (self.singleton_class.rules || [])
22
27
  end
23
28
 
24
29
  module ClassMethods
@@ -37,7 +42,7 @@ module Rbprolog
37
42
  if self.syms.include? sym
38
43
  Hash === args.last ? rule(sym, *args) : rule(sym, *args, :if => [])
39
44
  elsif self.syms.include? sym.to_s.chomp('?').to_sym
40
- Deduction.new(self, sym.to_s.chomp('?').to_sym, *args)
45
+ Deduction.new(sym.to_s.chomp('?').to_sym, *args)
41
46
  else
42
47
  super
43
48
  end
@@ -48,14 +53,19 @@ module Rbprolog
48
53
  self.rules << Rule.new(sym, *args, options[:if])
49
54
 
50
55
  unless method_defined?(sym)
51
- #FIXME only allow fact for now
52
- define_method(sym) do |*args|
53
- @rules ||= []
54
- @rules << Rule.new(sym, *args, [])
55
- end
56
-
57
56
  define_method("#{sym}!") do |*args|
58
- Deduction.new(self, sym, *args)
57
+ deduction = Deduction.new(sym, *args)
58
+
59
+ deduction.extend(Enumerable)
60
+
61
+ rules = self.rules
62
+ deduction.define_singleton_method(:each) do |&block|
63
+ each_deduce(Context.new, rules, []) do |hash|
64
+ block.call hash
65
+ end
66
+ end
67
+
68
+ deduction
59
69
  end
60
70
 
61
71
  define_method("#{sym}?") do |*args|
data/rbprolog.gemspec CHANGED
@@ -18,8 +18,6 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.metadata = { "Source Code" => "https://github.com/rli9/rbprolog" }
22
-
23
21
  spec.add_development_dependency "bundler", "~> 1.3"
24
22
  spec.add_development_dependency "rake"
25
23
  end
@@ -37,6 +37,26 @@ class TestRbprolog < Test::Unit::TestCase
37
37
  assert_equal ['p1', 'p2', 'p3', 'p4'], l.friends!('p1', Rbprolog::Var.new(:W)).map {|hash| hash[:W]}.uniq.sort
38
38
  end
39
39
 
40
+ def test_logic_instance_should_allow_new_fact
41
+ l = FriendLogic.new do
42
+ likes 'p5', 's1'
43
+ end
44
+
45
+ assert_equal true, l.likes?('p5', 's1')
46
+ assert_equal false, l.likes?('p5', 's2')
47
+ assert_equal true, l.friends?('p5', 'p3')
48
+ assert_equal false, l.friends?('p5', 'p2')
49
+ end
50
+
51
+ def test_logic_instance_should_allow_new_rule
52
+ l = FriendLogic.new %q{
53
+ friends 'p2', X, :if => likes?(X, 's1')
54
+ }
55
+
56
+ assert_equal true, l.friends?('p2', 'p3')
57
+ assert_equal true, l.friends?('p2', 'p1')
58
+ end
59
+
40
60
  def test_logic_instances_should_be_independent
41
61
  l1 = FriendLogic.new do
42
62
  likes 'p5', 's1'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbprolog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ruijia Li
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-29 00:00:00.000000000 Z
11
+ date: 2013-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -61,8 +61,7 @@ files:
61
61
  homepage: https://github.com/rli9/rbprolog
62
62
  licenses:
63
63
  - MIT
64
- metadata:
65
- Source Code: https://github.com/rli9/rbprolog
64
+ metadata: {}
66
65
  post_install_message:
67
66
  rdoc_options: []
68
67
  require_paths: