class Dentaku::AST::Arithmetic
Constants
- DECIMAL
- INTEGER
Public Class Methods
new(*)
click to toggle source
Calls superclass method
# File lib/dentaku/ast/arithmetic.rb, line 12 def initialize(*) super unless valid_left? raise NodeError.new(:numeric, left.type, :left), "#{self.class} requires numeric operands" end unless valid_right? raise NodeError.new(:numeric, right.type, :right), "#{self.class} requires numeric operands" end end
Public Instance Methods
operator()
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 30 def operator raise NotImplementedError end
type()
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 26 def type :numeric end
value(context = {})
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 34 def value(context = {}) calculate(left.value(context), right.value(context)) end
Private Instance Methods
calculate(left_value, right_value)
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 40 def calculate(left_value, right_value) l = cast(left_value) r = cast(right_value) l.public_send(operator, r) rescue ::TypeError => e # Right cannot be converted to a suitable type for left. e.g. [] + 1 raise Dentaku::ArgumentError.for(:incompatible_type, value: r, for: l.class), e.message end
cast(val)
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 50 def cast(val) validate_value(val) numeric(val) end
datetime?(val)
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 69 def datetime?(val) # val is a Date, Time, or DateTime return true if val.respond_to?(:strftime) val.to_s =~ Dentaku::TokenScanner::DATE_TIME_REGEXP end
decimal(val)
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 63 def decimal(val) BigDecimal(val.to_s, Float::DIG + 1) rescue # return as is, in case value can't be coerced to big decimal val end
numeric(val)
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 55 def numeric(val) case val.to_s when DECIMAL then decimal(val) when INTEGER then val.to_i else val end end
valid_left?()
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 80 def valid_left? valid_node?(left) || left.type == :datetime end
valid_node?(node)
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 76 def valid_node?(node) node && (node.type == :numeric || node.type == :integer || node.dependencies.any?) end
valid_right?()
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 84 def valid_right? valid_node?(right) || right.type == :duration || right.type == :datetime end
validate_format(string)
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 103 def validate_format(string) unless string =~ /\A-?\d*(\.\d+)?\z/ && !string.empty? raise Dentaku::ArgumentError.for(:invalid_value, value: string, for: BigDecimal), "String input '#{string}' is not coercible to numeric" end end
validate_operation(val)
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 96 def validate_operation(val) unless val.respond_to?(operator) raise Dentaku::ArgumentError.for(:invalid_operator, operation: self.class, operator: operator), "#{ self.class } requires operands that respond to #{operator}" end end
validate_value(val)
click to toggle source
# File lib/dentaku/ast/arithmetic.rb, line 88 def validate_value(val) if val.is_a?(::String) validate_format(val) else validate_operation(val) end end