Fuel plugin to deploy Sensu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

arithmetic.rb 2.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. require_relative './operation'
  2. require 'bigdecimal'
  3. require 'bigdecimal/util'
  4. module Dentaku
  5. module AST
  6. class Arithmetic < Operation
  7. def initialize(*)
  8. super
  9. unless valid_node?(left) && valid_node?(right)
  10. fail ParseError, "#{ self.class } requires numeric operands"
  11. end
  12. end
  13. def type
  14. :numeric
  15. end
  16. def value(context={})
  17. l = cast(left.value(context))
  18. r = cast(right.value(context))
  19. l.public_send(operator, r)
  20. end
  21. private
  22. def cast(value, prefer_integer=true)
  23. validate_numeric(value)
  24. v = BigDecimal.new(value, Float::DIG+1)
  25. v = v.to_i if prefer_integer && v.frac.zero?
  26. v
  27. end
  28. def valid_node?(node)
  29. node && (node.dependencies.any? || node.type == :numeric)
  30. end
  31. def validate_numeric(value)
  32. Float(value)
  33. rescue ::ArgumentError, ::TypeError
  34. fail Dentaku::ArgumentError, "#{ self.class } requires numeric operands"
  35. end
  36. end
  37. class Addition < Arithmetic
  38. def operator
  39. :+
  40. end
  41. def self.precedence
  42. 10
  43. end
  44. end
  45. class Subtraction < Arithmetic
  46. def operator
  47. :-
  48. end
  49. def self.precedence
  50. 10
  51. end
  52. end
  53. class Multiplication < Arithmetic
  54. def operator
  55. :*
  56. end
  57. def self.precedence
  58. 20
  59. end
  60. end
  61. class Division < Arithmetic
  62. def value(context={})
  63. r = cast(right.value(context), false)
  64. raise Dentaku::ZeroDivisionError if r.zero?
  65. cast(cast(left.value(context)) / r)
  66. end
  67. def self.precedence
  68. 20
  69. end
  70. end
  71. class Modulo < Arithmetic
  72. def initialize(left, right)
  73. @left = left
  74. @right = right
  75. unless (valid_node?(left) || left.nil?) && valid_node?(right)
  76. fail ParseError, "#{ self.class } requires numeric operands"
  77. end
  78. end
  79. def percent?
  80. left.nil?
  81. end
  82. def value(context={})
  83. if percent?
  84. cast(right.value(context)) * 0.01
  85. else
  86. super
  87. end
  88. end
  89. def operator
  90. :%
  91. end
  92. def self.precedence
  93. 20
  94. end
  95. end
  96. class Exponentiation < Arithmetic
  97. def operator
  98. :**
  99. end
  100. def self.precedence
  101. 30
  102. end
  103. end
  104. end
  105. end