expr icon indicating copy to clipboard operation
expr copied to clipboard

Cannot use map[string]interface {} as argument (type main.Env) to call dump

Open vmihailenco opened this issue 1 year ago • 5 comments

The following program incorrectly assumes that the type of $env is map[string]any, although args[0] holds Env:

package main

import (
	"fmt"
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/expr-lang/expr"
)

type Env struct {
}

func (Env) Dump(args ...any) (any, error) {
	spew.Dump(args)
	return nil, nil
}

func main() {
	code := `dump($env)`

	env := Env{}
	program, err := expr.Compile(code,
		expr.Function("dump", env.Dump, new(func(Env) any)),
		//expr.Function("dump", env.Dump, new(func(any) any)),
		expr.Env(env)) // Pass the struct as an environment.
	if err != nil {
		panic(err)
	}

	output, err := expr.Run(program, env)
	if err != nil {
		panic(err)
	}

	fmt.Print(output)
}

Changing expr.Function("dump", env.Dump, new(func(Env) any)) to expr.Function("dump", env.Dump, new(func(any) any)) will allow to compile the program and inspect the type of the arg.

vmihailenco avatar Aug 09 '24 09:08 vmihailenco

Type of $env is always a map. This is internal agreement of how env works. From expr perspective it is not important if env is struct or a map.

antonmedv avatar Aug 09 '24 13:08 antonmedv

Type of $env is always a map.

When I pass $env as an arg to a function I get main.Env, not a map.

vmihailenco avatar Aug 09 '24 14:08 vmihailenco

Yes, in golang. But Expr assumes it is a map. As you can use $env[“var”] and $env.var on any env.

antonmedv avatar Aug 10 '24 02:08 antonmedv

But I think we can improve our type checker to also allow this kind of usages.

Let me look into how to implement it.

antonmedv avatar Aug 10 '24 02:08 antonmedv

Note: there is no need to only use methods defence on environment. You can use any functions to defined anywhere.

expr.Function("dump", func(params ...any) (any, error) { return spew.Dump(params[0]) }, spew.Dump)

antonmedv avatar Aug 10 '24 02:08 antonmedv