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

3
.gitignore vendored
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,4 @@
package tengo
package xgo
import (
"errors"
@ -10,8 +10,8 @@ import (
"reflect"
"strings"
"github.com/d5/tengo/v2/parser"
"github.com/d5/tengo/v2/token"
"surdeus.su/core/xgo/v2/parser"
"surdeus.su/core/xgo/v2/token"
)
// 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".
//
// // this will search for *.tengo, *.foo, *.bar
// err := c.SetImportFileExt(".tengo", ".foo", ".bar")
// // this will search for *.tengo, *.foo, *.bar
// err := c.SetImportFileExt(".tengo", ".foo", ".bar")
//
// This function requires at least one argument, since it will replace the
// current list of extension name.

View file

@ -1,4 +1,4 @@
package tengo_test
package xgo_test
import (
"fmt"
@ -7,10 +7,10 @@ import (
"strings"
"testing"
"github.com/d5/tengo/v2"
"github.com/d5/tengo/v2/parser"
"github.com/d5/tengo/v2/require"
"github.com/d5/tengo/v2/stdlib"
"surdeus.su/core/xgo/v2"
"surdeus.su/core/xgo/v2/parser"
"surdeus.su/core/xgo/v2/require"
"surdeus.su/core/xgo/v2/stdlib"
)
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.
package tengo
package xgo

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,4 @@
package tengo
package xgo
import (
"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 (
"fmt"
"github.com/d5/tengo/v2/parser"
"surdeus.su/core/xgo/v2/parser"
)
// 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.
type Iterator interface {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,11 +1,16 @@
package stdlib
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.
var BuiltinModules = map[string]map[string]tengo.Object{
var BuiltinModules = map[string]map[string]xgo.Object{
"math": mathModule,
"os": osModule,
"text": textModule,
@ -15,4 +20,11 @@ var BuiltinModules = map[string]map[string]tengo.Object{
"json": jsonModule,
"base64": base64Module,
"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
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 {
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 (
"fmt"
"github.com/d5/tengo/v2"
"surdeus.su/core/xgo/v2"
)
var fmtModule = map[string]tengo.Object{
"print": &tengo.UserFunction{Name: "print", Value: fmtPrint},
"printf": &tengo.UserFunction{Name: "printf", Value: fmtPrintf},
"println": &tengo.UserFunction{Name: "println", Value: fmtPrintln},
"sprintf": &tengo.UserFunction{Name: "sprintf", Value: fmtSprintf},
var fmtModule = map[string]xgo.Object{
"print": &xgo.UserFunction{Name: "print", Value: fmtPrint},
"printf": &xgo.UserFunction{Name: "printf", Value: fmtPrintf},
"println": &xgo.UserFunction{Name: "println", Value: fmtPrintln},
"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...)
if err != nil {
return nil, err
@ -22,15 +22,15 @@ func fmtPrint(args ...tengo.Object) (ret tengo.Object, err error) {
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)
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 {
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "format",
Expected: "string",
Found: args[0].TypeName(),
@ -41,7 +41,7 @@ func fmtPrintf(args ...tengo.Object) (ret tengo.Object, err error) {
return nil, nil
}
s, err := tengo.Format(format.Value, args[1:]...)
s, err := xgo.Format(format.Value, args[1:]...)
if err != nil {
return nil, err
}
@ -49,7 +49,7 @@ func fmtPrintf(args ...tengo.Object) (ret tengo.Object, err error) {
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...)
if err != nil {
return nil, err
@ -59,15 +59,15 @@ func fmtPrintln(args ...tengo.Object) (ret tengo.Object, err error) {
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)
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 {
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "format",
Expected: "string",
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
return format, nil
}
s, err := tengo.Format(format.Value, args[1:]...)
s, err := xgo.Format(format.Value, args[1:]...)
if err != nil {
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{}
l := 0
for _, arg := range args {
s, _ := tengo.ToString(arg)
s, _ := xgo.ToString(arg)
slen := len(s)
// make sure length does not exceed the limit
if l+slen > tengo.MaxStringLen {
return nil, tengo.ErrStringLimit
if l+slen > xgo.MaxStringLen {
return nil, xgo.ErrStringLimit
}
l += slen
printArgs = append(printArgs, s)

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

@ -3,10 +3,10 @@ package stdlib
import (
"encoding/hex"
"github.com/d5/tengo/v2"
"surdeus.su/core/xgo/v2"
)
var hexModule = map[string]tengo.Object{
"encode": &tengo.UserFunction{Value: FuncAYRS(hex.EncodeToString)},
"decode": &tengo.UserFunction{Value: FuncASRYE(hex.DecodeString)},
var hexModule = map[string]xgo.Object{
"encode": &xgo.UserFunction{Value: FuncAYRS(hex.EncodeToString)},
"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"
gojson "encoding/json"
"github.com/d5/tengo/v2"
"github.com/d5/tengo/v2/stdlib/json"
"surdeus.su/core/xgo/v2"
"surdeus.su/core/xgo/v2/stdlib/json"
)
var jsonModule = map[string]tengo.Object{
"decode": &tengo.UserFunction{
var jsonModule = map[string]xgo.Object{
"decode": &xgo.UserFunction{
Name: "decode",
Value: jsonDecode,
},
"encode": &tengo.UserFunction{
"encode": &xgo.UserFunction{
Name: "encode",
Value: jsonEncode,
},
"indent": &tengo.UserFunction{
"indent": &xgo.UserFunction{
Name: "encode",
Value: jsonIndent,
},
"html_escape": &tengo.UserFunction{
"html_escape": &xgo.UserFunction{
Name: "html_escape",
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 {
return nil, tengo.ErrWrongNumArguments
return nil, xgo.ErrWrongNumArguments
}
switch o := args[0].(type) {
case *tengo.Bytes:
case *xgo.Bytes:
v, err := json.Decode(o.Value)
if err != nil {
return &tengo.Error{
Value: &tengo.String{Value: err.Error()},
return &xgo.Error{
Value: &xgo.String{Value: err.Error()},
}, nil
}
return v, nil
case *tengo.String:
case *xgo.String:
v, err := json.Decode([]byte(o.Value))
if err != nil {
return &tengo.Error{
Value: &tengo.String{Value: err.Error()},
return &xgo.Error{
Value: &xgo.String{Value: err.Error()},
}, nil
}
return v, nil
default:
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "bytes/string",
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 {
return nil, tengo.ErrWrongNumArguments
return nil, xgo.ErrWrongNumArguments
}
b, err := json.Encode(args[0])
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 {
return nil, tengo.ErrWrongNumArguments
return nil, xgo.ErrWrongNumArguments
}
prefix, ok := tengo.ToString(args[1])
prefix, ok := xgo.ToString(args[1])
if !ok {
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "prefix",
Expected: "string(compatible)",
Found: args[1].TypeName(),
}
}
indent, ok := tengo.ToString(args[2])
indent, ok := xgo.ToString(args[2])
if !ok {
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "indent",
Expected: "string(compatible)",
Found: args[2].TypeName(),
@ -95,26 +95,26 @@ func jsonIndent(args ...tengo.Object) (ret tengo.Object, err error) {
}
switch o := args[0].(type) {
case *tengo.Bytes:
case *xgo.Bytes:
var dst bytes.Buffer
err := gojson.Indent(&dst, o.Value, prefix, indent)
if err != nil {
return &tengo.Error{
Value: &tengo.String{Value: err.Error()},
return &xgo.Error{
Value: &xgo.String{Value: err.Error()},
}, nil
}
return &tengo.Bytes{Value: dst.Bytes()}, nil
case *tengo.String:
return &xgo.Bytes{Value: dst.Bytes()}, nil
case *xgo.String:
var dst bytes.Buffer
err := gojson.Indent(&dst, []byte(o.Value), prefix, indent)
if err != nil {
return &tengo.Error{
Value: &tengo.String{Value: err.Error()},
return &xgo.Error{
Value: &xgo.String{Value: err.Error()},
}, nil
}
return &tengo.Bytes{Value: dst.Bytes()}, nil
return &xgo.Bytes{Value: dst.Bytes()}, nil
default:
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "bytes/string",
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 {
return nil, tengo.ErrWrongNumArguments
return nil, xgo.ErrWrongNumArguments
}
switch o := args[0].(type) {
case *tengo.Bytes:
case *xgo.Bytes:
var dst bytes.Buffer
gojson.HTMLEscape(&dst, o.Value)
return &tengo.Bytes{Value: dst.Bytes()}, nil
case *tengo.String:
return &xgo.Bytes{Value: dst.Bytes()}, nil
case *xgo.String:
var dst bytes.Buffer
gojson.HTMLEscape(&dst, []byte(o.Value))
return &tengo.Bytes{Value: dst.Bytes()}, nil
return &xgo.Bytes{Value: dst.Bytes()}, nil
default:
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "bytes/string",
Found: args[0].TypeName(),

View file

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

View file

@ -14,7 +14,7 @@ import (
"strconv"
"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
@ -125,11 +125,11 @@ var safeSet = [utf8.RuneSelf]bool{
var hex = "0123456789abcdef"
// 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
switch o := o.(type) {
case *tengo.Array:
case *xgo.Array:
b = append(b, '[')
len1 := len(o.Value) - 1
for idx, elem := range o.Value {
@ -143,7 +143,7 @@ func Encode(o tengo.Object) ([]byte, error) {
}
}
b = append(b, ']')
case *tengo.ImmutableArray:
case *xgo.ImmutableArray:
b = append(b, '[')
len1 := len(o.Value) - 1
for idx, elem := range o.Value {
@ -157,7 +157,7 @@ func Encode(o tengo.Object) ([]byte, error) {
}
}
b = append(b, ']')
case *tengo.Map:
case *xgo.Map:
b = append(b, '{')
len1 := len(o.Value) - 1
idx := 0
@ -175,7 +175,7 @@ func Encode(o tengo.Object) ([]byte, error) {
idx++
}
b = append(b, '}')
case *tengo.ImmutableMap:
case *xgo.ImmutableMap:
b = append(b, '{')
len1 := len(o.Value) - 1
idx := 0
@ -193,22 +193,22 @@ func Encode(o tengo.Object) ([]byte, error) {
idx++
}
b = append(b, '}')
case *tengo.Bool:
case *xgo.Bool:
if o.IsFalsy() {
b = strconv.AppendBool(b, false)
} else {
b = strconv.AppendBool(b, true)
}
case *tengo.Bytes:
case *xgo.Bytes:
b = append(b, '"')
encodedLen := base64.StdEncoding.EncodedLen(len(o.Value))
dst := make([]byte, encodedLen)
base64.StdEncoding.Encode(dst, o.Value)
b = append(b, dst...)
b = append(b, '"')
case *tengo.Char:
case *xgo.Char:
b = strconv.AppendInt(b, int64(o.Value), 10)
case *tengo.Float:
case *xgo.Float:
var y []byte
f := o.Value
@ -236,19 +236,19 @@ func Encode(o tengo.Object) ([]byte, error) {
}
b = append(b, y...)
case *tengo.Int:
case *xgo.Int:
b = strconv.AppendInt(b, o.Value, 10)
case *tengo.String:
case *xgo.String:
// 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)
case *tengo.Time:
case *xgo.Time:
y, err := o.Value.MarshalJSON()
if err != nil {
return nil, err
}
b = append(b, y...)
case *tengo.Undefined:
case *xgo.Undefined:
b = append(b, "null"...)
default:
// unknown type: ignore

View file

@ -4,9 +4,9 @@ import (
gojson "encoding/json"
"testing"
"github.com/d5/tengo/v2"
"github.com/d5/tengo/v2/require"
"github.com/d5/tengo/v2/stdlib/json"
"surdeus.su/core/xgo/v2"
"surdeus.su/core/xgo/v2/require"
"surdeus.su/core/xgo/v2/stdlib/json"
)
type ARR = []interface{}
@ -31,7 +31,7 @@ func TestJSON(t *testing.T) {
testJSONEncodeDecode(t, "foo")
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, "çığöşü")
testJSONEncodeDecode(t, "ç1\u001C04IĞÖŞÜ")
@ -92,7 +92,7 @@ func testDecodeError(t *testing.T, input string) {
}
func testJSONEncodeDecode(t *testing.T, v interface{}) {
o, err := tengo.FromInterface(v)
o, err := xgo.FromInterface(v)
require.NoError(t, err)
b, err := json.Encode(o)
@ -104,7 +104,7 @@ func testJSONEncodeDecode(t *testing.T, v interface{}) {
vj, err := gojson.Marshal(v)
require.NoError(t, err)
aj, err := gojson.Marshal(tengo.ToInterface(a))
aj, err := gojson.Marshal(xgo.ToInterface(a))
require.NoError(t, err)
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 (
"math"
"github.com/d5/tengo/v2"
"surdeus.su/core/xgo/v2"
)
var mathModule = map[string]tengo.Object{
"e": &tengo.Float{Value: math.E},
"pi": &tengo.Float{Value: math.Pi},
"phi": &tengo.Float{Value: math.Phi},
"sqrt2": &tengo.Float{Value: math.Sqrt2},
"sqrtE": &tengo.Float{Value: math.SqrtE},
"sqrtPi": &tengo.Float{Value: math.SqrtPi},
"sqrtPhi": &tengo.Float{Value: math.SqrtPhi},
"ln2": &tengo.Float{Value: math.Ln2},
"log2E": &tengo.Float{Value: math.Log2E},
"ln10": &tengo.Float{Value: math.Ln10},
"log10E": &tengo.Float{Value: math.Log10E},
"maxFloat32": &tengo.Float{Value: math.MaxFloat32},
"smallestNonzeroFloat32": &tengo.Float{Value: math.SmallestNonzeroFloat32},
"maxFloat64": &tengo.Float{Value: math.MaxFloat64},
"smallestNonzeroFloat64": &tengo.Float{Value: math.SmallestNonzeroFloat64},
"maxInt": &tengo.Int{Value: math.MaxInt},
"minInt": &tengo.Int{Value: math.MinInt},
"maxInt8": &tengo.Int{Value: math.MaxInt8},
"minInt8": &tengo.Int{Value: math.MinInt8},
"maxInt16": &tengo.Int{Value: math.MaxInt16},
"minInt16": &tengo.Int{Value: math.MinInt16},
"maxInt32": &tengo.Int{Value: math.MaxInt32},
"minInt32": &tengo.Int{Value: math.MinInt32},
"maxInt64": &tengo.Int{Value: math.MaxInt64},
"minInt64": &tengo.Int{Value: math.MinInt64},
"abs": &tengo.UserFunction{
var mathModule = map[string]xgo.Object{
"e": &xgo.Float{Value: math.E},
"pi": &xgo.Float{Value: math.Pi},
"phi": &xgo.Float{Value: math.Phi},
"sqrt2": &xgo.Float{Value: math.Sqrt2},
"sqrtE": &xgo.Float{Value: math.SqrtE},
"sqrtPi": &xgo.Float{Value: math.SqrtPi},
"sqrtPhi": &xgo.Float{Value: math.SqrtPhi},
"ln2": &xgo.Float{Value: math.Ln2},
"log2E": &xgo.Float{Value: math.Log2E},
"ln10": &xgo.Float{Value: math.Ln10},
"log10E": &xgo.Float{Value: math.Log10E},
"maxFloat32": &xgo.Float{Value: math.MaxFloat32},
"smallestNonzeroFloat32": &xgo.Float{Value: math.SmallestNonzeroFloat32},
"maxFloat64": &xgo.Float{Value: math.MaxFloat64},
"smallestNonzeroFloat64": &xgo.Float{Value: math.SmallestNonzeroFloat64},
"maxInt": &xgo.Int{Value: math.MaxInt},
"minInt": &xgo.Int{Value: math.MinInt},
"maxInt8": &xgo.Int{Value: math.MaxInt8},
"minInt8": &xgo.Int{Value: math.MinInt8},
"maxInt16": &xgo.Int{Value: math.MaxInt16},
"minInt16": &xgo.Int{Value: math.MinInt16},
"maxInt32": &xgo.Int{Value: math.MaxInt32},
"minInt32": &xgo.Int{Value: math.MinInt32},
"maxInt64": &xgo.Int{Value: math.MaxInt64},
"minInt64": &xgo.Int{Value: math.MinInt64},
"abs": &xgo.UserFunction{
Name: "abs",
Value: FuncAFRF(math.Abs),
},
"acos": &tengo.UserFunction{
"acos": &xgo.UserFunction{
Name: "acos",
Value: FuncAFRF(math.Acos),
},
"acosh": &tengo.UserFunction{
"acosh": &xgo.UserFunction{
Name: "acosh",
Value: FuncAFRF(math.Acosh),
},
"asin": &tengo.UserFunction{
"asin": &xgo.UserFunction{
Name: "asin",
Value: FuncAFRF(math.Asin),
},
"asinh": &tengo.UserFunction{
"asinh": &xgo.UserFunction{
Name: "asinh",
Value: FuncAFRF(math.Asinh),
},
"atan": &tengo.UserFunction{
"atan": &xgo.UserFunction{
Name: "atan",
Value: FuncAFRF(math.Atan),
},
"atan2": &tengo.UserFunction{
"atan2": &xgo.UserFunction{
Name: "atan2",
Value: FuncAFFRF(math.Atan2),
},
"atanh": &tengo.UserFunction{
"atanh": &xgo.UserFunction{
Name: "atanh",
Value: FuncAFRF(math.Atanh),
},
"cbrt": &tengo.UserFunction{
"cbrt": &xgo.UserFunction{
Name: "cbrt",
Value: FuncAFRF(math.Cbrt),
},
"ceil": &tengo.UserFunction{
"ceil": &xgo.UserFunction{
Name: "ceil",
Value: FuncAFRF(math.Ceil),
},
"copysign": &tengo.UserFunction{
"copysign": &xgo.UserFunction{
Name: "copysign",
Value: FuncAFFRF(math.Copysign),
},
"cos": &tengo.UserFunction{
"cos": &xgo.UserFunction{
Name: "cos",
Value: FuncAFRF(math.Cos),
},
"cosh": &tengo.UserFunction{
"cosh": &xgo.UserFunction{
Name: "cosh",
Value: FuncAFRF(math.Cosh),
},
"dim": &tengo.UserFunction{
"dim": &xgo.UserFunction{
Name: "dim",
Value: FuncAFFRF(math.Dim),
},
"erf": &tengo.UserFunction{
"erf": &xgo.UserFunction{
Name: "erf",
Value: FuncAFRF(math.Erf),
},
"erfc": &tengo.UserFunction{
"erfc": &xgo.UserFunction{
Name: "erfc",
Value: FuncAFRF(math.Erfc),
},
"exp": &tengo.UserFunction{
"exp": &xgo.UserFunction{
Name: "exp",
Value: FuncAFRF(math.Exp),
},
"exp2": &tengo.UserFunction{
"exp2": &xgo.UserFunction{
Name: "exp2",
Value: FuncAFRF(math.Exp2),
},
"expm1": &tengo.UserFunction{
"expm1": &xgo.UserFunction{
Name: "expm1",
Value: FuncAFRF(math.Expm1),
},
"floor": &tengo.UserFunction{
"floor": &xgo.UserFunction{
Name: "floor",
Value: FuncAFRF(math.Floor),
},
"gamma": &tengo.UserFunction{
"gamma": &xgo.UserFunction{
Name: "gamma",
Value: FuncAFRF(math.Gamma),
},
"hypot": &tengo.UserFunction{
"hypot": &xgo.UserFunction{
Name: "hypot",
Value: FuncAFFRF(math.Hypot),
},
"ilogb": &tengo.UserFunction{
"ilogb": &xgo.UserFunction{
Name: "ilogb",
Value: FuncAFRI(math.Ilogb),
},
"inf": &tengo.UserFunction{
"inf": &xgo.UserFunction{
Name: "inf",
Value: FuncAIRF(math.Inf),
},
"is_inf": &tengo.UserFunction{
"is_inf": &xgo.UserFunction{
Name: "is_inf",
Value: FuncAFIRB(math.IsInf),
},
"is_nan": &tengo.UserFunction{
"is_nan": &xgo.UserFunction{
Name: "is_nan",
Value: FuncAFRB(math.IsNaN),
},
"j0": &tengo.UserFunction{
"j0": &xgo.UserFunction{
Name: "j0",
Value: FuncAFRF(math.J0),
},
"j1": &tengo.UserFunction{
"j1": &xgo.UserFunction{
Name: "j1",
Value: FuncAFRF(math.J1),
},
"jn": &tengo.UserFunction{
"jn": &xgo.UserFunction{
Name: "jn",
Value: FuncAIFRF(math.Jn),
},
"ldexp": &tengo.UserFunction{
"ldexp": &xgo.UserFunction{
Name: "ldexp",
Value: FuncAFIRF(math.Ldexp),
},
"log": &tengo.UserFunction{
"log": &xgo.UserFunction{
Name: "log",
Value: FuncAFRF(math.Log),
},
"log10": &tengo.UserFunction{
"log10": &xgo.UserFunction{
Name: "log10",
Value: FuncAFRF(math.Log10),
},
"log1p": &tengo.UserFunction{
"log1p": &xgo.UserFunction{
Name: "log1p",
Value: FuncAFRF(math.Log1p),
},
"log2": &tengo.UserFunction{
"log2": &xgo.UserFunction{
Name: "log2",
Value: FuncAFRF(math.Log2),
},
"logb": &tengo.UserFunction{
"logb": &xgo.UserFunction{
Name: "logb",
Value: FuncAFRF(math.Logb),
},
"max": &tengo.UserFunction{
"max": &xgo.UserFunction{
Name: "max",
Value: FuncAFFRF(math.Max),
},
"min": &tengo.UserFunction{
"min": &xgo.UserFunction{
Name: "min",
Value: FuncAFFRF(math.Min),
},
"mod": &tengo.UserFunction{
"mod": &xgo.UserFunction{
Name: "mod",
Value: FuncAFFRF(math.Mod),
},
"nan": &tengo.UserFunction{
"nan": &xgo.UserFunction{
Name: "nan",
Value: FuncARF(math.NaN),
},
"nextafter": &tengo.UserFunction{
"nextafter": &xgo.UserFunction{
Name: "nextafter",
Value: FuncAFFRF(math.Nextafter),
},
"pow": &tengo.UserFunction{
"pow": &xgo.UserFunction{
Name: "pow",
Value: FuncAFFRF(math.Pow),
},
"pow10": &tengo.UserFunction{
"pow10": &xgo.UserFunction{
Name: "pow10",
Value: FuncAIRF(math.Pow10),
},
"remainder": &tengo.UserFunction{
"remainder": &xgo.UserFunction{
Name: "remainder",
Value: FuncAFFRF(math.Remainder),
},
"signbit": &tengo.UserFunction{
"signbit": &xgo.UserFunction{
Name: "signbit",
Value: FuncAFRB(math.Signbit),
},
"sin": &tengo.UserFunction{
"sin": &xgo.UserFunction{
Name: "sin",
Value: FuncAFRF(math.Sin),
},
"sinh": &tengo.UserFunction{
"sinh": &xgo.UserFunction{
Name: "sinh",
Value: FuncAFRF(math.Sinh),
},
"sqrt": &tengo.UserFunction{
"sqrt": &xgo.UserFunction{
Name: "sqrt",
Value: FuncAFRF(math.Sqrt),
},
"tan": &tengo.UserFunction{
"tan": &xgo.UserFunction{
Name: "tan",
Value: FuncAFRF(math.Tan),
},
"tanh": &tengo.UserFunction{
"tanh": &xgo.UserFunction{
Name: "tanh",
Value: FuncAFRF(math.Tanh),
},
"trunc": &tengo.UserFunction{
"trunc": &xgo.UserFunction{
Name: "trunc",
Value: FuncAFRF(math.Trunc),
},
"y0": &tengo.UserFunction{
"y0": &xgo.UserFunction{
Name: "y0",
Value: FuncAFRF(math.Y0),
},
"y1": &tengo.UserFunction{
"y1": &xgo.UserFunction{
Name: "y1",
Value: FuncAFRF(math.Y1),
},
"yn": &tengo.UserFunction{
"yn": &xgo.UserFunction{
Name: "yn",
Value: FuncAIFRF(math.Yn),
},

View file

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

View file

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

View file

@ -3,67 +3,67 @@ package stdlib
import (
"os"
"github.com/d5/tengo/v2"
"surdeus.su/core/xgo/v2"
)
func makeOSFile(file *os.File) *tengo.ImmutableMap {
return &tengo.ImmutableMap{
Value: map[string]tengo.Object{
func makeOSFile(file *os.File) *xgo.ImmutableMap {
return &xgo.ImmutableMap{
Value: map[string]xgo.Object{
// chdir() => true/error
"chdir": &tengo.UserFunction{
"chdir": &xgo.UserFunction{
Name: "chdir",
Value: FuncARE(file.Chdir),
}, //
// chown(uid int, gid int) => true/error
"chown": &tengo.UserFunction{
"chown": &xgo.UserFunction{
Name: "chown",
Value: FuncAIIRE(file.Chown),
}, //
// close() => error
"close": &tengo.UserFunction{
"close": &xgo.UserFunction{
Name: "close",
Value: FuncARE(file.Close),
}, //
// name() => string
"name": &tengo.UserFunction{
"name": &xgo.UserFunction{
Name: "name",
Value: FuncARS(file.Name),
}, //
// readdirnames(n int) => array(string)/error
"readdirnames": &tengo.UserFunction{
"readdirnames": &xgo.UserFunction{
Name: "readdirnames",
Value: FuncAIRSsE(file.Readdirnames),
}, //
// sync() => error
"sync": &tengo.UserFunction{
"sync": &xgo.UserFunction{
Name: "sync",
Value: FuncARE(file.Sync),
}, //
// write(bytes) => int/error
"write": &tengo.UserFunction{
"write": &xgo.UserFunction{
Name: "write",
Value: FuncAYRIE(file.Write),
}, //
// write(string) => int/error
"write_string": &tengo.UserFunction{
"write_string": &xgo.UserFunction{
Name: "write_string",
Value: FuncASRIE(file.WriteString),
}, //
// read(bytes) => int/error
"read": &tengo.UserFunction{
"read": &xgo.UserFunction{
Name: "read",
Value: FuncAYRIE(file.Read),
}, //
// chmod(mode int) => error
"chmod": &tengo.UserFunction{
"chmod": &xgo.UserFunction{
Name: "chmod",
Value: func(args ...tengo.Object) (tengo.Object, error) {
Value: func(args ...xgo.Object) (xgo.Object, error) {
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 {
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "int(compatible)",
Found: args[0].TypeName(),
@ -73,23 +73,23 @@ func makeOSFile(file *os.File) *tengo.ImmutableMap {
},
},
// seek(offset int, whence int) => int/error
"seek": &tengo.UserFunction{
"seek": &xgo.UserFunction{
Name: "seek",
Value: func(args ...tengo.Object) (tengo.Object, error) {
Value: func(args ...xgo.Object) (xgo.Object, error) {
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 {
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "int(compatible)",
Found: args[0].TypeName(),
}
}
i2, ok := tengo.ToInt(args[1])
i2, ok := xgo.ToInt(args[1])
if !ok {
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "second",
Expected: "int(compatible)",
Found: args[1].TypeName(),
@ -99,17 +99,17 @@ func makeOSFile(file *os.File) *tengo.ImmutableMap {
if err != nil {
return wrapError(err), nil
}
return &tengo.Int{Value: res}, nil
return &xgo.Int{Value: res}, nil
},
},
// stat() => imap(fileinfo)/error
"stat": &tengo.UserFunction{
"stat": &xgo.UserFunction{
Name: "stat",
Value: func(args ...tengo.Object) (tengo.Object, error) {
Value: func(args ...xgo.Object) (xgo.Object, error) {
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"
"syscall"
"github.com/d5/tengo/v2"
"surdeus.su/core/xgo/v2"
)
func makeOSProcessState(state *os.ProcessState) *tengo.ImmutableMap {
return &tengo.ImmutableMap{
Value: map[string]tengo.Object{
"exited": &tengo.UserFunction{
func makeOSProcessState(state *os.ProcessState) *xgo.ImmutableMap {
return &xgo.ImmutableMap{
Value: map[string]xgo.Object{
"exited": &xgo.UserFunction{
Name: "exited",
Value: FuncARB(state.Exited),
},
"pid": &tengo.UserFunction{
"pid": &xgo.UserFunction{
Name: "pid",
Value: FuncARI(state.Pid),
},
"string": &tengo.UserFunction{
"string": &xgo.UserFunction{
Name: "string",
Value: FuncARS(state.String),
},
"success": &tengo.UserFunction{
"success": &xgo.UserFunction{
Name: "success",
Value: FuncARB(state.Success),
},
@ -30,26 +30,26 @@ func makeOSProcessState(state *os.ProcessState) *tengo.ImmutableMap {
}
}
func makeOSProcess(proc *os.Process) *tengo.ImmutableMap {
return &tengo.ImmutableMap{
Value: map[string]tengo.Object{
"kill": &tengo.UserFunction{
func makeOSProcess(proc *os.Process) *xgo.ImmutableMap {
return &xgo.ImmutableMap{
Value: map[string]xgo.Object{
"kill": &xgo.UserFunction{
Name: "kill",
Value: FuncARE(proc.Kill),
},
"release": &tengo.UserFunction{
"release": &xgo.UserFunction{
Name: "release",
Value: FuncARE(proc.Release),
},
"signal": &tengo.UserFunction{
"signal": &xgo.UserFunction{
Name: "signal",
Value: func(args ...tengo.Object) (tengo.Object, error) {
Value: func(args ...xgo.Object) (xgo.Object, error) {
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 {
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "int(compatible)",
Found: args[0].TypeName(),
@ -58,11 +58,11 @@ func makeOSProcess(proc *os.Process) *tengo.ImmutableMap {
return wrapError(proc.Signal(syscall.Signal(i1))), nil
},
},
"wait": &tengo.UserFunction{
"wait": &xgo.UserFunction{
Name: "wait",
Value: func(args ...tengo.Object) (tengo.Object, error) {
Value: func(args ...xgo.Object) (xgo.Object, error) {
if len(args) != 0 {
return nil, tengo.ErrWrongNumArguments
return nil, xgo.ErrWrongNumArguments
}
state, err := proc.Wait()
if err != nil {

View file

@ -5,8 +5,8 @@ import (
"os"
"testing"
"github.com/d5/tengo/v2"
"github.com/d5/tengo/v2/require"
"surdeus.su/core/xgo/v2"
"surdeus.su/core/xgo/v2/require"
)
func TestReadFile(t *testing.T) {
@ -20,7 +20,7 @@ func TestReadFile(t *testing.T) {
_ = tf.Close()
module(t, "os").call("read_file", tf.Name()).
expect(&tengo.Bytes{Value: content})
expect(&xgo.Bytes{Value: content})
}
func TestReadFileArgs(t *testing.T) {
@ -46,13 +46,13 @@ func TestFileStatFile(t *testing.T) {
return
}
module(t, "os").call("stat", tf.Name()).expect(&tengo.ImmutableMap{
Value: map[string]tengo.Object{
"name": &tengo.String{Value: stat.Name()},
"mtime": &tengo.Time{Value: stat.ModTime()},
"size": &tengo.Int{Value: stat.Size()},
"mode": &tengo.Int{Value: int64(stat.Mode())},
"directory": tengo.FalseValue,
module(t, "os").call("stat", tf.Name()).expect(&xgo.ImmutableMap{
Value: map[string]xgo.Object{
"name": &xgo.String{Value: stat.Name()},
"mtime": &xgo.Time{Value: stat.ModTime()},
"size": &xgo.Int{Value: stat.Size()},
"mode": &xgo.Int{Value: int64(stat.Mode())},
"directory": xgo.FalseValue,
},
})
}
@ -65,21 +65,21 @@ func TestFileStatDir(t *testing.T) {
stat, err := os.Stat(td)
require.NoError(t, err)
module(t, "os").call("stat", td).expect(&tengo.ImmutableMap{
Value: map[string]tengo.Object{
"name": &tengo.String{Value: stat.Name()},
"mtime": &tengo.Time{Value: stat.ModTime()},
"size": &tengo.Int{Value: stat.Size()},
"mode": &tengo.Int{Value: int64(stat.Mode())},
"directory": tengo.TrueValue,
module(t, "os").call("stat", td).expect(&xgo.ImmutableMap{
Value: map[string]xgo.Object{
"name": &xgo.String{Value: stat.Name()},
"mtime": &xgo.Time{Value: stat.ModTime()},
"size": &xgo.Int{Value: stat.Size()},
"mode": &xgo.Int{Value: int64(stat.Mode())},
"directory": xgo.TrueValue,
},
})
}
func TestOSExpandEnv(t *testing.T) {
curMaxStringLen := tengo.MaxStringLen
defer func() { tengo.MaxStringLen = curMaxStringLen }()
tengo.MaxStringLen = 12
curMaxStringLen := xgo.MaxStringLen
defer func() { xgo.MaxStringLen = curMaxStringLen }()
xgo.MaxStringLen = 12
_ = os.Setenv("TENGO", "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 (
"math/rand"
"github.com/d5/tengo/v2"
"surdeus.su/core/xgo/v2"
)
var randModule = map[string]tengo.Object{
"int": &tengo.UserFunction{
var randModule = map[string]xgo.Object{
"int": &xgo.UserFunction{
Name: "int",
Value: FuncARI64(rand.Int63),
},
"float": &tengo.UserFunction{
"float": &xgo.UserFunction{
Name: "float",
Value: FuncARF(rand.Float64),
},
"intn": &tengo.UserFunction{
"intn": &xgo.UserFunction{
Name: "intn",
Value: FuncAI64RI64(rand.Int63n),
},
"exp_float": &tengo.UserFunction{
"exp_float": &xgo.UserFunction{
Name: "exp_float",
Value: FuncARF(rand.ExpFloat64),
},
"norm_float": &tengo.UserFunction{
"norm_float": &xgo.UserFunction{
Name: "norm_float",
Value: FuncARF(rand.NormFloat64),
},
"perm": &tengo.UserFunction{
"perm": &xgo.UserFunction{
Name: "perm",
Value: FuncAIRIs(rand.Perm),
},
"seed": &tengo.UserFunction{
"seed": &xgo.UserFunction{
Name: "seed",
Value: FuncAI64R(rand.Seed),
},
"read": &tengo.UserFunction{
"read": &xgo.UserFunction{
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 {
return nil, tengo.ErrWrongNumArguments
return nil, xgo.ErrWrongNumArguments
}
y1, ok := args[0].(*tengo.Bytes)
y1, ok := args[0].(*xgo.Bytes)
if !ok {
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "bytes",
Found: args[0].TypeName(),
@ -54,18 +54,18 @@ var randModule = map[string]tengo.Object{
ret = wrapError(err)
return
}
return &tengo.Int{Value: int64(res)}, nil
return &xgo.Int{Value: int64(res)}, nil
},
},
"rand": &tengo.UserFunction{
"rand": &xgo.UserFunction{
Name: "rand",
Value: func(args ...tengo.Object) (tengo.Object, error) {
Value: func(args ...xgo.Object) (xgo.Object, error) {
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 {
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "int(compatible)",
Found: args[0].TypeName(),
@ -77,49 +77,49 @@ var randModule = map[string]tengo.Object{
},
}
func randRand(r *rand.Rand) *tengo.ImmutableMap {
return &tengo.ImmutableMap{
Value: map[string]tengo.Object{
"int": &tengo.UserFunction{
func randRand(r *rand.Rand) *xgo.ImmutableMap {
return &xgo.ImmutableMap{
Value: map[string]xgo.Object{
"int": &xgo.UserFunction{
Name: "int",
Value: FuncARI64(r.Int63),
},
"float": &tengo.UserFunction{
"float": &xgo.UserFunction{
Name: "float",
Value: FuncARF(r.Float64),
},
"intn": &tengo.UserFunction{
"intn": &xgo.UserFunction{
Name: "intn",
Value: FuncAI64RI64(r.Int63n),
},
"exp_float": &tengo.UserFunction{
"exp_float": &xgo.UserFunction{
Name: "exp_float",
Value: FuncARF(r.ExpFloat64),
},
"norm_float": &tengo.UserFunction{
"norm_float": &xgo.UserFunction{
Name: "norm_float",
Value: FuncARF(r.NormFloat64),
},
"perm": &tengo.UserFunction{
"perm": &xgo.UserFunction{
Name: "perm",
Value: FuncAIRIs(r.Perm),
},
"seed": &tengo.UserFunction{
"seed": &xgo.UserFunction{
Name: "seed",
Value: FuncAI64R(r.Seed),
},
"read": &tengo.UserFunction{
"read": &xgo.UserFunction{
Name: "read",
Value: func(args ...tengo.Object) (
ret tengo.Object,
Value: func(args ...xgo.Object) (
ret xgo.Object,
err error,
) {
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 {
return nil, tengo.ErrInvalidArgumentType{
return nil, xgo.ErrInvalidArgumentType{
Name: "first",
Expected: "bytes",
Found: args[0].TypeName(),
@ -130,7 +130,7 @@ func randRand(r *rand.Rand) *tengo.ImmutableMap {
ret = wrapError(err)
return
}
return &tengo.Int{Value: int64(res)}, nil
return &xgo.Int{Value: int64(res)}, nil
},
},
},

View file

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

View file

@ -2,7 +2,13 @@
package stdlib
import "embed"
var _ = embed.FS{}
//go:embed srcmod_enum.xgo
var srcmodEnum string
// SourceModules are source type standard library modules.
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
import (
"github.com/d5/tengo/v2"
"surdeus.su/core/xgo/v2"
)
// 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
// for the given module names.
func GetModuleMap(names ...string) *tengo.ModuleMap {
modules := tengo.NewModuleMap()
func GetModuleMap(names ...string) *xgo.ModuleMap {
modules := xgo.NewModuleMap()
for _, name := range names {
if mod := BuiltinModules[name]; mod != nil {
modules.AddBuiltinModule(name, mod)

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -4,8 +4,8 @@ import (
"testing"
"time"
"github.com/d5/tengo/v2"
"github.com/d5/tengo/v2/require"
"surdeus.su/core/xgo/v2"
"surdeus.su/core/xgo/v2/require"
)
func TestTimes(t *testing.T) {
@ -14,14 +14,14 @@ func TestTimes(t *testing.T) {
location, _ := time.LoadLocation("Pacific/Auckland")
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").
call("since", time.Now().Add(-time.Hour)).
o.(*tengo.Int).Value > 3600000000000)
o.(*xgo.Int).Value > 3600000000000)
require.True(t, module(t, "times").
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", "1ms").expect(1000000)
@ -41,7 +41,7 @@ func TestTimes(t *testing.T) {
expect(time3)
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
parsed, _ := time.Parse(time.RFC3339, "1982-09-28T19:21:44+07:00")
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.
type SymbolScope string

View file

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

View file

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

View file

@ -1,13 +1,13 @@
package tengo_test
package xgo_test
import (
"strings"
"testing"
"time"
"github.com/d5/tengo/v2"
"github.com/d5/tengo/v2/parser"
"github.com/d5/tengo/v2/require"
"surdeus.su/core/xgo/v2"
"surdeus.su/core/xgo/v2/parser"
"surdeus.su/core/xgo/v2/require"
)
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 (
"errors"

View file

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

6
vm.go
View file

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

View file

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