rubylog 0.0.1 → 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 (122) hide show
  1. data/Gemfile +1 -1
  2. data/README.hu.rb +58 -0
  3. data/README.rdoc +248 -89
  4. data/Rakefile +6 -1
  5. data/VERSION +1 -1
  6. data/bin/rubylog +18 -0
  7. data/examples/dcg.rb +35 -0
  8. data/examples/dcg2.rb +42 -0
  9. data/examples/enumerators.rb +30 -0
  10. data/examples/factorial.rb +9 -8
  11. data/examples/hanoi.rb +24 -0
  12. data/examples/hello.rb +11 -5
  13. data/examples/parsing.rb +27 -0
  14. data/examples/primitives.rb +24 -0
  15. data/examples/theory.rb +22 -10
  16. data/lib/rubylog/builtins/default.rb +10 -0
  17. data/lib/rubylog/builtins/file_system.rb +15 -0
  18. data/lib/rubylog/builtins/logic.rb +109 -0
  19. data/lib/rubylog/builtins/reflection.rb +94 -0
  20. data/lib/rubylog/builtins/term.rb +47 -0
  21. data/lib/rubylog/dsl/array_splat.rb +25 -0
  22. data/lib/rubylog/dsl/primitives.rb +17 -0
  23. data/lib/rubylog/dsl/thats.rb +22 -0
  24. data/lib/rubylog/dsl/variables.rb +30 -0
  25. data/lib/rubylog/dsl.rb +35 -17
  26. data/lib/rubylog/errors.rb +19 -1
  27. data/lib/rubylog/interfaces/assertable.rb +16 -0
  28. data/lib/rubylog/interfaces/callable.rb +18 -0
  29. data/lib/rubylog/interfaces/composite_term.rb +47 -0
  30. data/lib/rubylog/interfaces/predicate.rb +8 -0
  31. data/lib/rubylog/interfaces/procedure.rb +60 -0
  32. data/lib/rubylog/interfaces/term.rb +41 -0
  33. data/lib/rubylog/mixins/array.rb +118 -0
  34. data/lib/{class.rb → rubylog/mixins/class.rb} +2 -2
  35. data/lib/rubylog/mixins/hash.rb +8 -0
  36. data/lib/rubylog/mixins/kernel.rb +5 -0
  37. data/lib/rubylog/mixins/method.rb +3 -0
  38. data/lib/rubylog/mixins/object.rb +8 -0
  39. data/lib/rubylog/mixins/proc.rb +37 -0
  40. data/lib/rubylog/mixins/string.rb +104 -0
  41. data/lib/rubylog/mixins/symbol.rb +44 -0
  42. data/lib/rubylog/simple_procedure.rb +8 -0
  43. data/lib/rubylog/{clause.rb → structure.rb} +32 -31
  44. data/lib/rubylog/theory.rb +368 -79
  45. data/lib/rubylog/variable.rb +102 -23
  46. data/lib/rubylog.rb +33 -25
  47. data/logic/builtins/file_system_logic.rb +23 -0
  48. data/logic/builtins/reflection_logic.rb +40 -0
  49. data/logic/dereference_logic.rb +23 -0
  50. data/logic/directory_structure_logic.rb +19 -0
  51. data/logic/dsl_logic.rb +29 -0
  52. data/logic/errors_logic.rb +9 -0
  53. data/logic/guard_logic.rb +115 -0
  54. data/logic/list_logic.rb +55 -0
  55. data/logic/map_logic.rb +15 -0
  56. data/logic/multitheory.rb +23 -0
  57. data/logic/recursion_logic.rb +12 -0
  58. data/logic/string_logic.rb +41 -0
  59. data/logic/thats_logic.rb +51 -0
  60. data/logic/variable_logic.rb +24 -0
  61. data/rubylog.gemspec +85 -46
  62. data/spec/bartak_guide_spec.rb +57 -62
  63. data/spec/builtins/all_spec.rb +99 -0
  64. data/spec/builtins/and_spec.rb +22 -0
  65. data/spec/builtins/array_spec.rb +16 -0
  66. data/spec/builtins/branch_or_spec.rb +27 -0
  67. data/spec/builtins/cut_spec.rb +44 -0
  68. data/spec/builtins/fail_spec.rb +5 -0
  69. data/spec/builtins/false_spec.rb +5 -0
  70. data/spec/builtins/in_spec.rb +38 -0
  71. data/spec/builtins/is_false_spec.rb +12 -0
  72. data/spec/builtins/is_spec.rb +26 -0
  73. data/spec/builtins/matches_spec.rb +23 -0
  74. data/spec/builtins/or_spec.rb +22 -0
  75. data/spec/{rubylog/builtins → builtins}/splits_to.rb +0 -0
  76. data/spec/builtins/then_spec.rb +27 -0
  77. data/spec/builtins/true_spec.rb +5 -0
  78. data/spec/clause_spec.rb +82 -0
  79. data/spec/compilation_spec.rb +61 -0
  80. data/spec/custom_classes_spec.rb +43 -0
  81. data/spec/dereference.rb +10 -0
  82. data/spec/{inriasuite.rb → inriasuite_spec.rb} +2 -9
  83. data/spec/queries_spec.rb +150 -0
  84. data/spec/recursion_spec.rb +4 -4
  85. data/spec/ruby_code_spec.rb +52 -0
  86. data/spec/rules_spec.rb +97 -0
  87. data/spec/spec_helper.rb +6 -2
  88. data/spec/theory_spec.rb +28 -0
  89. data/spec/unification_spec.rb +84 -0
  90. data/spec/variable_spec.rb +26 -0
  91. metadata +153 -180
  92. data/examples/4queens.rb +0 -10
  93. data/examples/calculation.rb +0 -12
  94. data/examples/concepts.rb +0 -46
  95. data/examples/fp.rb +0 -56
  96. data/examples/historia_de_espana.rb +0 -31
  97. data/examples/idea.rb +0 -143
  98. data/examples/lists.rb +0 -5
  99. data/examples/mechanika.rb +0 -409
  100. data/examples/parse.rb +0 -15
  101. data/lib/array.rb +0 -24
  102. data/lib/method.rb +0 -4
  103. data/lib/object.rb +0 -5
  104. data/lib/proc.rb +0 -4
  105. data/lib/rubylog/builtins.rb +0 -193
  106. data/lib/rubylog/callable.rb +0 -20
  107. data/lib/rubylog/composite_term.rb +0 -38
  108. data/lib/rubylog/dsl/constants.rb +0 -15
  109. data/lib/rubylog/dsl/first_order_functors.rb +0 -9
  110. data/lib/rubylog/dsl/global_functors.rb +0 -3
  111. data/lib/rubylog/dsl/second_order_functors.rb +0 -8
  112. data/lib/rubylog/internal_helpers.rb +0 -16
  113. data/lib/rubylog/predicate.rb +0 -34
  114. data/lib/rubylog/proc_method_additions.rb +0 -69
  115. data/lib/rubylog/term.rb +0 -20
  116. data/lib/rubylog/unifiable.rb +0 -19
  117. data/lib/symbol.rb +0 -35
  118. data/script/inriasuite2spec +0 -0
  119. data/script/inriasuite2spec.pl +0 -22
  120. data/spec/rubylog/clause_spec.rb +0 -81
  121. data/spec/rubylog/variable_spec.rb +0 -25
  122. data/spec/rubylog_spec.rb +0 -914
