Class: Array

Inherits:
Object show all
Includes:
Rubylog::CompoundTerm
Defined in:
lib/rubylog/mixins/array.rb

Instance Attribute Summary

Attributes included from Rubylog::CompoundTerm

#rubylog_variables

Instance Method Summary collapse

Methods included from Rubylog::CompoundTerm

#rubylog_match_variables

Instance Method Details

#rubylog_clone(&block) ⇒ Object



129
130
131
# File 'lib/rubylog/mixins/array.rb', line 129

def rubylog_clone &block
  block[map{|t|t.rubylog_clone &block}]
end

#rubylog_deep_dereferenceObject



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/rubylog/mixins/array.rb', line 133

def rubylog_deep_dereference 
  map do |t|
    case t
    when Rubylog::DSL::ArraySplat
      v = t.var.rubylog_dereference
      if v.is_a?(Array)
        # if it could be resolved
        v.rubylog_deep_dereference
      else
        # if it is still a variable
        [t]
      end
    else
      [t.rubylog_deep_dereference]
    end
  end.inject(:concat) || []
end

#rubylog_unify(other) ⇒ Object

Term methods



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/rubylog/mixins/array.rb', line 6

def rubylog_unify other
  case

  when ! other.is_a?(Array)
    # [...] = 1
    return super{yield} 

  when empty? 
    case 
    when other.empty? 
      # if [] = []
      # then true
      yield
    when other[0].is_a?(Rubylog::DSL::ArraySplat)
      # if [] = [*A,...]
      # then [] = A, []=[...]
      [].rubylog_unify other[0].var do
        self.rubylog_unify other[1..-1] do
          yield
        end
      end
    else
      # fail
    end

  when self[0].is_a?(Rubylog::DSL::ArraySplat)
    # if [*A,...] = [...]
    case
    when other.empty?
      # [*A,...] = []
      self[0].var.rubylog_unify [] do
        self[1..-1].rubylog_unify [] do
          yield
        end
      end
    when other[0].is_a?(Rubylog::DSL::ArraySplat )
      # [*A,...] = [*B,...]
      case 
      when self.length == 1 && other.length == 1
        # if [*A] = [*B]
        # then A=B
        self[0].var.rubylog_unify other[0].var do
          yield
        end
      when self.length == 1
        # if [*A] = [*B,...]
        # then A=[...]
        self[0].var.rubylog_unify other do
          yield
        end
        # TODO: we can also optimize ends of arrays.
      else
        # this may lead to infinite loop if variables are unbound
        # TODO: Maybe an InstantiationError may be better.
        # if [*A,...] = [*B,...]
        # then eiter A=[], [...]=[*B,...]
        self[0].var.rubylog_unify [] do
          self[1..-1].rubylog_unify other do
            yield
          end
        end
        # or A=[H,*T], [H,*T,...]=[*B,...]
        part = [Rubylog::Variable.new, Rubylog::DSL::ArraySplat.new]
        self[0].var.rubylog_unify part do
          (part + self[1..-1]).rubylog_unify other do
            yield
          end
        end

      end

    else
      # if [*A,...] = [X,...]
      # then eiter A=[], [...]=[X,...]
      self[0].var.rubylog_unify [] do
        self[1..-1].rubylog_unify other do
          yield
        end
      end
      # or A=[H,*T], [H,*T,...]=[X,...]
      part = [Rubylog::Variable.new, Rubylog::DSL::ArraySplat.new]
      self[0].var.rubylog_unify part do
        (part + self[1..-1]).rubylog_unify other do
          yield
        end
      end
    end

  else
    # if [H,...]
    case
    when other.empty?
      # [H,...] = []
      # fail
    when other[0].is_a?(Rubylog::DSL::ArraySplat)
      # [H,...] = [*A,...]
      # either []=A, [H,...]=[...]
      [].rubylog_unify other[0].var do
        self.rubylog_unify other[1..-1] do
          yield
        end
      end
      # or A=[X,*R], [H,...]=[X,*R,...]
      part = [Rubylog::Variable.new, Rubylog::DSL::ArraySplat.new]
      other[0].var.rubylog_unify part do
        self.rubylog_unify(part + other[1..-1]) do
          yield
        end
      end
    else
      # if [H,...]=[X,...]
      # then H=X, [...]=[...]
      self[0].rubylog_unify other[0] do
        self[1..-1].rubylog_unify other[1..-1] do
          yield
        end
      end
    end
  end
end