fuel-plugin-sensu/deployment_scripts/puppet/files/embedded/lib/ruby/gems/2.3.0/gems/dentaku-2.0.9/lib/dentaku/ast/arithmetic.rb

130 lines
2.4 KiB
Ruby

require_relative './operation'
require 'bigdecimal'
require 'bigdecimal/util'
module Dentaku
module AST
class Arithmetic < Operation
def initialize(*)
super
unless valid_node?(left) && valid_node?(right)
fail ParseError, "#{ self.class } requires numeric operands"
end
end
def type
:numeric
end
def value(context={})
l = cast(left.value(context))
r = cast(right.value(context))
l.public_send(operator, r)
end
private
def cast(value, prefer_integer=true)
validate_numeric(value)
v = BigDecimal.new(value, Float::DIG+1)
v = v.to_i if prefer_integer && v.frac.zero?
v
end
def valid_node?(node)
node && (node.dependencies.any? || node.type == :numeric)
end
def validate_numeric(value)
Float(value)
rescue ::ArgumentError, ::TypeError
fail Dentaku::ArgumentError, "#{ self.class } requires numeric operands"
end
end
class Addition < Arithmetic
def operator
:+
end
def self.precedence
10
end
end
class Subtraction < Arithmetic
def operator
:-
end
def self.precedence
10
end
end
class Multiplication < Arithmetic
def operator
:*
end
def self.precedence
20
end
end
class Division < Arithmetic
def value(context={})
r = cast(right.value(context), false)
raise Dentaku::ZeroDivisionError if r.zero?
cast(cast(left.value(context)) / r)
end
def self.precedence
20
end
end
class Modulo < Arithmetic
def initialize(left, right)
@left = left
@right = right
unless (valid_node?(left) || left.nil?) && valid_node?(right)
fail ParseError, "#{ self.class } requires numeric operands"
end
end
def percent?
left.nil?
end
def value(context={})
if percent?
cast(right.value(context)) * 0.01
else
super
end
end
def operator
:%
end
def self.precedence
20
end
end
class Exponentiation < Arithmetic
def operator
:**
end
def self.precedence
30
end
end
end
end