@@ -0,0 +1,24 @@
1
+ $:.unshift File.dirname(__FILE__)+"/../lib"
2
+ require 'rubylog'
3
+
4
+ Rubylog.theory "Try" do
5
+ subject String
6
+
7
+ def primitives.hello
8
+ puts "Hello"
9
+ yield
10
+ end
11
+
12
+ def primitives.hello x
13
+ puts "Hello #{x.rubylog_deep_dereference}!"
14
+ yield
15
+ end
16
+
17
+ :hello_world.if "World".hello
18
+
19
+ end
20
+
21
+
22
+ p Try.prove :hello
23
+ p Try.prove :hello_world
24
+ p Try.prove{X.is("World").and X.hello}
data/examples/theory.rb CHANGED
@@ -1,20 +1,32 @@
1
+ $:.unshift File.dirname(__FILE__)+"/../lib"
1
2
  require 'rubylog'
2
3
 
3
- class << AccessControlTheory = Rubylog::Theory.new
4
- U.can_access_model(M).
5
- if U.cannot_access_model(M).then :cut.and :fail
6
- U.can_access_model(M).if M.is(Conversation).and {|u,m|m.users.include? u}
4
+ class User
5
+ attr_accessor :favorite, :possessions
7
6
 
8
- private
7
+ def initialize favorite, possessions
8
+ @favorite, @possessions = favorite, possessions
9
+ end
10
+ end
9
11
 
