/scalate-jruby/src/main/resources/haml-3.0.25/lib/sass/script/operation.rb

http://github.com/scalate/scalate · Ruby · 95 lines · 64 code · 12 blank · 19 comment · 11 complexity · 70c0ece5db9526ca44a08275cd8e1957 MD5 · raw file

  1. require 'set'
  2. require 'sass/script/string'
  3. require 'sass/script/number'
  4. require 'sass/script/color'
  5. require 'sass/script/functions'
  6. require 'sass/script/unary_operation'
  7. require 'sass/script/interpolation'
  8. require 'sass/script/string_interpolation'
  9. module Sass::Script
  10. # A SassScript parse node representing a binary operation,
  11. # such as `$a + $b` or `"foo" + 1`.
  12. class Operation < Node
  13. attr_reader :operand1
  14. attr_reader :operand2
  15. attr_reader :operator
  16. # @param operand1 [Script::Node] The parse-tree node
  17. # for the right-hand side of the operator
  18. # @param operand2 [Script::Node] The parse-tree node
  19. # for the left-hand side of the operator
  20. # @param operator [Symbol] The operator to perform.
  21. # This should be one of the binary operator names in {Lexer::OPERATORS}
  22. def initialize(operand1, operand2, operator)
  23. @operand1 = operand1
  24. @operand2 = operand2
  25. @operator = operator
  26. super()
  27. end
  28. # @return [String] A human-readable s-expression representation of the operation
  29. def inspect
  30. "(#{@operator.inspect} #{@operand1.inspect} #{@operand2.inspect})"
  31. end
  32. # @see Node#to_sass
  33. def to_sass(opts = {})
  34. pred = Sass::Script::Parser.precedence_of(@operator)
  35. o1 = operand_to_sass @operand1, :left, opts
  36. o2 = operand_to_sass @operand2, :right, opts
  37. sep =
  38. case @operator
  39. when :comma; ", "
  40. when :concat; " "
  41. else; " #{Lexer::OPERATORS_REVERSE[@operator]} "
  42. end
  43. "#{o1}#{sep}#{o2}"
  44. end
  45. # Returns the operands for this operation.
  46. #
  47. # @return [Array<Node>]
  48. # @see Node#children
  49. def children
  50. [@operand1, @operand2]
  51. end
  52. protected
  53. # Evaluates the operation.
  54. #
  55. # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
  56. # @return [Literal] The SassScript object that is the value of the operation
  57. # @raise [Sass::SyntaxError] if the operation is undefined for the operands
  58. def _perform(environment)
  59. literal1 = @operand1.perform(environment)
  60. literal2 = @operand2.perform(environment)
  61. if @operator == :concat && context == :equals
  62. literal1 = Sass::Script::String.new(literal1.value) if literal1.is_a?(Sass::Script::String)
  63. literal2 = Sass::Script::String.new(literal2.value) if literal2.is_a?(Sass::Script::String)
  64. end
  65. begin
  66. opts(literal1.send(@operator, literal2))
  67. rescue NoMethodError => e
  68. raise e unless e.name.to_s == @operator.to_s
  69. raise Sass::SyntaxError.new("Undefined operation: \"#{literal1} #{@operator} #{literal2}\".")
  70. end
  71. end
  72. private
  73. def operand_to_sass(op, side, opts)
  74. return op.to_sass(opts) unless op.is_a?(Operation)
  75. pred = Sass::Script::Parser.precedence_of(@operator)
  76. sub_pred = Sass::Script::Parser.precedence_of(op.operator)
  77. assoc = Sass::Script::Parser.associative?(@operator)
  78. return "(#{op.to_sass(opts)})" if sub_pred < pred ||
  79. (side == :right && sub_pred == pred && !assoc)
  80. op.to_sass(opts)
  81. end
  82. end
  83. end