github.com/MontFerret/ferret@v0.18.0/pkg/runtime/expressions/operators/math.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  )
     9  
    10  type (
    11  	MathOperatorVariant string
    12  
    13  	MathOperator struct {
    14  		*baseOperator
    15  		variant  MathOperatorVariant
    16  		fn       OperatorFunc
    17  		leftOnly bool
    18  	}
    19  )
    20  
    21  const (
    22  	MathOperatorVariantAdd       MathOperatorVariant = "+"
    23  	MathOperatorVariantSubtract  MathOperatorVariant = "-"
    24  	MathOperatorVariantMultiply  MathOperatorVariant = "*"
    25  	MathOperatorVariantDivide    MathOperatorVariant = "/"
    26  	MathOperatorVariantModulus   MathOperatorVariant = "%"
    27  	MathOperatorVariantIncrement MathOperatorVariant = "++"
    28  	MathOperatorVariantDecrement MathOperatorVariant = "--"
    29  )
    30  
    31  var mathOperatorVariants = map[MathOperatorVariant]OperatorFunc{
    32  	MathOperatorVariantAdd:       Add,
    33  	MathOperatorVariantSubtract:  Subtract,
    34  	MathOperatorVariantMultiply:  Multiply,
    35  	MathOperatorVariantDivide:    Divide,
    36  	MathOperatorVariantModulus:   Modulus,
    37  	MathOperatorVariantIncrement: Increment,
    38  	MathOperatorVariantDecrement: Decrement,
    39  }
    40  
    41  func NewMathOperator(
    42  	src core.SourceMap,
    43  	left core.Expression,
    44  	right core.Expression,
    45  	variantStr string,
    46  ) (*MathOperator, error) {
    47  	variant := MathOperatorVariant(variantStr)
    48  	fn, exists := mathOperatorVariants[variant]
    49  
    50  	if !exists {
    51  		return nil, core.Error(core.ErrInvalidArgument, "operator type")
    52  	}
    53  
    54  	var leftOnly bool
    55  
    56  	if variant == "++" || variant == "--" {
    57  		leftOnly = true
    58  	}
    59  
    60  	return &MathOperator{
    61  		&baseOperator{src, left, right},
    62  		variant,
    63  		fn,
    64  		leftOnly,
    65  	}, nil
    66  }
    67  
    68  func (operator *MathOperator) Type() MathOperatorVariant {
    69  	return operator.variant
    70  }
    71  
    72  func (operator *MathOperator) Exec(ctx context.Context, scope *core.Scope) (core.Value, error) {
    73  	left, err := operator.left.Exec(ctx, scope)
    74  
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	if operator.leftOnly {
    80  		return operator.Eval(ctx, left, values.None)
    81  	}
    82  
    83  	right, err := operator.right.Exec(ctx, scope)
    84  
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	return operator.Eval(ctx, left, right)
    90  }
    91  
    92  func (operator *MathOperator) Eval(_ context.Context, left, right core.Value) (core.Value, error) {
    93  	if operator.leftOnly {
    94  		return operator.fn(left, values.None), nil
    95  	}
    96  
    97  	return operator.fn(left, right), nil
    98  }