10
- U.cannot_access_model(M).if U.banned
11
- U.banned.if {|u| !u.active?}
12
+ Rubylog.theory "LikingTheory" do
13
+ functor :likes
14
+ U.likes(D).if {U.favorite == D}
15
+ end
12
16
 
17
+ Rubylog.theory "HavingTheory" do
18
+ functor :has
19
+ U.has(D).if {U.possessions.include? D}
13
20
  end
14
21
 
15
- class User
16
- include_theory AccessControlTheory
22
+ Rubylog.theory "DrinkingTheory" do
23
+ functor :drinks
24
+ include LikingTheory, HavingTheory
25
+ subject User
17
26
 
27
+ U.drinks(D).if U.likes(D).and U.has(D)
18
28
  end
19
29
 
20
-
30
+ joe = User.new :beer, [:water, :beer]
31
+ p DrinkingTheory.true? joe.drinks :water # false
32
+ p DrinkingTheory.true? joe.drinks :beer # true
@@ -0,0 +1,10 @@
1
+ # Includes every builtin library required. +logic+ and +term+ builtins are
2
+ # included by default.
3
+ Rubylog.theory "Rubylog::DefaultBuiltins", nil do
4
+ end
5
+
6
+ require File.dirname(__FILE__)+"/logic"
7
+ require File.dirname(__FILE__)+"/term"
8
+
9
+
10
+
@@ -0,0 +1,15 @@
1
+ theory "Rubylog::FileSystemBuiltins", nil do
2
+ subject String
3
+ functor :filename_in, :dirname_in, :file_in, :dir_in
4
+
5
+ X.filename_in(D).if Y.file_in(D).and X.is { File.basename Y }
6
+ X.dirname_in(D).if Y.dir_in(D).and X.is { File.basename Y }
7
+ X.file_in(D).if Y.in { d = D.rubylog_resolve_function; Dir["#{d}/*", "#{d}/.*"].sort }.and { not ['.','..'].include? File.basename(Y) and not File.directory? Y }.and X.is {File.expand_path Y}
8
+ X.dir_in(D). if Y.in { d = D.rubylog_resolve_function; Dir["#{d}/*", "#{d}/.*"].sort }.and { not ['.','..'].include? File.basename(Y) and File.directory? Y }.and X.is {File.expand_path Y}
9
+
10
+ end
11
+
12
+
13
+ Rubylog::DefaultBuiltins.amend do
14
+ include Rubylog::FileSystemBuiltins
15
+ end
@@ -0,0 +1,109 @@
1
+ Rubylog.theory "Rubylog::NullaryLogicBuiltins", nil do
2
+ class << primitives
3
+ # true
4
+ def true
5
+ yield
6
+ end
7
+
8
+ # fail
9
+ def fail
10
+ end
11
+
12
+ # !
13
+ def cut!
14
+ yield
15
+ throw :cut
16
+ end
17
+ end
18
+ end
19
+
20
+ Rubylog.theory "Rubylog::LogicBuiltinsForCallable", nil do
21
+ subject ::Rubylog::Callable, ::Rubylog::Structure, Symbol, Proc
22
+
23
+ class << primitives
24
+ # Succeeds if both +a+ and +b+ succeeds.
25
+ def and a, b
26
+ a.prove { b.prove { yield } }
27
+ end
28
+
29
+ # Succeeds if either +a+ or +b+ succeeds.
30
+ def or a, b
31
+ a.prove { yield }
32
+ b.prove { yield }
33
+ end
34
+
35
+ # Succeeds if +a+ does not succeed.
36
+ def false a
37
+ a.prove { return }
38
+ yield
39
+ end
40
+
41
+ # ruby iterator predicate allegories
42
+
43
+ # For each successful execution of +a+, executes +b+. If any of +b+'s
44
+ # executions fails, it fails, otherwise it succeeds.
45
+ def all a,b
46
+ a.prove {
47
+ stands = false;
48
+ b.prove { stands = true; break }
49
+ return if not stands
50
+ }
51
+ yield
52
+ end
53
+
54
+ # Equivalent with +a.all(b).and b.all(a)+
55
+ def iff a,b
56
+ all(a,b) { all(b,a) { yield } }
57
+ end
58
+
59
+ #
60
+ def any a,b
61
+ a.prove { b.prove { yield; return } }
62
+ end
63
+
64
+ def one a,b
65
+ stands = false
66
+ a.prove {
67
+ b.prove {
68
+ return if stands
69
+ stands = true
70
+ }
71
+ }
72
+ yield if stands
73
+ end
74
+
75
+ def none a,b
76
+ a.prove { b.prove { return } }
77
+ yield
78
+ end
79
+
80
+ def any a
81
+ a.prove { yield; return }
82
+ end
83
+
84
+ def one a
85
+ stands = false
86
+ a.prove {
87
+ return if stands
88
+ stands = true
89
+ }
90
+ yield if stands
91
+ end
92
+
93
+ alias none false
94
+
95
+ end
96
+
97
+ prefix_functor :all, :any, :one, :none, :iff
98
+
99
+ end
100
+
101
+ Rubylog.theory "Rubylog::LogicBuiltins", nil do
102
+ include Rubylog::NullaryLogicBuiltins
103
+ include Rubylog::LogicBuiltinsForCallable
104
+ end
105
+
106
+ Rubylog::DefaultBuiltins.amend do
107
+ include Rubylog::LogicBuiltins
108
+ end
109
+
@@ -0,0 +1,94 @@
1
+ Rubylog.theory "Rubylog::ReflectionBuiltinsForStructure", nil do
2
+ subject Rubylog::Structure
3
+
4
+ class << primitives
5
+
6
+ # Succeeds if +c+ is a structure, with functor +fct+ and arguments +args+
7
+ def structure c, fct, args
8
+ c = c.rubylog_dereference
9
+ if c.is_a? Rubylog::Variable
10
+ fct = fct.rubylog_dereference
11
+ args = args.rubylog_dereference
12
+ # We enable variable functors
13
+ #raise Rubylog::InstantiationError, fct if fct.is_a? Rubylog::Variable
14
+ raise Rubylog::InstantiationError, args if args.is_a? Rubylog::Variable
15
+ c.rubylog_unify(Rubylog::Structure.new(fct, *args)) { yield }
16
+ elsif c.is_a? Rubylog::Structure
17
+ c.functor.rubylog_unify fct do
18
+ c.args.rubylog_unify args do
19
+ yield
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ # I don't remember what this is supposed to be.
26
+ #def predicate l
27
+ #_functor = Rubylog::Variable.new(:_functor)
28
+ #_arity = Rubylog::Variable.new(:_arity)
29
+ #l.rubylog_unify [f, a] do
30
+ #if f = _functor.value
31
+ ## TODO
32
+ #else
33
+ ## TODO
34
+ #end
35
+ #end
36
+ #end
37
+
38
+ # Succeeds if +head+ unifies with a fact.
39
+ def fact head
40
+ head = head.rubylog_dereference
41
+ raise Rubylog::InstantiationError, head if head.is_a? Rubylog::Variable
42
+ return yield if head == :true
43
+ return unless head.respond_to? :functor
44
+ predicate = Rubylog.current_theory[head.indicator]
45
+ if predicate.respond_to? :each # if it is a procedure
46
+ predicate.each do |rule|
47
+ if rule[1] == :true
48
+ rule = rule.rubylog_compile_variables
49
+ rule[0].args.rubylog_unify head.args do
50
+ yield
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ # Succeeds if +head+ unifies with a rule's head and +body+ unifies with
58
+ # this rule's body.
59
+ def follows_from head, body
60
+ head = head.rubylog_dereference
61
+ raise Rubylog::InstantiationError, head if head.is_a? Rubylog::Variable
62
+ return unless head.respond_to? :functor
63
+ predicate = Rubylog.current_theory[head.indicator]
64
+ if predicate.respond_to? :each
65
+ predicate.each do |rule|
66
+ unless rule[1]==:true # do not succeed for facts
67
+ rule = rule.rubylog_compile_variables
68
+ rule[0].args.rubylog_unify head.args do
69
+ rule[1].rubylog_unify body do
70
+ yield
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ # Succeeds if +a+ unifies with a variable by the name +name+ in the variable binding
79
+ # context of +name+.
80
+ # Removed because of the "every built-in prediate is pure logical" principle
81
+ #def variable a, name
82
+ #vars = name.rubylog_variables
83
+ #raise Rubylog::InvalidStateError, "variables not available" if not vars
84
+ #vars.find
85
+ #end
86
+ end
87
+ end
88
+ Rubylog.theory "Rubylog::ReflectionBuiltins", nil do
89
+ include Rubylog::ReflectionBuiltinsForStructure
90
+ end
91
+
92
+ Rubylog::DefaultBuiltins.amend do
93
+ include Rubylog::ReflectionBuiltins
94
+ end
@@ -0,0 +1,47 @@
1
+ Rubylog.theory "Rubylog::TermBuiltins", nil do
2
+ subject ::Rubylog::Term
3
+
4
+ class << primitives
5
+ # = is
6
+ def is a,b
7
+ a = a.rubylog_resolve_function
8
+ b = b.rubylog_resolve_function
9
+ a.rubylog_unify(b) { yield }
10
+ end
11
+
12
+ def is_not a,b
13
+ a = a.rubylog_resolve_function
14
+ b = b.rubylog_resolve_function
15
+ a.rubylog_unify(b) { return }
16
+ yield
17
+ end
18
+
19
+ # member
20
+ def in a,b
21
+ a = a.rubylog_resolve_function
22
+ b = b.rubylog_resolve_function.rubylog_dereference
23
+ if b.instance_of? Rubylog::Variable
24
+ Rubylog::InternalHelpers.non_empty_list {|l|
25
+ a.rubylog_unify(l[-1]) {
26
+ b.rubylog_unify(l) {
27
+ yield
28
+ }
29
+ }
30
+ }
31
+ else
32
+ b.each do |e|
33
+ a.rubylog_unify(e) { yield }
34
+ end
35
+ end
36
+ end
37
+
38
+ def not_in a, b
39
+ self.in(a, b) { return }
40
+ yield
41
+ end
42
+ end
43
+ end
44
+
45
+ Rubylog::DefaultBuiltins.amend do
46
+ include Rubylog::TermBuiltins
47
+ end
@@ -0,0 +1,25 @@
1
+ # this class is used as a placeholder for array splats.
2
+ # [*A] => [ArraySplat.new(A)]
3
+ class Rubylog::DSL::ArraySplat
4
+
5
+ attr_reader :var
6
+
7
+ def initialize var = Rubylog::Variable.new
8
+ @var = var
9
+ end
10
+
11
+ def inspect
12
+ "*#{var}"
13
+ end
14
+
15
+ # CompositeTerm methods
16
+ include Rubylog::CompositeTerm
17
+
18
+ def rubylog_clone &block
19
+ block[Rubylog::DSL::ArraySplat.new(@var.rubylog_clone(&block))]
20
+ end
21
+
22
+ def rubylog_deep_dereference
23
+ Rubylog::DSL::ArraySplat.new(@var.rubylog_deep_dereference)
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ class Rubylog::DSL::Primitives
2
+ def initialize theory
3
+ @theory = theory
4
+ end
5
+
6
+ def singleton_method_added name
7
+ unless name == :singleton_method_added
8
+ m = method(name)
9
+ @theory.functor name unless m.arity.zero?
10
+ @theory[[name, m.arity]] = m
11
+ end
12
+ end
13
+
14
+ def inspect
15
+ "primitives"
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ class Rubylog::DSL::Thats < BasicObject
2
+ def method_missing *msg
3
+ @messages ||= []
4
+ @messages << msg
5
+ self
6
+ end
7
+
8
+ def rubylog_matches_as_guard? other
9
+ @messages.inject(other) {|o,msg|o.send *msg}
10
+ end
11
+
12
+ def == *msg
13
+ method_missing :==, *msg
14
+ end
15
+
16
+ debug = true
17
+ if debug
18
+ def inspect
19
+ @messages
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ module Rubylog::DSL::Variables
2
+ def self.included mod
3
+ def mod.const_missing c
4
+ # different semantics in native blocks than otherwise
5
+ # @see Proc#call_with_rubylog_variables
6
+ if vars = Thread.current[:rubylog_current_variables]
7
+ # in native blocks
8
+
9
+ # find the appropriate variable name
10
+ var = vars.find{|v|v.name == c}
11
+
12
+ # return new variable if not found (probably the user wants to start using a new
13
+ # one)
14
+ return Rubylog::Variable.new c unless var
15
+
16
+ # dereference it
17
+ result = var.rubylog_deep_dereference
18
+
19
+ # return nil if not bound
20
+ return nil if result.is_a? Rubylog::Variable
21
+
22
+ # return the value
23
+ result
24
+ else
25
+ Rubylog::Variable.new c
26
+ end
27
+ end
28
+ end
29
+ end
30
+
data/lib/rubylog/dsl.rb CHANGED
@@ -1,52 +1,70 @@
1
1
  module Rubylog::DSL
