class Array

Public Instance Methods

rubylog_clone(&block) click to toggle source
# File lib/rubylog/mixins/array.rb, line 129
def rubylog_clone &block
  block[map{|t|t.rubylog_clone &block}]
end
rubylog_deep_dereference() click to toggle source
# 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) { || ... } click to toggle source

Term methods

Calls superclass method Rubylog::Term#rubylog_unify
# 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