rubylog 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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