2
- def self.add_first_order_functor *fs
3
- add_functors_to FirstOrderFunctors, *fs
4
- end
5
-
6
- def self.add_second_order_functor *fs
7
- add_functors_to SecondOrderFunctors, *fs
8
- end
9
-
10
2
  def self.add_functors_to class_or_module, *functors
11
3
  functors.each do |f|
12
4
  m = functor_module(f)
13
5
  class_or_module.send :include, m
14
6
  Rubylog::Variable.send :include, m
15
- add_global_functor f
16
7
  end
17
8
  end
9
+
18
10
 
19
11
  @functor_modules ||= {}
20
12
 
13
+ def self.normalize_functor fct
14
+ case s = fct.to_s
15
+ when /[?!]\z/ then :"#{s[0...-1]}"
16
+ when /=\z/ then nil
17
+ else fct
18
+ end
19
+ end
20
+
21
21
  def self.functor_module f
22
22
  @functor_modules[f] ||= Module.new do
23
23
  define_method f do |*args, &block|
24
24
  args << block if block
25
- Rubylog::Clause.new f, self, *args
25
+ Rubylog::Structure.new f, self, *args
26
26
  end
27
27
 
28
28
  f_bang = :"#{f}!"
29
29
  define_method f_bang do |*args, &block|
30
30
  args << block if block
