package pp import ( "github.com/d5/tengo/v2" "github.com/d5/tengo/v2/stdlib" "fmt" "context" ) type Tengo struct { head string modules *tengo.ModuleMap } func NewTengo() *Tengo { evaler := &Tengo{} evaler.modules = stdlib.GetModuleMap(stdlib.AllModuleNames()...) return evaler } func (pp *Tengo) Tags() [2]string { return [2]string{ "", } } // Simple Evaler implementation for the Tengo language func (pp *Tengo) Eval(filePath string, codes []string) ([]string, error) { const retHead = ` __ret_one__ := "" printf := func(format, ...vals) { __ret_one__ += sprintf(format, vals...) } print := func(...vals) { __ret_one__ += sprint(vals...) } println := func(...vals) { __ret_one__ += sprintln(vals...) } ` const retSeparator = ` __Separate(__ret_one__) __ret_one__ = "" ` rets := []string{} fullCode := retHead + "\n" + pp.head for _, code := range codes { fullCode += "\n" + code + retSeparator + "\n" } script := tengo.NewScript([]byte(fullCode)) script.SetImports(pp.modules) script.EnableFileImport(true) script.SetImportDir(".") err := script.Add("sprintf", &tengo.UserFunction{ Value: func(args ...tengo.Object) (tengo.Object, error){ if len(args) < 1 { return nil, tengo.ErrWrongNumArguments } format, ok := tengo.ToString(args[0]) if !ok { return nil, tengo.ErrInvalidArgumentType{ Expected: "string", } } gargs := make([]any, len(args) - 1) for i := range gargs { gargs[i] = tengo.ToInterface(args[i+1]) //fmt.Printf("shit: %q\n", gargs[i]) } str := fmt.Sprintf(format, gargs...) return tengo.FromInterface(str) }, }, ) if err != nil { return nil, err } err = script.Add("sprint", &tengo.UserFunction{ Value: func(args ...tengo.Object) (tengo.Object, error){ gargs := make([]any, len(args)) for i := range gargs { gargs[i] = tengo.ToInterface(args[i]) } str := fmt.Sprint(gargs...) return tengo.FromInterface(str) }, }, ) if err != nil { return nil, err } err = script.Add("sprintln", &tengo.UserFunction{ Value: func(args ...tengo.Object) (tengo.Object, error){ gargs := make([]any, len(args)) for i := range gargs { gargs[i] = tengo.ToInterface(args[i]) } str := fmt.Sprintln(gargs...) return tengo.FromInterface(str) }, }, ) if err != nil { return nil, err } err = script.Add("__Separate", &tengo.UserFunction{ Value: func(args ...tengo.Object) (tengo.Object, error){ if len(args) < 1 { return nil, tengo.ErrWrongNumArguments } str, ok := tengo.ToString(args[0]) if !ok { return nil, tengo.ErrInvalidArgumentType{ } } rets = append(rets, str) return nil, nil }, }, ) if err != nil { return nil, err } _, err = script.RunContext(context.Background()) if err != nil { return nil, err } return rets, nil }