expr-lang/expr

Add a method to disable Operator to change the usage logic of Operator

Closed this issue · 2 comments

Q16G commented

Whether to set that you can add a disabled Operator or disable an Operator? Because I want to rewrite the use of contains as follows: contains("abc","a"), but I find that after the rewrite, it is still used in the way of Operator and cannot be completely overwritten.

code

package operation

import (
	"fmt"
	"github.com/expr-lang/expr"
	"testing"
)

type Env struct {
	Contains func(_ string, _ string) bool
}

func TestOperations_Execute(t *testing.T) {
	var a = []expr.Option{
		expr.Env(Env{}),
		expr.DisableAllBuiltins(),
		expr.Operator("contains", "Contains"),
		expr.Function("Contains", func(params ...any) (any, error) {
			fmt.Println(params)
			return false, nil
		}),
	}
	compile, err := expr.Compile(`contains("a","a")`, a...)

	if err != nil {
		fmt.Println(err)
		return
	}
	run, err := expr.Run(compile, a)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(run)
}

output:

unexpected token Operator("contains") (1:1)
 | contains("a","a")
 | ^

Here is a working example. The problem is with expr expression. contains is an operator and can't be used as a function name (I can see if it is possible to change parser to support this use case as well).

Here is a correct example:

"a" contains "b"

Also, a bug was fixed: now operator overloading can be used with expr.Function.

package main

import (
	"fmt"

	"github.com/expr-lang/expr"
)

func main() {
	options := []expr.Option{
		expr.Operator("contains", "Contains"),
		expr.Function(
			"Contains",
			func(params ...any) (any, error) {
				fmt.Println(params)
				return false, nil
			},
			new(func(string, string) bool),
		),
	}

	compile, err := expr.Compile(`"a" contains "b"`, options...)
	if err != nil {
		fmt.Println(err)
		return
	}

	run, err := expr.Run(compile, nil)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(run) 
	// Output:
	// [a b]
	// false
}
Q16G commented

So can I disable the contains operator and then re-declare it as a function to use