Class: Janeway::Interpreters::BinaryOperatorInterpreter
- Defined in:
- lib/janeway/interpreters/binary_operator_interpreter.rb
Overview
Interprets a binary operator within filter selector.
Constant Summary
Constants inherited from Base
Janeway::Interpreters::Base::NOTHING
Instance Attribute Summary
Attributes inherited from Base
Instance Method Summary collapse
-
#initialize(operator) ⇒ BinaryOperatorInterpreter
constructor
Set up the internal interpreter chain for the BinaryOperator.
-
#interpret(input, parent, root, _path = nil) ⇒ Object
The binary operators are all comparison operators that test equality.
-
#interpret_and(lhs, rhs) ⇒ Object
Interpret && operator May receive node lists, in which case empty node list == false.
- #interpret_boolean(boolean, _input) ⇒ Boolean
- #interpret_equal(lhs, rhs) ⇒ Object
- #interpret_greater_than(lhs, rhs) ⇒ Object
- #interpret_greater_than_or_equal(lhs, rhs) ⇒ Object
- #interpret_less_than(lhs, rhs) ⇒ Object
- #interpret_less_than_or_equal(lhs, rhs) ⇒ Object
-
#interpret_not_equal(lhs, rhs) ⇒ Object
Interpret != operator.
- #interpret_null(_null, _input) ⇒ Object
- #interpret_number(number, _input) ⇒ Integer, Float
-
#interpret_or(lhs, rhs) ⇒ Object
Interpret || operator May receive node lists, in which case empty node list == false.
- #interpret_string_type(string, _input) ⇒ String
-
#to_single_value(result) ⇒ String, ...
Convert an expression result into a single value suitable for use by a comparison operator.
Methods inherited from Base
#as_json, #selector, #to_s, #type
Constructor Details
#initialize(operator) ⇒ BinaryOperatorInterpreter
Set up the internal interpreter chain for the BinaryOperator.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 12 def initialize(operator) super @left = TreeConstructor.ast_node_to_interpreter(operator.left) @right = TreeConstructor.ast_node_to_interpreter(operator.right) # Bind the per-op behavior at construction time to avoid dispatching # on operator.name and allocating a symbol on every candidate value. case operator.name when :and, :or @extract_single_value = false when :equal, :not_equal, :less_than, :greater_than, :less_than_or_equal, :greater_than_or_equal @extract_single_value = true else raise "Don't know how to handle binary operator #{operator.name.inspect}" end @op = method(:"interpret_#{operator.name}") end |
Instance Method Details
#interpret(input, parent, root, _path = nil) ⇒ Object
The binary operators are all comparison operators that test equality.
- boolean values specified in the query
- JSONPath expressions which must be evaluated
After a JSONPath expression is evaluated, it results in a node list. This may contain literal values or nodes, whose value must be extracted before comparison.
42 43 44 45 46 47 48 49 50 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 42 def interpret(input, parent, root, _path = nil) lhs = @left.interpret(input, parent, root, []) rhs = @right.interpret(input, parent, root, []) if @extract_single_value lhs = to_single_value(lhs) rhs = to_single_value(rhs) end @op.call(lhs, rhs) end |
#interpret_and(lhs, rhs) ⇒ Object
Interpret && operator May receive node lists, in which case empty node list == false
98 99 100 101 102 103 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 98 def interpret_and(lhs, rhs) # non-empty array is already truthy, so that works properly without conversion lhs = false if lhs == [] rhs = false if rhs == [] lhs && rhs end |
#interpret_boolean(boolean, _input) ⇒ Boolean
148 149 150 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 148 def interpret_boolean(boolean, _input) boolean.value end |
#interpret_equal(lhs, rhs) ⇒ Object
87 88 89 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 87 def interpret_equal(lhs, rhs) lhs == rhs end |
#interpret_greater_than(lhs, rhs) ⇒ Object
132 133 134 135 136 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 132 def interpret_greater_than(lhs, rhs) lhs > rhs rescue StandardError false end |
#interpret_greater_than_or_equal(lhs, rhs) ⇒ Object
138 139 140 141 142 143 144 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 138 def interpret_greater_than_or_equal(lhs, rhs) return true if interpret_equal(lhs, rhs) lhs > rhs rescue StandardError false end |
#interpret_less_than(lhs, rhs) ⇒ Object
114 115 116 117 118 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 114 def interpret_less_than(lhs, rhs) lhs < rhs rescue StandardError false end |
#interpret_less_than_or_equal(lhs, rhs) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 120 def interpret_less_than_or_equal(lhs, rhs) # Must be done in 2 comparisons, because the equality comparison is # valid for many types that do not support the < operator. return true if interpret_equal(lhs, rhs) lhs < rhs rescue StandardError # This catches type mismatches like {} <= 1 # RFC says that both < and > return false for such comparisons false end |
#interpret_not_equal(lhs, rhs) ⇒ Object
Interpret != operator
92 93 94 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 92 def interpret_not_equal(lhs, rhs) !interpret_equal(lhs, rhs) end |
#interpret_null(_null, _input) ⇒ Object
166 167 168 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 166 def interpret_null(_null, _input) nil end |
#interpret_number(number, _input) ⇒ Integer, Float
154 155 156 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 154 def interpret_number(number, _input) number.value end |
#interpret_or(lhs, rhs) ⇒ Object
Interpret || operator May receive node lists, in which case empty node list == false
107 108 109 110 111 112 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 107 def interpret_or(lhs, rhs) # non-empty array is already truthy, so that works properly without conversion lhs = false if lhs.is_a?(Array) && lhs.empty? rhs = false if rhs.is_a?(Array) && rhs.empty? lhs || rhs end |
#interpret_string_type(string, _input) ⇒ String
160 161 162 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 160 def interpret_string_type(string, _input) string.value end |
#to_single_value(result) ⇒ String, ...
Convert an expression result into a single value suitable for use by a comparison operator. Expression result may already ba single value (ie. from a literal like AST::String) or it may be a node list from a singular query.
Any node list is guaranteed not to contain multiple values because the expression that produce it was already verified to be a singular query.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 67 def to_single_value(result) # Return basic types (ie. from AST::Number, AST::StringType, AST::Null) return result unless result.is_a?(Array) # Node lists are returned by Selectors, ChildSegment, DescendantSegment. # # For a comparison operator, an empty node list represents a missing element. # This must not match any literal value (including null/nil) but must match another missing value. return NOTHING if result.empty? # The parsing stage has already verified that both the left and right # expressions evaluate to a single value. Both are either a literal or a singular query. # So, this check will never raise an error. raise 'node list contains multiple elements but this is a comparison' unless result.size == 1 result.first # Return the only node in the node list end |