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 |
# 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) 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.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 30 def interpret(input, parent, root, _path = nil) # FIXME: this branch could be pushed into the constructor, to convert O(n) work to O(1) case operator.name when :and, :or # handle node list for existence check lhs = @left.interpret(input, parent, root, []) rhs = @right.interpret(input, parent, root, []) when :equal, :not_equal, :less_than, :greater_than, :less_than_or_equal, :greater_than_or_equal # handle node values for comparison check lhs = to_single_value @left.interpret(input, parent, root, []) rhs = to_single_value @right.interpret(input, parent, root, []) else raise "Don't know how to handle binary operator #{operator.name.inspect}" end send(:"interpret_#{operator.name}", lhs, rhs) end |
#interpret_and(lhs, rhs) ⇒ Object
Interpret && operator May receive node lists, in which case empty node list == false
93 94 95 96 97 98 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 93 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
143 144 145 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 143 def interpret_boolean(boolean, _input) boolean.value end |
#interpret_equal(lhs, rhs) ⇒ Object
82 83 84 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 82 def interpret_equal(lhs, rhs) lhs == rhs end |
#interpret_greater_than(lhs, rhs) ⇒ Object
127 128 129 130 131 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 127 def interpret_greater_than(lhs, rhs) lhs > rhs rescue StandardError false end |
#interpret_greater_than_or_equal(lhs, rhs) ⇒ Object
133 134 135 136 137 138 139 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 133 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
109 110 111 112 113 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 109 def interpret_less_than(lhs, rhs) lhs < rhs rescue StandardError false end |
#interpret_less_than_or_equal(lhs, rhs) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 115 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
87 88 89 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 87 def interpret_not_equal(lhs, rhs) !interpret_equal(lhs, rhs) end |
#interpret_null(_null, _input) ⇒ Object
161 162 163 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 161 def interpret_null(_null, _input) nil end |
#interpret_number(number, _input) ⇒ Integer, Float
149 150 151 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 149 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
102 103 104 105 106 107 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 102 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
155 156 157 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 155 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.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/janeway/interpreters/binary_operator_interpreter.rb', line 62 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 |