rbprolog 0.0.2 → 0.1.0

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