31
- Rubylog.theory.assert Rubylog::Clause.new(f, self, *args), :true
31
+ Rubylog.current_theory.assert Rubylog::Structure.new(f, self, *args), :true
32
32
  self
33
33
  end
34
34
 
35
35
  f_qmark = :"#{f}?"
36
36
  define_method f_qmark do |*args, &block|
37
37
  args << block if block
38
- Rubylog.theory.true? Rubylog::Clause.new(f, self, *args)
38
+ Rubylog.current_theory.true? Rubylog::Structure.new(f, self, *args)
39
39
  end
40
40
  end
41
41
  end
42
42
 
43
- protected
43
+ def self.add_prefix_functors_to class_or_module, *functors
44
+ functors.each do |f|
45
+ class_or_module.class_eval do
46
+ define_method f do |*args, &block|
47
+ args << block if block
48
+ Rubylog::Structure.new f, *args
49
+ end
50
+
51
+ f_bang = :"#{f}!"
52
+ define_method f_bang do |*args, &block|
53
+ args << block if block
54
+ # TODO consider self.assert
55
+ Rubylog.current_theory.assert Rubylog::Structure.new(f, *args), :true
56
+ self
57
+ end
44
58
 
45
- def self.add_global_functor f
46
- GlobalFunctors.send :define_method, f do |*args, &block|
47
- args << block if block
48
- Rubylog::Clause.new f, *args
59
+ f_qmark = :"#{f}?"
60
+ define_method f_qmark do |*args, &block|
61
+ args << block if block
62
+ #TODO consider self.true?
63
+ Rubylog.current_theory.true? Rubylog::Structure.new(f, *args)
64
+ end
65
+ end
49
66
  end
