rubylog 1.0.0 → 2.0pre1
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.
- data/Gemfile +3 -12
- data/Gemfile.lock +22 -48
- data/README.rdoc +38 -38
- data/README.rdoc.orig +284 -0
- data/RELEASE_NOTES.rdoc +51 -0
- data/Rakefile +14 -18
- data/TODO.txt +0 -0
- data/VERSION +1 -1
- data/examples/a_plus_b.rb +6 -0
- data/examples/checkmate.rb +88 -0
- data/examples/combination.rb +17 -0
- data/examples/dcg.rb +3 -2
- data/examples/dcg2.rb +2 -2
- data/{logic → examples}/directory_structure_logic.rb +3 -5
- data/examples/dirlist.rb +4 -0
- data/examples/divisors.rb +6 -0
- data/examples/enumerators.rb +3 -3
- data/examples/factorial.rb +2 -3
- data/examples/file_search.rb +14 -0
- data/examples/hanoi.rb +4 -5
- data/examples/hello.rb +6 -4
- data/examples/mice.rb +92 -0
- data/examples/mice2.rb +19 -0
- data/examples/n_queens.rb +32 -0
- data/examples/object_oriented.rb +14 -0
- data/examples/palindrome_detection.rb +18 -0
- data/examples/parsing.rb +6 -4
- data/examples/permutation.rb +12 -0
- data/examples/prefix.rb +13 -0
- data/examples/primality_by_division.rb +22 -0
- data/examples/primitives.rb +10 -8
- data/examples/sieve_of_eratosthenes.rb +14 -0
- data/examples/string_interpolation.rb +4 -0
- data/examples/sudoku.rb +52 -0
- data/examples/tracing.rb +19 -0
- data/lib/rspec/rubylog.rb +29 -0
- data/lib/rubylog/assertable.rb +24 -0
- data/lib/rubylog/builtins/arithmetics.rb +63 -0
- data/lib/rubylog/builtins/assumption.rb +71 -0
- data/lib/rubylog/builtins/ensure.rb +13 -0
- data/lib/rubylog/builtins/file_system.rb +30 -8
- data/lib/rubylog/builtins/logic.rb +69 -38
- data/lib/rubylog/builtins/reflection.rb +35 -50
- data/lib/rubylog/builtins/term.rb +15 -17
- data/lib/rubylog/builtins.rb +11 -0
- data/lib/rubylog/clause.rb +19 -0
- data/lib/rubylog/{interfaces/composite_term.rb → compound_term.rb} +3 -3
- data/lib/rubylog/context.rb +24 -0
- data/lib/rubylog/context_creation.rb +71 -0
- data/lib/rubylog/context_modules/checks.rb +35 -0
- data/lib/rubylog/context_modules/demonstration.rb +16 -0
- data/lib/rubylog/context_modules/predicates.rb +86 -0
- data/lib/rubylog/context_modules/primitives.rb +18 -0
- data/lib/rubylog/context_modules/thats.rb +13 -0
- data/lib/rubylog/default_context.rb +9 -0
- data/lib/rubylog/dsl/array_splat.rb +11 -3
- data/lib/rubylog/dsl/primitives.rb +24 -12
- data/lib/rubylog/dsl/thats.rb +6 -0
- data/lib/rubylog/dsl/variables.rb +56 -21
- data/lib/rubylog/errors.rb +26 -15
- data/lib/rubylog/mixins/array.rb +95 -62
- data/lib/rubylog/mixins/kernel.rb +3 -2
- data/lib/rubylog/mixins/method.rb +0 -1
- data/lib/rubylog/mixins/object.rb +2 -1
- data/lib/rubylog/mixins/proc.rb +9 -12
- data/lib/rubylog/mixins/string.rb +15 -23
- data/lib/rubylog/mixins/symbol.rb +7 -24
- data/lib/rubylog/nullary_predicates.rb +3 -0
- data/lib/rubylog/predicate.rb +53 -0
- data/lib/rubylog/primitive.rb +15 -0
- data/lib/rubylog/procedure.rb +42 -0
- data/lib/rubylog/rule.rb +24 -0
- data/lib/rubylog/structure.rb +19 -38
- data/lib/rubylog/{interfaces/term.rb → term.rb} +2 -7
- data/lib/rubylog/tracing.rb +75 -0
- data/lib/rubylog/variable.rb +31 -12
- data/lib/rubylog.rb +36 -32
- data/rubylog.gemspec +92 -84
- data/spec/inriasuite_spec.rb +906 -9
- data/spec/integration/custom_classes_spec.rb +61 -0
- data/spec/integration/dsl_spec.rb +38 -0
- data/spec/integration/recursion_spec.rb +14 -0
- data/spec/integration/theory_as_module_spec.rb +20 -0
- data/spec/integration/theory_as_module_with_include_spec.rb +14 -0
- data/spec/rspec/rubylog_spec.rb +75 -0
- data/spec/rubylog/assertable_spec.rb +111 -0
- data/spec/rubylog/builtins/arithmetics_spec.rb +94 -0
- data/spec/rubylog/builtins/assumption_spec.rb +70 -0
- data/spec/rubylog/builtins/ensure_spec.rb +8 -0
- data/spec/rubylog/builtins/file_system_spec.rb +40 -0
- data/spec/rubylog/builtins/logic_spec.rb +340 -0
- data/spec/rubylog/builtins/reflection_spec.rb +43 -0
- data/spec/rubylog/builtins/term_spec.rb +85 -0
- data/spec/rubylog/context_modules/demonstration_spec.rb +132 -0
- data/spec/rubylog/context_modules/predicates_spec.rb +57 -0
- data/spec/rubylog/context_modules/thats_spec.rb +94 -0
- data/spec/rubylog/dsl/array_splat_spec.rb +15 -0
- data/spec/rubylog/dsl/primitives_spec.rb +43 -0
- data/spec/rubylog/errors_spec.rb +18 -0
- data/spec/{unification_spec.rb → rubylog/interfaces/term_spec.rb} +8 -9
- data/spec/rubylog/mixins/array_spec.rb +80 -0
- data/spec/rubylog/mixins/composite_term_spec.rb +66 -0
- data/spec/rubylog/mixins/proc_spec.rb +59 -0
- data/spec/rubylog/mixins/string_spec.rb +48 -0
- data/spec/rubylog/mixins/symbol_spec.rb +9 -0
- data/spec/{clause_spec.rb → rubylog/structure_spec.rb} +16 -15
- data/spec/rubylog/term_spec.rb +7 -0
- data/spec/rubylog/tracing_spec.input +27 -0
- data/spec/rubylog/tracing_spec.rb +44 -0
- data/spec/rubylog/variable_spec.rb +279 -0
- data/spec/spec_helper.rb +1 -0
- data/vimrc +11 -0
- metadata +103 -123
- data/README.hu.rb +0 -58
- data/bin/rubylog +0 -18
- data/examples/theory.rb +0 -32
- data/lib/rubylog/builtins/default.rb +0 -10
- data/lib/rubylog/dsl.rb +0 -70
- data/lib/rubylog/interfaces/assertable.rb +0 -16
- data/lib/rubylog/interfaces/callable.rb +0 -18
- data/lib/rubylog/interfaces/predicate.rb +0 -8
- data/lib/rubylog/interfaces/procedure.rb +0 -60
- data/lib/rubylog/mixins/class.rb +0 -11
- data/lib/rubylog/simple_procedure.rb +0 -8
- data/lib/rubylog/theory.rb +0 -422
- data/logic/builtins/file_system_logic.rb +0 -23
- data/logic/builtins/reflection_logic.rb +0 -40
- data/logic/dereference_logic.rb +0 -23
- data/logic/dsl_logic.rb +0 -29
- data/logic/errors_logic.rb +0 -9
- data/logic/guard_logic.rb +0 -115
- data/logic/list_logic.rb +0 -55
- data/logic/map_logic.rb +0 -15
- data/logic/multitheory.rb +0 -23
- data/logic/recursion_logic.rb +0 -12
- data/logic/string_logic.rb +0 -41
- data/logic/thats_logic.rb +0 -51
- data/logic/variable_logic.rb +0 -24
- data/spec/bartak_guide_spec.rb +0 -86
- data/spec/builtins/all_spec.rb +0 -99
- data/spec/builtins/and_spec.rb +0 -22
- data/spec/builtins/array_spec.rb +0 -16
- data/spec/builtins/branch_or_spec.rb +0 -27
- data/spec/builtins/cut_spec.rb +0 -44
- data/spec/builtins/fail_spec.rb +0 -5
- data/spec/builtins/false_spec.rb +0 -5
- data/spec/builtins/in_spec.rb +0 -38
- data/spec/builtins/is_false_spec.rb +0 -12
- data/spec/builtins/is_spec.rb +0 -26
- data/spec/builtins/matches_spec.rb +0 -23
- data/spec/builtins/or_spec.rb +0 -22
- data/spec/builtins/splits_to.rb +0 -18
- data/spec/builtins/then_spec.rb +0 -27
- data/spec/builtins/true_spec.rb +0 -5
- data/spec/compilation_spec.rb +0 -61
- data/spec/custom_classes_spec.rb +0 -43
- data/spec/dereference.rb +0 -10
- data/spec/queries_spec.rb +0 -150
- data/spec/recursion_spec.rb +0 -18
- data/spec/ruby_code_spec.rb +0 -52
- data/spec/rules_spec.rb +0 -97
- data/spec/theory_spec.rb +0 -29
- data/spec/variable_spec.rb +0 -26
data/lib/rubylog/mixins/proc.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
class Proc
|
2
2
|
|
3
|
-
#
|
4
|
-
include Rubylog::
|
3
|
+
# Clause methods
|
4
|
+
include Rubylog::Clause
|
5
5
|
|
6
6
|
def prove
|
7
7
|
yield if call_with_rubylog_variables
|
8
8
|
end
|
9
9
|
|
10
|
-
#
|
11
|
-
include Rubylog::
|
10
|
+
# CompoundTerm methods
|
11
|
+
include Rubylog::CompoundTerm
|
12
12
|
def rubylog_clone
|
13
13
|
yield dup
|
14
14
|
end
|
@@ -20,18 +20,15 @@ class Proc
|
|
20
20
|
call_with_rubylog_variables
|
21
21
|
end
|
22
22
|
|
23
|
+
# Calls the proc with the given rubylog variables or with the currently
|
24
|
+
# available variables.
|
23
25
|
def call_with_rubylog_variables vars = nil
|
24
26
|
vars ||= @rubylog_variables
|
25
|
-
raise Rubylog::InvalidStateError, "
|
27
|
+
raise Rubylog::InvalidStateError, "Variables not matched" if not vars
|
26
28
|
|
27
|
-
|
29
|
+
# Call the block with the variables substituted
|
30
|
+
Rubylog::DSL::Variables.with_vars vars do
|
28
31
|
return call
|
29
32
|
end
|
30
|
-
# to pass arguments:
|
31
|
-
#if arity == -1
|
32
|
-
# call *@rubylog_variables.map{|v|v.value}
|
33
|
-
#else
|
34
|
-
# call *@rubylog_variables[0...arity].map{|v|v.value}
|
35
|
-
#end
|
36
33
|
end
|
37
34
|
end
|
@@ -6,11 +6,9 @@ class String
|
|
6
6
|
RubylogStringVariableGuards = [[]]
|
7
7
|
|
8
8
|
def self.rubylog_unify_strings a, a_segments, a_vars, b
|
9
|
-
#p a, a_segments, a_vars, b
|
10
9
|
if a_segments.count == 1
|
11
10
|
segment = a_segments[0]
|
12
11
|
if b.end_with?(segment)
|
13
|
-
#p b[0...b.length-segment.length]
|
14
12
|
a_vars[0].rubylog_unify b[0...b.length-segment.length] do
|
15
13
|
yield
|
16
14
|
end
|
@@ -34,7 +32,7 @@ class String
|
|
34
32
|
other_has_vars = other =~ RUBYLOG_VAR_REGEXP
|
35
33
|
|
36
34
|
return super{yield} unless self_has_vars or other_has_vars
|
37
|
-
raise
|
35
|
+
raise ArgumentError, "Cannot unify two strings with variables inside" if self_has_vars and other_has_vars
|
38
36
|
|
39
37
|
a, b = self_has_vars ? [self, other] : [other, self]
|
40
38
|
a_segments, a_vars = a.rubylog_segments
|
@@ -48,8 +46,8 @@ class String
|
|
48
46
|
|
49
47
|
end
|
50
48
|
|
51
|
-
#
|
52
|
-
include Rubylog::
|
49
|
+
# CompoundTerm methods
|
50
|
+
include Rubylog::CompoundTerm
|
53
51
|
def rubylog_clone &block
|
54
52
|
scan RUBYLOG_VAR_REGEXP do
|
55
53
|
guards = RubylogStringVariableGuards[$2.to_i]
|
@@ -60,45 +58,39 @@ class String
|
|
60
58
|
|
61
59
|
def rubylog_deep_dereference
|
62
60
|
gsub RUBYLOG_VAR_REGEXP do
|
63
|
-
rubylog_get_string_variable($1).rubylog_deep_dereference.to_s
|
61
|
+
rubylog_get_string_variable($1,$2).rubylog_deep_dereference.to_s
|
64
62
|
end
|
65
63
|
end
|
66
64
|
|
67
|
-
# returns a list of substrings which are before, between and after the
|
68
|
-
#
|
65
|
+
# returns a list of substrings which are before, between and after the
|
66
|
+
# rubylog
|
67
|
+
# string variables, and the list of variabes in between
|
69
68
|
def rubylog_segments
|
70
69
|
segments = [[0]]
|
71
70
|
vars = []
|
72
71
|
|
73
72
|
scan RUBYLOG_VAR_REGEXP do
|
74
73
|
match = Regexp.last_match
|
75
|
-
#p match
|
76
|
-
#p match.begin(0)
|
77
|
-
#p match.end(0)
|
78
|
-
#p match[0]
|
79
|
-
#p match[1]
|
80
74
|
segments.last << match.begin(0)
|
81
75
|
segments << [match.end(0)]
|
82
|
-
vars << rubylog_get_string_variable(match[1])
|
76
|
+
vars << rubylog_get_string_variable(match[1], match[2])
|
83
77
|
end
|
84
78
|
|
85
79
|
|
86
80
|
segments.last << length
|
87
|
-
#p segments, vars
|
88
81
|
segments = segments.map{|s|self[s[0]...s[1]]}
|
89
|
-
#p [self, segments, vars]
|
90
82
|
return segments, vars
|
91
83
|
end
|
92
84
|
|
93
85
|
protected
|
94
86
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
87
|
+
#
|
88
|
+
def rubylog_get_string_variable name, guards_index
|
89
|
+
name = name.to_sym
|
90
|
+
raise Rubylog::InvalidStateError, "Variables not matched" unless @rubylog_variables
|
91
|
+
|
92
|
+
@rubylog_variables.find{|v|v.name == name} ||
|
93
|
+
Rubylog::Variable.new[*RubylogStringVariableGuards[guards_index.to_i]]
|
102
94
|
end
|
103
95
|
|
104
96
|
end
|
@@ -1,16 +1,7 @@
|
|
1
1
|
class Symbol
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
self
|
6
|
-
end
|
7
|
-
|
8
|
-
def arity
|
9
|
-
0
|
10
|
-
end
|
11
|
-
|
12
|
-
def indicator
|
13
|
-
[self, 0]
|
3
|
+
def predicate
|
4
|
+
Rubylog::NullaryPredicates[self] or raise Rubylog::ExistenceError.new(self)
|
14
5
|
end
|
15
6
|
|
16
7
|
def args
|
@@ -23,22 +14,14 @@ class Symbol
|
|
23
14
|
# Term methods
|
24
15
|
include Rubylog::Term
|
25
16
|
|
26
|
-
#
|
27
|
-
include Rubylog::
|
17
|
+
# Clause methods
|
18
|
+
include Rubylog::Clause
|
28
19
|
|
29
20
|
def prove
|
30
|
-
|
31
|
-
Rubylog.current_theory.print_trace 1, self, rubylog_variables_hash
|
32
|
-
|
33
|
-
predicate = Rubylog.current_theory[[self,0]]
|
34
|
-
raise Rubylog::ExistenceError, indicator if not predicate
|
35
|
-
|
36
|
-
predicate.call(*args) { yield }
|
37
|
-
|
38
|
-
ensure
|
39
|
-
Rubylog.current_theory.print_trace -1
|
40
|
-
end
|
21
|
+
predicate.call { yield }
|
41
22
|
end
|
42
23
|
|
24
|
+
rubylog_traceable :prove
|
25
|
+
|
43
26
|
|
44
27
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Rubylog
|
2
|
+
class Predicate
|
3
|
+
|
4
|
+
attr_reader :functor, :arity
|
5
|
+
def initialize functor, arity
|
6
|
+
@functor = functor
|
7
|
+
@arity = arity
|
8
|
+
end
|
9
|
+
|
10
|
+
# Yields for each solution of the predicate
|
11
|
+
def call *args
|
12
|
+
raise "abstract method called on #{self.inspect}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_functor_to subjects
|
16
|
+
if arity == 0
|
17
|
+
# We treat nullary predicates differently. Do not even create functors.
|
18
|
+
Rubylog::NullaryPredicates[functor] = self
|
19
|
+
return
|
20
|
+
end
|
21
|
+
|
22
|
+
predicate = self
|
23
|
+
|
24
|
+
[subjects].flatten.each do |subject|
|
25
|
+
raise ArgumentError, "#{subject.inspect} is not a class or module" unless subject.is_a? Module
|
26
|
+
subject.class_eval do
|
27
|
+
f = predicate.functor
|
28
|
+
define_method f do |*args, &block|
|
29
|
+
args << block if block
|
30
|
+
Rubylog::Structure.new predicate, f, self, *args
|
31
|
+
end
|
32
|
+
|
33
|
+
f_bang = :"#{f}!"
|
34
|
+
define_method f_bang do |*args, &block|
|
35
|
+
args << block if block
|
36
|
+
predicate.assert Rubylog::Structure.new(predicate, f, self, *args), :true
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
f_qmark = :"#{f}?"
|
41
|
+
define_method f_qmark do |*args, &block|
|
42
|
+
args << block if block
|
43
|
+
Rubylog::Structure.new(predicate, f, self, *args).true?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Rubylog
|
2
|
+
class Primitive < Predicate
|
3
|
+
|
4
|
+
def initialize functor, callable
|
5
|
+
super functor, callable.arity
|
6
|
+
@callable = callable
|
7
|
+
end
|
8
|
+
|
9
|
+
# calls the callable with the argumens
|
10
|
+
def call *args
|
11
|
+
@callable.call(*args) { yield }
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Rubylog
|
2
|
+
class Procedure < Predicate
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize functor, arity, rules=Array.new
|
6
|
+
super functor, arity
|
7
|
+
@rules = rules
|
8
|
+
end
|
9
|
+
|
10
|
+
def method_missing name, *args, &block
|
11
|
+
@rules.send name, *args, &block
|
12
|
+
end
|
13
|
+
|
14
|
+
# accepts the *args of the called structure
|
15
|
+
def call *args
|
16
|
+
# catch cuts
|
17
|
+
catch :cut do
|
18
|
+
|
19
|
+
# for each rule
|
20
|
+
each do |rule|
|
21
|
+
# compile
|
22
|
+
rule = rule.rubylog_match_variables
|
23
|
+
|
24
|
+
# unify the head with the arguments
|
25
|
+
rule.head.args.rubylog_unify(args) do
|
26
|
+
# call the body
|
27
|
+
rule.body.prove do
|
28
|
+
yield
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
rubylog_traceable :call
|
35
|
+
|
36
|
+
# Asserts a rule with a given head and body.
|
37
|
+
def assert head, body=:true
|
38
|
+
push Rubylog::Rule.new(head, body)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
data/lib/rubylog/rule.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module Rubylog
|
2
|
+
|
3
|
+
# This is an internally used class that represents a rule of a predicate.
|
4
|
+
#
|
5
|
+
class Rule
|
6
|
+
attr_reader :head, :body
|
7
|
+
|
8
|
+
def initialize head, body
|
9
|
+
@head = head
|
10
|
+
@body = body
|
11
|
+
end
|
12
|
+
|
13
|
+
# CompoundTerm methods
|
14
|
+
include Rubylog::CompoundTerm
|
15
|
+
def rubylog_clone &block
|
16
|
+
block.call Rule.new @head.rubylog_clone(&block), @body.rubylog_clone(&block)
|
17
|
+
end
|
18
|
+
def rubylog_deep_dereference
|
19
|
+
# this is not necessary
|
20
|
+
#Rule.new @head.rubylog_deep_dereference, @body.rubylog_deep_dereference
|
21
|
+
raise "Not implemented."
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/rubylog/structure.rb
CHANGED
@@ -3,13 +3,19 @@ module Rubylog
|
|
3
3
|
|
4
4
|
# data structure
|
5
5
|
attr_reader :functor, :args
|
6
|
-
|
6
|
+
|
7
|
+
def initialize predicate, functor, *args
|
7
8
|
#raise Rubylog::TypeError, "functor cannot be #{functor}" unless functor.is_a? Symbol
|
9
|
+
@predicate = predicate
|
8
10
|
@functor = functor
|
9
11
|
@args = args.freeze
|
10
12
|
@arity = args.count
|
11
13
|
end
|
12
14
|
|
15
|
+
def predicate
|
16
|
+
@predicate
|
17
|
+
end
|
18
|
+
|
13
19
|
def [] i
|
14
20
|
@args[i]
|
15
21
|
end
|
@@ -45,21 +51,15 @@ module Rubylog
|
|
45
51
|
# Assertable methods
|
46
52
|
include Rubylog::Assertable
|
47
53
|
|
48
|
-
#
|
49
|
-
include Rubylog::
|
54
|
+
# Clause methods
|
55
|
+
include Rubylog::Clause
|
50
56
|
|
51
57
|
def prove
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
raise Rubylog::ExistenceError, indicator.inspect if not predicate
|
56
|
-
count = 0
|
57
|
-
predicate.call(*@args) { yield; count+=1 }
|
58
|
-
count
|
59
|
-
ensure
|
60
|
-
Rubylog.current_theory.print_trace -1
|
61
|
-
end
|
58
|
+
count = 0
|
59
|
+
predicate.call(*@args) { yield; count+=1 }
|
60
|
+
count
|
62
61
|
end
|
62
|
+
rubylog_traceable :prove
|
63
63
|
|
64
64
|
|
65
65
|
# enumerable methods
|
@@ -77,38 +77,19 @@ module Rubylog
|
|
77
77
|
|
78
78
|
attr_reader :rubylog_variables
|
79
79
|
|
80
|
-
#
|
81
|
-
include Rubylog::
|
80
|
+
# CompoundTerm methods
|
81
|
+
include Rubylog::CompoundTerm
|
82
|
+
|
82
83
|
def rubylog_clone &block
|
83
|
-
block.call Structure.new @functor,
|
84
|
+
block.call Structure.new @predicate, @functor.rubylog_clone(&block),
|
84
85
|
*@args.map{|a| a.rubylog_clone &block}
|
85
86
|
end
|
87
|
+
|
86
88
|
def rubylog_deep_dereference
|
87
|
-
Structure.new @functor.rubylog_deep_dereference,
|
89
|
+
Structure.new @predicate, @functor.rubylog_deep_dereference,
|
88
90
|
*@args.rubylog_deep_dereference
|
89
91
|
end
|
90
92
|
|
91
|
-
|
92
|
-
# convenience methods
|
93
|
-
#def each_solution
|
94
|
-
#goal = rubylog_compile_variables
|
95
|
-
#goal.variable_hashes_without_compile.each do |hash|
|
96
|
-
#yield goal.rubylog_clone {|i| hash[i] || i }
|
97
|
-
#end
|
98
|
-
#end
|
99
|
-
|
100
|
-
def variable_hashes
|
101
|
-
rubylog_compile_variables.variable_hashes_without_compile
|
102
|
-
end
|
103
|
-
|
104
|
-
protected
|
105
|
-
|
106
|
-
def variable_hashes_without_compile
|
107
|
-
variables = rubylog_variables
|
108
|
-
map do |*values|
|
109
|
-
Hash[variables.zip values]
|
110
|
-
end
|
111
|
-
end
|
112
93
|
end
|
113
94
|
end
|
114
95
|
|
@@ -11,16 +11,11 @@ module Rubylog::Term
|
|
11
11
|
self
|
12
12
|
end
|
13
13
|
|
14
|
-
def rubylog_variables_hash
|
15
|
-
vars = rubylog_variables
|
16
|
-
Hash[vars.zip(vars.map{|v|v.value})]
|
17
|
-
end
|
18
|
-
|
19
14
|
def rubylog_unify other
|
20
15
|
if other.kind_of? Rubylog::Variable
|
21
16
|
other.rubylog_unify(self) do yield end
|
22
17
|
else
|
23
|
-
yield if self
|
18
|
+
yield if self.eql? other
|
24
19
|
end
|
25
20
|
end
|
26
21
|
|
@@ -32,7 +27,7 @@ module Rubylog::Term
|
|
32
27
|
self
|
33
28
|
end
|
34
29
|
|
35
|
-
def
|
30
|
+
def rubylog_match_variables
|
36
31
|
self
|
37
32
|
end
|
38
33
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
class Class
|
2
|
+
def rubylog_traceable name
|
3
|
+
Rubylog.traceable instance_method(name)
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
module Rubylog
|
8
|
+
module Tracing
|
9
|
+
attr_reader :traceable_methods
|
10
|
+
attr_accessor :trace_levels
|
11
|
+
|
12
|
+
# Turns trace on. If value is given and is false, turns trace off. If a
|
13
|
+
# block is given, calls the block with trace on.
|
14
|
+
#
|
15
|
+
def trace value=true
|
16
|
+
if not block_given?
|
17
|
+
@trace = value
|
18
|
+
@trace_levels = 0
|
19
|
+
update_trace
|
20
|
+
else
|
21
|
+
begin
|
22
|
+
trace
|
23
|
+
return yield
|
24
|
+
ensure
|
25
|
+
trace false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# returns true if tracing is active
|
31
|
+
def trace?
|
32
|
+
@trace
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def traceable method
|
37
|
+
@traceable_methods ||= []
|
38
|
+
@traceable_methods << method
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def update_trace
|
44
|
+
if trace?
|
45
|
+
traceable_methods.each do |m|
|
46
|
+
m.owner.send :define_method, m.name do |*args,&block|
|
47
|
+
begin
|
48
|
+
print " "*Rubylog.trace_levels
|
49
|
+
Rubylog.trace_levels += 1
|
50
|
+
print "#{inspect}.#{m.name}(#{args.map{|k|k.inspect}.join(", ")})?"
|
51
|
+
gets
|
52
|
+
|
53
|
+
return m.bind(self).call *args, &block
|
54
|
+
ensure
|
55
|
+
Rubylog.trace_levels -= 1
|
56
|
+
print " "*Rubylog.trace_levels
|
57
|
+
print "*"
|
58
|
+
puts
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
else
|
63
|
+
traceable_methods.each do |m|
|
64
|
+
m.owner.send :define_method, m.name do |*args, &block|
|
65
|
+
m.bind(self).call(*args, &block)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
extend Tracing
|
73
|
+
end
|
74
|
+
|
75
|
+
|
data/lib/rubylog/variable.rb
CHANGED
@@ -35,8 +35,7 @@ module Rubylog
|
|
35
35
|
|
36
36
|
|
37
37
|
def value
|
38
|
-
|
39
|
-
val
|
38
|
+
@value if @bound
|
40
39
|
end
|
41
40
|
|
42
41
|
def dont_care?
|
@@ -51,7 +50,13 @@ module Rubylog
|
|
51
50
|
[self]
|
52
51
|
end
|
53
52
|
|
54
|
-
#
|
53
|
+
# Unifies the receiver with another value.
|
54
|
+
#
|
55
|
+
# First dereferences both the receiver and the other. If both dereferenced
|
56
|
+
# values are variables, unifies them with the other being bound to the
|
57
|
+
# receiver. If one of them is a variable, it gets bound to the other value.
|
58
|
+
# If none of them is a variable, they are checked for equality with eql?.
|
59
|
+
#
|
55
60
|
def rubylog_unify other
|
56
61
|
# check if we are bound
|
57
62
|
if @bound
|
@@ -68,7 +73,9 @@ module Rubylog
|
|
68
73
|
if other.is_a? Rubylog::Variable
|
69
74
|
# we union our guards with the other's
|
70
75
|
other.append_guards guards do
|
71
|
-
|
76
|
+
# we bind the other to self (this order comes from
|
77
|
+
# inriasuite_spec#unify)
|
78
|
+
other.bind_to self do
|
72
79
|
yield
|
73
80
|
end
|
74
81
|
end
|
@@ -102,13 +109,21 @@ module Rubylog
|
|
102
109
|
end
|
103
110
|
end
|
104
111
|
|
105
|
-
#
|
106
|
-
include
|
112
|
+
# Clause methods
|
113
|
+
include Clause
|
107
114
|
|
108
115
|
def prove
|
109
|
-
v =
|
110
|
-
raise InstantiationError
|
111
|
-
|
116
|
+
v = rubylog_dereference
|
117
|
+
raise Rubylog::InstantiationError.new(self) if v.is_a? Rubylog::Variable
|
118
|
+
|
119
|
+
# match variables if not matched
|
120
|
+
unless v.rubylog_variables
|
121
|
+
v = v.rubylog_match_variables
|
122
|
+
end
|
123
|
+
|
124
|
+
catch :cut do
|
125
|
+
v.prove{yield}
|
126
|
+
end
|
112
127
|
end
|
113
128
|
|
114
129
|
|
@@ -145,15 +160,19 @@ module Rubylog
|
|
145
160
|
def bind_to other
|
146
161
|
begin
|
147
162
|
@bound = true; @value = other
|
148
|
-
Rubylog.current_theory.print_trace 1, "#{inspect}=#{@value.inspect}"
|
149
163
|
|
150
164
|
yield
|
151
|
-
|
152
165
|
ensure
|
153
166
|
@bound = false
|
154
|
-
Rubylog.current_theory.print_trace -1
|
155
167
|
end
|
156
168
|
end
|
169
|
+
rubylog_traceable :bind_to
|
170
|
+
|
171
|
+
def bind_to! other
|
172
|
+
@bound = true; @value = other
|
173
|
+
self
|
174
|
+
end
|
175
|
+
private :bind_to!
|
157
176
|
|
158
177
|
# yields with self.guards = self.guards + other_guards, then restores guards
|
159
178
|
def append_guards other_guards
|