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  }