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