Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
544 changes: 159 additions & 385 deletions builtins.go

Large diffs are not rendered by default.

80 changes: 52 additions & 28 deletions builtins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,32 +33,48 @@ func Test_builtinDelete(t *testing.T) {
{name: "invalid-arg", args: args{[]tengo.Object{&tengo.String{},
&tengo.String{}}}, wantErr: true,
wantedErr: tengo.ErrInvalidArgumentType{
Name: "first",
Index: 0,
Expected: "map",
Found: "string"},
Actual: "string"},
},
{name: "no-args",
wantErr: true, wantedErr: tengo.ErrWrongNumArguments},
{name: "empty-args", args: args{[]tengo.Object{}}, wantErr: true,
wantedErr: tengo.ErrWrongNumArguments,
{name: "no-args", wantErr: true,
wantedErr: tengo.ErrInvalidArgumentCount{Min: 2, Max: 2, Actual: 0},
},
{name: "3-args", args: args{[]tengo.Object{
(*tengo.Map)(nil), (*tengo.String)(nil), (*tengo.String)(nil)}},
wantErr: true, wantedErr: tengo.ErrWrongNumArguments,
{
name: "empty-args",
args: args{[]tengo.Object{}},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentCount{Min: 2, Max: 2, Actual: 0},
},
{
name: "3-args",
args: args{[]tengo.Object{
(*tengo.Map)(nil), (*tengo.String)(nil), (*tengo.String)(nil)},
},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentCount{Min: 2, Max: 2, Actual: 3},
},
{name: "nil-map-empty-key-int",
args: args{[]tengo.Object{&tengo.Map{}, &tengo.String{}, &tengo.Int{}}},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentCount{Min: 2, Max: 2, Actual: 3},
},
{name: "nil-map-empty-key",
args: args{[]tengo.Object{&tengo.Map{}, &tengo.String{}}},
want: tengo.UndefinedValue,
},
{name: "nil-map-nonstr-key",
{
name: "nil-map-nonstr-key",
args: args{[]tengo.Object{
&tengo.Map{}, &tengo.Int{}}}, wantErr: true,
wantedErr: tengo.ErrInvalidArgumentType{
Name: "second", Expected: "string", Found: "int"},
&tengo.Map{}, &tengo.Int{}}},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentType{Index: 1, Expected: tengo.StringTN, Actual: tengo.IntTN},
},
{name: "nil-map-no-key",
args: args{[]tengo.Object{&tengo.Map{}}}, wantErr: true,
wantedErr: tengo.ErrWrongNumArguments,
{
name: "nil-map-no-key",
args: args{[]tengo.Object{&tengo.Map{}}},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentCount{Min: 2, Max: 2, Actual: 1},
},
{name: "map-missing-key",
args: args{
Expand Down Expand Up @@ -152,18 +168,20 @@ func Test_builtinSplice(t *testing.T) {
wantedErr error
}{
{name: "no args", args: []tengo.Object{}, wantErr: true,
wantedErr: tengo.ErrWrongNumArguments,
wantedErr: tengo.ErrInvalidArgumentCount{
Min: 1, Max: -1, Actual: 0,
},
},
{name: "invalid args", args: []tengo.Object{&tengo.Map{}},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentType{
Name: "first", Expected: "array", Found: "map"},
Index: 0, Expected: tengo.ArrayTN, Actual: tengo.MapTN},
},
{name: "invalid args",
args: []tengo.Object{&tengo.Array{}, &tengo.String{}},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentType{
Name: "second", Expected: "int", Found: "string"},
Index: 1, Expected: tengo.IntTN, Actual: tengo.StringTN},
},
{name: "negative index",
args: []tengo.Object{&tengo.Array{}, &tengo.Int{Value: -1}},
Expand All @@ -175,7 +193,7 @@ func Test_builtinSplice(t *testing.T) {
&tengo.String{Value: ""}},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentType{
Name: "third", Expected: "int", Found: "string"},
Index: 2, Expected: tengo.IntTN, Actual: tengo.StringTN},
},
{name: "negative count",
args: []tengo.Object{
Expand Down Expand Up @@ -371,33 +389,39 @@ func Test_builtinRange(t *testing.T) {
wantedErr error
}{
{name: "no args", args: []tengo.Object{}, wantErr: true,
wantedErr: tengo.ErrWrongNumArguments,
wantedErr: tengo.ErrInvalidArgumentCount{
Min: 2, Max: 3, Actual: 0,
},
},
{name: "single args", args: []tengo.Object{&tengo.Map{}},
wantErr: true,
wantedErr: tengo.ErrWrongNumArguments,
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentCount{
Min: 2, Max: 3, Actual: 1,
},
},
{name: "4 args", args: []tengo.Object{&tengo.Map{}, &tengo.String{}, &tengo.String{}, &tengo.String{}},
wantErr: true,
wantedErr: tengo.ErrWrongNumArguments,
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentCount{
Min: 2, Max: 3, Actual: 4,
},
},
{name: "invalid start",
args: []tengo.Object{&tengo.String{}, &tengo.String{}},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentType{
Name: "start", Expected: "int", Found: "string"},
Index: 0, Expected: tengo.IntTN, Actual: tengo.StringTN},
},
{name: "invalid stop",
args: []tengo.Object{&tengo.Int{}, &tengo.String{}},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentType{
Name: "stop", Expected: "int", Found: "string"},
Index: 1, Expected: tengo.IntTN, Actual: tengo.StringTN},
},
{name: "invalid step",
args: []tengo.Object{&tengo.Int{}, &tengo.Int{}, &tengo.String{}},
wantErr: true,
wantedErr: tengo.ErrInvalidArgumentType{
Name: "step", Expected: "int", Found: "string"},
Index: 2, Expected: tengo.IntTN, Actual: tengo.StringTN},
},
{name: "zero step",
args: []tengo.Object{&tengo.Int{}, &tengo.Int{}, &tengo.Int{}}, //must greate than 0
Expand Down
36 changes: 17 additions & 19 deletions cmd/tengo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@ func CompileOnly(
modules *tengo.ModuleMap,
data []byte,
inputFile, outputFile string,
) (err error) {
) error {
bytecode, err := compileSrc(modules, data, inputFile)
if err != nil {
return
return err
}

if outputFile == "" {
Expand All @@ -111,7 +111,7 @@ func CompileOnly(

out, err := os.OpenFile(outputFile, os.O_CREATE|os.O_WRONLY, os.ModePerm)
if err != nil {
return
return err
}
defer func() {
if err != nil {
Expand All @@ -123,39 +123,37 @@ func CompileOnly(

err = bytecode.Encode(out)
if err != nil {
return
return err
}
fmt.Println(outputFile)
return
return err
}

// CompileAndRun compiles the source code and executes it.
func CompileAndRun(
modules *tengo.ModuleMap,
data []byte,
inputFile string,
) (err error) {
) error {
bytecode, err := compileSrc(modules, data, inputFile)
if err != nil {
return
return err
}

machine := tengo.NewVM(bytecode, nil, -1)
err = machine.Run()
return
return machine.Run()
}

// RunCompiled reads the compiled binary from file and executes it.
func RunCompiled(modules *tengo.ModuleMap, data []byte) (err error) {
func RunCompiled(modules *tengo.ModuleMap, data []byte) error {
bytecode := &tengo.Bytecode{}
err = bytecode.Decode(bytes.NewReader(data), modules)
err := bytecode.Decode(bytes.NewReader(data), modules)
if err != nil {
return
return err
}

machine := tengo.NewVM(bytecode, nil, -1)
err = machine.Run()
return
return machine.Run()
}

// RunREPL starts REPL.
Expand All @@ -172,19 +170,19 @@ func RunREPL(modules *tengo.ModuleMap, in io.Reader, out io.Writer) {
symbol := symbolTable.Define("__repl_println__")
globals[symbol.Index] = &tengo.UserFunction{
Name: "println",
Value: func(args ...tengo.Object) (ret tengo.Object, err error) {
Value: func(args ...tengo.Object) (tengo.Object, error) {
var printArgs []interface{}
for _, arg := range args {
if _, isUndefined := arg.(*tengo.Undefined); isUndefined {
for i := range args {
if _, isUndefined := args[i].(*tengo.Undefined); isUndefined {
printArgs = append(printArgs, "<undefined>")
} else {
s, _ := tengo.ToString(arg)
s, _ := tengo.ToString(i, args...)
printArgs = append(printArgs, s)
}
}
printArgs = append(printArgs, "\n")
_, _ = fmt.Print(printArgs...)
return
return nil, nil
},
}

Expand Down
14 changes: 6 additions & 8 deletions compiler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1296,15 +1296,15 @@ type compileTracer struct {
Out []string
}

func (o *compileTracer) Write(p []byte) (n int, err error) {
func (o *compileTracer) Write(p []byte) (int, error) {
o.Out = append(o.Out, string(p))
return len(p), nil
}

func traceCompile(
input string,
symbols map[string]tengo.Object,
) (res *tengo.Bytecode, trace []string, err error) {
) (*tengo.Bytecode, []string, error) {
fileSet := parser.NewFileSet()
file := fileSet.AddFile("test", -1, len(input))

Expand All @@ -1322,11 +1322,12 @@ func traceCompile(
c := tengo.NewCompiler(file, symTable, nil, nil, tr)
parsed, err := p.ParseFile()
if err != nil {
return
return nil, nil, err
}

err = c.Compile(parsed)
res = c.Bytecode()
var trace []string
res := c.Bytecode()
res.RemoveDuplicates()
{
trace = append(trace, fmt.Sprintf("Compiler Trace:\n%s",
Expand All @@ -1336,10 +1337,7 @@ func traceCompile(
trace = append(trace, fmt.Sprintf("Compiled Instructions:\n%s\n",
strings.Join(res.FormatInstructions(), "\n")))
}
if err != nil {
return
}
return
return res, trace, err
}

func objectsArray(o ...tengo.Object) []tengo.Object {
Expand Down
43 changes: 18 additions & 25 deletions docs/objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,12 @@ type StringArray struct {
Value []string
}

const StringArrayTN = "string-array"

func (o *StringArray) TypeName() string {
return StringArrayTN
}

func (o *StringArray) String() string {
return strings.Join(o.Value, ", ")
}
Expand Down Expand Up @@ -283,10 +289,6 @@ func (o *StringArray) Copy() tengo.Object {
Value: append([]string{}, o.Value...),
}
}

func (o *StringArray) TypeName() string {
return "string-array"
}
```

You can use a user type via either
Expand Down Expand Up @@ -359,27 +361,16 @@ func (o *StringArray) CanCall() bool {
return true
}

func (o *StringArray) Call(args ...tengo.Object) (ret tengo.Object, err error) {
if len(args) != 1 {
return nil, tengo.ErrWrongNumArguments
}

s1, ok := tengo.ToString(args[0])
if !ok {
return nil, tengo.ErrInvalidArgumentType{
Name: "first",
Expected: "string",
Found: args[0].TypeName(),
}
}

for i, v := range o.Value {
if v == s1 {
return &tengo.Int{Value: int64(i)}, nil
func (o *StringArray) Call(args ...tengo.Object) (tengo.Object, error) {
return tengo.CheckStrictArgs(func(args ...tengo.Object) (tengo.Object, error){
s1, _ := tengo.ToString(0, args...)
for i, v := range o.Value {
if v == s1 {
return &tengo.Int{Value: int64(i)}, nil
}
}
}

return tengo.UndefinedValue, nil
return tengo.UndefinedValue, nil
}, tengo.StringTN)(args...)
}
```

Expand Down Expand Up @@ -414,8 +405,10 @@ type StringArrayIterator struct {
idx int
}

const StringArrayIteratorTN = "string-array-iterator"

func (i *StringArrayIterator) TypeName() string {
return "string-array-iterator"
return StringArrayIteratorTN
}

func (i *StringArrayIterator) Next() bool {
Expand Down
Loading