50
67
  end
68
+
51
69
  end
52
70
 
@@ -1,8 +1,14 @@
1
1
  module Rubylog
2
2
  class RubylogError < StandardError
3
3
  end
4
+
5
+ class SyntaxError < RubylogError
6
+ end
7
+
8
+ class DiscontiguousPredicateError < RubylogError
9
+ end
4
10
 
5
- class DiscontinuousPredicateError < RubylogError
11
+ class MultitheoryError < RubylogError
6
12
  end
7
13
 
8
14
  class BuiltinPredicateError < RubylogError
@@ -14,5 +20,17 @@ module Rubylog
14
20
  class InvalidStateError < RubylogError
15
21
  end
16
22
 
23
+ class InstantiationError < RubylogError
24
+ end
25
+
26
+ class TypeError < RubylogError
27
+ end
28
+
29
+ class UnknownVariableError < RubylogError
30
+ end
31
+
32
+ class CheckFailed < StandardError
33
+ end
34
+
17
35
  end
18
36
 
@@ -0,0 +1,16 @@
1
+ module Rubylog::Assertable
2
+ def if body=nil, &block
3
+ raise Rubylog::SyntaxError, "No body given", caller unless body || block
4
+ Rubylog.current_theory.assert self, body || block
5
+ end
6
+
7
+ def if! body=nil, &block
8
+ raise Rubylog::SyntaxError, "No body given", caller unless body || block
9
+ Rubylog.current_theory.assert self, Rubylog::Structure.new(:and, :cut!, body || block)
10
+ end
11
+
12
+ def unless body=nil, &block
13
+ raise Rubylog::SyntaxError, "No body given", caller unless body || block
14
+ Rubylog.current_theory.assert self, Rubylog::Structure.new(:false, body || block)
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ module Rubylog::Callable
2
+ # should yield for each possible solution of the term
3
+ #def prove
4
+ # raise "abstract method called"
5
+ #end
6
+
7
+ def true?
8
+ Rubylog.current_theory.true? self
9
+ end
10
+
11
+ def solve
12
+ if block_given?
13
+ Rubylog.current_theory.solve(self) {|*a| yield *a}
14
+ else
15
+ Rubylog.current_theory.solve(self) {|*a|}
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,47 @@
1
+ module Rubylog::CompositeTerm
2
+ def rubylog_compile_variables
3
+ vars = []; vars_by_name = {}
4
+ rubylog_clone do |subterm|
5
+ case subterm
6
+ when Rubylog::Variable
7
+ var = subterm
8
+
9
+ if var.dont_care?
10
+ var.dup
11
+ else
12
+ new_var = vars_by_name[var.name]
13
+ if new_var
14
+ new_var.guards = new_var.guards + var.guards
15
+ new_var
16
+ else
17
+ new_var = var.dup
18
+ vars << new_var
19
+ vars_by_name[var.name] = new_var
20
+ new_var
21
+ end
22
+ end
23
+
24
+ when Rubylog::CompositeTerm
25
+ subterm.instance_variable_set :"@rubylog_variables", vars
26
+ subterm
27
+ else
28
+ subterm
29
+ end
30
+ end
31
+ end
32
+
33
+ #should return a copy with rubylog_deep_dereference called for sub-terms
34
+ #def rubylog_deep_dereference
35
+ #self.class.new attr1.rubylog_deep_dereference
36
+ #end
37
+
38
+ attr_reader :rubylog_variables
39
+
40
+
41
+ # This is a general deep-copy generating method
42
+ # should return a deep copy of the term, atomic terms treated as
43
+ # leaves, with &block called post-order
44
+ #def rubylog_clone &block
45
+ #block.call self.class.new attr1.rubylog_clone &block
46
+ #end
47
+ end
@@ -0,0 +1,8 @@
1
+ module Rubylog::Predicate
2
+ # should yield iff the predicate is solvable eg.
3
+ # def call
4
+ # ...
5
+ # yield if ...
6
+ # ...
7
+ # end
8
+ end