class Puppet::Pops::Evaluator::CompareOperator

Compares the puppet DSL way

Equality

All string vs. numeric equalities check for numeric equality first, then string equality Arrays are equal to arrays if they have the same length, and each element equals Hashes are equal to hashes if they have the same size and keys and values equals. All other objects are equal if they are ruby #== equal

Public Instance Methods

compare(a, b) click to toggle source

Performs a comparison of a and b, and return > 0 if a is bigger, 0 if equal, and < 0 if b is bigger. Comparison of String vs. Numeric always compares using numeric.

# File lib/puppet/pops/evaluator/compare_operator.rb, line 31
def compare(a, b)
  @@compare_visitor.visit_this_1(self, a, b)
end
equals(a, b) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 25
def equals (a, b)
  @@equals_visitor.visit_this_1(self, a, b)
end
include?(a, b, scope) click to toggle source

Answers is b included in a

# File lib/puppet/pops/evaluator/compare_operator.rb, line 41
def include?(a, b, scope)
  @@include_visitor.visit_this_2(self, a, b, scope)
end
match(a, b, scope) click to toggle source

Performs a match of a and b, and returns true if b matches a

# File lib/puppet/pops/evaluator/compare_operator.rb, line 36
def match(a, b, scope)
  @@match_visitor.visit_this_2(self, b, a, scope)
end

Protected Instance Methods

cmp_Numeric(a, b) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 58
def cmp_Numeric(a, b)
  if b.is_a?(Numeric)
    a <=> b
  else
    raise ArgumentError.new("A Numeric is not comparable to non Numeric")
  end
end
cmp_Object(a, b) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 94
def cmp_Object(a, b)
  raise ArgumentError.new("Only Strings and Numbers are comparable")
end
cmp_String(a, b) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 47
def cmp_String(a, b)
  return a.casecmp(b) if b.is_a?(String)
  raise ArgumentError.new("A String is not comparable to a non String")
end
cmp_Symbol(a, b) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 86
def cmp_Symbol(a, b)
  if b.is_a?(Symbol)
    a <=> b
  else
    raise ArgumentError.new("Symbol not comparable to non Symbol")
  end
end
equals_Array(a, b) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 74
def equals_Array(a, b)
  return false unless b.is_a?(Array) && a.size == b.size
  a.each_index {|i| return false unless equals(a.slice(i), b.slice(i)) }
  true
end
equals_Hash(a, b) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 80
def equals_Hash(a, b)
  return false unless b.is_a?(Hash) && a.size == b.size
  a.each {|ak, av| return false unless equals(b[ak], av)}
  true
end
equals_NilClass(a, b) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 103
def equals_NilClass(a, b)
  # :undef supported in case it is passed from a 3x data structure
  b.nil? || b == :undef
end
equals_Numeric(a, b) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 66
def equals_Numeric(a, b)
  if b.is_a?(Numeric)
    a == b
  else
    false
  end
end
equals_Object(a, b) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 99
def equals_Object(a, b)
  a == b
end
equals_String(a, b) click to toggle source

Equality is case independent.

# File lib/puppet/pops/evaluator/compare_operator.rb, line 53
def equals_String(a, b)
  return false unless b.is_a?(String)
  a.casecmp(b) == 0
end
equals_Symbol(a, b) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 108
def equals_Symbol(a, b)
  # :undef supported in case it is passed from a 3x data structure
  a == b || a == :undef && b.nil?
end
include_Array(a, b, scope) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 134
def include_Array(a, b, scope)
  case b
  when Regexp
    matched = nil
    a.each do |element|
      next unless element.is_a? String
      matched = element.match(b) # nil, or MatchData
      break if matched
    end
    # Always set match data, a "not found" should not keep old match data visible
    set_match_data(matched, scope) # creates ephemeral
    return !!matched
  when Puppet::Pops::Types::PAnyType
    a.each {|element| return true if @type_calculator.instance?(b, element) }
    return false
  else
    a.each {|element| return true if equals(element, b) }
    return false
  end
end
include_Hash(a, b, scope) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 155
def include_Hash(a, b, scope)
  include?(a.keys, b, scope)
end
include_Object(a, b, scope) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 113
def include_Object(a, b, scope)
  false
end
include_String(a, b, scope) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 117
def include_String(a, b, scope)
  case b
  when String
    # subsstring search downcased
    a.downcase.include?(b.downcase)
  when Regexp
    matched = a.match(b)           # nil, or MatchData
    set_match_data(matched, scope) # creates ephemeral
    !!matched                      # match (convert to boolean)
  when Numeric
    # convert string to number, true if ==
    equals(a, b)
  else
    false
  end
end
match_Array(array, left, scope) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 180
def match_Array(array, left, scope)
  return false unless left.is_a?(Array)
  return false unless left.length == array.length
  array.each_with_index.all? { | pattern, index| match(left[index], pattern, scope) }
end
match_Hash(hash, left, scope) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 186
def match_Hash(hash, left, scope)
  return false unless left.is_a?(Hash)
  hash.all? {|x,y| match(left[x], y, scope) }
end
match_Object(pattern, a, scope) click to toggle source

Matches in general by using == operator

# File lib/puppet/pops/evaluator/compare_operator.rb, line 160
def match_Object(pattern, a, scope)
  equals(a, pattern)
end
match_PAnyType(any_type, left, scope) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 172
def match_PAnyType(any_type, left, scope)
  # right is a type and left is not - check if left is an instance of the given type
  # (The reverse is not terribly meaningful - computing which of the case options that first produces
  # an instance of a given type).
  #
  @type_calculator.instance?(any_type, left)
end
match_Regexp(regexp, left, scope) click to toggle source

Matches only against strings

# File lib/puppet/pops/evaluator/compare_operator.rb, line 165
def match_Regexp(regexp, left, scope)
  return false unless left.is_a? String
  matched = regexp.match(left)
  set_match_data(matched, scope) # creates or clears ephemeral
  !!matched # convert to boolean
end
match_Symbol(symbol, left, scope) click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 191
def match_Symbol(symbol, left, scope)
  return true if symbol == :default
  equals(left, default, scope)
end

Public Class Methods

new() click to toggle source
# File lib/puppet/pops/evaluator/compare_operator.rb, line 17
def initialize
  @@equals_visitor  ||= Puppet::Pops::Visitor.new(self, "equals", 1, 1)
  @@compare_visitor ||= Puppet::Pops::Visitor.new(self, "cmp", 1, 1)
  @@match_visitor ||= Puppet::Pops::Visitor.new(self, "match", 2, 2)
  @@include_visitor ||= Puppet::Pops::Visitor.new(self, "include", 2, 2)
  @type_calculator = Puppet::Pops::Types::TypeCalculator.new()
end