github.com/MontFerret/ferret@v0.18.0/pkg/runtime/expressions/operators/logical.go (about) 1 package operators 2 3 import ( 4 "context" 5 6 "github.com/MontFerret/ferret/pkg/runtime/core" 7 "github.com/MontFerret/ferret/pkg/runtime/values" 8 "github.com/MontFerret/ferret/pkg/runtime/values/types" 9 ) 10 11 type ( 12 LogicalOperatorVariant int 13 14 LogicalOperator struct { 15 *baseOperator 16 variant LogicalOperatorVariant 17 } 18 ) 19 20 const ( 21 LogicalOperatorVariantAnd LogicalOperatorVariant = 0 22 LogicalOperatorVariantOr LogicalOperatorVariant = 1 23 LogicalOperatorVariantNot LogicalOperatorVariant = 2 24 ) 25 26 var logicalOperators = map[string]LogicalOperatorVariant{ 27 "&&": LogicalOperatorVariantAnd, 28 "AND": LogicalOperatorVariantAnd, 29 "||": LogicalOperatorVariantOr, 30 "OR": LogicalOperatorVariantOr, 31 "NOT": LogicalOperatorVariantNot, 32 } 33 34 func NewLogicalOperator( 35 src core.SourceMap, 36 left core.Expression, 37 right core.Expression, 38 operator string, 39 ) (*LogicalOperator, error) { 40 op, exists := logicalOperators[operator] 41 42 if !exists { 43 return nil, core.Error(core.ErrInvalidArgument, "operator") 44 } 45 46 return &LogicalOperator{ 47 &baseOperator{ 48 src, 49 left, 50 right, 51 }, 52 op, 53 }, nil 54 } 55 56 func (operator *LogicalOperator) Exec(ctx context.Context, scope *core.Scope) (core.Value, error) { 57 if operator.variant == LogicalOperatorVariantNot { 58 val, err := operator.right.Exec(ctx, scope) 59 60 if err != nil { 61 return values.None, core.SourceError(operator.src, err) 62 } 63 64 return Not(val, values.None), nil 65 } 66 67 left, err := operator.left.Exec(ctx, scope) 68 69 if err != nil { 70 return values.None, core.SourceError(operator.src, err) 71 } 72 73 leftBool := values.ToBoolean(left) 74 75 if operator.variant == LogicalOperatorVariantAnd && leftBool == values.False { 76 if left.Type() == types.Boolean { 77 return values.False, nil 78 } 79 80 return left, nil 81 } 82 83 if operator.variant == LogicalOperatorVariantOr && leftBool == values.True { 84 return left, nil 85 } 86 87 right, err := operator.right.Exec(ctx, scope) 88 89 if err != nil { 90 return values.None, core.SourceError(operator.src, err) 91 } 92 93 return right, nil 94 } 95 96 func (operator *LogicalOperator) Eval(_ context.Context, left, right core.Value) (core.Value, error) { 97 if operator.variant == LogicalOperatorVariantNot { 98 return Not(right, values.None), nil 99 } 100 101 leftBool := values.ToBoolean(left) 102 103 if operator.variant == LogicalOperatorVariantAnd && leftBool == values.False { 104 if left.Type() == types.Boolean { 105 return values.False, nil 106 } 107 108 return left, nil 109 } 110 111 if operator.variant == LogicalOperatorVariantOr && leftBool == values.True { 112 return left, nil 113 } 114 115 return right, nil 116 }