go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/nodes/pkg/funcs/cutoff_expression.go (about)

     1  /*
     2  
     3  Copyright (c) 2023 - Present. Will Charczuk. All rights reserved.
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     5  
     6  */
     7  
     8  package funcs
     9  
    10  import (
    11  	"context"
    12  	"fmt"
    13  
    14  	"github.com/wcharczuk/go-incr"
    15  	"go.starlark.net/starlark"
    16  )
    17  
    18  func CutoffExpression[Input any](expression string) func(context.Context, Input, Input) (bool, error) {
    19  	return func(ctx context.Context, oldValue, newValue Input) (output bool, err error) {
    20  		oldfn := func(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
    21  			return castAsStarlarkValue(oldValue)
    22  		}
    23  		newfn := func(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
    24  			return castAsStarlarkValue(newValue)
    25  		}
    26  
    27  		var builtins = starlark.StringDict{
    28  			"oldValue": starlark.NewBuiltin("oldValue", oldfn),
    29  			"newValue": starlark.NewBuiltin("newValue", newfn),
    30  		}
    31  		for k, v := range defaultBuiltins {
    32  			builtins[k] = v
    33  		}
    34  
    35  		thread := new(starlark.Thread)
    36  		if tracer := incr.GetTracer(ctx); tracer != nil {
    37  			thread.Print = func(_ *starlark.Thread, msg string) {
    38  				tracer.Print("cutoff_expression:", msg)
    39  			}
    40  		}
    41  		var sd starlark.StringDict
    42  		sd, err = starlark.ExecFileOptions(&expressionFileOptions, thread, "<expr>", expression, builtins)
    43  		if err != nil {
    44  			return
    45  		}
    46  
    47  		v, ok := sd["output"]
    48  		if !ok {
    49  			err = fmt.Errorf("cutoff expression: you must use the `output` global to set the output")
    50  			return
    51  		}
    52  		switch typed := v.(type) {
    53  		case starlark.Bool:
    54  			output, err = starlarkScalarToOutput[bool](typed)
    55  		default:
    56  			err = fmt.Errorf("cutoff expression; the output type must be a boolean, was %T", typed)
    57  		}
    58  		return
    59  	}
    60  }