This commit is contained in:
Andrey Parhomenko 2024-08-02 02:55:30 +05:00
parent c461a7fe60
commit 3afc180451
97 changed files with 2853 additions and 1917 deletions

5
.gitignore vendored
View file

@ -1,3 +1,4 @@
/bin
/xgo
dist/ dist/
.idea
.idea

View file

@ -1,4 +1,4 @@
package tengo package xgo
var builtinFuncs = []*BuiltinFunction{ var builtinFuncs = []*BuiltinFunction{
{ {

View file

@ -1,11 +1,11 @@
package tengo_test package xgo_test
import ( import (
"errors" "errors"
"reflect" "reflect"
"testing" "testing"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
func Test_builtinDelete(t *testing.T) { func Test_builtinDelete(t *testing.T) {

View file

@ -1,4 +1,4 @@
package tengo package xgo
import ( import (
"encoding/gob" "encoding/gob"
@ -6,7 +6,7 @@ import (
"io" "io"
"reflect" "reflect"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
) )
// Bytecode is a compiled instructions and constants. // Bytecode is a compiled instructions and constants.

View file

@ -1,13 +1,13 @@
package tengo_test package xgo_test
import ( import (
"bytes" "bytes"
"testing" "testing"
"time" "time"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
) )
type srcfile struct { type srcfile struct {

View file

@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
) )
func main() { func main() {

View file

@ -6,18 +6,17 @@ import (
"flag" "flag"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
"github.com/d5/tengo/v2/stdlib" "surdeus.su/core/xgo/v2/stdlib"
) )
const ( const (
sourceFileExt = ".tengo" sourceFileExt = ".xgo"
replPrompt = ">> " replPrompt = ">> "
) )
@ -55,7 +54,7 @@ func main() {
return return
} }
inputData, err := ioutil.ReadFile(inputFile) inputData, err := os.ReadFile(inputFile)
if err != nil { if err != nil {
_, _ = fmt.Fprintf(os.Stderr, _, _ = fmt.Fprintf(os.Stderr,
"Error reading input file: %s\n", err.Error()) "Error reading input file: %s\n", err.Error())
@ -96,7 +95,7 @@ func main() {
// CompileOnly compiles the source code and writes the compiled binary into // CompileOnly compiles the source code and writes the compiled binary into
// outputFile. // outputFile.
func CompileOnly( func CompileOnly(
modules *tengo.ModuleMap, modules *xgo.ModuleMap,
data []byte, data []byte,
inputFile, outputFile string, inputFile, outputFile string,
) (err error) { ) (err error) {
@ -131,7 +130,7 @@ func CompileOnly(
// CompileAndRun compiles the source code and executes it. // CompileAndRun compiles the source code and executes it.
func CompileAndRun( func CompileAndRun(
modules *tengo.ModuleMap, modules *xgo.ModuleMap,
data []byte, data []byte,
inputFile string, inputFile string,
) (err error) { ) (err error) {
@ -140,45 +139,45 @@ func CompileAndRun(
return return
} }
machine := tengo.NewVM(bytecode, nil, -1) machine := xgo.NewVM(bytecode, nil, -1)
err = machine.Run() err = machine.Run()
return return
} }
// RunCompiled reads the compiled binary from file and executes it. // RunCompiled reads the compiled binary from file and executes it.
func RunCompiled(modules *tengo.ModuleMap, data []byte) (err error) { func RunCompiled(modules *xgo.ModuleMap, data []byte) (err error) {
bytecode := &tengo.Bytecode{} bytecode := &xgo.Bytecode{}
err = bytecode.Decode(bytes.NewReader(data), modules) err = bytecode.Decode(bytes.NewReader(data), modules)
if err != nil { if err != nil {
return return
} }
machine := tengo.NewVM(bytecode, nil, -1) machine := xgo.NewVM(bytecode, nil, -1)
err = machine.Run() err = machine.Run()
return return
} }
// RunREPL starts REPL. // RunREPL starts REPL.
func RunREPL(modules *tengo.ModuleMap, in io.Reader, out io.Writer) { func RunREPL(modules *xgo.ModuleMap, in io.Reader, out io.Writer) {
stdin := bufio.NewScanner(in) stdin := bufio.NewScanner(in)
fileSet := parser.NewFileSet() fileSet := parser.NewFileSet()
globals := make([]tengo.Object, tengo.GlobalsSize) globals := make([]xgo.Object, xgo.GlobalsSize)
symbolTable := tengo.NewSymbolTable() symbolTable := xgo.NewSymbolTable()
for idx, fn := range tengo.GetAllBuiltinFunctions() { for idx, fn := range xgo.GetAllBuiltinFunctions() {
symbolTable.DefineBuiltin(idx, fn.Name) symbolTable.DefineBuiltin(idx, fn.Name)
} }
// embed println function // embed println function
symbol := symbolTable.Define("__repl_println__") symbol := symbolTable.Define("__repl_println__")
globals[symbol.Index] = &tengo.UserFunction{ globals[symbol.Index] = &xgo.UserFunction{
Name: "println", Name: "println",
Value: func(args ...tengo.Object) (ret tengo.Object, err error) { Value: func(args ...xgo.Object) (ret xgo.Object, err error) {
var printArgs []interface{} var printArgs []interface{}
for _, arg := range args { for _, arg := range args {
if _, isUndefined := arg.(*tengo.Undefined); isUndefined { if _, isUndefined := arg.(*xgo.Undefined); isUndefined {
printArgs = append(printArgs, "<undefined>") printArgs = append(printArgs, "<undefined>")
} else { } else {
s, _ := tengo.ToString(arg) s, _ := xgo.ToString(arg)
printArgs = append(printArgs, s) printArgs = append(printArgs, s)
} }
} }
@ -188,7 +187,7 @@ func RunREPL(modules *tengo.ModuleMap, in io.Reader, out io.Writer) {
}, },
} }
var constants []tengo.Object var constants []xgo.Object
for { for {
_, _ = fmt.Fprint(out, replPrompt) _, _ = fmt.Fprint(out, replPrompt)
scanned := stdin.Scan() scanned := stdin.Scan()
@ -206,14 +205,14 @@ func RunREPL(modules *tengo.ModuleMap, in io.Reader, out io.Writer) {
} }
file = addPrints(file) file = addPrints(file)
c := tengo.NewCompiler(srcFile, symbolTable, constants, modules, nil) c := xgo.NewCompiler(srcFile, symbolTable, constants, modules, nil)
if err := c.Compile(file); err != nil { if err := c.Compile(file); err != nil {
_, _ = fmt.Fprintln(out, err.Error()) _, _ = fmt.Fprintln(out, err.Error())
continue continue
} }
bytecode := c.Bytecode() bytecode := c.Bytecode()
machine := tengo.NewVM(bytecode, globals, -1) machine := xgo.NewVM(bytecode, globals, -1)
if err := machine.Run(); err != nil { if err := machine.Run(); err != nil {
_, _ = fmt.Fprintln(out, err.Error()) _, _ = fmt.Fprintln(out, err.Error())
continue continue
@ -223,10 +222,10 @@ func RunREPL(modules *tengo.ModuleMap, in io.Reader, out io.Writer) {
} }
func compileSrc( func compileSrc(
modules *tengo.ModuleMap, modules *xgo.ModuleMap,
src []byte, src []byte,
inputFile string, inputFile string,
) (*tengo.Bytecode, error) { ) (*xgo.Bytecode, error) {
fileSet := parser.NewFileSet() fileSet := parser.NewFileSet()
srcFile := fileSet.AddFile(filepath.Base(inputFile), -1, len(src)) srcFile := fileSet.AddFile(filepath.Base(inputFile), -1, len(src))
@ -236,7 +235,7 @@ func compileSrc(
return nil, err return nil, err
} }
c := tengo.NewCompiler(srcFile, nil, nil, modules, nil) c := xgo.NewCompiler(srcFile, nil, nil, modules, nil)
c.EnableFileImport(true) c.EnableFileImport(true)
if resolvePath { if resolvePath {
c.SetImportDir(filepath.Dir(inputFile)) c.SetImportDir(filepath.Dir(inputFile))
@ -254,7 +253,7 @@ func compileSrc(
func doHelp() { func doHelp() {
fmt.Println("Usage:") fmt.Println("Usage:")
fmt.Println() fmt.Println()
fmt.Println(" tengo [flags] {input-file}") fmt.Println(" xgo [flags] {input-file}")
fmt.Println() fmt.Println()
fmt.Println("Flags:") fmt.Println("Flags:")
fmt.Println() fmt.Println()
@ -263,20 +262,20 @@ func doHelp() {
fmt.Println() fmt.Println()
fmt.Println("Examples:") fmt.Println("Examples:")
fmt.Println() fmt.Println()
fmt.Println(" tengo") fmt.Println(" xgo")
fmt.Println() fmt.Println()
fmt.Println(" Start Tengo REPL") fmt.Println(" Start Tengo REPL")
fmt.Println() fmt.Println()
fmt.Println(" tengo myapp.tengo") fmt.Println(" xgo myapp.xgo")
fmt.Println() fmt.Println()
fmt.Println(" Compile and run source file (myapp.tengo)") fmt.Println(" Compile and run source file (myapp.xgo)")
fmt.Println(" Source file must have .tengo extension") fmt.Println(" Source file must have .xgo extension")
fmt.Println() fmt.Println()
fmt.Println(" tengo -o myapp myapp.tengo") fmt.Println(" xgo -o myapp myapp.xgo")
fmt.Println() fmt.Println()
fmt.Println(" Compile source file (myapp.tengo) into bytecode file (myapp)") fmt.Println(" Compile source file (myapp.xgo) into bytecode file (myapp)")
fmt.Println() fmt.Println()
fmt.Println(" tengo myapp") fmt.Println(" xgo myapp")
fmt.Println() fmt.Println()
fmt.Println(" Run bytecode file (myapp)") fmt.Println(" Run bytecode file (myapp)")
fmt.Println() fmt.Println()

View file

@ -1,4 +1,4 @@
package tengo package xgo
import ( import (
"errors" "errors"
@ -10,8 +10,8 @@ import (
"reflect" "reflect"
"strings" "strings"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
"github.com/d5/tengo/v2/token" "surdeus.su/core/xgo/v2/token"
) )
// compilationScope represents a compiled instructions and the last two // compilationScope represents a compiled instructions and the last two
@ -631,8 +631,8 @@ func (c *Compiler) SetImportDir(dir string) {
// //
// Use this method if you want other source file extension than ".tengo". // Use this method if you want other source file extension than ".tengo".
// //
// // this will search for *.tengo, *.foo, *.bar // // this will search for *.tengo, *.foo, *.bar
// err := c.SetImportFileExt(".tengo", ".foo", ".bar") // err := c.SetImportFileExt(".tengo", ".foo", ".bar")
// //
// This function requires at least one argument, since it will replace the // This function requires at least one argument, since it will replace the
// current list of extension name. // current list of extension name.

View file

@ -1,4 +1,4 @@
package tengo_test package xgo_test
import ( import (
"fmt" "fmt"
@ -7,10 +7,10 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
"github.com/d5/tengo/v2/stdlib" "surdeus.su/core/xgo/v2/stdlib"
) )
func TestCompiler_Compile(t *testing.T) { func TestCompiler_Compile(t *testing.T) {

2
doc.go
View file

@ -1,3 +1,3 @@
// tengo is a small, dynamic, fast, secure script language for Go. // tengo is a small, dynamic, fast, secure script language for Go.
package tengo package xgo

View file

@ -1,4 +1,4 @@
package tengo package xgo
import ( import (
"errors" "errors"

View file

@ -1,4 +1,4 @@
package tengo package xgo
import ( import (
"context" "context"

View file

@ -1,11 +1,11 @@
package tengo_test package xgo_test
import ( import (
"context" "context"
"testing" "testing"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
) )
func TestEval(t *testing.T) { func TestEval(t *testing.T) {

View file

@ -1,10 +1,10 @@
package tengo_test package xgo_test
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
func Example() { func Example() {

View file

@ -11,7 +11,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
// CallArgs holds function name to be executed and its required parameters with // CallArgs holds function name to be executed and its required parameters with

View file

@ -1,4 +1,4 @@
package tengo package xgo
import ( import (
"strconv" "strconv"

4
go.mod
View file

@ -1,3 +1,3 @@
module github.com/d5/tengo/v2 module surdeus.su/core/xgo/v2
go 1.13 go 1.18

View file

@ -1,9 +1,9 @@
package tengo package xgo
import ( import (
"fmt" "fmt"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
) )
// MakeInstruction returns a bytecode for an opcode and the operands. // MakeInstruction returns a bytecode for an opcode and the operands.

View file

@ -1,4 +1,4 @@
package tengo package xgo
// Iterator represents an iterator for underlying data type. // Iterator represents an iterator for underlying data type.
type Iterator interface { type Iterator interface {

View file

@ -1,4 +1,4 @@
package tengo package xgo
// Importable interface represents importable module instance. // Importable interface represents importable module instance.
type Importable interface { type Importable interface {

View file

@ -1,4 +1,4 @@
package tengo package xgo
import ( import (
"bytes" "bytes"
@ -8,8 +8,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
"github.com/d5/tengo/v2/token" "surdeus.su/core/xgo/v2/token"
) )
var ( var (

View file

@ -1,11 +1,11 @@
package tengo_test package xgo_test
import ( import (
"testing" "testing"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
"github.com/d5/tengo/v2/token" "surdeus.su/core/xgo/v2/token"
) )
func TestObject_TypeName(t *testing.T) { func TestObject_TypeName(t *testing.T) {

View file

@ -3,7 +3,7 @@ package parser_test
import ( import (
"testing" "testing"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
) )
func TestIdentListString(t *testing.T) { func TestIdentListString(t *testing.T) {

View file

@ -3,7 +3,7 @@ package parser
import ( import (
"strings" "strings"
"github.com/d5/tengo/v2/token" "surdeus.su/core/xgo/v2/token"
) )
// Expr represents an expression node in the AST. // Expr represents an expression node in the AST.

View file

@ -6,7 +6,7 @@ import (
"sort" "sort"
"strconv" "strconv"
"github.com/d5/tengo/v2/token" "surdeus.su/core/xgo/v2/token"
) )
type bailout struct{} type bailout struct{}

View file

@ -8,9 +8,9 @@ import (
"strings" "strings"
"testing" "testing"
. "github.com/d5/tengo/v2/parser" . "surdeus.su/core/xgo/v2/parser"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
"github.com/d5/tengo/v2/token" "surdeus.su/core/xgo/v2/token"
) )
func TestParserError(t *testing.T) { func TestParserError(t *testing.T) {

View file

@ -5,7 +5,7 @@ import (
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
"github.com/d5/tengo/v2/token" "surdeus.su/core/xgo/v2/token"
) )
// byte order mark // byte order mark

View file

@ -7,9 +7,9 @@ import (
"testing" "testing"
"time" "time"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
"github.com/d5/tengo/v2/token" "surdeus.su/core/xgo/v2/token"
) )
var testFileSet = parser.NewFileSet() var testFileSet = parser.NewFileSet()

View file

@ -3,7 +3,7 @@ package parser
import ( import (
"strings" "strings"
"github.com/d5/tengo/v2/token" "surdeus.su/core/xgo/v2/token"
) )
// Stmt represents a statement in the AST. // Stmt represents a statement in the AST.

View file

@ -10,9 +10,9 @@ import (
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
"github.com/d5/tengo/v2/token" "surdeus.su/core/xgo/v2/token"
) )
// NoError asserts err is not an error. // NoError asserts err is not an error.

View file

@ -1,4 +1,4 @@
package tengo package xgo
import ( import (
"context" "context"
@ -6,7 +6,7 @@ import (
"path/filepath" "path/filepath"
"sync" "sync"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
) )
// Script can simplify compilation and execution of embedded scripts. // Script can simplify compilation and execution of embedded scripts.

View file

@ -1,4 +1,4 @@
package tengo_test package xgo_test
import ( import (
"context" "context"
@ -11,10 +11,10 @@ import (
"testing" "testing"
"time" "time"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
"github.com/d5/tengo/v2/stdlib" "surdeus.su/core/xgo/v2/stdlib"
"github.com/d5/tengo/v2/token" "surdeus.su/core/xgo/v2/token"
) )
func TestScript_Add(t *testing.T) { func TestScript_Add(t *testing.T) {

View file

@ -3,32 +3,32 @@ package stdlib
import ( import (
"encoding/base64" "encoding/base64"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
var base64Module = map[string]tengo.Object{ var base64Module = map[string]xgo.Object{
"encode": &tengo.UserFunction{ "encode": &xgo.UserFunction{
Value: FuncAYRS(base64.StdEncoding.EncodeToString), Value: FuncAYRS(base64.StdEncoding.EncodeToString),
}, },
"decode": &tengo.UserFunction{ "decode": &xgo.UserFunction{
Value: FuncASRYE(base64.StdEncoding.DecodeString), Value: FuncASRYE(base64.StdEncoding.DecodeString),
}, },
"raw_encode": &tengo.UserFunction{ "raw_encode": &xgo.UserFunction{
Value: FuncAYRS(base64.RawStdEncoding.EncodeToString), Value: FuncAYRS(base64.RawStdEncoding.EncodeToString),
}, },
"raw_decode": &tengo.UserFunction{ "raw_decode": &xgo.UserFunction{
Value: FuncASRYE(base64.RawStdEncoding.DecodeString), Value: FuncASRYE(base64.RawStdEncoding.DecodeString),
}, },
"url_encode": &tengo.UserFunction{ "url_encode": &xgo.UserFunction{
Value: FuncAYRS(base64.URLEncoding.EncodeToString), Value: FuncAYRS(base64.URLEncoding.EncodeToString),
}, },
"url_decode": &tengo.UserFunction{ "url_decode": &xgo.UserFunction{
Value: FuncASRYE(base64.URLEncoding.DecodeString), Value: FuncASRYE(base64.URLEncoding.DecodeString),
}, },
"raw_url_encode": &tengo.UserFunction{ "raw_url_encode": &xgo.UserFunction{
Value: FuncAYRS(base64.RawURLEncoding.EncodeToString), Value: FuncAYRS(base64.RawURLEncoding.EncodeToString),
}, },
"raw_url_decode": &tengo.UserFunction{ "raw_url_decode": &xgo.UserFunction{
Value: FuncASRYE(base64.RawURLEncoding.DecodeString), Value: FuncASRYE(base64.RawURLEncoding.DecodeString),
}, },
} }

View file

@ -1,11 +1,16 @@
package stdlib package stdlib
import ( import (
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"surdeus.su/core/xgo/v2/stdlib/http"
"surdeus.su/core/xgo/v2/stdlib/paths"
"surdeus.su/core/xgo/v2/stdlib/html"
"surdeus.su/core/xgo/v2/stdlib/log"
"surdeus.su/core/xgo/v2/stdlib/cjson"
) )
// BuiltinModules are builtin type standard library modules. // BuiltinModules are builtin type standard library modules.
var BuiltinModules = map[string]map[string]tengo.Object{ var BuiltinModules = map[string]map[string]xgo.Object{
"math": mathModule, "math": mathModule,
"os": osModule, "os": osModule,
"text": textModule, "text": textModule,
@ -15,4 +20,11 @@ var BuiltinModules = map[string]map[string]tengo.Object{
"json": jsonModule, "json": jsonModule,
"base64": base64Module, "base64": base64Module,
"hex": hexModule, "hex": hexModule,
// Implement later.
"url": nil,
"http": http.Module,
"paths": paths.Module,
"html": html.Module,
"log": log.Module,
"cjson": cjson.Module,
} }

108
stdlib/cjson/dec.go Normal file
View file

@ -0,0 +1,108 @@
package cjson
import "surdeus.su/core/xgo/v2"
import tjson "surdeus.su/core/xgo/v2/stdlib/json"
import "encoding/json"
import "io"
import "errors"
import "os"
type Decoder struct {
xgo.ObjectImpl
dec *json.Decoder
end bool
inputName string
}
func (d *Decoder) TypeName() string {
return "cjson.Decoder"
}
func (d *Decoder) String() string {
return "cjson.Decoder{...}"
}
func NewDecoder(args ...xgo.Object) (xgo.Object, error) {
var inputName string
if len(args) == 0 {
inputName = StrStdin
} else if len(args) > 1 {
return nil, xgo.ErrWrongNumArguments
} else {
var ok bool
inputObject := args[0]
inputName, ok = xgo.ToString(inputObject)
if !ok {
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "stringer",
Found: inputObject.TypeName(),
}
}
}
var reader io.Reader
var err error
switch {
case inputName == StrStdin:
reader = os.Stdin
default:
reader, err = os.Open(inputName)
if err != nil {
return nil, err
}
}
ret := &Decoder{}
ret.dec = json.NewDecoder(reader)
return ret, nil
}
func (d *Decoder) IndexGet(
index xgo.Object,
) (xgo.Object, error) {
key, ok := xgo.ToString(index)
if !ok {
return nil, xgo.ErrInvalidIndexValueType
}
switch key {
case "decode":
return &xgo.UserFunction{
Name: "decode",
Value: d.Decode,
}, nil
}
// Nothing found.
return nil, nil
}
func (d *Decoder) Decode(
args ...xgo.Object,
) (xgo.Object, error) {
if len(args) > 0 {
return nil, xgo.ErrWrongNumArguments
}
if d.end {
return nil, nil
}
var v any
err := d.dec.Decode(&v)
if err != nil {
if errors.Is(err, io.EOF) {
d.end = true
} else {
return nil, err
}
}
bts, err := json.Marshal(v)
if err != nil {
return nil, err
}
return tjson.Decode(bts)
}

23
stdlib/cjson/main.go Normal file
View file

@ -0,0 +1,23 @@
package cjson
import "surdeus.su/core/xgo/v2"
import "io"
import "encoding/json"
//import "github.com/d5/xgo/v2/stdlib"
const (
StrStdin = "<stdin>"
)
var Module = map[string]xgo.Object{
"Decoder": &xgo.BuiltinFunction{
Name: "Decoder",
Value: NewDecoder,
},
}
type Encoder struct {
enc *json.Encoder
output io.Writer
}

View file

@ -1,12 +1,12 @@
package stdlib package stdlib
import ( import (
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
func wrapError(err error) tengo.Object { func wrapError(err error) xgo.Object {
if err == nil { if err == nil {
return tengo.TrueValue return xgo.TrueValue
} }
return &tengo.Error{Value: &tengo.String{Value: err.Error()}} return &xgo.Error{Value: &xgo.String{Value: err.Error()}}
} }

View file

@ -3,17 +3,17 @@ package stdlib
import ( import (
"fmt" "fmt"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
var fmtModule = map[string]tengo.Object{ var fmtModule = map[string]xgo.Object{
"print": &tengo.UserFunction{Name: "print", Value: fmtPrint}, "print": &xgo.UserFunction{Name: "print", Value: fmtPrint},
"printf": &tengo.UserFunction{Name: "printf", Value: fmtPrintf}, "printf": &xgo.UserFunction{Name: "printf", Value: fmtPrintf},
"println": &tengo.UserFunction{Name: "println", Value: fmtPrintln}, "println": &xgo.UserFunction{Name: "println", Value: fmtPrintln},
"sprintf": &tengo.UserFunction{Name: "sprintf", Value: fmtSprintf}, "sprintf": &xgo.UserFunction{Name: "sprintf", Value: fmtSprintf},
} }
func fmtPrint(args ...tengo.Object) (ret tengo.Object, err error) { func fmtPrint(args ...xgo.Object) (ret xgo.Object, err error) {
printArgs, err := getPrintArgs(args...) printArgs, err := getPrintArgs(args...)
if err != nil { if err != nil {
return nil, err return nil, err
@ -22,15 +22,15 @@ func fmtPrint(args ...tengo.Object) (ret tengo.Object, err error) {
return nil, nil return nil, nil
} }
func fmtPrintf(args ...tengo.Object) (ret tengo.Object, err error) { func fmtPrintf(args ...xgo.Object) (ret xgo.Object, err error) {
numArgs := len(args) numArgs := len(args)
if numArgs == 0 { if numArgs == 0 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
format, ok := args[0].(*tengo.String) format, ok := args[0].(*xgo.String)
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "format", Name: "format",
Expected: "string", Expected: "string",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -41,7 +41,7 @@ func fmtPrintf(args ...tengo.Object) (ret tengo.Object, err error) {
return nil, nil return nil, nil
} }
s, err := tengo.Format(format.Value, args[1:]...) s, err := xgo.Format(format.Value, args[1:]...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -49,7 +49,7 @@ func fmtPrintf(args ...tengo.Object) (ret tengo.Object, err error) {
return nil, nil return nil, nil
} }
func fmtPrintln(args ...tengo.Object) (ret tengo.Object, err error) { func fmtPrintln(args ...xgo.Object) (ret xgo.Object, err error) {
printArgs, err := getPrintArgs(args...) printArgs, err := getPrintArgs(args...)
if err != nil { if err != nil {
return nil, err return nil, err
@ -59,15 +59,15 @@ func fmtPrintln(args ...tengo.Object) (ret tengo.Object, err error) {
return nil, nil return nil, nil
} }
func fmtSprintf(args ...tengo.Object) (ret tengo.Object, err error) { func fmtSprintf(args ...xgo.Object) (ret xgo.Object, err error) {
numArgs := len(args) numArgs := len(args)
if numArgs == 0 { if numArgs == 0 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
format, ok := args[0].(*tengo.String) format, ok := args[0].(*xgo.String)
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "format", Name: "format",
Expected: "string", Expected: "string",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -77,22 +77,22 @@ func fmtSprintf(args ...tengo.Object) (ret tengo.Object, err error) {
// okay to return 'format' directly as String is immutable // okay to return 'format' directly as String is immutable
return format, nil return format, nil
} }
s, err := tengo.Format(format.Value, args[1:]...) s, err := xgo.Format(format.Value, args[1:]...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &tengo.String{Value: s}, nil return &xgo.String{Value: s}, nil
} }
func getPrintArgs(args ...tengo.Object) ([]interface{}, error) { func getPrintArgs(args ...xgo.Object) ([]interface{}, error) {
var printArgs []interface{} var printArgs []interface{}
l := 0 l := 0
for _, arg := range args { for _, arg := range args {
s, _ := tengo.ToString(arg) s, _ := xgo.ToString(arg)
slen := len(s) slen := len(s)
// make sure length does not exceed the limit // make sure length does not exceed the limit
if l+slen > tengo.MaxStringLen { if l+slen > xgo.MaxStringLen {
return nil, tengo.ErrStringLimit return nil, xgo.ErrStringLimit
} }
l += slen l += slen
printArgs = append(printArgs, s) printArgs = append(printArgs, s)

File diff suppressed because it is too large Load diff

View file

@ -6,51 +6,51 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
"github.com/d5/tengo/v2/stdlib" "surdeus.su/core/xgo/v2/stdlib"
) )
func TestFuncAIR(t *testing.T) { func TestFuncAIR(t *testing.T) {
uf := stdlib.FuncAIR(func(int) {}) uf := stdlib.FuncAIR(func(int) {})
ret, err := funcCall(uf, &tengo.Int{Value: 10}) ret, err := funcCall(uf, &xgo.Int{Value: 10})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tengo.UndefinedValue, ret) require.Equal(t, xgo.UndefinedValue, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAR(t *testing.T) { func TestFuncAR(t *testing.T) {
uf := stdlib.FuncAR(func() {}) uf := stdlib.FuncAR(func() {})
ret, err := funcCall(uf) ret, err := funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tengo.UndefinedValue, ret) require.Equal(t, xgo.UndefinedValue, ret)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncARI(t *testing.T) { func TestFuncARI(t *testing.T) {
uf := stdlib.FuncARI(func() int { return 10 }) uf := stdlib.FuncARI(func() int { return 10 })
ret, err := funcCall(uf) ret, err := funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 10}, ret) require.Equal(t, &xgo.Int{Value: 10}, ret)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncARE(t *testing.T) { func TestFuncARE(t *testing.T) {
uf := stdlib.FuncARE(func() error { return nil }) uf := stdlib.FuncARE(func() error { return nil })
ret, err := funcCall(uf) ret, err := funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret) require.Equal(t, xgo.TrueValue, ret)
uf = stdlib.FuncARE(func() error { return errors.New("some error") }) uf = stdlib.FuncARE(func() error { return errors.New("some error") })
ret, err = funcCall(uf) ret, err = funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Error{ require.Equal(t, &xgo.Error{
Value: &tengo.String{Value: "some error"}, Value: &xgo.String{Value: "some error"},
}, ret) }, ret)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncARIsE(t *testing.T) { func TestFuncARIsE(t *testing.T) {
@ -59,364 +59,364 @@ func TestFuncARIsE(t *testing.T) {
}) })
ret, err := funcCall(uf) ret, err := funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, array(&tengo.Int{Value: 1}, require.Equal(t, array(&xgo.Int{Value: 1},
&tengo.Int{Value: 2}, &tengo.Int{Value: 3}), ret) &xgo.Int{Value: 2}, &xgo.Int{Value: 3}), ret)
uf = stdlib.FuncARIsE(func() ([]int, error) { uf = stdlib.FuncARIsE(func() ([]int, error) {
return nil, errors.New("some error") return nil, errors.New("some error")
}) })
ret, err = funcCall(uf) ret, err = funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Error{ require.Equal(t, &xgo.Error{
Value: &tengo.String{Value: "some error"}, Value: &xgo.String{Value: "some error"},
}, ret) }, ret)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncARS(t *testing.T) { func TestFuncARS(t *testing.T) {
uf := stdlib.FuncARS(func() string { return "foo" }) uf := stdlib.FuncARS(func() string { return "foo" })
ret, err := funcCall(uf) ret, err := funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.String{Value: "foo"}, ret) require.Equal(t, &xgo.String{Value: "foo"}, ret)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncARSE(t *testing.T) { func TestFuncARSE(t *testing.T) {
uf := stdlib.FuncARSE(func() (string, error) { return "foo", nil }) uf := stdlib.FuncARSE(func() (string, error) { return "foo", nil })
ret, err := funcCall(uf) ret, err := funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.String{Value: "foo"}, ret) require.Equal(t, &xgo.String{Value: "foo"}, ret)
uf = stdlib.FuncARSE(func() (string, error) { uf = stdlib.FuncARSE(func() (string, error) {
return "", errors.New("some error") return "", errors.New("some error")
}) })
ret, err = funcCall(uf) ret, err = funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Error{ require.Equal(t, &xgo.Error{
Value: &tengo.String{Value: "some error"}, Value: &xgo.String{Value: "some error"},
}, ret) }, ret)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncARSs(t *testing.T) { func TestFuncARSs(t *testing.T) {
uf := stdlib.FuncARSs(func() []string { return []string{"foo", "bar"} }) uf := stdlib.FuncARSs(func() []string { return []string{"foo", "bar"} })
ret, err := funcCall(uf) ret, err := funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, array(&tengo.String{Value: "foo"}, require.Equal(t, array(&xgo.String{Value: "foo"},
&tengo.String{Value: "bar"}), ret) &xgo.String{Value: "bar"}), ret)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASRE(t *testing.T) { func TestFuncASRE(t *testing.T) {
uf := stdlib.FuncASRE(func(a string) error { return nil }) uf := stdlib.FuncASRE(func(a string) error { return nil })
ret, err := funcCall(uf, &tengo.String{Value: "foo"}) ret, err := funcCall(uf, &xgo.String{Value: "foo"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret) require.Equal(t, xgo.TrueValue, ret)
uf = stdlib.FuncASRE(func(a string) error { uf = stdlib.FuncASRE(func(a string) error {
return errors.New("some error") return errors.New("some error")
}) })
ret, err = funcCall(uf, &tengo.String{Value: "foo"}) ret, err = funcCall(uf, &xgo.String{Value: "foo"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Error{ require.Equal(t, &xgo.Error{
Value: &tengo.String{Value: "some error"}, Value: &xgo.String{Value: "some error"},
}, ret) }, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASRS(t *testing.T) { func TestFuncASRS(t *testing.T) {
uf := stdlib.FuncASRS(func(a string) string { return a }) uf := stdlib.FuncASRS(func(a string) string { return a })
ret, err := funcCall(uf, &tengo.String{Value: "foo"}) ret, err := funcCall(uf, &xgo.String{Value: "foo"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.String{Value: "foo"}, ret) require.Equal(t, &xgo.String{Value: "foo"}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASRSs(t *testing.T) { func TestFuncASRSs(t *testing.T) {
uf := stdlib.FuncASRSs(func(a string) []string { return []string{a} }) uf := stdlib.FuncASRSs(func(a string) []string { return []string{a} })
ret, err := funcCall(uf, &tengo.String{Value: "foo"}) ret, err := funcCall(uf, &xgo.String{Value: "foo"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, array(&tengo.String{Value: "foo"}), ret) require.Equal(t, array(&xgo.String{Value: "foo"}), ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASI64RE(t *testing.T) { func TestFuncASI64RE(t *testing.T) {
uf := stdlib.FuncASI64RE(func(a string, b int64) error { return nil }) uf := stdlib.FuncASI64RE(func(a string, b int64) error { return nil })
ret, err := funcCall(uf, &tengo.String{Value: "foo"}, &tengo.Int{Value: 5}) ret, err := funcCall(uf, &xgo.String{Value: "foo"}, &xgo.Int{Value: 5})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret) require.Equal(t, xgo.TrueValue, ret)
uf = stdlib.FuncASI64RE(func(a string, b int64) error { uf = stdlib.FuncASI64RE(func(a string, b int64) error {
return errors.New("some error") return errors.New("some error")
}) })
ret, err = funcCall(uf, &tengo.String{Value: "foo"}, &tengo.Int{Value: 5}) ret, err = funcCall(uf, &xgo.String{Value: "foo"}, &xgo.Int{Value: 5})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, require.Equal(t,
&tengo.Error{Value: &tengo.String{Value: "some error"}}, ret) &xgo.Error{Value: &xgo.String{Value: "some error"}}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAIIRE(t *testing.T) { func TestFuncAIIRE(t *testing.T) {
uf := stdlib.FuncAIIRE(func(a, b int) error { return nil }) uf := stdlib.FuncAIIRE(func(a, b int) error { return nil })
ret, err := funcCall(uf, &tengo.Int{Value: 5}, &tengo.Int{Value: 7}) ret, err := funcCall(uf, &xgo.Int{Value: 5}, &xgo.Int{Value: 7})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret) require.Equal(t, xgo.TrueValue, ret)
uf = stdlib.FuncAIIRE(func(a, b int) error { uf = stdlib.FuncAIIRE(func(a, b int) error {
return errors.New("some error") return errors.New("some error")
}) })
ret, err = funcCall(uf, &tengo.Int{Value: 5}, &tengo.Int{Value: 7}) ret, err = funcCall(uf, &xgo.Int{Value: 5}, &xgo.Int{Value: 7})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, require.Equal(t,
&tengo.Error{Value: &tengo.String{Value: "some error"}}, ret) &xgo.Error{Value: &xgo.String{Value: "some error"}}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASIIRE(t *testing.T) { func TestFuncASIIRE(t *testing.T) {
uf := stdlib.FuncASIIRE(func(a string, b, c int) error { return nil }) uf := stdlib.FuncASIIRE(func(a string, b, c int) error { return nil })
ret, err := funcCall(uf, &tengo.String{Value: "foo"}, &tengo.Int{Value: 5}, ret, err := funcCall(uf, &xgo.String{Value: "foo"}, &xgo.Int{Value: 5},
&tengo.Int{Value: 7}) &xgo.Int{Value: 7})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret) require.Equal(t, xgo.TrueValue, ret)
uf = stdlib.FuncASIIRE(func(a string, b, c int) error { uf = stdlib.FuncASIIRE(func(a string, b, c int) error {
return errors.New("some error") return errors.New("some error")
}) })
ret, err = funcCall(uf, &tengo.String{Value: "foo"}, &tengo.Int{Value: 5}, ret, err = funcCall(uf, &xgo.String{Value: "foo"}, &xgo.Int{Value: 5},
&tengo.Int{Value: 7}) &xgo.Int{Value: 7})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, require.Equal(t,
&tengo.Error{Value: &tengo.String{Value: "some error"}}, ret) &xgo.Error{Value: &xgo.String{Value: "some error"}}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASRSE(t *testing.T) { func TestFuncASRSE(t *testing.T) {
uf := stdlib.FuncASRSE(func(a string) (string, error) { return a, nil }) uf := stdlib.FuncASRSE(func(a string) (string, error) { return a, nil })
ret, err := funcCall(uf, &tengo.String{Value: "foo"}) ret, err := funcCall(uf, &xgo.String{Value: "foo"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.String{Value: "foo"}, ret) require.Equal(t, &xgo.String{Value: "foo"}, ret)
uf = stdlib.FuncASRSE(func(a string) (string, error) { uf = stdlib.FuncASRSE(func(a string) (string, error) {
return a, errors.New("some error") return a, errors.New("some error")
}) })
ret, err = funcCall(uf, &tengo.String{Value: "foo"}) ret, err = funcCall(uf, &xgo.String{Value: "foo"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, require.Equal(t,
&tengo.Error{Value: &tengo.String{Value: "some error"}}, ret) &xgo.Error{Value: &xgo.String{Value: "some error"}}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASSRE(t *testing.T) { func TestFuncASSRE(t *testing.T) {
uf := stdlib.FuncASSRE(func(a, b string) error { return nil }) uf := stdlib.FuncASSRE(func(a, b string) error { return nil })
ret, err := funcCall(uf, &tengo.String{Value: "foo"}, ret, err := funcCall(uf, &xgo.String{Value: "foo"},
&tengo.String{Value: "bar"}) &xgo.String{Value: "bar"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret) require.Equal(t, xgo.TrueValue, ret)
uf = stdlib.FuncASSRE(func(a, b string) error { uf = stdlib.FuncASSRE(func(a, b string) error {
return errors.New("some error") return errors.New("some error")
}) })
ret, err = funcCall(uf, &tengo.String{Value: "foo"}, ret, err = funcCall(uf, &xgo.String{Value: "foo"},
&tengo.String{Value: "bar"}) &xgo.String{Value: "bar"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, require.Equal(t,
&tengo.Error{Value: &tengo.String{Value: "some error"}}, ret) &xgo.Error{Value: &xgo.String{Value: "some error"}}, ret)
_, err = funcCall(uf, &tengo.String{Value: "foo"}) _, err = funcCall(uf, &xgo.String{Value: "foo"})
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASsRS(t *testing.T) { func TestFuncASsRS(t *testing.T) {
uf := stdlib.FuncASsSRS(func(a []string, b string) string { uf := stdlib.FuncASsSRS(func(a []string, b string) string {
return strings.Join(a, b) return strings.Join(a, b)
}) })
ret, err := funcCall(uf, array(&tengo.String{Value: "foo"}, ret, err := funcCall(uf, array(&xgo.String{Value: "foo"},
&tengo.String{Value: "bar"}), &tengo.String{Value: " "}) &xgo.String{Value: "bar"}), &xgo.String{Value: " "})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.String{Value: "foo bar"}, ret) require.Equal(t, &xgo.String{Value: "foo bar"}, ret)
_, err = funcCall(uf, &tengo.String{Value: "foo"}) _, err = funcCall(uf, &xgo.String{Value: "foo"})
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncARF(t *testing.T) { func TestFuncARF(t *testing.T) {
uf := stdlib.FuncARF(func() float64 { return 10.0 }) uf := stdlib.FuncARF(func() float64 { return 10.0 })
ret, err := funcCall(uf) ret, err := funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Float{Value: 10.0}, ret) require.Equal(t, &xgo.Float{Value: 10.0}, ret)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAFRF(t *testing.T) { func TestFuncAFRF(t *testing.T) {
uf := stdlib.FuncAFRF(func(a float64) float64 { return a }) uf := stdlib.FuncAFRF(func(a float64) float64 { return a })
ret, err := funcCall(uf, &tengo.Float{Value: 10.0}) ret, err := funcCall(uf, &xgo.Float{Value: 10.0})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Float{Value: 10.0}, ret) require.Equal(t, &xgo.Float{Value: 10.0}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAIRF(t *testing.T) { func TestFuncAIRF(t *testing.T) {
uf := stdlib.FuncAIRF(func(a int) float64 { uf := stdlib.FuncAIRF(func(a int) float64 {
return float64(a) return float64(a)
}) })
ret, err := funcCall(uf, &tengo.Int{Value: 10.0}) ret, err := funcCall(uf, &xgo.Int{Value: 10.0})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Float{Value: 10.0}, ret) require.Equal(t, &xgo.Float{Value: 10.0}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAFRI(t *testing.T) { func TestFuncAFRI(t *testing.T) {
uf := stdlib.FuncAFRI(func(a float64) int { uf := stdlib.FuncAFRI(func(a float64) int {
return int(a) return int(a)
}) })
ret, err := funcCall(uf, &tengo.Float{Value: 10.5}) ret, err := funcCall(uf, &xgo.Float{Value: 10.5})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 10}, ret) require.Equal(t, &xgo.Int{Value: 10}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAFRB(t *testing.T) { func TestFuncAFRB(t *testing.T) {
uf := stdlib.FuncAFRB(func(a float64) bool { uf := stdlib.FuncAFRB(func(a float64) bool {
return a > 0.0 return a > 0.0
}) })
ret, err := funcCall(uf, &tengo.Float{Value: 0.1}) ret, err := funcCall(uf, &xgo.Float{Value: 0.1})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret) require.Equal(t, xgo.TrueValue, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAFFRF(t *testing.T) { func TestFuncAFFRF(t *testing.T) {
uf := stdlib.FuncAFFRF(func(a, b float64) float64 { uf := stdlib.FuncAFFRF(func(a, b float64) float64 {
return a + b return a + b
}) })
ret, err := funcCall(uf, &tengo.Float{Value: 10.0}, ret, err := funcCall(uf, &xgo.Float{Value: 10.0},
&tengo.Float{Value: 20.0}) &xgo.Float{Value: 20.0})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Float{Value: 30.0}, ret) require.Equal(t, &xgo.Float{Value: 30.0}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASIRS(t *testing.T) { func TestFuncASIRS(t *testing.T) {
uf := stdlib.FuncASIRS(func(a string, b int) string { uf := stdlib.FuncASIRS(func(a string, b int) string {
return strings.Repeat(a, b) return strings.Repeat(a, b)
}) })
ret, err := funcCall(uf, &tengo.String{Value: "ab"}, &tengo.Int{Value: 2}) ret, err := funcCall(uf, &xgo.String{Value: "ab"}, &xgo.Int{Value: 2})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.String{Value: "abab"}, ret) require.Equal(t, &xgo.String{Value: "abab"}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAIFRF(t *testing.T) { func TestFuncAIFRF(t *testing.T) {
uf := stdlib.FuncAIFRF(func(a int, b float64) float64 { uf := stdlib.FuncAIFRF(func(a int, b float64) float64 {
return float64(a) + b return float64(a) + b
}) })
ret, err := funcCall(uf, &tengo.Int{Value: 10}, &tengo.Float{Value: 20.0}) ret, err := funcCall(uf, &xgo.Int{Value: 10}, &xgo.Float{Value: 20.0})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Float{Value: 30.0}, ret) require.Equal(t, &xgo.Float{Value: 30.0}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAFIRF(t *testing.T) { func TestFuncAFIRF(t *testing.T) {
uf := stdlib.FuncAFIRF(func(a float64, b int) float64 { uf := stdlib.FuncAFIRF(func(a float64, b int) float64 {
return a + float64(b) return a + float64(b)
}) })
ret, err := funcCall(uf, &tengo.Float{Value: 10.0}, &tengo.Int{Value: 20}) ret, err := funcCall(uf, &xgo.Float{Value: 10.0}, &xgo.Int{Value: 20})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Float{Value: 30.0}, ret) require.Equal(t, &xgo.Float{Value: 30.0}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAFIRB(t *testing.T) { func TestFuncAFIRB(t *testing.T) {
uf := stdlib.FuncAFIRB(func(a float64, b int) bool { uf := stdlib.FuncAFIRB(func(a float64, b int) bool {
return a < float64(b) return a < float64(b)
}) })
ret, err := funcCall(uf, &tengo.Float{Value: 10.0}, &tengo.Int{Value: 20}) ret, err := funcCall(uf, &xgo.Float{Value: 10.0}, &xgo.Int{Value: 20})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret) require.Equal(t, xgo.TrueValue, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAIRSsE(t *testing.T) { func TestFuncAIRSsE(t *testing.T) {
uf := stdlib.FuncAIRSsE(func(a int) ([]string, error) { uf := stdlib.FuncAIRSsE(func(a int) ([]string, error) {
return []string{"foo", "bar"}, nil return []string{"foo", "bar"}, nil
}) })
ret, err := funcCall(uf, &tengo.Int{Value: 10}) ret, err := funcCall(uf, &xgo.Int{Value: 10})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, array(&tengo.String{Value: "foo"}, require.Equal(t, array(&xgo.String{Value: "foo"},
&tengo.String{Value: "bar"}), ret) &xgo.String{Value: "bar"}), ret)
uf = stdlib.FuncAIRSsE(func(a int) ([]string, error) { uf = stdlib.FuncAIRSsE(func(a int) ([]string, error) {
return nil, errors.New("some error") return nil, errors.New("some error")
}) })
ret, err = funcCall(uf, &tengo.Int{Value: 10}) ret, err = funcCall(uf, &xgo.Int{Value: 10})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, require.Equal(t,
&tengo.Error{Value: &tengo.String{Value: "some error"}}, ret) &xgo.Error{Value: &xgo.String{Value: "some error"}}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASSRSs(t *testing.T) { func TestFuncASSRSs(t *testing.T) {
uf := stdlib.FuncASSRSs(func(a, b string) []string { uf := stdlib.FuncASSRSs(func(a, b string) []string {
return []string{a, b} return []string{a, b}
}) })
ret, err := funcCall(uf, &tengo.String{Value: "foo"}, ret, err := funcCall(uf, &xgo.String{Value: "foo"},
&tengo.String{Value: "bar"}) &xgo.String{Value: "bar"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, array(&tengo.String{Value: "foo"}, require.Equal(t, array(&xgo.String{Value: "foo"},
&tengo.String{Value: "bar"}), ret) &xgo.String{Value: "bar"}), ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASSIRSs(t *testing.T) { func TestFuncASSIRSs(t *testing.T) {
uf := stdlib.FuncASSIRSs(func(a, b string, c int) []string { uf := stdlib.FuncASSIRSs(func(a, b string, c int) []string {
return []string{a, b, strconv.Itoa(c)} return []string{a, b, strconv.Itoa(c)}
}) })
ret, err := funcCall(uf, &tengo.String{Value: "foo"}, ret, err := funcCall(uf, &xgo.String{Value: "foo"},
&tengo.String{Value: "bar"}, &tengo.Int{Value: 5}) &xgo.String{Value: "bar"}, &xgo.Int{Value: 5})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, array(&tengo.String{Value: "foo"}, require.Equal(t, array(&xgo.String{Value: "foo"},
&tengo.String{Value: "bar"}, &tengo.String{Value: "5"}), ret) &xgo.String{Value: "bar"}, &xgo.String{Value: "5"}), ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncARB(t *testing.T) { func TestFuncARB(t *testing.T) {
uf := stdlib.FuncARB(func() bool { return true }) uf := stdlib.FuncARB(func() bool { return true })
ret, err := funcCall(uf) ret, err := funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret) require.Equal(t, xgo.TrueValue, ret)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncARYE(t *testing.T) { func TestFuncARYE(t *testing.T) {
@ -425,114 +425,114 @@ func TestFuncARYE(t *testing.T) {
}) })
ret, err := funcCall(uf) ret, err := funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Bytes{Value: []byte("foo bar")}, ret) require.Equal(t, &xgo.Bytes{Value: []byte("foo bar")}, ret)
uf = stdlib.FuncARYE(func() ([]byte, error) { uf = stdlib.FuncARYE(func() ([]byte, error) {
return nil, errors.New("some error") return nil, errors.New("some error")
}) })
ret, err = funcCall(uf) ret, err = funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, require.Equal(t,
&tengo.Error{Value: &tengo.String{Value: "some error"}}, ret) &xgo.Error{Value: &xgo.String{Value: "some error"}}, ret)
_, err = funcCall(uf, tengo.TrueValue) _, err = funcCall(uf, xgo.TrueValue)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASRIE(t *testing.T) { func TestFuncASRIE(t *testing.T) {
uf := stdlib.FuncASRIE(func(a string) (int, error) { return 5, nil }) uf := stdlib.FuncASRIE(func(a string) (int, error) { return 5, nil })
ret, err := funcCall(uf, &tengo.String{Value: "foo"}) ret, err := funcCall(uf, &xgo.String{Value: "foo"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 5}, ret) require.Equal(t, &xgo.Int{Value: 5}, ret)
uf = stdlib.FuncASRIE(func(a string) (int, error) { uf = stdlib.FuncASRIE(func(a string) (int, error) {
return 0, errors.New("some error") return 0, errors.New("some error")
}) })
ret, err = funcCall(uf, &tengo.String{Value: "foo"}) ret, err = funcCall(uf, &xgo.String{Value: "foo"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, require.Equal(t,
&tengo.Error{Value: &tengo.String{Value: "some error"}}, ret) &xgo.Error{Value: &xgo.String{Value: "some error"}}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAYRIE(t *testing.T) { func TestFuncAYRIE(t *testing.T) {
uf := stdlib.FuncAYRIE(func(a []byte) (int, error) { return 5, nil }) uf := stdlib.FuncAYRIE(func(a []byte) (int, error) { return 5, nil })
ret, err := funcCall(uf, &tengo.Bytes{Value: []byte("foo")}) ret, err := funcCall(uf, &xgo.Bytes{Value: []byte("foo")})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 5}, ret) require.Equal(t, &xgo.Int{Value: 5}, ret)
uf = stdlib.FuncAYRIE(func(a []byte) (int, error) { uf = stdlib.FuncAYRIE(func(a []byte) (int, error) {
return 0, errors.New("some error") return 0, errors.New("some error")
}) })
ret, err = funcCall(uf, &tengo.Bytes{Value: []byte("foo")}) ret, err = funcCall(uf, &xgo.Bytes{Value: []byte("foo")})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, require.Equal(t,
&tengo.Error{Value: &tengo.String{Value: "some error"}}, ret) &xgo.Error{Value: &xgo.String{Value: "some error"}}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASSRI(t *testing.T) { func TestFuncASSRI(t *testing.T) {
uf := stdlib.FuncASSRI(func(a, b string) int { return len(a) + len(b) }) uf := stdlib.FuncASSRI(func(a, b string) int { return len(a) + len(b) })
ret, err := funcCall(uf, ret, err := funcCall(uf,
&tengo.String{Value: "foo"}, &tengo.String{Value: "bar"}) &xgo.String{Value: "foo"}, &xgo.String{Value: "bar"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 6}, ret) require.Equal(t, &xgo.Int{Value: 6}, ret)
_, err = funcCall(uf, &tengo.String{Value: "foo"}) _, err = funcCall(uf, &xgo.String{Value: "foo"})
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASSRS(t *testing.T) { func TestFuncASSRS(t *testing.T) {
uf := stdlib.FuncASSRS(func(a, b string) string { return a + b }) uf := stdlib.FuncASSRS(func(a, b string) string { return a + b })
ret, err := funcCall(uf, ret, err := funcCall(uf,
&tengo.String{Value: "foo"}, &tengo.String{Value: "bar"}) &xgo.String{Value: "foo"}, &xgo.String{Value: "bar"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.String{Value: "foobar"}, ret) require.Equal(t, &xgo.String{Value: "foobar"}, ret)
_, err = funcCall(uf, &tengo.String{Value: "foo"}) _, err = funcCall(uf, &xgo.String{Value: "foo"})
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASSRB(t *testing.T) { func TestFuncASSRB(t *testing.T) {
uf := stdlib.FuncASSRB(func(a, b string) bool { return len(a) > len(b) }) uf := stdlib.FuncASSRB(func(a, b string) bool { return len(a) > len(b) })
ret, err := funcCall(uf, ret, err := funcCall(uf,
&tengo.String{Value: "123"}, &tengo.String{Value: "12"}) &xgo.String{Value: "123"}, &xgo.String{Value: "12"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tengo.TrueValue, ret) require.Equal(t, xgo.TrueValue, ret)
_, err = funcCall(uf, &tengo.String{Value: "foo"}) _, err = funcCall(uf, &xgo.String{Value: "foo"})
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAIRS(t *testing.T) { func TestFuncAIRS(t *testing.T) {
uf := stdlib.FuncAIRS(func(a int) string { return strconv.Itoa(a) }) uf := stdlib.FuncAIRS(func(a int) string { return strconv.Itoa(a) })
ret, err := funcCall(uf, &tengo.Int{Value: 55}) ret, err := funcCall(uf, &xgo.Int{Value: 55})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.String{Value: "55"}, ret) require.Equal(t, &xgo.String{Value: "55"}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAIRIs(t *testing.T) { func TestFuncAIRIs(t *testing.T) {
uf := stdlib.FuncAIRIs(func(a int) []int { return []int{a, a} }) uf := stdlib.FuncAIRIs(func(a int) []int { return []int{a, a} })
ret, err := funcCall(uf, &tengo.Int{Value: 55}) ret, err := funcCall(uf, &xgo.Int{Value: 55})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, array(&tengo.Int{Value: 55}, &tengo.Int{Value: 55}), ret) require.Equal(t, array(&xgo.Int{Value: 55}, &xgo.Int{Value: 55}), ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAI64R(t *testing.T) { func TestFuncAI64R(t *testing.T) {
uf := stdlib.FuncAIR(func(a int) {}) uf := stdlib.FuncAIR(func(a int) {})
ret, err := funcCall(uf, &tengo.Int{Value: 55}) ret, err := funcCall(uf, &xgo.Int{Value: 55})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tengo.UndefinedValue, ret) require.Equal(t, xgo.UndefinedValue, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncARI64(t *testing.T) { func TestFuncARI64(t *testing.T) {
uf := stdlib.FuncARI64(func() int64 { return 55 }) uf := stdlib.FuncARI64(func() int64 { return 55 })
ret, err := funcCall(uf) ret, err := funcCall(uf)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 55}, ret) require.Equal(t, &xgo.Int{Value: 55}, ret)
_, err = funcCall(uf, &tengo.Int{Value: 55}) _, err = funcCall(uf, &xgo.Int{Value: 55})
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncASsSRS(t *testing.T) { func TestFuncASsSRS(t *testing.T) {
@ -540,31 +540,31 @@ func TestFuncASsSRS(t *testing.T) {
return strings.Join(a, b) return strings.Join(a, b)
}) })
ret, err := funcCall(uf, ret, err := funcCall(uf,
array(&tengo.String{Value: "abc"}, &tengo.String{Value: "def"}), array(&xgo.String{Value: "abc"}, &xgo.String{Value: "def"}),
&tengo.String{Value: "-"}) &xgo.String{Value: "-"})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.String{Value: "abc-def"}, ret) require.Equal(t, &xgo.String{Value: "abc-def"}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func TestFuncAI64RI64(t *testing.T) { func TestFuncAI64RI64(t *testing.T) {
uf := stdlib.FuncAI64RI64(func(a int64) int64 { return a * 2 }) uf := stdlib.FuncAI64RI64(func(a int64) int64 { return a * 2 })
ret, err := funcCall(uf, &tengo.Int{Value: 55}) ret, err := funcCall(uf, &xgo.Int{Value: 55})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, &tengo.Int{Value: 110}, ret) require.Equal(t, &xgo.Int{Value: 110}, ret)
_, err = funcCall(uf) _, err = funcCall(uf)
require.Equal(t, tengo.ErrWrongNumArguments, err) require.Equal(t, xgo.ErrWrongNumArguments, err)
} }
func funcCall( func funcCall(
fn tengo.CallableFunc, fn xgo.CallableFunc,
args ...tengo.Object, args ...xgo.Object,
) (tengo.Object, error) { ) (xgo.Object, error) {
userFunc := &tengo.UserFunction{Value: fn} userFunc := &xgo.UserFunction{Value: fn}
return userFunc.Call(args...) return userFunc.Call(args...)
} }
func array(elements ...tengo.Object) *tengo.Array { func array(elements ...xgo.Object) *xgo.Array {
return &tengo.Array{Value: elements} return &xgo.Array{Value: elements}
} }

View file

@ -10,7 +10,7 @@ import (
"strconv" "strconv"
) )
var tengoModFileRE = regexp.MustCompile(`^srcmod_(\w+).tengo$`) var xgoModFileRE = regexp.MustCompile(`^srcmod_(\w+).xgo$`)
func main() { func main() {
modules := make(map[string]string) modules := make(map[string]string)
@ -21,7 +21,7 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
for _, file := range files { for _, file := range files {
m := tengoModFileRE.FindStringSubmatch(file.Name()) m := xgoModFileRE.FindStringSubmatch(file.Name())
if m != nil { if m != nil {
modName := m[1] modName := m[1]

View file

@ -3,10 +3,10 @@ package stdlib
import ( import (
"encoding/hex" "encoding/hex"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
var hexModule = map[string]tengo.Object{ var hexModule = map[string]xgo.Object{
"encode": &tengo.UserFunction{Value: FuncAYRS(hex.EncodeToString)}, "encode": &xgo.UserFunction{Value: FuncAYRS(hex.EncodeToString)},
"decode": &tengo.UserFunction{Value: FuncASRYE(hex.DecodeString)}, "decode": &xgo.UserFunction{Value: FuncASRYE(hex.DecodeString)},
} }

136
stdlib/html/element.go Normal file
View file

@ -0,0 +1,136 @@
package html
import (
"surdeus.su/core/xgo/v2"
"strings"
"html"
"fmt"
)
const RawTag = "raw"
// The type implements basic
// way to structrize HTML elements.
type Element struct {
xgo.ObjectImpl
Tag string
Attr map[string]string
Children []*Element
// The value makes sense only if
// the tag is the "raw"
Content string
Final bool
}
func (el *Element) TypeName() string {
return "*HTMLElement"
}
// The method renders the element to it's
// HTML representation.
func (el *Element) String() string {
if el.Tag == RawTag {
return html.EscapeString(el.Content)
}
var b strings.Builder
fmt.Fprintf(&b, "<%s", el.Tag)
for k, v := range el.Attr {
fmt.Fprintf(&b, " %s=%q", k, v)
}
fmt.Fprint(&b, ">")
if el.Final {
return b.String()
}
for _, child := range el.Children {
if child == nil {
continue
}
fmt.Fprint(&b, child.String())
}
fmt.Fprintf(&b, "</%s>", el.Tag)
return b.String()
}
func MakeElements(args ...xgo.Object) ([]*Element, error) {
s := []*Element{}
for _, arg := range args {
el, ok := arg.(*Element)
if !ok {
str, ok := xgo.ToString(arg)
if ok {
s = append(s, &Element{
Tag: RawTag,
Content: str,
})
}
continue
}
s = append(s, el)
}
return s, nil
}
func (el *Element) SetBody(
args ...xgo.Object,
) (xgo.Object, error) {
els, err := MakeElements(args...)
if err != nil {
return nil, err
}
el.Children = els
return el, nil
}
func (el *Element) Add(
args ...xgo.Object,
) (xgo.Object, error) {
s, err := MakeElements(args...)
if err != nil {
return nil, err
}
el.Children = append(el.Children, s...)
return el, nil
}
func (el *Element) SetFinal(
args ...xgo.Object,
) (xgo.Object, error) {
if len(args) > 0 {
return nil, xgo.ErrWrongNumArguments
}
el.Final = true
return el, nil
}
func (el *Element) IndexGet(
index xgo.Object,
) (xgo.Object, error) {
arg, ok := xgo.ToString(index)
if !ok {
return nil, xgo.ErrInvalidIndexValueType
}
switch arg {
case "body":
return &xgo.UserFunction{
Name: "element.body",
Value: el.SetBody,
}, nil
case "final":
return &xgo.UserFunction{
Name: "element.final",
Value: el.SetFinal,
}, nil
case "add":
return &xgo.UserFunction{
Name: "element.add",
Value: el.Add,
}, nil
}
return nil, nil
}

101
stdlib/html/html.go Normal file
View file

@ -0,0 +1,101 @@
package html
import "surdeus.su/core/xgo/v2"
var Module = map[string]xgo.Object{
"Renderer": &xgo.BuiltinFunction{
Name: "Renderer",
Value: func(args ...xgo.Object) (xgo.Object, error) {
ret := &Renderer{}
return ret, nil
},
},
}
type Renderer struct {
xgo.ObjectImpl
}
func (html *Renderer) TypeName() string {
return "html.Renderer"
}
func (html *Renderer) String() string {
return "html.Renderer(...)"
}
/*
html.div({
id: "some-el-id",
value: "shit value"
}).body(
html.raw("cock "),
html.strong("something")
)
*/
func (html *Renderer) IndexGet(
index xgo.Object,
) (xgo.Object, error) {
str, ok := xgo.ToString(index)
if !ok {
return nil, xgo.ErrInvalidIndexValueType
}
fn := func(args ...xgo.Object) (xgo.Object, error) {
if len(args) > 1 {
return nil, xgo.ErrWrongNumArguments
}
var arg xgo.Object
if len(args) == 1 {
arg = args[0]
}
if arg == nil {
return &Element{
Tag: str,
}, nil
}
if can := arg.CanIterate(); !can {
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "iterable",
Found: arg.TypeName(),
}
}
attr := map[string]string{}
iter := arg.Iterate()
for iter.Next() {
key, val := iter.Key(), iter.Value()
skey, ok := xgo.ToString(key)
if !ok {
return nil, xgo.ErrInvalidArgumentType{
Name: "attribute(key)",
Expected: "stringer",
Found: key.TypeName(),
}
}
sval, ok := xgo.ToString(val)
if !ok {
return nil, xgo.ErrInvalidArgumentType{
Name: "attribute(value)",
Expected: "stringer",
Found: val.TypeName(),
}
}
attr[skey] = sval
}
return &Element{
Tag: str,
Attr: attr,
}, nil
}
return &xgo.UserFunction{
Name: str,
Value: fn,
}, nil
}

2
stdlib/http/http.go Normal file
View file

@ -0,0 +1,2 @@
package http

70
stdlib/http/module.go Normal file
View file

@ -0,0 +1,70 @@
package http
import "surdeus.su/core/xgo/v2"
import "net/http"
import "bytes"
import tjson "surdeus.su/core/xgo/v2/stdlib/json"
var Module = map[string]xgo.Object{
"get": &xgo.BuiltinFunction{
Name: "get",
Value: func(
args ...xgo.Object,
) (xgo.Object, error) {
if len(args) != 1 {
return nil, xgo.ErrWrongNumArguments
}
url, ok := xgo.ToString(args[0])
if !ok {
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "string",
Found: args[0].TypeName(),
}
}
resp, err := http.Get(url)
if err != nil {
return nil, err
}
return &Response{
Response: resp,
}, nil
},
},
"post_json": &xgo.BuiltinFunction{
Name: "post",
Value: func(
args ...xgo.Object,
) (xgo.Object, error) {
if len(args) < 2 {
return nil, xgo.ErrWrongNumArguments
}
url, ok := xgo.ToString(args[0])
if !ok {
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "string",
Found: args[0].TypeName(),
}
}
var body bytes.Buffer
ret, err := tjson.Encode(args[1])
if err != nil {
return nil, err
}
body.Write(ret)
resp, err := http.Post(
url, "application/json",
&body,
)
if err != nil {
return nil, err
}
return &Response{
Response: resp,
}, nil
},
},
}

49
stdlib/http/request.go Normal file
View file

@ -0,0 +1,49 @@
package http
import (
"surdeus.su/core/xgo/v2"
"net/http"
"io"
//"log"
xurl "surdeus.su/core/xgo/v2/stdlib/url"
)
type Request struct {
*http.Request
xgo.ObjectImpl
}
func (r *Request) TypeName() string {
return "http.Request"
}
func (r *Request) String() string {
return "http.Request{...}"
}
func (r *Request) IndexGet(
index xgo.Object,
) (xgo.Object, error) {
key, ok := xgo.ToString(index)
if !ok {
return nil, xgo.ErrInvalidIndexValueType
}
switch key {
case "url":
return &xurl.URL{
URL: r.URL,
}, nil
case "body":
bts, err := io.ReadAll(r.Body)
if err != nil {
return nil, err
}
return &xgo.Bytes{
Value: bts,
}, nil
}
// Nothing found.
return nil, nil
}

49
stdlib/http/response.go Normal file
View file

@ -0,0 +1,49 @@
package http
import "net/http"
import "surdeus.su/core/xgo/v2"
import "io"
import tjson "surdeus.su/core/xgo/v2/stdlib/json"
type Response struct {
*http.Response
xgo.ObjectImpl
}
func (r *Response) TypeName() string {
return "http.Response"
}
func (r *Response) String() string {
return "http.Response{...}"
}
func (r *Response) IndexGet(
index xgo.Object,
) (xgo.Object, error) {
key, ok := xgo.ToString(index)
if !ok {
return nil, xgo.ErrInvalidIndexValueType
}
switch key {
case "body":
bts, err := io.ReadAll(r.Body)
if err != nil {
return nil, err
}
return &xgo.Bytes{
Value: bts,
}, nil
case "body_json":
bts, err := io.ReadAll(r.Body)
if err != nil {
return nil, err
}
return tjson.Decode(bts)
}
// Nothing found.
return nil, nil
}

View file

@ -4,53 +4,53 @@ import (
"bytes" "bytes"
gojson "encoding/json" gojson "encoding/json"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/stdlib/json" "surdeus.su/core/xgo/v2/stdlib/json"
) )
var jsonModule = map[string]tengo.Object{ var jsonModule = map[string]xgo.Object{
"decode": &tengo.UserFunction{ "decode": &xgo.UserFunction{
Name: "decode", Name: "decode",
Value: jsonDecode, Value: jsonDecode,
}, },
"encode": &tengo.UserFunction{ "encode": &xgo.UserFunction{
Name: "encode", Name: "encode",
Value: jsonEncode, Value: jsonEncode,
}, },
"indent": &tengo.UserFunction{ "indent": &xgo.UserFunction{
Name: "encode", Name: "encode",
Value: jsonIndent, Value: jsonIndent,
}, },
"html_escape": &tengo.UserFunction{ "html_escape": &xgo.UserFunction{
Name: "html_escape", Name: "html_escape",
Value: jsonHTMLEscape, Value: jsonHTMLEscape,
}, },
} }
func jsonDecode(args ...tengo.Object) (ret tengo.Object, err error) { func jsonDecode(args ...xgo.Object) (ret xgo.Object, err error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
switch o := args[0].(type) { switch o := args[0].(type) {
case *tengo.Bytes: case *xgo.Bytes:
v, err := json.Decode(o.Value) v, err := json.Decode(o.Value)
if err != nil { if err != nil {
return &tengo.Error{ return &xgo.Error{
Value: &tengo.String{Value: err.Error()}, Value: &xgo.String{Value: err.Error()},
}, nil }, nil
} }
return v, nil return v, nil
case *tengo.String: case *xgo.String:
v, err := json.Decode([]byte(o.Value)) v, err := json.Decode([]byte(o.Value))
if err != nil { if err != nil {
return &tengo.Error{ return &xgo.Error{
Value: &tengo.String{Value: err.Error()}, Value: &xgo.String{Value: err.Error()},
}, nil }, nil
} }
return v, nil return v, nil
default: default:
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "bytes/string", Expected: "bytes/string",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -58,36 +58,36 @@ func jsonDecode(args ...tengo.Object) (ret tengo.Object, err error) {
} }
} }
func jsonEncode(args ...tengo.Object) (ret tengo.Object, err error) { func jsonEncode(args ...xgo.Object) (ret xgo.Object, err error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
b, err := json.Encode(args[0]) b, err := json.Encode(args[0])
if err != nil { if err != nil {
return &tengo.Error{Value: &tengo.String{Value: err.Error()}}, nil return &xgo.Error{Value: &xgo.String{Value: err.Error()}}, nil
} }
return &tengo.Bytes{Value: b}, nil return &xgo.Bytes{Value: b}, nil
} }
func jsonIndent(args ...tengo.Object) (ret tengo.Object, err error) { func jsonIndent(args ...xgo.Object) (ret xgo.Object, err error) {
if len(args) != 3 { if len(args) != 3 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
prefix, ok := tengo.ToString(args[1]) prefix, ok := xgo.ToString(args[1])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "prefix", Name: "prefix",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[1].TypeName(), Found: args[1].TypeName(),
} }
} }
indent, ok := tengo.ToString(args[2]) indent, ok := xgo.ToString(args[2])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "indent", Name: "indent",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[2].TypeName(), Found: args[2].TypeName(),
@ -95,26 +95,26 @@ func jsonIndent(args ...tengo.Object) (ret tengo.Object, err error) {
} }
switch o := args[0].(type) { switch o := args[0].(type) {
case *tengo.Bytes: case *xgo.Bytes:
var dst bytes.Buffer var dst bytes.Buffer
err := gojson.Indent(&dst, o.Value, prefix, indent) err := gojson.Indent(&dst, o.Value, prefix, indent)
if err != nil { if err != nil {
return &tengo.Error{ return &xgo.Error{
Value: &tengo.String{Value: err.Error()}, Value: &xgo.String{Value: err.Error()},
}, nil }, nil
} }
return &tengo.Bytes{Value: dst.Bytes()}, nil return &xgo.Bytes{Value: dst.Bytes()}, nil
case *tengo.String: case *xgo.String:
var dst bytes.Buffer var dst bytes.Buffer
err := gojson.Indent(&dst, []byte(o.Value), prefix, indent) err := gojson.Indent(&dst, []byte(o.Value), prefix, indent)
if err != nil { if err != nil {
return &tengo.Error{ return &xgo.Error{
Value: &tengo.String{Value: err.Error()}, Value: &xgo.String{Value: err.Error()},
}, nil }, nil
} }
return &tengo.Bytes{Value: dst.Bytes()}, nil return &xgo.Bytes{Value: dst.Bytes()}, nil
default: default:
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "bytes/string", Expected: "bytes/string",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -122,22 +122,22 @@ func jsonIndent(args ...tengo.Object) (ret tengo.Object, err error) {
} }
} }
func jsonHTMLEscape(args ...tengo.Object) (ret tengo.Object, err error) { func jsonHTMLEscape(args ...xgo.Object) (ret xgo.Object, err error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
switch o := args[0].(type) { switch o := args[0].(type) {
case *tengo.Bytes: case *xgo.Bytes:
var dst bytes.Buffer var dst bytes.Buffer
gojson.HTMLEscape(&dst, o.Value) gojson.HTMLEscape(&dst, o.Value)
return &tengo.Bytes{Value: dst.Bytes()}, nil return &xgo.Bytes{Value: dst.Bytes()}, nil
case *tengo.String: case *xgo.String:
var dst bytes.Buffer var dst bytes.Buffer
gojson.HTMLEscape(&dst, []byte(o.Value)) gojson.HTMLEscape(&dst, []byte(o.Value))
return &tengo.Bytes{Value: dst.Bytes()}, nil return &xgo.Bytes{Value: dst.Bytes()}, nil
default: default:
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "bytes/string", Expected: "bytes/string",
Found: args[0].TypeName(), Found: args[0].TypeName(),

View file

@ -12,11 +12,11 @@ import (
"unicode/utf16" "unicode/utf16"
"unicode/utf8" "unicode/utf8"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
// Decode parses the JSON-encoded data and returns the result object. // Decode parses the JSON-encoded data and returns the result object.
func Decode(data []byte) (tengo.Object, error) { func Decode(data []byte) (xgo.Object, error) {
var d decodeState var d decodeState
err := checkValid(data, &d.scan) err := checkValid(data, &d.scan)
if err != nil { if err != nil {
@ -82,7 +82,7 @@ func (d *decodeState) scanWhile(op int) (isFloat bool) {
return return
} }
func (d *decodeState) value() (tengo.Object, error) { func (d *decodeState) value() (xgo.Object, error) {
switch d.opcode { switch d.opcode {
default: default:
panic(phasePanicMsg) panic(phasePanicMsg)
@ -105,8 +105,8 @@ func (d *decodeState) value() (tengo.Object, error) {
} }
} }
func (d *decodeState) array() (tengo.Object, error) { func (d *decodeState) array() (xgo.Object, error) {
var arr []tengo.Object var arr []xgo.Object
for { for {
// Look ahead for ] - can only happen on first iteration. // Look ahead for ] - can only happen on first iteration.
d.scanWhile(scanSkipSpace) d.scanWhile(scanSkipSpace)
@ -130,11 +130,11 @@ func (d *decodeState) array() (tengo.Object, error) {
panic(phasePanicMsg) panic(phasePanicMsg)
} }
} }
return &tengo.Array{Value: arr}, nil return &xgo.Array{Value: arr}, nil
} }
func (d *decodeState) object() (tengo.Object, error) { func (d *decodeState) object() (xgo.Object, error) {
m := make(map[string]tengo.Object) m := make(map[string]xgo.Object)
for { for {
// Read opening " of string key or closing }. // Read opening " of string key or closing }.
d.scanWhile(scanSkipSpace) d.scanWhile(scanSkipSpace)
@ -183,10 +183,10 @@ func (d *decodeState) object() (tengo.Object, error) {
panic(phasePanicMsg) panic(phasePanicMsg)
} }
} }
return &tengo.Map{Value: m}, nil return &xgo.Map{Value: m}, nil
} }
func (d *decodeState) literal() (tengo.Object, error) { func (d *decodeState) literal() (xgo.Object, error) {
// All bytes inside literal return scanContinue op code. // All bytes inside literal return scanContinue op code.
start := d.readIndex() start := d.readIndex()
isFloat := d.scanWhile(scanContinue) isFloat := d.scanWhile(scanContinue)
@ -195,20 +195,20 @@ func (d *decodeState) literal() (tengo.Object, error) {
switch c := item[0]; c { switch c := item[0]; c {
case 'n': // null case 'n': // null
return tengo.UndefinedValue, nil return xgo.UndefinedValue, nil
case 't', 'f': // true, false case 't', 'f': // true, false
if c == 't' { if c == 't' {
return tengo.TrueValue, nil return xgo.TrueValue, nil
} }
return tengo.FalseValue, nil return xgo.FalseValue, nil
case '"': // string case '"': // string
s, ok := unquote(item) s, ok := unquote(item)
if !ok { if !ok {
panic(phasePanicMsg) panic(phasePanicMsg)
} }
return &tengo.String{Value: s}, nil return &xgo.String{Value: s}, nil
default: // number default: // number
if c != '-' && (c < '0' || c > '9') { if c != '-' && (c < '0' || c > '9') {
@ -216,10 +216,10 @@ func (d *decodeState) literal() (tengo.Object, error) {
} }
if isFloat { if isFloat {
n, _ := strconv.ParseFloat(string(item), 10) n, _ := strconv.ParseFloat(string(item), 10)
return &tengo.Float{Value: n}, nil return &xgo.Float{Value: n}, nil
} }
n, _ := strconv.ParseInt(string(item), 10, 64) n, _ := strconv.ParseInt(string(item), 10, 64)
return &tengo.Int{Value: n}, nil return &xgo.Int{Value: n}, nil
} }
} }

View file

@ -14,7 +14,7 @@ import (
"strconv" "strconv"
"unicode/utf8" "unicode/utf8"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
// safeSet holds the value true if the ASCII character with the given array // safeSet holds the value true if the ASCII character with the given array
@ -125,11 +125,11 @@ var safeSet = [utf8.RuneSelf]bool{
var hex = "0123456789abcdef" var hex = "0123456789abcdef"
// Encode returns the JSON encoding of the object. // Encode returns the JSON encoding of the object.
func Encode(o tengo.Object) ([]byte, error) { func Encode(o xgo.Object) ([]byte, error) {
var b []byte var b []byte
switch o := o.(type) { switch o := o.(type) {
case *tengo.Array: case *xgo.Array:
b = append(b, '[') b = append(b, '[')
len1 := len(o.Value) - 1 len1 := len(o.Value) - 1
for idx, elem := range o.Value { for idx, elem := range o.Value {
@ -143,7 +143,7 @@ func Encode(o tengo.Object) ([]byte, error) {
} }
} }
b = append(b, ']') b = append(b, ']')
case *tengo.ImmutableArray: case *xgo.ImmutableArray:
b = append(b, '[') b = append(b, '[')
len1 := len(o.Value) - 1 len1 := len(o.Value) - 1
for idx, elem := range o.Value { for idx, elem := range o.Value {
@ -157,7 +157,7 @@ func Encode(o tengo.Object) ([]byte, error) {
} }
} }
b = append(b, ']') b = append(b, ']')
case *tengo.Map: case *xgo.Map:
b = append(b, '{') b = append(b, '{')
len1 := len(o.Value) - 1 len1 := len(o.Value) - 1
idx := 0 idx := 0
@ -175,7 +175,7 @@ func Encode(o tengo.Object) ([]byte, error) {
idx++ idx++
} }
b = append(b, '}') b = append(b, '}')
case *tengo.ImmutableMap: case *xgo.ImmutableMap:
b = append(b, '{') b = append(b, '{')
len1 := len(o.Value) - 1 len1 := len(o.Value) - 1
idx := 0 idx := 0
@ -193,22 +193,22 @@ func Encode(o tengo.Object) ([]byte, error) {
idx++ idx++
} }
b = append(b, '}') b = append(b, '}')
case *tengo.Bool: case *xgo.Bool:
if o.IsFalsy() { if o.IsFalsy() {
b = strconv.AppendBool(b, false) b = strconv.AppendBool(b, false)
} else { } else {
b = strconv.AppendBool(b, true) b = strconv.AppendBool(b, true)
} }
case *tengo.Bytes: case *xgo.Bytes:
b = append(b, '"') b = append(b, '"')
encodedLen := base64.StdEncoding.EncodedLen(len(o.Value)) encodedLen := base64.StdEncoding.EncodedLen(len(o.Value))
dst := make([]byte, encodedLen) dst := make([]byte, encodedLen)
base64.StdEncoding.Encode(dst, o.Value) base64.StdEncoding.Encode(dst, o.Value)
b = append(b, dst...) b = append(b, dst...)
b = append(b, '"') b = append(b, '"')
case *tengo.Char: case *xgo.Char:
b = strconv.AppendInt(b, int64(o.Value), 10) b = strconv.AppendInt(b, int64(o.Value), 10)
case *tengo.Float: case *xgo.Float:
var y []byte var y []byte
f := o.Value f := o.Value
@ -236,19 +236,19 @@ func Encode(o tengo.Object) ([]byte, error) {
} }
b = append(b, y...) b = append(b, y...)
case *tengo.Int: case *xgo.Int:
b = strconv.AppendInt(b, o.Value, 10) b = strconv.AppendInt(b, o.Value, 10)
case *tengo.String: case *xgo.String:
// string encoding bug is fixed with newly introduced function // string encoding bug is fixed with newly introduced function
// encodeString(). See: https://github.com/d5/tengo/issues/268 // encodeString(). See: https://github.com/d5/xgo/issues/268
b = encodeString(b, o.Value) b = encodeString(b, o.Value)
case *tengo.Time: case *xgo.Time:
y, err := o.Value.MarshalJSON() y, err := o.Value.MarshalJSON()
if err != nil { if err != nil {
return nil, err return nil, err
} }
b = append(b, y...) b = append(b, y...)
case *tengo.Undefined: case *xgo.Undefined:
b = append(b, "null"...) b = append(b, "null"...)
default: default:
// unknown type: ignore // unknown type: ignore

View file

@ -4,9 +4,9 @@ import (
gojson "encoding/json" gojson "encoding/json"
"testing" "testing"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
"github.com/d5/tengo/v2/stdlib/json" "surdeus.su/core/xgo/v2/stdlib/json"
) )
type ARR = []interface{} type ARR = []interface{}
@ -31,7 +31,7 @@ func TestJSON(t *testing.T) {
testJSONEncodeDecode(t, "foo") testJSONEncodeDecode(t, "foo")
testJSONEncodeDecode(t, "foo bar") testJSONEncodeDecode(t, "foo bar")
testJSONEncodeDecode(t, "foo \"bar\"") testJSONEncodeDecode(t, "foo \"bar\"")
// See: https://github.com/d5/tengo/issues/268 // See: https://github.com/d5/xgo/issues/268
testJSONEncodeDecode(t, "1\u001C04") testJSONEncodeDecode(t, "1\u001C04")
testJSONEncodeDecode(t, "çığöşü") testJSONEncodeDecode(t, "çığöşü")
testJSONEncodeDecode(t, "ç1\u001C04IĞÖŞÜ") testJSONEncodeDecode(t, "ç1\u001C04IĞÖŞÜ")
@ -92,7 +92,7 @@ func testDecodeError(t *testing.T, input string) {
} }
func testJSONEncodeDecode(t *testing.T, v interface{}) { func testJSONEncodeDecode(t *testing.T, v interface{}) {
o, err := tengo.FromInterface(v) o, err := xgo.FromInterface(v)
require.NoError(t, err) require.NoError(t, err)
b, err := json.Encode(o) b, err := json.Encode(o)
@ -104,7 +104,7 @@ func testJSONEncodeDecode(t *testing.T, v interface{}) {
vj, err := gojson.Marshal(v) vj, err := gojson.Marshal(v)
require.NoError(t, err) require.NoError(t, err)
aj, err := gojson.Marshal(tengo.ToInterface(a)) aj, err := gojson.Marshal(xgo.ToInterface(a))
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, vj, aj) require.Equal(t, vj, aj)

76
stdlib/log/main.go Normal file
View file

@ -0,0 +1,76 @@
package log
import "surdeus.su/core/xgo/v2"
import "log"
var Module = map[string]xgo.Object{
"printf": &xgo.BuiltinFunction{
Name: "printf",
Value: func(
args ...xgo.Object,
) (xgo.Object, error) {
if len(args) < 1 {
return nil, xgo.ErrWrongNumArguments
}
formatObject := args[0]
format, hasFormat := xgo.ToString(
formatObject,
)
if !hasFormat {
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "string",
Found: formatObject.TypeName(),
}
}
/*v := make([]any, len(args[1:]))
for i, o := range args[1:] {
v[i] = xgo.ToInterface(o)
}*/
str, err := xgo.Format(format, args...)
if err != nil {
return nil, err
}
log.Print(str)
return nil, nil
},
},
"print": &xgo.BuiltinFunction{
Name: "print",
Value: func(
args ...xgo.Object,
) (xgo.Object, error) {
v := make([]any, len(args))
for i, o := range args {
var ok bool
v[i], ok = xgo.ToString(o)
if !ok {
v[i] = xgo.Undefined{}
}
}
log.Print(v...)
return nil, nil
},
},
"println": &xgo.BuiltinFunction{
Name: "println",
Value: func(
args ...xgo.Object,
) (xgo.Object, error) {
v := make([]any, len(args))
for i, o := range args {
var ok bool
v[i], ok = xgo.ToString(o)
if !ok {
v[i] = xgo.Undefined{}
}
}
log.Println(v...)
return nil, nil
},
},
}

View file

@ -3,244 +3,244 @@ package stdlib
import ( import (
"math" "math"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
var mathModule = map[string]tengo.Object{ var mathModule = map[string]xgo.Object{
"e": &tengo.Float{Value: math.E}, "e": &xgo.Float{Value: math.E},
"pi": &tengo.Float{Value: math.Pi}, "pi": &xgo.Float{Value: math.Pi},
"phi": &tengo.Float{Value: math.Phi}, "phi": &xgo.Float{Value: math.Phi},
"sqrt2": &tengo.Float{Value: math.Sqrt2}, "sqrt2": &xgo.Float{Value: math.Sqrt2},
"sqrtE": &tengo.Float{Value: math.SqrtE}, "sqrtE": &xgo.Float{Value: math.SqrtE},
"sqrtPi": &tengo.Float{Value: math.SqrtPi}, "sqrtPi": &xgo.Float{Value: math.SqrtPi},
"sqrtPhi": &tengo.Float{Value: math.SqrtPhi}, "sqrtPhi": &xgo.Float{Value: math.SqrtPhi},
"ln2": &tengo.Float{Value: math.Ln2}, "ln2": &xgo.Float{Value: math.Ln2},
"log2E": &tengo.Float{Value: math.Log2E}, "log2E": &xgo.Float{Value: math.Log2E},
"ln10": &tengo.Float{Value: math.Ln10}, "ln10": &xgo.Float{Value: math.Ln10},
"log10E": &tengo.Float{Value: math.Log10E}, "log10E": &xgo.Float{Value: math.Log10E},
"maxFloat32": &tengo.Float{Value: math.MaxFloat32}, "maxFloat32": &xgo.Float{Value: math.MaxFloat32},
"smallestNonzeroFloat32": &tengo.Float{Value: math.SmallestNonzeroFloat32}, "smallestNonzeroFloat32": &xgo.Float{Value: math.SmallestNonzeroFloat32},
"maxFloat64": &tengo.Float{Value: math.MaxFloat64}, "maxFloat64": &xgo.Float{Value: math.MaxFloat64},
"smallestNonzeroFloat64": &tengo.Float{Value: math.SmallestNonzeroFloat64}, "smallestNonzeroFloat64": &xgo.Float{Value: math.SmallestNonzeroFloat64},
"maxInt": &tengo.Int{Value: math.MaxInt}, "maxInt": &xgo.Int{Value: math.MaxInt},
"minInt": &tengo.Int{Value: math.MinInt}, "minInt": &xgo.Int{Value: math.MinInt},
"maxInt8": &tengo.Int{Value: math.MaxInt8}, "maxInt8": &xgo.Int{Value: math.MaxInt8},
"minInt8": &tengo.Int{Value: math.MinInt8}, "minInt8": &xgo.Int{Value: math.MinInt8},
"maxInt16": &tengo.Int{Value: math.MaxInt16}, "maxInt16": &xgo.Int{Value: math.MaxInt16},
"minInt16": &tengo.Int{Value: math.MinInt16}, "minInt16": &xgo.Int{Value: math.MinInt16},
"maxInt32": &tengo.Int{Value: math.MaxInt32}, "maxInt32": &xgo.Int{Value: math.MaxInt32},
"minInt32": &tengo.Int{Value: math.MinInt32}, "minInt32": &xgo.Int{Value: math.MinInt32},
"maxInt64": &tengo.Int{Value: math.MaxInt64}, "maxInt64": &xgo.Int{Value: math.MaxInt64},
"minInt64": &tengo.Int{Value: math.MinInt64}, "minInt64": &xgo.Int{Value: math.MinInt64},
"abs": &tengo.UserFunction{ "abs": &xgo.UserFunction{
Name: "abs", Name: "abs",
Value: FuncAFRF(math.Abs), Value: FuncAFRF(math.Abs),
}, },
"acos": &tengo.UserFunction{ "acos": &xgo.UserFunction{
Name: "acos", Name: "acos",
Value: FuncAFRF(math.Acos), Value: FuncAFRF(math.Acos),
}, },
"acosh": &tengo.UserFunction{ "acosh": &xgo.UserFunction{
Name: "acosh", Name: "acosh",
Value: FuncAFRF(math.Acosh), Value: FuncAFRF(math.Acosh),
}, },
"asin": &tengo.UserFunction{ "asin": &xgo.UserFunction{
Name: "asin", Name: "asin",
Value: FuncAFRF(math.Asin), Value: FuncAFRF(math.Asin),
}, },
"asinh": &tengo.UserFunction{ "asinh": &xgo.UserFunction{
Name: "asinh", Name: "asinh",
Value: FuncAFRF(math.Asinh), Value: FuncAFRF(math.Asinh),
}, },
"atan": &tengo.UserFunction{ "atan": &xgo.UserFunction{
Name: "atan", Name: "atan",
Value: FuncAFRF(math.Atan), Value: FuncAFRF(math.Atan),
}, },
"atan2": &tengo.UserFunction{ "atan2": &xgo.UserFunction{
Name: "atan2", Name: "atan2",
Value: FuncAFFRF(math.Atan2), Value: FuncAFFRF(math.Atan2),
}, },
"atanh": &tengo.UserFunction{ "atanh": &xgo.UserFunction{
Name: "atanh", Name: "atanh",
Value: FuncAFRF(math.Atanh), Value: FuncAFRF(math.Atanh),
}, },
"cbrt": &tengo.UserFunction{ "cbrt": &xgo.UserFunction{
Name: "cbrt", Name: "cbrt",
Value: FuncAFRF(math.Cbrt), Value: FuncAFRF(math.Cbrt),
}, },
"ceil": &tengo.UserFunction{ "ceil": &xgo.UserFunction{
Name: "ceil", Name: "ceil",
Value: FuncAFRF(math.Ceil), Value: FuncAFRF(math.Ceil),
}, },
"copysign": &tengo.UserFunction{ "copysign": &xgo.UserFunction{
Name: "copysign", Name: "copysign",
Value: FuncAFFRF(math.Copysign), Value: FuncAFFRF(math.Copysign),
}, },
"cos": &tengo.UserFunction{ "cos": &xgo.UserFunction{
Name: "cos", Name: "cos",
Value: FuncAFRF(math.Cos), Value: FuncAFRF(math.Cos),
}, },
"cosh": &tengo.UserFunction{ "cosh": &xgo.UserFunction{
Name: "cosh", Name: "cosh",
Value: FuncAFRF(math.Cosh), Value: FuncAFRF(math.Cosh),
}, },
"dim": &tengo.UserFunction{ "dim": &xgo.UserFunction{
Name: "dim", Name: "dim",
Value: FuncAFFRF(math.Dim), Value: FuncAFFRF(math.Dim),
}, },
"erf": &tengo.UserFunction{ "erf": &xgo.UserFunction{
Name: "erf", Name: "erf",
Value: FuncAFRF(math.Erf), Value: FuncAFRF(math.Erf),
}, },
"erfc": &tengo.UserFunction{ "erfc": &xgo.UserFunction{
Name: "erfc", Name: "erfc",
Value: FuncAFRF(math.Erfc), Value: FuncAFRF(math.Erfc),
}, },
"exp": &tengo.UserFunction{ "exp": &xgo.UserFunction{
Name: "exp", Name: "exp",
Value: FuncAFRF(math.Exp), Value: FuncAFRF(math.Exp),
}, },
"exp2": &tengo.UserFunction{ "exp2": &xgo.UserFunction{
Name: "exp2", Name: "exp2",
Value: FuncAFRF(math.Exp2), Value: FuncAFRF(math.Exp2),
}, },
"expm1": &tengo.UserFunction{ "expm1": &xgo.UserFunction{
Name: "expm1", Name: "expm1",
Value: FuncAFRF(math.Expm1), Value: FuncAFRF(math.Expm1),
}, },
"floor": &tengo.UserFunction{ "floor": &xgo.UserFunction{
Name: "floor", Name: "floor",
Value: FuncAFRF(math.Floor), Value: FuncAFRF(math.Floor),
}, },
"gamma": &tengo.UserFunction{ "gamma": &xgo.UserFunction{
Name: "gamma", Name: "gamma",
Value: FuncAFRF(math.Gamma), Value: FuncAFRF(math.Gamma),
}, },
"hypot": &tengo.UserFunction{ "hypot": &xgo.UserFunction{
Name: "hypot", Name: "hypot",
Value: FuncAFFRF(math.Hypot), Value: FuncAFFRF(math.Hypot),
}, },
"ilogb": &tengo.UserFunction{ "ilogb": &xgo.UserFunction{
Name: "ilogb", Name: "ilogb",
Value: FuncAFRI(math.Ilogb), Value: FuncAFRI(math.Ilogb),
}, },
"inf": &tengo.UserFunction{ "inf": &xgo.UserFunction{
Name: "inf", Name: "inf",
Value: FuncAIRF(math.Inf), Value: FuncAIRF(math.Inf),
}, },
"is_inf": &tengo.UserFunction{ "is_inf": &xgo.UserFunction{
Name: "is_inf", Name: "is_inf",
Value: FuncAFIRB(math.IsInf), Value: FuncAFIRB(math.IsInf),
}, },
"is_nan": &tengo.UserFunction{ "is_nan": &xgo.UserFunction{
Name: "is_nan", Name: "is_nan",
Value: FuncAFRB(math.IsNaN), Value: FuncAFRB(math.IsNaN),
}, },
"j0": &tengo.UserFunction{ "j0": &xgo.UserFunction{
Name: "j0", Name: "j0",
Value: FuncAFRF(math.J0), Value: FuncAFRF(math.J0),
}, },
"j1": &tengo.UserFunction{ "j1": &xgo.UserFunction{
Name: "j1", Name: "j1",
Value: FuncAFRF(math.J1), Value: FuncAFRF(math.J1),
}, },
"jn": &tengo.UserFunction{ "jn": &xgo.UserFunction{
Name: "jn", Name: "jn",
Value: FuncAIFRF(math.Jn), Value: FuncAIFRF(math.Jn),
}, },
"ldexp": &tengo.UserFunction{ "ldexp": &xgo.UserFunction{
Name: "ldexp", Name: "ldexp",
Value: FuncAFIRF(math.Ldexp), Value: FuncAFIRF(math.Ldexp),
}, },
"log": &tengo.UserFunction{ "log": &xgo.UserFunction{
Name: "log", Name: "log",
Value: FuncAFRF(math.Log), Value: FuncAFRF(math.Log),
}, },
"log10": &tengo.UserFunction{ "log10": &xgo.UserFunction{
Name: "log10", Name: "log10",
Value: FuncAFRF(math.Log10), Value: FuncAFRF(math.Log10),
}, },
"log1p": &tengo.UserFunction{ "log1p": &xgo.UserFunction{
Name: "log1p", Name: "log1p",
Value: FuncAFRF(math.Log1p), Value: FuncAFRF(math.Log1p),
}, },
"log2": &tengo.UserFunction{ "log2": &xgo.UserFunction{
Name: "log2", Name: "log2",
Value: FuncAFRF(math.Log2), Value: FuncAFRF(math.Log2),
}, },
"logb": &tengo.UserFunction{ "logb": &xgo.UserFunction{
Name: "logb", Name: "logb",
Value: FuncAFRF(math.Logb), Value: FuncAFRF(math.Logb),
}, },
"max": &tengo.UserFunction{ "max": &xgo.UserFunction{
Name: "max", Name: "max",
Value: FuncAFFRF(math.Max), Value: FuncAFFRF(math.Max),
}, },
"min": &tengo.UserFunction{ "min": &xgo.UserFunction{
Name: "min", Name: "min",
Value: FuncAFFRF(math.Min), Value: FuncAFFRF(math.Min),
}, },
"mod": &tengo.UserFunction{ "mod": &xgo.UserFunction{
Name: "mod", Name: "mod",
Value: FuncAFFRF(math.Mod), Value: FuncAFFRF(math.Mod),
}, },
"nan": &tengo.UserFunction{ "nan": &xgo.UserFunction{
Name: "nan", Name: "nan",
Value: FuncARF(math.NaN), Value: FuncARF(math.NaN),
}, },
"nextafter": &tengo.UserFunction{ "nextafter": &xgo.UserFunction{
Name: "nextafter", Name: "nextafter",
Value: FuncAFFRF(math.Nextafter), Value: FuncAFFRF(math.Nextafter),
}, },
"pow": &tengo.UserFunction{ "pow": &xgo.UserFunction{
Name: "pow", Name: "pow",
Value: FuncAFFRF(math.Pow), Value: FuncAFFRF(math.Pow),
}, },
"pow10": &tengo.UserFunction{ "pow10": &xgo.UserFunction{
Name: "pow10", Name: "pow10",
Value: FuncAIRF(math.Pow10), Value: FuncAIRF(math.Pow10),
}, },
"remainder": &tengo.UserFunction{ "remainder": &xgo.UserFunction{
Name: "remainder", Name: "remainder",
Value: FuncAFFRF(math.Remainder), Value: FuncAFFRF(math.Remainder),
}, },
"signbit": &tengo.UserFunction{ "signbit": &xgo.UserFunction{
Name: "signbit", Name: "signbit",
Value: FuncAFRB(math.Signbit), Value: FuncAFRB(math.Signbit),
}, },
"sin": &tengo.UserFunction{ "sin": &xgo.UserFunction{
Name: "sin", Name: "sin",
Value: FuncAFRF(math.Sin), Value: FuncAFRF(math.Sin),
}, },
"sinh": &tengo.UserFunction{ "sinh": &xgo.UserFunction{
Name: "sinh", Name: "sinh",
Value: FuncAFRF(math.Sinh), Value: FuncAFRF(math.Sinh),
}, },
"sqrt": &tengo.UserFunction{ "sqrt": &xgo.UserFunction{
Name: "sqrt", Name: "sqrt",
Value: FuncAFRF(math.Sqrt), Value: FuncAFRF(math.Sqrt),
}, },
"tan": &tengo.UserFunction{ "tan": &xgo.UserFunction{
Name: "tan", Name: "tan",
Value: FuncAFRF(math.Tan), Value: FuncAFRF(math.Tan),
}, },
"tanh": &tengo.UserFunction{ "tanh": &xgo.UserFunction{
Name: "tanh", Name: "tanh",
Value: FuncAFRF(math.Tanh), Value: FuncAFRF(math.Tanh),
}, },
"trunc": &tengo.UserFunction{ "trunc": &xgo.UserFunction{
Name: "trunc", Name: "trunc",
Value: FuncAFRF(math.Trunc), Value: FuncAFRF(math.Trunc),
}, },
"y0": &tengo.UserFunction{ "y0": &xgo.UserFunction{
Name: "y0", Name: "y0",
Value: FuncAFRF(math.Y0), Value: FuncAFRF(math.Y0),
}, },
"y1": &tengo.UserFunction{ "y1": &xgo.UserFunction{
Name: "y1", Name: "y1",
Value: FuncAFRF(math.Y1), Value: FuncAFRF(math.Y1),
}, },
"yn": &tengo.UserFunction{ "yn": &xgo.UserFunction{
Name: "yn", Name: "yn",
Value: FuncAIFRF(math.Yn), Value: FuncAIFRF(math.Yn),
}, },

View file

@ -8,208 +8,208 @@ import (
"os/exec" "os/exec"
"runtime" "runtime"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
var osModule = map[string]tengo.Object{ var osModule = map[string]xgo.Object{
"platform": &tengo.String{Value: runtime.GOOS}, "platform": &xgo.String{Value: runtime.GOOS},
"arch": &tengo.String{Value: runtime.GOARCH}, "arch": &xgo.String{Value: runtime.GOARCH},
"o_rdonly": &tengo.Int{Value: int64(os.O_RDONLY)}, "o_rdonly": &xgo.Int{Value: int64(os.O_RDONLY)},
"o_wronly": &tengo.Int{Value: int64(os.O_WRONLY)}, "o_wronly": &xgo.Int{Value: int64(os.O_WRONLY)},
"o_rdwr": &tengo.Int{Value: int64(os.O_RDWR)}, "o_rdwr": &xgo.Int{Value: int64(os.O_RDWR)},
"o_append": &tengo.Int{Value: int64(os.O_APPEND)}, "o_append": &xgo.Int{Value: int64(os.O_APPEND)},
"o_create": &tengo.Int{Value: int64(os.O_CREATE)}, "o_create": &xgo.Int{Value: int64(os.O_CREATE)},
"o_excl": &tengo.Int{Value: int64(os.O_EXCL)}, "o_excl": &xgo.Int{Value: int64(os.O_EXCL)},
"o_sync": &tengo.Int{Value: int64(os.O_SYNC)}, "o_sync": &xgo.Int{Value: int64(os.O_SYNC)},
"o_trunc": &tengo.Int{Value: int64(os.O_TRUNC)}, "o_trunc": &xgo.Int{Value: int64(os.O_TRUNC)},
"mode_dir": &tengo.Int{Value: int64(os.ModeDir)}, "mode_dir": &xgo.Int{Value: int64(os.ModeDir)},
"mode_append": &tengo.Int{Value: int64(os.ModeAppend)}, "mode_append": &xgo.Int{Value: int64(os.ModeAppend)},
"mode_exclusive": &tengo.Int{Value: int64(os.ModeExclusive)}, "mode_exclusive": &xgo.Int{Value: int64(os.ModeExclusive)},
"mode_temporary": &tengo.Int{Value: int64(os.ModeTemporary)}, "mode_temporary": &xgo.Int{Value: int64(os.ModeTemporary)},
"mode_symlink": &tengo.Int{Value: int64(os.ModeSymlink)}, "mode_symlink": &xgo.Int{Value: int64(os.ModeSymlink)},
"mode_device": &tengo.Int{Value: int64(os.ModeDevice)}, "mode_device": &xgo.Int{Value: int64(os.ModeDevice)},
"mode_named_pipe": &tengo.Int{Value: int64(os.ModeNamedPipe)}, "mode_named_pipe": &xgo.Int{Value: int64(os.ModeNamedPipe)},
"mode_socket": &tengo.Int{Value: int64(os.ModeSocket)}, "mode_socket": &xgo.Int{Value: int64(os.ModeSocket)},
"mode_setuid": &tengo.Int{Value: int64(os.ModeSetuid)}, "mode_setuid": &xgo.Int{Value: int64(os.ModeSetuid)},
"mode_setgui": &tengo.Int{Value: int64(os.ModeSetgid)}, "mode_setgui": &xgo.Int{Value: int64(os.ModeSetgid)},
"mode_char_device": &tengo.Int{Value: int64(os.ModeCharDevice)}, "mode_char_device": &xgo.Int{Value: int64(os.ModeCharDevice)},
"mode_sticky": &tengo.Int{Value: int64(os.ModeSticky)}, "mode_sticky": &xgo.Int{Value: int64(os.ModeSticky)},
"mode_type": &tengo.Int{Value: int64(os.ModeType)}, "mode_type": &xgo.Int{Value: int64(os.ModeType)},
"mode_perm": &tengo.Int{Value: int64(os.ModePerm)}, "mode_perm": &xgo.Int{Value: int64(os.ModePerm)},
"path_separator": &tengo.Char{Value: os.PathSeparator}, "path_separator": &xgo.Char{Value: os.PathSeparator},
"path_list_separator": &tengo.Char{Value: os.PathListSeparator}, "path_list_separator": &xgo.Char{Value: os.PathListSeparator},
"dev_null": &tengo.String{Value: os.DevNull}, "dev_null": &xgo.String{Value: os.DevNull},
"seek_set": &tengo.Int{Value: int64(io.SeekStart)}, "seek_set": &xgo.Int{Value: int64(io.SeekStart)},
"seek_cur": &tengo.Int{Value: int64(io.SeekCurrent)}, "seek_cur": &xgo.Int{Value: int64(io.SeekCurrent)},
"seek_end": &tengo.Int{Value: int64(io.SeekEnd)}, "seek_end": &xgo.Int{Value: int64(io.SeekEnd)},
"args": &tengo.UserFunction{ "args": &xgo.UserFunction{
Name: "args", Name: "args",
Value: osArgs, Value: osArgs,
}, // args() => array(string) }, // args() => array(string)
"chdir": &tengo.UserFunction{ "chdir": &xgo.UserFunction{
Name: "chdir", Name: "chdir",
Value: FuncASRE(os.Chdir), Value: FuncASRE(os.Chdir),
}, // chdir(dir string) => error }, // chdir(dir string) => error
"chmod": osFuncASFmRE("chmod", os.Chmod), // chmod(name string, mode int) => error "chmod": osFuncASFmRE("chmod", os.Chmod), // chmod(name string, mode int) => error
"chown": &tengo.UserFunction{ "chown": &xgo.UserFunction{
Name: "chown", Name: "chown",
Value: FuncASIIRE(os.Chown), Value: FuncASIIRE(os.Chown),
}, // chown(name string, uid int, gid int) => error }, // chown(name string, uid int, gid int) => error
"clearenv": &tengo.UserFunction{ "clearenv": &xgo.UserFunction{
Name: "clearenv", Name: "clearenv",
Value: FuncAR(os.Clearenv), Value: FuncAR(os.Clearenv),
}, // clearenv() }, // clearenv()
"environ": &tengo.UserFunction{ "environ": &xgo.UserFunction{
Name: "environ", Name: "environ",
Value: FuncARSs(os.Environ), Value: FuncARSs(os.Environ),
}, // environ() => array(string) }, // environ() => array(string)
"exit": &tengo.UserFunction{ "exit": &xgo.UserFunction{
Name: "exit", Name: "exit",
Value: FuncAIR(os.Exit), Value: FuncAIR(os.Exit),
}, // exit(code int) }, // exit(code int)
"expand_env": &tengo.UserFunction{ "expand_env": &xgo.UserFunction{
Name: "expand_env", Name: "expand_env",
Value: osExpandEnv, Value: osExpandEnv,
}, // expand_env(s string) => string }, // expand_env(s string) => string
"getegid": &tengo.UserFunction{ "getegid": &xgo.UserFunction{
Name: "getegid", Name: "getegid",
Value: FuncARI(os.Getegid), Value: FuncARI(os.Getegid),
}, // getegid() => int }, // getegid() => int
"getenv": &tengo.UserFunction{ "getenv": &xgo.UserFunction{
Name: "getenv", Name: "getenv",
Value: FuncASRS(os.Getenv), Value: FuncASRS(os.Getenv),
}, // getenv(s string) => string }, // getenv(s string) => string
"geteuid": &tengo.UserFunction{ "geteuid": &xgo.UserFunction{
Name: "geteuid", Name: "geteuid",
Value: FuncARI(os.Geteuid), Value: FuncARI(os.Geteuid),
}, // geteuid() => int }, // geteuid() => int
"getgid": &tengo.UserFunction{ "getgid": &xgo.UserFunction{
Name: "getgid", Name: "getgid",
Value: FuncARI(os.Getgid), Value: FuncARI(os.Getgid),
}, // getgid() => int }, // getgid() => int
"getgroups": &tengo.UserFunction{ "getgroups": &xgo.UserFunction{
Name: "getgroups", Name: "getgroups",
Value: FuncARIsE(os.Getgroups), Value: FuncARIsE(os.Getgroups),
}, // getgroups() => array(string)/error }, // getgroups() => array(string)/error
"getpagesize": &tengo.UserFunction{ "getpagesize": &xgo.UserFunction{
Name: "getpagesize", Name: "getpagesize",
Value: FuncARI(os.Getpagesize), Value: FuncARI(os.Getpagesize),
}, // getpagesize() => int }, // getpagesize() => int
"getpid": &tengo.UserFunction{ "getpid": &xgo.UserFunction{
Name: "getpid", Name: "getpid",
Value: FuncARI(os.Getpid), Value: FuncARI(os.Getpid),
}, // getpid() => int }, // getpid() => int
"getppid": &tengo.UserFunction{ "getppid": &xgo.UserFunction{
Name: "getppid", Name: "getppid",
Value: FuncARI(os.Getppid), Value: FuncARI(os.Getppid),
}, // getppid() => int }, // getppid() => int
"getuid": &tengo.UserFunction{ "getuid": &xgo.UserFunction{
Name: "getuid", Name: "getuid",
Value: FuncARI(os.Getuid), Value: FuncARI(os.Getuid),
}, // getuid() => int }, // getuid() => int
"getwd": &tengo.UserFunction{ "getwd": &xgo.UserFunction{
Name: "getwd", Name: "getwd",
Value: FuncARSE(os.Getwd), Value: FuncARSE(os.Getwd),
}, // getwd() => string/error }, // getwd() => string/error
"hostname": &tengo.UserFunction{ "hostname": &xgo.UserFunction{
Name: "hostname", Name: "hostname",
Value: FuncARSE(os.Hostname), Value: FuncARSE(os.Hostname),
}, // hostname() => string/error }, // hostname() => string/error
"lchown": &tengo.UserFunction{ "lchown": &xgo.UserFunction{
Name: "lchown", Name: "lchown",
Value: FuncASIIRE(os.Lchown), Value: FuncASIIRE(os.Lchown),
}, // lchown(name string, uid int, gid int) => error }, // lchown(name string, uid int, gid int) => error
"link": &tengo.UserFunction{ "link": &xgo.UserFunction{
Name: "link", Name: "link",
Value: FuncASSRE(os.Link), Value: FuncASSRE(os.Link),
}, // link(oldname string, newname string) => error }, // link(oldname string, newname string) => error
"lookup_env": &tengo.UserFunction{ "lookup_env": &xgo.UserFunction{
Name: "lookup_env", Name: "lookup_env",
Value: osLookupEnv, Value: osLookupEnv,
}, // lookup_env(key string) => string/false }, // lookup_env(key string) => string/false
"mkdir": osFuncASFmRE("mkdir", os.Mkdir), // mkdir(name string, perm int) => error "mkdir": osFuncASFmRE("mkdir", os.Mkdir), // mkdir(name string, perm int) => error
"mkdir_all": osFuncASFmRE("mkdir_all", os.MkdirAll), // mkdir_all(name string, perm int) => error "mkdir_all": osFuncASFmRE("mkdir_all", os.MkdirAll), // mkdir_all(name string, perm int) => error
"readlink": &tengo.UserFunction{ "readlink": &xgo.UserFunction{
Name: "readlink", Name: "readlink",
Value: FuncASRSE(os.Readlink), Value: FuncASRSE(os.Readlink),
}, // readlink(name string) => string/error }, // readlink(name string) => string/error
"remove": &tengo.UserFunction{ "remove": &xgo.UserFunction{
Name: "remove", Name: "remove",
Value: FuncASRE(os.Remove), Value: FuncASRE(os.Remove),
}, // remove(name string) => error }, // remove(name string) => error
"remove_all": &tengo.UserFunction{ "remove_all": &xgo.UserFunction{
Name: "remove_all", Name: "remove_all",
Value: FuncASRE(os.RemoveAll), Value: FuncASRE(os.RemoveAll),
}, // remove_all(name string) => error }, // remove_all(name string) => error
"rename": &tengo.UserFunction{ "rename": &xgo.UserFunction{
Name: "rename", Name: "rename",
Value: FuncASSRE(os.Rename), Value: FuncASSRE(os.Rename),
}, // rename(oldpath string, newpath string) => error }, // rename(oldpath string, newpath string) => error
"setenv": &tengo.UserFunction{ "setenv": &xgo.UserFunction{
Name: "setenv", Name: "setenv",
Value: FuncASSRE(os.Setenv), Value: FuncASSRE(os.Setenv),
}, // setenv(key string, value string) => error }, // setenv(key string, value string) => error
"symlink": &tengo.UserFunction{ "symlink": &xgo.UserFunction{
Name: "symlink", Name: "symlink",
Value: FuncASSRE(os.Symlink), Value: FuncASSRE(os.Symlink),
}, // symlink(oldname string newname string) => error }, // symlink(oldname string newname string) => error
"temp_dir": &tengo.UserFunction{ "temp_dir": &xgo.UserFunction{
Name: "temp_dir", Name: "temp_dir",
Value: FuncARS(os.TempDir), Value: FuncARS(os.TempDir),
}, // temp_dir() => string }, // temp_dir() => string
"truncate": &tengo.UserFunction{ "truncate": &xgo.UserFunction{
Name: "truncate", Name: "truncate",
Value: FuncASI64RE(os.Truncate), Value: FuncASI64RE(os.Truncate),
}, // truncate(name string, size int) => error }, // truncate(name string, size int) => error
"unsetenv": &tengo.UserFunction{ "unsetenv": &xgo.UserFunction{
Name: "unsetenv", Name: "unsetenv",
Value: FuncASRE(os.Unsetenv), Value: FuncASRE(os.Unsetenv),
}, // unsetenv(key string) => error }, // unsetenv(key string) => error
"create": &tengo.UserFunction{ "create": &xgo.UserFunction{
Name: "create", Name: "create",
Value: osCreate, Value: osCreate,
}, // create(name string) => imap(file)/error }, // create(name string) => imap(file)/error
"open": &tengo.UserFunction{ "open": &xgo.UserFunction{
Name: "open", Name: "open",
Value: osOpen, Value: osOpen,
}, // open(name string) => imap(file)/error }, // open(name string) => imap(file)/error
"open_file": &tengo.UserFunction{ "open_file": &xgo.UserFunction{
Name: "open_file", Name: "open_file",
Value: osOpenFile, Value: osOpenFile,
}, // open_file(name string, flag int, perm int) => imap(file)/error }, // open_file(name string, flag int, perm int) => imap(file)/error
"find_process": &tengo.UserFunction{ "find_process": &xgo.UserFunction{
Name: "find_process", Name: "find_process",
Value: osFindProcess, Value: osFindProcess,
}, // find_process(pid int) => imap(process)/error }, // find_process(pid int) => imap(process)/error
"start_process": &tengo.UserFunction{ "start_process": &xgo.UserFunction{
Name: "start_process", Name: "start_process",
Value: osStartProcess, Value: osStartProcess,
}, // start_process(name string, argv array(string), dir string, env array(string)) => imap(process)/error }, // start_process(name string, argv array(string), dir string, env array(string)) => imap(process)/error
"exec_look_path": &tengo.UserFunction{ "exec_look_path": &xgo.UserFunction{
Name: "exec_look_path", Name: "exec_look_path",
Value: FuncASRSE(exec.LookPath), Value: FuncASRSE(exec.LookPath),
}, // exec_look_path(file) => string/error }, // exec_look_path(file) => string/error
"exec": &tengo.UserFunction{ "exec": &xgo.UserFunction{
Name: "exec", Name: "exec",
Value: osExec, Value: osExec,
}, // exec(name, args...) => command }, // exec(name, args...) => command
"stat": &tengo.UserFunction{ "stat": &xgo.UserFunction{
Name: "stat", Name: "stat",
Value: osStat, Value: osStat,
}, // stat(name) => imap(fileinfo)/error }, // stat(name) => imap(fileinfo)/error
"read_file": &tengo.UserFunction{ "read_file": &xgo.UserFunction{
Name: "read_file", Name: "read_file",
Value: osReadFile, Value: osReadFile,
}, // readfile(name) => array(byte)/error }, // readfile(name) => array(byte)/error
} }
func osReadFile(args ...tengo.Object) (ret tengo.Object, err error) { func osReadFile(args ...xgo.Object) (ret xgo.Object, err error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
fname, ok := tengo.ToString(args[0]) fname, ok := xgo.ToString(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -219,19 +219,19 @@ func osReadFile(args ...tengo.Object) (ret tengo.Object, err error) {
if err != nil { if err != nil {
return wrapError(err), nil return wrapError(err), nil
} }
if len(bytes) > tengo.MaxBytesLen { if len(bytes) > xgo.MaxBytesLen {
return nil, tengo.ErrBytesLimit return nil, xgo.ErrBytesLimit
} }
return &tengo.Bytes{Value: bytes}, nil return &xgo.Bytes{Value: bytes}, nil
} }
func osStat(args ...tengo.Object) (ret tengo.Object, err error) { func osStat(args ...xgo.Object) (ret xgo.Object, err error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
fname, ok := tengo.ToString(args[0]) fname, ok := xgo.ToString(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -241,29 +241,29 @@ func osStat(args ...tengo.Object) (ret tengo.Object, err error) {
if err != nil { if err != nil {
return wrapError(err), nil return wrapError(err), nil
} }
fstat := &tengo.ImmutableMap{ fstat := &xgo.ImmutableMap{
Value: map[string]tengo.Object{ Value: map[string]xgo.Object{
"name": &tengo.String{Value: stat.Name()}, "name": &xgo.String{Value: stat.Name()},
"mtime": &tengo.Time{Value: stat.ModTime()}, "mtime": &xgo.Time{Value: stat.ModTime()},
"size": &tengo.Int{Value: stat.Size()}, "size": &xgo.Int{Value: stat.Size()},
"mode": &tengo.Int{Value: int64(stat.Mode())}, "mode": &xgo.Int{Value: int64(stat.Mode())},
}, },
} }
if stat.IsDir() { if stat.IsDir() {
fstat.Value["directory"] = tengo.TrueValue fstat.Value["directory"] = xgo.TrueValue
} else { } else {
fstat.Value["directory"] = tengo.FalseValue fstat.Value["directory"] = xgo.FalseValue
} }
return fstat, nil return fstat, nil
} }
func osCreate(args ...tengo.Object) (tengo.Object, error) { func osCreate(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
s1, ok := tengo.ToString(args[0]) s1, ok := xgo.ToString(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -276,13 +276,13 @@ func osCreate(args ...tengo.Object) (tengo.Object, error) {
return makeOSFile(res), nil return makeOSFile(res), nil
} }
func osOpen(args ...tengo.Object) (tengo.Object, error) { func osOpen(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
s1, ok := tengo.ToString(args[0]) s1, ok := xgo.ToString(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -295,29 +295,29 @@ func osOpen(args ...tengo.Object) (tengo.Object, error) {
return makeOSFile(res), nil return makeOSFile(res), nil
} }
func osOpenFile(args ...tengo.Object) (tengo.Object, error) { func osOpenFile(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 3 { if len(args) != 3 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
s1, ok := tengo.ToString(args[0]) s1, ok := xgo.ToString(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
} }
} }
i2, ok := tengo.ToInt(args[1]) i2, ok := xgo.ToInt(args[1])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "second", Name: "second",
Expected: "int(compatible)", Expected: "int(compatible)",
Found: args[1].TypeName(), Found: args[1].TypeName(),
} }
} }
i3, ok := tengo.ToInt(args[2]) i3, ok := xgo.ToInt(args[2])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "third", Name: "third",
Expected: "int(compatible)", Expected: "int(compatible)",
Found: args[2].TypeName(), Found: args[2].TypeName(),
@ -330,16 +330,16 @@ func osOpenFile(args ...tengo.Object) (tengo.Object, error) {
return makeOSFile(res), nil return makeOSFile(res), nil
} }
func osArgs(args ...tengo.Object) (tengo.Object, error) { func osArgs(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 0 { if len(args) != 0 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
arr := &tengo.Array{} arr := &xgo.Array{}
for _, osArg := range os.Args { for _, osArg := range os.Args {
if len(osArg) > tengo.MaxStringLen { if len(osArg) > xgo.MaxStringLen {
return nil, tengo.ErrStringLimit return nil, xgo.ErrStringLimit
} }
arr.Value = append(arr.Value, &tengo.String{Value: osArg}) arr.Value = append(arr.Value, &xgo.String{Value: osArg})
} }
return arr, nil return arr, nil
} }
@ -347,24 +347,24 @@ func osArgs(args ...tengo.Object) (tengo.Object, error) {
func osFuncASFmRE( func osFuncASFmRE(
name string, name string,
fn func(string, os.FileMode) error, fn func(string, os.FileMode) error,
) *tengo.UserFunction { ) *xgo.UserFunction {
return &tengo.UserFunction{ return &xgo.UserFunction{
Name: name, Name: name,
Value: func(args ...tengo.Object) (tengo.Object, error) { Value: func(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 2 { if len(args) != 2 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
s1, ok := tengo.ToString(args[0]) s1, ok := xgo.ToString(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
} }
} }
i2, ok := tengo.ToInt64(args[1]) i2, ok := xgo.ToInt64(args[1])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "second", Name: "second",
Expected: "int(compatible)", Expected: "int(compatible)",
Found: args[1].TypeName(), Found: args[1].TypeName(),
@ -375,13 +375,13 @@ func osFuncASFmRE(
} }
} }
func osLookupEnv(args ...tengo.Object) (tengo.Object, error) { func osLookupEnv(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
s1, ok := tengo.ToString(args[0]) s1, ok := xgo.ToString(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -389,21 +389,21 @@ func osLookupEnv(args ...tengo.Object) (tengo.Object, error) {
} }
res, ok := os.LookupEnv(s1) res, ok := os.LookupEnv(s1)
if !ok { if !ok {
return tengo.FalseValue, nil return xgo.FalseValue, nil
} }
if len(res) > tengo.MaxStringLen { if len(res) > xgo.MaxStringLen {
return nil, tengo.ErrStringLimit return nil, xgo.ErrStringLimit
} }
return &tengo.String{Value: res}, nil return &xgo.String{Value: res}, nil
} }
func osExpandEnv(args ...tengo.Object) (tengo.Object, error) { func osExpandEnv(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
s1, ok := tengo.ToString(args[0]) s1, ok := xgo.ToString(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -420,25 +420,25 @@ func osExpandEnv(args ...tengo.Object) (tengo.Object, error) {
// this does not count the other texts that are not being replaced // this does not count the other texts that are not being replaced
// but the code checks the final length at the end // but the code checks the final length at the end
vlen += len(v) vlen += len(v)
if vlen > tengo.MaxStringLen { if vlen > xgo.MaxStringLen {
failed = true failed = true
return "" return ""
} }
return v return v
}) })
if failed || len(s) > tengo.MaxStringLen { if failed || len(s) > xgo.MaxStringLen {
return nil, tengo.ErrStringLimit return nil, xgo.ErrStringLimit
} }
return &tengo.String{Value: s}, nil return &xgo.String{Value: s}, nil
} }
func osExec(args ...tengo.Object) (tengo.Object, error) { func osExec(args ...xgo.Object) (xgo.Object, error) {
if len(args) == 0 { if len(args) == 0 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
name, ok := tengo.ToString(args[0]) name, ok := xgo.ToString(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -446,9 +446,9 @@ func osExec(args ...tengo.Object) (tengo.Object, error) {
} }
var execArgs []string var execArgs []string
for idx, arg := range args[1:] { for idx, arg := range args[1:] {
execArg, ok := tengo.ToString(arg) execArg, ok := xgo.ToString(arg)
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: fmt.Sprintf("args[%d]", idx), Name: fmt.Sprintf("args[%d]", idx),
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[1+idx].TypeName(), Found: args[1+idx].TypeName(),
@ -459,13 +459,13 @@ func osExec(args ...tengo.Object) (tengo.Object, error) {
return makeOSExecCommand(exec.Command(name, execArgs...)), nil return makeOSExecCommand(exec.Command(name, execArgs...)), nil
} }
func osFindProcess(args ...tengo.Object) (tengo.Object, error) { func osFindProcess(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
i1, ok := tengo.ToInt(args[0]) i1, ok := xgo.ToInt(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "int(compatible)", Expected: "int(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -478,13 +478,13 @@ func osFindProcess(args ...tengo.Object) (tengo.Object, error) {
return makeOSProcess(proc), nil return makeOSProcess(proc), nil
} }
func osStartProcess(args ...tengo.Object) (tengo.Object, error) { func osStartProcess(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 4 { if len(args) != 4 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
name, ok := tengo.ToString(args[0]) name, ok := xgo.ToString(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -493,27 +493,27 @@ func osStartProcess(args ...tengo.Object) (tengo.Object, error) {
var argv []string var argv []string
var err error var err error
switch arg1 := args[1].(type) { switch arg1 := args[1].(type) {
case *tengo.Array: case *xgo.Array:
argv, err = stringArray(arg1.Value, "second") argv, err = stringArray(arg1.Value, "second")
if err != nil { if err != nil {
return nil, err return nil, err
} }
case *tengo.ImmutableArray: case *xgo.ImmutableArray:
argv, err = stringArray(arg1.Value, "second") argv, err = stringArray(arg1.Value, "second")
if err != nil { if err != nil {
return nil, err return nil, err
} }
default: default:
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "second", Name: "second",
Expected: "array", Expected: "array",
Found: arg1.TypeName(), Found: arg1.TypeName(),
} }
} }
dir, ok := tengo.ToString(args[2]) dir, ok := xgo.ToString(args[2])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "third", Name: "third",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[2].TypeName(), Found: args[2].TypeName(),
@ -522,18 +522,18 @@ func osStartProcess(args ...tengo.Object) (tengo.Object, error) {
var env []string var env []string
switch arg3 := args[3].(type) { switch arg3 := args[3].(type) {
case *tengo.Array: case *xgo.Array:
env, err = stringArray(arg3.Value, "fourth") env, err = stringArray(arg3.Value, "fourth")
if err != nil { if err != nil {
return nil, err return nil, err
} }
case *tengo.ImmutableArray: case *xgo.ImmutableArray:
env, err = stringArray(arg3.Value, "fourth") env, err = stringArray(arg3.Value, "fourth")
if err != nil { if err != nil {
return nil, err return nil, err
} }
default: default:
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "fourth", Name: "fourth",
Expected: "array", Expected: "array",
Found: arg3.TypeName(), Found: arg3.TypeName(),
@ -550,12 +550,12 @@ func osStartProcess(args ...tengo.Object) (tengo.Object, error) {
return makeOSProcess(proc), nil return makeOSProcess(proc), nil
} }
func stringArray(arr []tengo.Object, argName string) ([]string, error) { func stringArray(arr []xgo.Object, argName string) ([]string, error) {
var sarr []string var sarr []string
for idx, elem := range arr { for idx, elem := range arr {
str, ok := elem.(*tengo.String) str, ok := elem.(*xgo.String)
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: fmt.Sprintf("%s[%d]", argName, idx), Name: fmt.Sprintf("%s[%d]", argName, idx),
Expected: "string", Expected: "string",
Found: elem.TypeName(), Found: elem.TypeName(),

View file

@ -3,113 +3,113 @@ package stdlib
import ( import (
"os/exec" "os/exec"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
func makeOSExecCommand(cmd *exec.Cmd) *tengo.ImmutableMap { func makeOSExecCommand(cmd *exec.Cmd) *xgo.ImmutableMap {
return &tengo.ImmutableMap{ return &xgo.ImmutableMap{
Value: map[string]tengo.Object{ Value: map[string]xgo.Object{
// combined_output() => bytes/error // combined_output() => bytes/error
"combined_output": &tengo.UserFunction{ "combined_output": &xgo.UserFunction{
Name: "combined_output", Name: "combined_output",
Value: FuncARYE(cmd.CombinedOutput), Value: FuncARYE(cmd.CombinedOutput),
}, },
// output() => bytes/error // output() => bytes/error
"output": &tengo.UserFunction{ "output": &xgo.UserFunction{
Name: "output", Name: "output",
Value: FuncARYE(cmd.Output), Value: FuncARYE(cmd.Output),
}, // }, //
// run() => error // run() => error
"run": &tengo.UserFunction{ "run": &xgo.UserFunction{
Name: "run", Name: "run",
Value: FuncARE(cmd.Run), Value: FuncARE(cmd.Run),
}, // }, //
// start() => error // start() => error
"start": &tengo.UserFunction{ "start": &xgo.UserFunction{
Name: "start", Name: "start",
Value: FuncARE(cmd.Start), Value: FuncARE(cmd.Start),
}, // }, //
// wait() => error // wait() => error
"wait": &tengo.UserFunction{ "wait": &xgo.UserFunction{
Name: "wait", Name: "wait",
Value: FuncARE(cmd.Wait), Value: FuncARE(cmd.Wait),
}, // }, //
// set_path(path string) // set_path(path string)
"set_path": &tengo.UserFunction{ "set_path": &xgo.UserFunction{
Name: "set_path", Name: "set_path",
Value: func(args ...tengo.Object) (tengo.Object, error) { Value: func(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
s1, ok := tengo.ToString(args[0]) s1, ok := xgo.ToString(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
} }
} }
cmd.Path = s1 cmd.Path = s1
return tengo.UndefinedValue, nil return xgo.UndefinedValue, nil
}, },
}, },
// set_dir(dir string) // set_dir(dir string)
"set_dir": &tengo.UserFunction{ "set_dir": &xgo.UserFunction{
Name: "set_dir", Name: "set_dir",
Value: func(args ...tengo.Object) (tengo.Object, error) { Value: func(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
s1, ok := tengo.ToString(args[0]) s1, ok := xgo.ToString(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
} }
} }
cmd.Dir = s1 cmd.Dir = s1
return tengo.UndefinedValue, nil return xgo.UndefinedValue, nil
}, },
}, },
// set_env(env array(string)) // set_env(env array(string))
"set_env": &tengo.UserFunction{ "set_env": &xgo.UserFunction{
Name: "set_env", Name: "set_env",
Value: func(args ...tengo.Object) (tengo.Object, error) { Value: func(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
var env []string var env []string
var err error var err error
switch arg0 := args[0].(type) { switch arg0 := args[0].(type) {
case *tengo.Array: case *xgo.Array:
env, err = stringArray(arg0.Value, "first") env, err = stringArray(arg0.Value, "first")
if err != nil { if err != nil {
return nil, err return nil, err
} }
case *tengo.ImmutableArray: case *xgo.ImmutableArray:
env, err = stringArray(arg0.Value, "first") env, err = stringArray(arg0.Value, "first")
if err != nil { if err != nil {
return nil, err return nil, err
} }
default: default:
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "array", Expected: "array",
Found: arg0.TypeName(), Found: arg0.TypeName(),
} }
} }
cmd.Env = env cmd.Env = env
return tengo.UndefinedValue, nil return xgo.UndefinedValue, nil
}, },
}, },
// process() => imap(process) // process() => imap(process)
"process": &tengo.UserFunction{ "process": &xgo.UserFunction{
Name: "process", Name: "process",
Value: func(args ...tengo.Object) (tengo.Object, error) { Value: func(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 0 { if len(args) != 0 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
return makeOSProcess(cmd.Process), nil return makeOSProcess(cmd.Process), nil
}, },

View file

@ -3,67 +3,67 @@ package stdlib
import ( import (
"os" "os"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
func makeOSFile(file *os.File) *tengo.ImmutableMap { func makeOSFile(file *os.File) *xgo.ImmutableMap {
return &tengo.ImmutableMap{ return &xgo.ImmutableMap{
Value: map[string]tengo.Object{ Value: map[string]xgo.Object{
// chdir() => true/error // chdir() => true/error
"chdir": &tengo.UserFunction{ "chdir": &xgo.UserFunction{
Name: "chdir", Name: "chdir",
Value: FuncARE(file.Chdir), Value: FuncARE(file.Chdir),
}, // }, //
// chown(uid int, gid int) => true/error // chown(uid int, gid int) => true/error
"chown": &tengo.UserFunction{ "chown": &xgo.UserFunction{
Name: "chown", Name: "chown",
Value: FuncAIIRE(file.Chown), Value: FuncAIIRE(file.Chown),
}, // }, //
// close() => error // close() => error
"close": &tengo.UserFunction{ "close": &xgo.UserFunction{
Name: "close", Name: "close",
Value: FuncARE(file.Close), Value: FuncARE(file.Close),
}, // }, //
// name() => string // name() => string
"name": &tengo.UserFunction{ "name": &xgo.UserFunction{
Name: "name", Name: "name",
Value: FuncARS(file.Name), Value: FuncARS(file.Name),
}, // }, //
// readdirnames(n int) => array(string)/error // readdirnames(n int) => array(string)/error
"readdirnames": &tengo.UserFunction{ "readdirnames": &xgo.UserFunction{
Name: "readdirnames", Name: "readdirnames",
Value: FuncAIRSsE(file.Readdirnames), Value: FuncAIRSsE(file.Readdirnames),
}, // }, //
// sync() => error // sync() => error
"sync": &tengo.UserFunction{ "sync": &xgo.UserFunction{
Name: "sync", Name: "sync",
Value: FuncARE(file.Sync), Value: FuncARE(file.Sync),
}, // }, //
// write(bytes) => int/error // write(bytes) => int/error
"write": &tengo.UserFunction{ "write": &xgo.UserFunction{
Name: "write", Name: "write",
Value: FuncAYRIE(file.Write), Value: FuncAYRIE(file.Write),
}, // }, //
// write(string) => int/error // write(string) => int/error
"write_string": &tengo.UserFunction{ "write_string": &xgo.UserFunction{
Name: "write_string", Name: "write_string",
Value: FuncASRIE(file.WriteString), Value: FuncASRIE(file.WriteString),
}, // }, //
// read(bytes) => int/error // read(bytes) => int/error
"read": &tengo.UserFunction{ "read": &xgo.UserFunction{
Name: "read", Name: "read",
Value: FuncAYRIE(file.Read), Value: FuncAYRIE(file.Read),
}, // }, //
// chmod(mode int) => error // chmod(mode int) => error
"chmod": &tengo.UserFunction{ "chmod": &xgo.UserFunction{
Name: "chmod", Name: "chmod",
Value: func(args ...tengo.Object) (tengo.Object, error) { Value: func(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
i1, ok := tengo.ToInt64(args[0]) i1, ok := xgo.ToInt64(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "int(compatible)", Expected: "int(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -73,23 +73,23 @@ func makeOSFile(file *os.File) *tengo.ImmutableMap {
}, },
}, },
// seek(offset int, whence int) => int/error // seek(offset int, whence int) => int/error
"seek": &tengo.UserFunction{ "seek": &xgo.UserFunction{
Name: "seek", Name: "seek",
Value: func(args ...tengo.Object) (tengo.Object, error) { Value: func(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 2 { if len(args) != 2 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
i1, ok := tengo.ToInt64(args[0]) i1, ok := xgo.ToInt64(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "int(compatible)", Expected: "int(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
} }
} }
i2, ok := tengo.ToInt(args[1]) i2, ok := xgo.ToInt(args[1])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "second", Name: "second",
Expected: "int(compatible)", Expected: "int(compatible)",
Found: args[1].TypeName(), Found: args[1].TypeName(),
@ -99,17 +99,17 @@ func makeOSFile(file *os.File) *tengo.ImmutableMap {
if err != nil { if err != nil {
return wrapError(err), nil return wrapError(err), nil
} }
return &tengo.Int{Value: res}, nil return &xgo.Int{Value: res}, nil
}, },
}, },
// stat() => imap(fileinfo)/error // stat() => imap(fileinfo)/error
"stat": &tengo.UserFunction{ "stat": &xgo.UserFunction{
Name: "stat", Name: "stat",
Value: func(args ...tengo.Object) (tengo.Object, error) { Value: func(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 0 { if len(args) != 0 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
return osStat(&tengo.String{Value: file.Name()}) return osStat(&xgo.String{Value: file.Name()})
}, },
}, },
}, },

View file

@ -4,25 +4,25 @@ import (
"os" "os"
"syscall" "syscall"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
func makeOSProcessState(state *os.ProcessState) *tengo.ImmutableMap { func makeOSProcessState(state *os.ProcessState) *xgo.ImmutableMap {
return &tengo.ImmutableMap{ return &xgo.ImmutableMap{
Value: map[string]tengo.Object{ Value: map[string]xgo.Object{
"exited": &tengo.UserFunction{ "exited": &xgo.UserFunction{
Name: "exited", Name: "exited",
Value: FuncARB(state.Exited), Value: FuncARB(state.Exited),
}, },
"pid": &tengo.UserFunction{ "pid": &xgo.UserFunction{
Name: "pid", Name: "pid",
Value: FuncARI(state.Pid), Value: FuncARI(state.Pid),
}, },
"string": &tengo.UserFunction{ "string": &xgo.UserFunction{
Name: "string", Name: "string",
Value: FuncARS(state.String), Value: FuncARS(state.String),
}, },
"success": &tengo.UserFunction{ "success": &xgo.UserFunction{
Name: "success", Name: "success",
Value: FuncARB(state.Success), Value: FuncARB(state.Success),
}, },
@ -30,26 +30,26 @@ func makeOSProcessState(state *os.ProcessState) *tengo.ImmutableMap {
} }
} }
func makeOSProcess(proc *os.Process) *tengo.ImmutableMap { func makeOSProcess(proc *os.Process) *xgo.ImmutableMap {
return &tengo.ImmutableMap{ return &xgo.ImmutableMap{
Value: map[string]tengo.Object{ Value: map[string]xgo.Object{
"kill": &tengo.UserFunction{ "kill": &xgo.UserFunction{
Name: "kill", Name: "kill",
Value: FuncARE(proc.Kill), Value: FuncARE(proc.Kill),
}, },
"release": &tengo.UserFunction{ "release": &xgo.UserFunction{
Name: "release", Name: "release",
Value: FuncARE(proc.Release), Value: FuncARE(proc.Release),
}, },
"signal": &tengo.UserFunction{ "signal": &xgo.UserFunction{
Name: "signal", Name: "signal",
Value: func(args ...tengo.Object) (tengo.Object, error) { Value: func(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
i1, ok := tengo.ToInt64(args[0]) i1, ok := xgo.ToInt64(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "int(compatible)", Expected: "int(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -58,11 +58,11 @@ func makeOSProcess(proc *os.Process) *tengo.ImmutableMap {
return wrapError(proc.Signal(syscall.Signal(i1))), nil return wrapError(proc.Signal(syscall.Signal(i1))), nil
}, },
}, },
"wait": &tengo.UserFunction{ "wait": &xgo.UserFunction{
Name: "wait", Name: "wait",
Value: func(args ...tengo.Object) (tengo.Object, error) { Value: func(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 0 { if len(args) != 0 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
state, err := proc.Wait() state, err := proc.Wait()
if err != nil { if err != nil {

View file

@ -5,8 +5,8 @@ import (
"os" "os"
"testing" "testing"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
) )
func TestReadFile(t *testing.T) { func TestReadFile(t *testing.T) {
@ -20,7 +20,7 @@ func TestReadFile(t *testing.T) {
_ = tf.Close() _ = tf.Close()
module(t, "os").call("read_file", tf.Name()). module(t, "os").call("read_file", tf.Name()).
expect(&tengo.Bytes{Value: content}) expect(&xgo.Bytes{Value: content})
} }
func TestReadFileArgs(t *testing.T) { func TestReadFileArgs(t *testing.T) {
@ -46,13 +46,13 @@ func TestFileStatFile(t *testing.T) {
return return
} }
module(t, "os").call("stat", tf.Name()).expect(&tengo.ImmutableMap{ module(t, "os").call("stat", tf.Name()).expect(&xgo.ImmutableMap{
Value: map[string]tengo.Object{ Value: map[string]xgo.Object{
"name": &tengo.String{Value: stat.Name()}, "name": &xgo.String{Value: stat.Name()},
"mtime": &tengo.Time{Value: stat.ModTime()}, "mtime": &xgo.Time{Value: stat.ModTime()},
"size": &tengo.Int{Value: stat.Size()}, "size": &xgo.Int{Value: stat.Size()},
"mode": &tengo.Int{Value: int64(stat.Mode())}, "mode": &xgo.Int{Value: int64(stat.Mode())},
"directory": tengo.FalseValue, "directory": xgo.FalseValue,
}, },
}) })
} }
@ -65,21 +65,21 @@ func TestFileStatDir(t *testing.T) {
stat, err := os.Stat(td) stat, err := os.Stat(td)
require.NoError(t, err) require.NoError(t, err)
module(t, "os").call("stat", td).expect(&tengo.ImmutableMap{ module(t, "os").call("stat", td).expect(&xgo.ImmutableMap{
Value: map[string]tengo.Object{ Value: map[string]xgo.Object{
"name": &tengo.String{Value: stat.Name()}, "name": &xgo.String{Value: stat.Name()},
"mtime": &tengo.Time{Value: stat.ModTime()}, "mtime": &xgo.Time{Value: stat.ModTime()},
"size": &tengo.Int{Value: stat.Size()}, "size": &xgo.Int{Value: stat.Size()},
"mode": &tengo.Int{Value: int64(stat.Mode())}, "mode": &xgo.Int{Value: int64(stat.Mode())},
"directory": tengo.TrueValue, "directory": xgo.TrueValue,
}, },
}) })
} }
func TestOSExpandEnv(t *testing.T) { func TestOSExpandEnv(t *testing.T) {
curMaxStringLen := tengo.MaxStringLen curMaxStringLen := xgo.MaxStringLen
defer func() { tengo.MaxStringLen = curMaxStringLen }() defer func() { xgo.MaxStringLen = curMaxStringLen }()
tengo.MaxStringLen = 12 xgo.MaxStringLen = 12
_ = os.Setenv("TENGO", "FOO BAR") _ = os.Setenv("TENGO", "FOO BAR")
module(t, "os").call("expand_env", "$TENGO").expect("FOO BAR") module(t, "os").call("expand_env", "$TENGO").expect("FOO BAR")

46
stdlib/paths/main.go Normal file
View file

@ -0,0 +1,46 @@
package paths
import (
"surdeus.su/core/xgo/v2"
"path"
)
var Module = map[string]xgo.Object{
"base": &xgo.UserFunction{
Name: "base",
Value: wrapOneArg(path.Base),
},
"ext": &xgo.UserFunction{
Name: "ext",
Value: wrapOneArg(path.Ext),
},
"dir": &xgo.UserFunction{
Name: "dir",
Value: wrapOneArg(path.Dir),
},
"clean": &xgo.UserFunction{
Name: "clean",
Value: wrapOneArg(path.Clean),
},
}
func wrapOneArg(
fn func(string) string,
) func(...xgo.Object) (xgo.Object, error) {
return func(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 1 {
return nil, xgo.ErrWrongNumArguments
}
str, ok := xgo.ToString(args[0])
if !ok {
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "string(compatible)",
Found: args[0].TypeName(),
}
}
return &xgo.String{
Value: fn(str),
}, nil
}
}

View file

@ -3,47 +3,47 @@ package stdlib
import ( import (
"math/rand" "math/rand"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
var randModule = map[string]tengo.Object{ var randModule = map[string]xgo.Object{
"int": &tengo.UserFunction{ "int": &xgo.UserFunction{
Name: "int", Name: "int",
Value: FuncARI64(rand.Int63), Value: FuncARI64(rand.Int63),
}, },
"float": &tengo.UserFunction{ "float": &xgo.UserFunction{
Name: "float", Name: "float",
Value: FuncARF(rand.Float64), Value: FuncARF(rand.Float64),
}, },
"intn": &tengo.UserFunction{ "intn": &xgo.UserFunction{
Name: "intn", Name: "intn",
Value: FuncAI64RI64(rand.Int63n), Value: FuncAI64RI64(rand.Int63n),
}, },
"exp_float": &tengo.UserFunction{ "exp_float": &xgo.UserFunction{
Name: "exp_float", Name: "exp_float",
Value: FuncARF(rand.ExpFloat64), Value: FuncARF(rand.ExpFloat64),
}, },
"norm_float": &tengo.UserFunction{ "norm_float": &xgo.UserFunction{
Name: "norm_float", Name: "norm_float",
Value: FuncARF(rand.NormFloat64), Value: FuncARF(rand.NormFloat64),
}, },
"perm": &tengo.UserFunction{ "perm": &xgo.UserFunction{
Name: "perm", Name: "perm",
Value: FuncAIRIs(rand.Perm), Value: FuncAIRIs(rand.Perm),
}, },
"seed": &tengo.UserFunction{ "seed": &xgo.UserFunction{
Name: "seed", Name: "seed",
Value: FuncAI64R(rand.Seed), Value: FuncAI64R(rand.Seed),
}, },
"read": &tengo.UserFunction{ "read": &xgo.UserFunction{
Name: "read", Name: "read",
Value: func(args ...tengo.Object) (ret tengo.Object, err error) { Value: func(args ...xgo.Object) (ret xgo.Object, err error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
y1, ok := args[0].(*tengo.Bytes) y1, ok := args[0].(*xgo.Bytes)
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "bytes", Expected: "bytes",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -54,18 +54,18 @@ var randModule = map[string]tengo.Object{
ret = wrapError(err) ret = wrapError(err)
return return
} }
return &tengo.Int{Value: int64(res)}, nil return &xgo.Int{Value: int64(res)}, nil
}, },
}, },
"rand": &tengo.UserFunction{ "rand": &xgo.UserFunction{
Name: "rand", Name: "rand",
Value: func(args ...tengo.Object) (tengo.Object, error) { Value: func(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
i1, ok := tengo.ToInt64(args[0]) i1, ok := xgo.ToInt64(args[0])
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "int(compatible)", Expected: "int(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -77,49 +77,49 @@ var randModule = map[string]tengo.Object{
}, },
} }
func randRand(r *rand.Rand) *tengo.ImmutableMap { func randRand(r *rand.Rand) *xgo.ImmutableMap {
return &tengo.ImmutableMap{ return &xgo.ImmutableMap{
Value: map[string]tengo.Object{ Value: map[string]xgo.Object{
"int": &tengo.UserFunction{ "int": &xgo.UserFunction{
Name: "int", Name: "int",
Value: FuncARI64(r.Int63), Value: FuncARI64(r.Int63),
}, },
"float": &tengo.UserFunction{ "float": &xgo.UserFunction{
Name: "float", Name: "float",
Value: FuncARF(r.Float64), Value: FuncARF(r.Float64),
}, },
"intn": &tengo.UserFunction{ "intn": &xgo.UserFunction{
Name: "intn", Name: "intn",
Value: FuncAI64RI64(r.Int63n), Value: FuncAI64RI64(r.Int63n),
}, },
"exp_float": &tengo.UserFunction{ "exp_float": &xgo.UserFunction{
Name: "exp_float", Name: "exp_float",
Value: FuncARF(r.ExpFloat64), Value: FuncARF(r.ExpFloat64),
}, },
"norm_float": &tengo.UserFunction{ "norm_float": &xgo.UserFunction{
Name: "norm_float", Name: "norm_float",
Value: FuncARF(r.NormFloat64), Value: FuncARF(r.NormFloat64),
}, },
"perm": &tengo.UserFunction{ "perm": &xgo.UserFunction{
Name: "perm", Name: "perm",
Value: FuncAIRIs(r.Perm), Value: FuncAIRIs(r.Perm),
}, },
"seed": &tengo.UserFunction{ "seed": &xgo.UserFunction{
Name: "seed", Name: "seed",
Value: FuncAI64R(r.Seed), Value: FuncAI64R(r.Seed),
}, },
"read": &tengo.UserFunction{ "read": &xgo.UserFunction{
Name: "read", Name: "read",
Value: func(args ...tengo.Object) ( Value: func(args ...xgo.Object) (
ret tengo.Object, ret xgo.Object,
err error, err error,
) { ) {
if len(args) != 1 { if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments return nil, xgo.ErrWrongNumArguments
} }
y1, ok := args[0].(*tengo.Bytes) y1, ok := args[0].(*xgo.Bytes)
if !ok { if !ok {
return nil, tengo.ErrInvalidArgumentType{ return nil, xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "bytes", Expected: "bytes",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -130,7 +130,7 @@ func randRand(r *rand.Rand) *tengo.ImmutableMap {
ret = wrapError(err) ret = wrapError(err)
return return
} }
return &tengo.Int{Value: int64(res)}, nil return &xgo.Int{Value: int64(res)}, nil
}, },
}, },
}, },

View file

@ -4,15 +4,15 @@ import (
"math/rand" "math/rand"
"testing" "testing"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
) )
func TestRand(t *testing.T) { func TestRand(t *testing.T) {
var seed int64 = 1234 var seed int64 = 1234
r := rand.New(rand.NewSource(seed)) r := rand.New(rand.NewSource(seed))
module(t, "rand").call("seed", seed).expect(tengo.UndefinedValue) module(t, "rand").call("seed", seed).expect(xgo.UndefinedValue)
module(t, "rand").call("int").expect(r.Int63()) module(t, "rand").call("int").expect(r.Int63())
module(t, "rand").call("float").expect(r.Float64()) module(t, "rand").call("float").expect(r.Float64())
module(t, "rand").call("intn", 111).expect(r.Int63n(111)) module(t, "rand").call("intn", 111).expect(r.Int63n(111))
@ -21,7 +21,7 @@ func TestRand(t *testing.T) {
module(t, "rand").call("perm", 10).expect(r.Perm(10)) module(t, "rand").call("perm", 10).expect(r.Perm(10))
buf1 := make([]byte, 10) buf1 := make([]byte, 10)
buf2 := &tengo.Bytes{Value: make([]byte, 10)} buf2 := &xgo.Bytes{Value: make([]byte, 10)}
n, _ := r.Read(buf1) n, _ := r.Read(buf1)
module(t, "rand").call("read", buf2).expect(n) module(t, "rand").call("read", buf2).expect(n)
require.Equal(t, buf1, buf2.Value) require.Equal(t, buf1, buf2.Value)
@ -29,7 +29,7 @@ func TestRand(t *testing.T) {
seed = 9191 seed = 9191
r = rand.New(rand.NewSource(seed)) r = rand.New(rand.NewSource(seed))
randObj := module(t, "rand").call("rand", seed) randObj := module(t, "rand").call("rand", seed)
randObj.call("seed", seed).expect(tengo.UndefinedValue) randObj.call("seed", seed).expect(xgo.UndefinedValue)
randObj.call("int").expect(r.Int63()) randObj.call("int").expect(r.Int63())
randObj.call("float").expect(r.Float64()) randObj.call("float").expect(r.Float64())
randObj.call("intn", 111).expect(r.Int63n(111)) randObj.call("intn", 111).expect(r.Int63n(111))
@ -38,7 +38,7 @@ func TestRand(t *testing.T) {
randObj.call("perm", 10).expect(r.Perm(10)) randObj.call("perm", 10).expect(r.Perm(10))
buf1 = make([]byte, 12) buf1 = make([]byte, 12)
buf2 = &tengo.Bytes{Value: make([]byte, 12)} buf2 = &xgo.Bytes{Value: make([]byte, 12)}
n, _ = r.Read(buf1) n, _ = r.Read(buf1)
randObj.call("read", buf2).expect(n) randObj.call("read", buf2).expect(n)
require.Equal(t, buf1, buf2.Value) require.Equal(t, buf1, buf2.Value)

View file

@ -2,7 +2,13 @@
package stdlib package stdlib
import "embed"
var _ = embed.FS{}
//go:embed srcmod_enum.xgo
var srcmodEnum string
// SourceModules are source type standard library modules. // SourceModules are source type standard library modules.
var SourceModules = map[string]string{ var SourceModules = map[string]string{
"enum": "is_enumerable := func(x) {\n return is_array(x) || is_map(x) || is_immutable_array(x) || is_immutable_map(x)\n}\n\nis_array_like := func(x) {\n return is_array(x) || is_immutable_array(x)\n}\n\nexport {\n // all returns true if the given function `fn` evaluates to a truthy value on\n // all of the items in `x`. It returns undefined if `x` is not enumerable.\n all: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n if !fn(k, v) { return false }\n }\n\n return true\n },\n // any returns true if the given function `fn` evaluates to a truthy value on\n // any of the items in `x`. It returns undefined if `x` is not enumerable.\n any: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n if fn(k, v) { return true }\n }\n\n return false\n },\n // chunk returns an array of elements split into groups the length of size.\n // If `x` can't be split evenly, the final chunk will be the remaining elements.\n // It returns undefined if `x` is not array.\n chunk: func(x, size) {\n if !is_array_like(x) || !size { return undefined }\n\n numElements := len(x)\n if !numElements { return [] }\n\n res := []\n idx := 0\n for idx < numElements {\n res = append(res, x[idx:idx+size])\n idx += size\n }\n\n return res\n },\n // at returns an element at the given index (if `x` is array) or\n // key (if `x` is map). It returns undefined if `x` is not enumerable.\n at: func(x, key) {\n if !is_enumerable(x) { return undefined }\n\n if is_array_like(x) {\n if !is_int(key) { return undefined }\n } else {\n if !is_string(key) { return undefined }\n }\n\n return x[key]\n },\n // each iterates over elements of `x` and invokes `fn` for each element. `fn` is\n // invoked with two arguments: `key` and `value`. `key` is an int index\n // if `x` is array. `key` is a string key if `x` is map. It does not iterate\n // and returns undefined if `x` is not enumerable.\n each: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n fn(k, v)\n }\n },\n // filter iterates over elements of `x`, returning an array of all elements `fn`\n // returns truthy for. `fn` is invoked with two arguments: `key` and `value`.\n // `key` is an int index if `x` is array. It returns undefined if `x` is not array.\n filter: func(x, fn) {\n if !is_array_like(x) { return undefined }\n\n dst := []\n for k, v in x {\n if fn(k, v) { dst = append(dst, v) }\n }\n\n return dst\n },\n // find iterates over elements of `x`, returning value of the first element `fn`\n // returns truthy for. `fn` is invoked with two arguments: `key` and `value`.\n // `key` is an int index if `x` is array. `key` is a string key if `x` is map.\n // It returns undefined if `x` is not enumerable.\n find: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n if fn(k, v) { return v }\n }\n },\n // find_key iterates over elements of `x`, returning key or index of the first\n // element `fn` returns truthy for. `fn` is invoked with two arguments: `key`\n // and `value`. `key` is an int index if `x` is array. `key` is a string key if\n // `x` is map. It returns undefined if `x` is not enumerable.\n find_key: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n for k, v in x {\n if fn(k, v) { return k }\n }\n },\n // map creates an array of values by running each element in `x` through `fn`.\n // `fn` is invoked with two arguments: `key` and `value`. `key` is an int index\n // if `x` is array. `key` is a string key if `x` is map. It returns undefined\n // if `x` is not enumerable.\n map: func(x, fn) {\n if !is_enumerable(x) { return undefined }\n\n dst := []\n for k, v in x {\n dst = append(dst, fn(k, v))\n }\n\n return dst\n },\n // key returns the first argument.\n key: func(k, _) { return k },\n // value returns the second argument.\n value: func(_, v) { return v }\n}\n", "enum": srcmodEnum,
} }

View file

@ -1,127 +0,0 @@
is_enumerable := func(x) {
return is_array(x) || is_map(x) || is_immutable_array(x) || is_immutable_map(x)
}
is_array_like := func(x) {
return is_array(x) || is_immutable_array(x)
}
export {
// all returns true if the given function `fn` evaluates to a truthy value on
// all of the items in `x`. It returns undefined if `x` is not enumerable.
all: func(x, fn) {
if !is_enumerable(x) { return undefined }
for k, v in x {
if !fn(k, v) { return false }
}
return true
},
// any returns true if the given function `fn` evaluates to a truthy value on
// any of the items in `x`. It returns undefined if `x` is not enumerable.
any: func(x, fn) {
if !is_enumerable(x) { return undefined }
for k, v in x {
if fn(k, v) { return true }
}
return false
},
// chunk returns an array of elements split into groups the length of size.
// If `x` can't be split evenly, the final chunk will be the remaining elements.
// It returns undefined if `x` is not array.
chunk: func(x, size) {
if !is_array_like(x) || !size { return undefined }
numElements := len(x)
if !numElements { return [] }
res := []
idx := 0
for idx < numElements {
res = append(res, x[idx:idx+size])
idx += size
}
return res
},
// at returns an element at the given index (if `x` is array) or
// key (if `x` is map). It returns undefined if `x` is not enumerable.
at: func(x, key) {
if !is_enumerable(x) { return undefined }
if is_array_like(x) {
if !is_int(key) { return undefined }
} else {
if !is_string(key) { return undefined }
}
return x[key]
},
// each iterates over elements of `x` and invokes `fn` for each element. `fn` is
// invoked with two arguments: `key` and `value`. `key` is an int index
// if `x` is array. `key` is a string key if `x` is map. It does not iterate
// and returns undefined if `x` is not enumerable.
each: func(x, fn) {
if !is_enumerable(x) { return undefined }
for k, v in x {
fn(k, v)
}
},
// filter iterates over elements of `x`, returning an array of all elements `fn`
// returns truthy for. `fn` is invoked with two arguments: `key` and `value`.
// `key` is an int index if `x` is array. It returns undefined if `x` is not array.
filter: func(x, fn) {
if !is_array_like(x) { return undefined }
dst := []
for k, v in x {
if fn(k, v) { dst = append(dst, v) }
}
return dst
},
// find iterates over elements of `x`, returning value of the first element `fn`
// returns truthy for. `fn` is invoked with two arguments: `key` and `value`.
// `key` is an int index if `x` is array. `key` is a string key if `x` is map.
// It returns undefined if `x` is not enumerable.
find: func(x, fn) {
if !is_enumerable(x) { return undefined }
for k, v in x {
if fn(k, v) { return v }
}
},
// find_key iterates over elements of `x`, returning key or index of the first
// element `fn` returns truthy for. `fn` is invoked with two arguments: `key`
// and `value`. `key` is an int index if `x` is array. `key` is a string key if
// `x` is map. It returns undefined if `x` is not enumerable.
find_key: func(x, fn) {
if !is_enumerable(x) { return undefined }
for k, v in x {
if fn(k, v) { return k }
}
},
// map creates an array of values by running each element in `x` through `fn`.
// `fn` is invoked with two arguments: `key` and `value`. `key` is an int index
// if `x` is array. `key` is a string key if `x` is map. It returns undefined
// if `x` is not enumerable.
map: func(x, fn) {
if !is_enumerable(x) { return undefined }
dst := []
for k, v in x {
dst = append(dst, fn(k, v))
}
return dst
},
// key returns the first argument.
key: func(k, _) { return k },
// value returns the second argument.
value: func(_, v) { return v }
}

179
stdlib/srcmod_enum.xgo Normal file
View file

@ -0,0 +1,179 @@
is_enumerable := func(x) {
return is_array(x) || is_map(x) || is_immutable_array(x) || is_immutable_map(x)
}
is_array_like := func(x) {
return is_array(x) || is_immutable_array(x)
}
_swap := func(arr, left, right) {
if arr == undefined || len(arr) <= 1 || left < 0 || left >= len(arr) || right < 0 || right >= len(arr) || left >= right {
return
}
temp := arr[right]
arr[right] = arr[left]
arr[left] = temp
}
_sort := func(arr, left, right, less) {
if arr == undefined || len(arr) <= 1 || left < 0 || left >= len(arr) || right < 0 || right >= len(arr) || left >= right {
return arr
}
idx := left
for i := left; i < right; i++ {
if less(arr[i], arr[right]) {
_swap(arr, idx, i)
idx++
}
}
_swap(arr, idx, right)
_sort(arr, left, idx-1, less)
_sort(arr, idx+1, right, less)
return arr
}
export {
keys: func(x){
ret := []
for k, _ in x {
ret += [k]
}
return ret
},
values: func(x){
ret := []
for _, v in x {
ret += [v]
}
return ret
},
sort: func(arr, ...less) {
if !less {
less = func(a, b){
return a < b
}
} else {
less = less[0]
}
if arr == undefined || len(arr) <= 1 {
return arr
}
return _sort(arr, 0, len(arr)-1, less)
},
// all returns true if the given function `fn` evaluates to a truthy value on
// all of the items in `x`. It returns undefined if `x` is not enumerable.
all: func(x, fn) {
if !is_enumerable(x) { return undefined }
for k, v in x {
if !fn(k, v) { return false }
}
return true
},
// any returns true if the given function `fn` evaluates to a truthy value on
// any of the items in `x`. It returns undefined if `x` is not enumerable.
any: func(x, fn) {
if !is_enumerable(x) { return undefined }
for k, v in x {
if fn(k, v) { return true }
}
return false
},
// chunk returns an array of elements split into groups the length of size.
// If `x` can't be split evenly, the final chunk will be the remaining elements.
// It returns undefined if `x` is not array.
chunk: func(x, size) {
if !is_array_like(x) || !size { return undefined }
numElements := len(x)
if !numElements { return [] }
res := []
idx := 0
for idx < numElements {
res = append(res, x[idx:idx+size])
idx += size
}
return res
},
// at returns an element at the given index (if `x` is array) or
// key (if `x` is map). It returns undefined if `x` is not enumerable.
at: func(x, key) {
if !is_enumerable(x) { return undefined }
if is_array_like(x) {
if !is_int(key) { return undefined }
} else {
if !is_string(key) { return undefined }
}
return x[key]
},
// each iterates over elements of `x` and invokes `fn` for each element. `fn` is
// invoked with two arguments: `key` and `value`. `key` is an int index
// if `x` is array. `key` is a string key if `x` is map. It does not iterate
// and returns undefined if `x` is not enumerable.
each: func(x, fn) {
if !is_enumerable(x) { return undefined }
for k, v in x {
fn(k, v)
}
},
// filter iterates over elements of `x`, returning an array of all elements `fn`
// returns truthy for. `fn` is invoked with two arguments: `key` and `value`.
// `key` is an int index if `x` is array. It returns undefined if `x` is not array.
filter: func(x, fn) {
if !is_array_like(x) { return undefined }
dst := []
for k, v in x {
if fn(k, v) { dst = append(dst, v) }
}
return dst
},
// find iterates over elements of `x`, returning value of the first element `fn`
// returns truthy for. `fn` is invoked with two arguments: `key` and `value`.
// `key` is an int index if `x` is array. `key` is a string key if `x` is map.
// It returns undefined if `x` is not enumerable.
find: func(x, fn) {
if !is_enumerable(x) { return undefined }
for k, v in x {
if fn(k, v) { return v }
}
},
// find_key iterates over elements of `x`, returning key or index of the first
// element `fn` returns truthy for. `fn` is invoked with two arguments: `key`
// and `value`. `key` is an int index if `x` is array. `key` is a string key if
// `x` is map. It returns undefined if `x` is not enumerable.
find_key: func(x, fn) {
if !is_enumerable(x) { return undefined }
for k, v in x {
if fn(k, v) { return k }
}
},
// map creates an array of values by running each element in `x` through `fn`.
// `fn` is invoked with two arguments: `key` and `value`. `key` is an int index
// if `x` is array. `key` is a string key if `x` is map. It returns undefined
// if `x` is not enumerable.
map: func(x, fn) {
if !is_enumerable(x) { return undefined }
dst := []
for k, v in x {
dst = append(dst, fn(k, v))
}
return dst
},
// key returns the first argument.
key: func(k, _) { return k },
// value returns the second argument.
value: func(_, v) { return v }
}

View file

@ -3,7 +3,7 @@ package stdlib
//go:generate go run gensrcmods.go //go:generate go run gensrcmods.go
import ( import (
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
// AllModuleNames returns a list of all default module names. // AllModuleNames returns a list of all default module names.
@ -20,8 +20,8 @@ func AllModuleNames() []string {
// GetModuleMap returns the module map that includes all modules // GetModuleMap returns the module map that includes all modules
// for the given module names. // for the given module names.
func GetModuleMap(names ...string) *tengo.ModuleMap { func GetModuleMap(names ...string) *xgo.ModuleMap {
modules := tengo.NewModuleMap() modules := xgo.NewModuleMap()
for _, name := range names { for _, name := range names {
if mod := BuiltinModules[name]; mod != nil { if mod := BuiltinModules[name]; mod != nil {
modules.AddBuiltinModule(name, mod) modules.AddBuiltinModule(name, mod)

View file

@ -5,9 +5,9 @@ import (
"testing" "testing"
"time" "time"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
"github.com/d5/tengo/v2/stdlib" "surdeus.su/core/xgo/v2/stdlib"
) )
type ARR = []interface{} type ARR = []interface{}
@ -105,20 +105,20 @@ func (c callres) call(funcName string, args ...interface{}) callres {
return c return c
} }
var oargs []tengo.Object var oargs []xgo.Object
for _, v := range args { for _, v := range args {
oargs = append(oargs, object(v)) oargs = append(oargs, object(v))
} }
switch o := c.o.(type) { switch o := c.o.(type) {
case *tengo.BuiltinModule: case *xgo.BuiltinModule:
m, ok := o.Attrs[funcName] m, ok := o.Attrs[funcName]
if !ok { if !ok {
return callres{t: c.t, e: fmt.Errorf( return callres{t: c.t, e: fmt.Errorf(
"function not found: %s", funcName)} "function not found: %s", funcName)}
} }
f, ok := m.(*tengo.UserFunction) f, ok := m.(*xgo.UserFunction)
if !ok { if !ok {
return callres{t: c.t, e: fmt.Errorf( return callres{t: c.t, e: fmt.Errorf(
"non-callable: %s", funcName)} "non-callable: %s", funcName)}
@ -126,16 +126,16 @@ func (c callres) call(funcName string, args ...interface{}) callres {
res, err := f.Value(oargs...) res, err := f.Value(oargs...)
return callres{t: c.t, o: res, e: err} return callres{t: c.t, o: res, e: err}
case *tengo.UserFunction: case *xgo.UserFunction:
res, err := o.Value(oargs...) res, err := o.Value(oargs...)
return callres{t: c.t, o: res, e: err} return callres{t: c.t, o: res, e: err}
case *tengo.ImmutableMap: case *xgo.ImmutableMap:
m, ok := o.Value[funcName] m, ok := o.Value[funcName]
if !ok { if !ok {
return callres{t: c.t, e: fmt.Errorf("function not found: %s", funcName)} return callres{t: c.t, e: fmt.Errorf("function not found: %s", funcName)}
} }
f, ok := m.(*tengo.UserFunction) f, ok := m.(*xgo.UserFunction)
if !ok { if !ok {
return callres{t: c.t, e: fmt.Errorf("non-callable: %s", funcName)} return callres{t: c.t, e: fmt.Errorf("non-callable: %s", funcName)}
} }
@ -165,73 +165,73 @@ func module(t *testing.T, moduleName string) callres {
return callres{t: t, o: mod} return callres{t: t, o: mod}
} }
func object(v interface{}) tengo.Object { func object(v interface{}) xgo.Object {
switch v := v.(type) { switch v := v.(type) {
case tengo.Object: case xgo.Object:
return v return v
case string: case string:
return &tengo.String{Value: v} return &xgo.String{Value: v}
case int64: case int64:
return &tengo.Int{Value: v} return &xgo.Int{Value: v}
case int: // for convenience case int: // for convenience
return &tengo.Int{Value: int64(v)} return &xgo.Int{Value: int64(v)}
case bool: case bool:
if v { if v {
return tengo.TrueValue return xgo.TrueValue
} }
return tengo.FalseValue return xgo.FalseValue
case rune: case rune:
return &tengo.Char{Value: v} return &xgo.Char{Value: v}
case byte: // for convenience case byte: // for convenience
return &tengo.Char{Value: rune(v)} return &xgo.Char{Value: rune(v)}
case float64: case float64:
return &tengo.Float{Value: v} return &xgo.Float{Value: v}
case []byte: case []byte:
return &tengo.Bytes{Value: v} return &xgo.Bytes{Value: v}
case MAP: case MAP:
objs := make(map[string]tengo.Object) objs := make(map[string]xgo.Object)
for k, v := range v { for k, v := range v {
objs[k] = object(v) objs[k] = object(v)
} }
return &tengo.Map{Value: objs} return &xgo.Map{Value: objs}
case ARR: case ARR:
var objs []tengo.Object var objs []xgo.Object
for _, e := range v { for _, e := range v {
objs = append(objs, object(e)) objs = append(objs, object(e))
} }
return &tengo.Array{Value: objs} return &xgo.Array{Value: objs}
case IMAP: case IMAP:
objs := make(map[string]tengo.Object) objs := make(map[string]xgo.Object)
for k, v := range v { for k, v := range v {
objs[k] = object(v) objs[k] = object(v)
} }
return &tengo.ImmutableMap{Value: objs} return &xgo.ImmutableMap{Value: objs}
case IARR: case IARR:
var objs []tengo.Object var objs []xgo.Object
for _, e := range v { for _, e := range v {
objs = append(objs, object(e)) objs = append(objs, object(e))
} }
return &tengo.ImmutableArray{Value: objs} return &xgo.ImmutableArray{Value: objs}
case time.Time: case time.Time:
return &tengo.Time{Value: v} return &xgo.Time{Value: v}
case []int: case []int:
var objs []tengo.Object var objs []xgo.Object
for _, e := range v { for _, e := range v {
objs = append(objs, &tengo.Int{Value: int64(e)}) objs = append(objs, &xgo.Int{Value: int64(e)})
} }
return &tengo.Array{Value: objs} return &xgo.Array{Value: objs}
} }
panic(fmt.Errorf("unknown type: %T", v)) panic(fmt.Errorf("unknown type: %T", v))
} }
func expect(t *testing.T, input string, expected interface{}) { func expect(t *testing.T, input string, expected interface{}) {
s := tengo.NewScript([]byte(input)) s := xgo.NewScript([]byte(input))
s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...)) s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...))
c, err := s.Run() c, err := s.Run()
require.NoError(t, err) require.NoError(t, err)

File diff suppressed because it is too large Load diff

View file

@ -3,26 +3,26 @@ package stdlib
import ( import (
"regexp" "regexp"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap { func makeTextRegexp(re *regexp.Regexp) *xgo.ImmutableMap {
return &tengo.ImmutableMap{ return &xgo.ImmutableMap{
Value: map[string]tengo.Object{ Value: map[string]xgo.Object{
// match(text) => bool // match(text) => bool
"match": &tengo.UserFunction{ "match": &xgo.UserFunction{
Value: func(args ...tengo.Object) ( Value: func(args ...xgo.Object) (
ret tengo.Object, ret xgo.Object,
err error, err error,
) { ) {
if len(args) != 1 { if len(args) != 1 {
err = tengo.ErrWrongNumArguments err = xgo.ErrWrongNumArguments
return return
} }
s1, ok := tengo.ToString(args[0]) s1, ok := xgo.ToString(args[0])
if !ok { if !ok {
err = tengo.ErrInvalidArgumentType{ err = xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -31,9 +31,9 @@ func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap {
} }
if re.MatchString(s1) { if re.MatchString(s1) {
ret = tengo.TrueValue ret = xgo.TrueValue
} else { } else {
ret = tengo.FalseValue ret = xgo.FalseValue
} }
return return
@ -42,20 +42,20 @@ func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap {
// find(text) => array(array({text:,begin:,end:}))/undefined // find(text) => array(array({text:,begin:,end:}))/undefined
// find(text, maxCount) => array(array({text:,begin:,end:}))/undefined // find(text, maxCount) => array(array({text:,begin:,end:}))/undefined
"find": &tengo.UserFunction{ "find": &xgo.UserFunction{
Value: func(args ...tengo.Object) ( Value: func(args ...xgo.Object) (
ret tengo.Object, ret xgo.Object,
err error, err error,
) { ) {
numArgs := len(args) numArgs := len(args)
if numArgs != 1 && numArgs != 2 { if numArgs != 1 && numArgs != 2 {
err = tengo.ErrWrongNumArguments err = xgo.ErrWrongNumArguments
return return
} }
s1, ok := tengo.ToString(args[0]) s1, ok := xgo.ToString(args[0])
if !ok { if !ok {
err = tengo.ErrInvalidArgumentType{ err = xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -66,35 +66,35 @@ func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap {
if numArgs == 1 { if numArgs == 1 {
m := re.FindStringSubmatchIndex(s1) m := re.FindStringSubmatchIndex(s1)
if m == nil { if m == nil {
ret = tengo.UndefinedValue ret = xgo.UndefinedValue
return return
} }
arr := &tengo.Array{} arr := &xgo.Array{}
for i := 0; i < len(m); i += 2 { for i := 0; i < len(m); i += 2 {
arr.Value = append(arr.Value, arr.Value = append(arr.Value,
&tengo.ImmutableMap{ &xgo.ImmutableMap{
Value: map[string]tengo.Object{ Value: map[string]xgo.Object{
"text": &tengo.String{ "text": &xgo.String{
Value: s1[m[i]:m[i+1]], Value: s1[m[i]:m[i+1]],
}, },
"begin": &tengo.Int{ "begin": &xgo.Int{
Value: int64(m[i]), Value: int64(m[i]),
}, },
"end": &tengo.Int{ "end": &xgo.Int{
Value: int64(m[i+1]), Value: int64(m[i+1]),
}, },
}}) }})
} }
ret = &tengo.Array{Value: []tengo.Object{arr}} ret = &xgo.Array{Value: []xgo.Object{arr}}
return return
} }
i2, ok := tengo.ToInt(args[1]) i2, ok := xgo.ToInt(args[1])
if !ok { if !ok {
err = tengo.ErrInvalidArgumentType{ err = xgo.ErrInvalidArgumentType{
Name: "second", Name: "second",
Expected: "int(compatible)", Expected: "int(compatible)",
Found: args[1].TypeName(), Found: args[1].TypeName(),
@ -103,24 +103,24 @@ func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap {
} }
m := re.FindAllStringSubmatchIndex(s1, i2) m := re.FindAllStringSubmatchIndex(s1, i2)
if m == nil { if m == nil {
ret = tengo.UndefinedValue ret = xgo.UndefinedValue
return return
} }
arr := &tengo.Array{} arr := &xgo.Array{}
for _, m := range m { for _, m := range m {
subMatch := &tengo.Array{} subMatch := &xgo.Array{}
for i := 0; i < len(m); i += 2 { for i := 0; i < len(m); i += 2 {
subMatch.Value = append(subMatch.Value, subMatch.Value = append(subMatch.Value,
&tengo.ImmutableMap{ &xgo.ImmutableMap{
Value: map[string]tengo.Object{ Value: map[string]xgo.Object{
"text": &tengo.String{ "text": &xgo.String{
Value: s1[m[i]:m[i+1]], Value: s1[m[i]:m[i+1]],
}, },
"begin": &tengo.Int{ "begin": &xgo.Int{
Value: int64(m[i]), Value: int64(m[i]),
}, },
"end": &tengo.Int{ "end": &xgo.Int{
Value: int64(m[i+1]), Value: int64(m[i+1]),
}, },
}}) }})
@ -136,19 +136,19 @@ func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap {
}, },
// replace(src, repl) => string // replace(src, repl) => string
"replace": &tengo.UserFunction{ "replace": &xgo.UserFunction{
Value: func(args ...tengo.Object) ( Value: func(args ...xgo.Object) (
ret tengo.Object, ret xgo.Object,
err error, err error,
) { ) {
if len(args) != 2 { if len(args) != 2 {
err = tengo.ErrWrongNumArguments err = xgo.ErrWrongNumArguments
return return
} }
s1, ok := tengo.ToString(args[0]) s1, ok := xgo.ToString(args[0])
if !ok { if !ok {
err = tengo.ErrInvalidArgumentType{ err = xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -156,9 +156,9 @@ func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap {
return return
} }
s2, ok := tengo.ToString(args[1]) s2, ok := xgo.ToString(args[1])
if !ok { if !ok {
err = tengo.ErrInvalidArgumentType{ err = xgo.ErrInvalidArgumentType{
Name: "second", Name: "second",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[1].TypeName(), Found: args[1].TypeName(),
@ -168,10 +168,10 @@ func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap {
s, ok := doTextRegexpReplace(re, s1, s2) s, ok := doTextRegexpReplace(re, s1, s2)
if !ok { if !ok {
return nil, tengo.ErrStringLimit return nil, xgo.ErrStringLimit
} }
ret = &tengo.String{Value: s} ret = &xgo.String{Value: s}
return return
}, },
@ -179,20 +179,20 @@ func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap {
// split(text) => array(string) // split(text) => array(string)
// split(text, maxCount) => array(string) // split(text, maxCount) => array(string)
"split": &tengo.UserFunction{ "split": &xgo.UserFunction{
Value: func(args ...tengo.Object) ( Value: func(args ...xgo.Object) (
ret tengo.Object, ret xgo.Object,
err error, err error,
) { ) {
numArgs := len(args) numArgs := len(args)
if numArgs != 1 && numArgs != 2 { if numArgs != 1 && numArgs != 2 {
err = tengo.ErrWrongNumArguments err = xgo.ErrWrongNumArguments
return return
} }
s1, ok := tengo.ToString(args[0]) s1, ok := xgo.ToString(args[0])
if !ok { if !ok {
err = tengo.ErrInvalidArgumentType{ err = xgo.ErrInvalidArgumentType{
Name: "first", Name: "first",
Expected: "string(compatible)", Expected: "string(compatible)",
Found: args[0].TypeName(), Found: args[0].TypeName(),
@ -202,9 +202,9 @@ func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap {
var i2 = -1 var i2 = -1
if numArgs > 1 { if numArgs > 1 {
i2, ok = tengo.ToInt(args[1]) i2, ok = xgo.ToInt(args[1])
if !ok { if !ok {
err = tengo.ErrInvalidArgumentType{ err = xgo.ErrInvalidArgumentType{
Name: "second", Name: "second",
Expected: "int(compatible)", Expected: "int(compatible)",
Found: args[1].TypeName(), Found: args[1].TypeName(),
@ -213,10 +213,10 @@ func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap {
} }
} }
arr := &tengo.Array{} arr := &xgo.Array{}
for _, s := range re.Split(s1, i2) { for _, s := range re.Split(s1, i2) {
arr.Value = append(arr.Value, arr.Value = append(arr.Value,
&tengo.String{Value: s}) &xgo.String{Value: s})
} }
ret = arr ret = arr
@ -235,14 +235,14 @@ func doTextRegexpReplace(re *regexp.Regexp, src, repl string) (string, bool) {
for _, m := range re.FindAllStringSubmatchIndex(src, -1) { for _, m := range re.FindAllStringSubmatchIndex(src, -1) {
var exp []byte var exp []byte
exp = re.ExpandString(exp, repl, src, m) exp = re.ExpandString(exp, repl, src, m)
if len(out)+m[0]-idx+len(exp) > tengo.MaxStringLen { if len(out)+m[0]-idx+len(exp) > xgo.MaxStringLen {
return "", false return "", false
} }
out += src[idx:m[0]] + string(exp) out += src[idx:m[0]] + string(exp)
idx = m[1] idx = m[1]
} }
if idx < len(src) { if idx < len(src) {
if len(out)+len(src)-idx > tengo.MaxStringLen { if len(out)+len(src)-idx > xgo.MaxStringLen {
return "", false return "", false
} }
out += src[idx:] out += src[idx:]

View file

@ -4,7 +4,7 @@ import (
"regexp" "regexp"
"testing" "testing"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
) )
func TestTextRE(t *testing.T) { func TestTextRE(t *testing.T) {
@ -33,7 +33,7 @@ func TestTextRE(t *testing.T) {
text string text string
expected interface{} expected interface{}
}{ }{
{"a(b)", "", tengo.UndefinedValue}, {"a(b)", "", xgo.UndefinedValue},
{"a(b)", "ab", ARR{ {"a(b)", "ab", ARR{
ARR{ ARR{
IMAP{"text": "ab", "begin": 0, "end": 2}, IMAP{"text": "ab", "begin": 0, "end": 2},
@ -67,7 +67,7 @@ func TestTextRE(t *testing.T) {
count int count int
expected interface{} expected interface{}
}{ }{
{"a(b)", "", -1, tengo.UndefinedValue}, {"a(b)", "", -1, xgo.UndefinedValue},
{"a(b)", "ab", -1, ARR{ {"a(b)", "ab", -1, ARR{
ARR{ ARR{
IMAP{"text": "ab", "begin": 0, "end": 2}, IMAP{"text": "ab", "begin": 0, "end": 2},
@ -96,7 +96,7 @@ func TestTextRE(t *testing.T) {
IMAP{"text": "c", "begin": 9, "end": 10}, IMAP{"text": "c", "begin": 9, "end": 10},
}, },
}}, }},
{"(a)b(c)d", "abcdefgabcd", 0, tengo.UndefinedValue}, {"(a)b(c)d", "abcdefgabcd", 0, xgo.UndefinedValue},
{"(a)b(c)d", "abcdefgabcd", 1, ARR{ {"(a)b(c)d", "abcdefgabcd", 1, ARR{
ARR{ ARR{
IMAP{"text": "abcd", "begin": 0, "end": 4}, IMAP{"text": "abcd", "begin": 0, "end": 4},
@ -232,9 +232,9 @@ func TestText(t *testing.T) {
} }
func TestReplaceLimit(t *testing.T) { func TestReplaceLimit(t *testing.T) {
curMaxStringLen := tengo.MaxStringLen curMaxStringLen := xgo.MaxStringLen
defer func() { tengo.MaxStringLen = curMaxStringLen }() defer func() { xgo.MaxStringLen = curMaxStringLen }()
tengo.MaxStringLen = 12 xgo.MaxStringLen = 12
module(t, "text").call("replace", "123456789012", "1", "x", -1). module(t, "text").call("replace", "123456789012", "1", "x", -1).
expect("x234567890x2") expect("x234567890x2")
@ -264,9 +264,9 @@ func TestReplaceLimit(t *testing.T) {
} }
func TestTextRepeat(t *testing.T) { func TestTextRepeat(t *testing.T) {
curMaxStringLen := tengo.MaxStringLen curMaxStringLen := xgo.MaxStringLen
defer func() { tengo.MaxStringLen = curMaxStringLen }() defer func() { xgo.MaxStringLen = curMaxStringLen }()
tengo.MaxStringLen = 12 xgo.MaxStringLen = 12
module(t, "text").call("repeat", "1234", "3"). module(t, "text").call("repeat", "1234", "3").
expect("123412341234") expect("123412341234")

File diff suppressed because it is too large Load diff

View file

@ -4,8 +4,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
) )
func TestTimes(t *testing.T) { func TestTimes(t *testing.T) {
@ -14,14 +14,14 @@ func TestTimes(t *testing.T) {
location, _ := time.LoadLocation("Pacific/Auckland") location, _ := time.LoadLocation("Pacific/Auckland")
time3 := time.Date(1982, 9, 28, 19, 21, 44, 999, location) time3 := time.Date(1982, 9, 28, 19, 21, 44, 999, location)
module(t, "times").call("sleep", 1).expect(tengo.UndefinedValue) module(t, "times").call("sleep", 1).expect(xgo.UndefinedValue)
require.True(t, module(t, "times"). require.True(t, module(t, "times").
call("since", time.Now().Add(-time.Hour)). call("since", time.Now().Add(-time.Hour)).
o.(*tengo.Int).Value > 3600000000000) o.(*xgo.Int).Value > 3600000000000)
require.True(t, module(t, "times"). require.True(t, module(t, "times").
call("until", time.Now().Add(time.Hour)). call("until", time.Now().Add(time.Hour)).
o.(*tengo.Int).Value < 3600000000000) o.(*xgo.Int).Value < 3600000000000)
module(t, "times").call("parse_duration", "1ns").expect(1) module(t, "times").call("parse_duration", "1ns").expect(1)
module(t, "times").call("parse_duration", "1ms").expect(1000000) module(t, "times").call("parse_duration", "1ms").expect(1000000)
@ -41,7 +41,7 @@ func TestTimes(t *testing.T) {
expect(time3) expect(time3)
nowD := time.Until(module(t, "times").call("now"). nowD := time.Until(module(t, "times").call("now").
o.(*tengo.Time).Value).Nanoseconds() o.(*xgo.Time).Value).Nanoseconds()
require.True(t, 0 > nowD && nowD > -100000000) // within 100ms require.True(t, 0 > nowD && nowD > -100000000) // within 100ms
parsed, _ := time.Parse(time.RFC3339, "1982-09-28T19:21:44+07:00") parsed, _ := time.Parse(time.RFC3339, "1982-09-28T19:21:44+07:00")
module(t, "times"). module(t, "times").

77
stdlib/url/url.go Normal file
View file

@ -0,0 +1,77 @@
package url
import (
"surdeus.su/core/xgo/v2"
"net/url"
"fmt"
)
var _ = xgo.Object(&Values{})
type Values struct {
xgo.ObjectImpl
url.Values
}
func (vs *Values) TypeName() string {
return "*url.Values"
}
func (vs *Values) String() string {
return fmt.Sprintf("%v", vs.Values)
}
func (vs *Values) IndexGet(
index xgo.Object,
) (xgo.Object, error) {
key, ok := xgo.ToString(index)
if !ok {
return nil, xgo.ErrInvalidIndexValueType
}
val, ok := vs.Values[key]
if !ok {
return nil, nil
}
arr := make([]xgo.Object, len(val))
for i, v := range val {
arr[i], _ = xgo.FromInterface(v)
}
return &xgo.Array{Value: arr}, nil
}
type URL struct {
xgo.ObjectImpl
*url.URL
}
func (u *URL) TypeName() string {
return "<URL>"
}
func (u *URL) String() string {
return u.URL.String()
}
func (u *URL) IndexGet(
index xgo.Object,
) (xgo.Object, error) {
key, ok := xgo.ToString(index)
if !ok {
return nil, xgo.ErrInvalidIndexValueType
}
switch key {
case "path":
return xgo.FromInterface(u.Path)
case "query":
return &Values{
Values: u.Query(),
}, nil
}
// Nothing found.
return nil, nil
}

View file

@ -1,4 +1,4 @@
package tengo package xgo
// SymbolScope represents a symbol scope. // SymbolScope represents a symbol scope.
type SymbolScope string type SymbolScope string

View file

@ -1,10 +1,10 @@
package tengo_test package xgo_test
import ( import (
"testing" "testing"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
) )
func TestSymbolTable(t *testing.T) { func TestSymbolTable(t *testing.T) {

View file

@ -1,4 +1,4 @@
package tengo package xgo
import ( import (
"errors" "errors"
@ -28,7 +28,7 @@ const (
MaxFrames = 1024 MaxFrames = 1024
// SourceFileExtDefault is the default extension for source files. // SourceFileExtDefault is the default extension for source files.
SourceFileExtDefault = ".tengo" SourceFileExtDefault = ".xgo"
) )
// CallableFunc is a function signature for the callable functions. // CallableFunc is a function signature for the callable functions.

View file

@ -1,13 +1,13 @@
package tengo_test package xgo_test
import ( import (
"strings" "strings"
"testing" "testing"
"time" "time"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
) )
func TestInstructions_String(t *testing.T) { func TestInstructions_String(t *testing.T) {

22
testdata/libs/array.tengo vendored Normal file
View file

@ -0,0 +1,22 @@
enum := import("enumx")
fmt := import("log")
object := {
key1: "cock",
key2: "dick",
key3: "check",
key4: "die",
key5: "wasd"
}
keys := enum.keys(object)
values := enum.values(object)
sorted_values := enum.sort(values, func(a, b){
return b < a
})
ia := [5, 100, 531, 7537, 1, 2, -100, 1.535]
fmt.println(enum.sort(ia))
fmt.println(sorted_values)

20
testdata/libs/cjson.xgo vendored Normal file
View file

@ -0,0 +1,20 @@
cjson := import("cjson")
fmt := import("fmt")
log := import("log")
dec := cjson.Decoder("<stdin>")
log.print("cock")
log.print("die")
log.println("some log")
for {
v := dec.decode()
if is_error(v) {
break
}
if !v {
break
}
log.println("got one more value")
fmt.println(v)
}

4
testdata/libs/data.cjson vendored Normal file
View file

@ -0,0 +1,4 @@
{"somename": {
"value": 1
}}
["array",135,"integers", 135, 135]

22
testdata/libs/dogs.xgo vendored Normal file
View file

@ -0,0 +1,22 @@
objects := import("objects")
fmt := import("fmt")
new := func(name) {
ret := objects.new()
ret.name = name
ret.def("bark", func(self, n){
fmt.print(self.name, ": ")
for i:=0 ; i<n ; i++ {
fmt.print("BARK!")
}
fmt.println()
})
return ret
}
export {
"new": new
}

27
testdata/libs/html.xgo vendored Normal file
View file

@ -0,0 +1,27 @@
fmt := import("fmt")
http := import("http")
html := import("html").Renderer()
added := html.ul()
for i in [1, 2, 3, 4, 5] {
added.add(html.li().body(i))
}
fmt.println(
html.html({
lang: "en"
}).body(
html.head().body(
html.link({
rel: "stylesheet",
href: "/web/main.css"
}).final()
),
html.body().body(
html.p().body(
">>>shit"
)
),
added
)
)

19
testdata/libs/http.xgo vendored Normal file
View file

@ -0,0 +1,19 @@
fmt := import("fmt")
http := import("http")
os := import("os")
resp := http.post_json(
"https://jsonplaceholder.typicode.com/posts", {
title: "Hello, World!",
body: "Checking shit out!",
userId: 1
}
)
if is_error(resp) {
fmt.println(resp)
os.exit(1)
}
body := resp.body_json
fmt.println(body)

7
testdata/libs/import.xgo vendored Normal file
View file

@ -0,0 +1,7 @@
fmt := import("fmt")
dogs := import("./tests/dogs")
dog := dogs.new("check")
//fmt.println(dog)
dog.bark(10)

8
testdata/libs/paths.xgo vendored Normal file
View file

@ -0,0 +1,8 @@
fmt := import("fmt")
paths := import("paths")
os := import("os")
for path in os.args()[2:] {
fmt.println(paths.base(path))
}

View file

@ -1,4 +1,4 @@
package tengo package xgo
import ( import (
"errors" "errors"

View file

@ -1,10 +1,10 @@
package tengo_test package xgo_test
import ( import (
"testing" "testing"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
) )
type VariableTest struct { type VariableTest struct {

6
vm.go
View file

@ -1,11 +1,11 @@
package tengo package xgo
import ( import (
"fmt" "fmt"
"sync/atomic" "sync/atomic"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
"github.com/d5/tengo/v2/token" "surdeus.su/core/xgo/v2/token"
) )
// frame represents a function call frame. // frame represents a function call frame.

View file

@ -1,4 +1,4 @@
package tengo_test package xgo_test
import ( import (
"errors" "errors"
@ -10,11 +10,11 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/d5/tengo/v2" "surdeus.su/core/xgo/v2"
"github.com/d5/tengo/v2/parser" "surdeus.su/core/xgo/v2/parser"
"github.com/d5/tengo/v2/require" "surdeus.su/core/xgo/v2/require"
"github.com/d5/tengo/v2/stdlib" "surdeus.su/core/xgo/v2/stdlib"
"github.com/d5/tengo/v2/token" "surdeus.su/core/xgo/v2/token"
) )
const testOut = "out" const testOut = "out"