Skip to content

Commit 26cd5e3

Browse files
committed
dry-er type checking
1 parent ac80580 commit 26cd5e3

30 files changed

+2149
-3673
lines changed

builtins.go

Lines changed: 159 additions & 385 deletions
Large diffs are not rendered by default.

builtins_test.go

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,32 +33,48 @@ func Test_builtinDelete(t *testing.T) {
3333
{name: "invalid-arg", args: args{[]tengo.Object{&tengo.String{},
3434
&tengo.String{}}}, wantErr: true,
3535
wantedErr: tengo.ErrInvalidArgumentType{
36-
Name: "first",
36+
Index: 0,
3737
Expected: "map",
38-
Found: "string"},
38+
Actual: "string"},
3939
},
40-
{name: "no-args",
41-
wantErr: true, wantedErr: tengo.ErrWrongNumArguments},
42-
{name: "empty-args", args: args{[]tengo.Object{}}, wantErr: true,
43-
wantedErr: tengo.ErrWrongNumArguments,
40+
{name: "no-args", wantErr: true,
41+
wantedErr: tengo.ErrInvalidArgumentCount{Min: 2, Max: 2, Actual: 0},
4442
},
45-
{name: "3-args", args: args{[]tengo.Object{
46-
(*tengo.Map)(nil), (*tengo.String)(nil), (*tengo.String)(nil)}},
47-
wantErr: true, wantedErr: tengo.ErrWrongNumArguments,
43+
{
44+
name: "empty-args",
45+
args: args{[]tengo.Object{}},
46+
wantErr: true,
47+
wantedErr: tengo.ErrInvalidArgumentCount{Min: 2, Max: 2, Actual: 0},
48+
},
49+
{
50+
name: "3-args",
51+
args: args{[]tengo.Object{
52+
(*tengo.Map)(nil), (*tengo.String)(nil), (*tengo.String)(nil)},
53+
},
54+
wantErr: true,
55+
wantedErr: tengo.ErrInvalidArgumentCount{Min: 2, Max: 2, Actual: 3},
56+
},
57+
{name: "nil-map-empty-key-int",
58+
args: args{[]tengo.Object{&tengo.Map{}, &tengo.String{}, &tengo.Int{}}},
59+
wantErr: true,
60+
wantedErr: tengo.ErrInvalidArgumentCount{Min: 2, Max: 2, Actual: 3},
4861
},
4962
{name: "nil-map-empty-key",
5063
args: args{[]tengo.Object{&tengo.Map{}, &tengo.String{}}},
5164
want: tengo.UndefinedValue,
5265
},
53-
{name: "nil-map-nonstr-key",
66+
{
67+
name: "nil-map-nonstr-key",
5468
args: args{[]tengo.Object{
55-
&tengo.Map{}, &tengo.Int{}}}, wantErr: true,
56-
wantedErr: tengo.ErrInvalidArgumentType{
57-
Name: "second", Expected: "string", Found: "int"},
69+
&tengo.Map{}, &tengo.Int{}}},
70+
wantErr: true,
71+
wantedErr: tengo.ErrInvalidArgumentType{Index: 1, Expected: tengo.StringTN, Actual: tengo.IntTN},
5872
},
59-
{name: "nil-map-no-key",
60-
args: args{[]tengo.Object{&tengo.Map{}}}, wantErr: true,
61-
wantedErr: tengo.ErrWrongNumArguments,
73+
{
74+
name: "nil-map-no-key",
75+
args: args{[]tengo.Object{&tengo.Map{}}},
76+
wantErr: true,
77+
wantedErr: tengo.ErrInvalidArgumentCount{Min: 2, Max: 2, Actual: 1},
6278
},
6379
{name: "map-missing-key",
6480
args: args{
@@ -152,18 +168,20 @@ func Test_builtinSplice(t *testing.T) {
152168
wantedErr error
153169
}{
154170
{name: "no args", args: []tengo.Object{}, wantErr: true,
155-
wantedErr: tengo.ErrWrongNumArguments,
171+
wantedErr: tengo.ErrInvalidArgumentCount{
172+
Min: 1, Max: -1, Actual: 0,
173+
},
156174
},
157175
{name: "invalid args", args: []tengo.Object{&tengo.Map{}},
158176
wantErr: true,
159177
wantedErr: tengo.ErrInvalidArgumentType{
160-
Name: "first", Expected: "array", Found: "map"},
178+
Index: 0, Expected: tengo.ArrayTN, Actual: tengo.MapTN},
161179
},
162180
{name: "invalid args",
163181
args: []tengo.Object{&tengo.Array{}, &tengo.String{}},
164182
wantErr: true,
165183
wantedErr: tengo.ErrInvalidArgumentType{
166-
Name: "second", Expected: "int", Found: "string"},
184+
Index: 1, Expected: tengo.IntTN, Actual: tengo.StringTN},
167185
},
168186
{name: "negative index",
169187
args: []tengo.Object{&tengo.Array{}, &tengo.Int{Value: -1}},
@@ -175,7 +193,7 @@ func Test_builtinSplice(t *testing.T) {
175193
&tengo.String{Value: ""}},
176194
wantErr: true,
177195
wantedErr: tengo.ErrInvalidArgumentType{
178-
Name: "third", Expected: "int", Found: "string"},
196+
Index: 2, Expected: tengo.IntTN, Actual: tengo.StringTN},
179197
},
180198
{name: "negative count",
181199
args: []tengo.Object{
@@ -371,33 +389,39 @@ func Test_builtinRange(t *testing.T) {
371389
wantedErr error
372390
}{
373391
{name: "no args", args: []tengo.Object{}, wantErr: true,
374-
wantedErr: tengo.ErrWrongNumArguments,
392+
wantedErr: tengo.ErrInvalidArgumentCount{
393+
Min: 2, Max: 3, Actual: 0,
394+
},
375395
},
376396
{name: "single args", args: []tengo.Object{&tengo.Map{}},
377-
wantErr: true,
378-
wantedErr: tengo.ErrWrongNumArguments,
397+
wantErr: true,
398+
wantedErr: tengo.ErrInvalidArgumentCount{
399+
Min: 2, Max: 3, Actual: 1,
400+
},
379401
},
380402
{name: "4 args", args: []tengo.Object{&tengo.Map{}, &tengo.String{}, &tengo.String{}, &tengo.String{}},
381-
wantErr: true,
382-
wantedErr: tengo.ErrWrongNumArguments,
403+
wantErr: true,
404+
wantedErr: tengo.ErrInvalidArgumentCount{
405+
Min: 2, Max: 3, Actual: 4,
406+
},
383407
},
384408
{name: "invalid start",
385409
args: []tengo.Object{&tengo.String{}, &tengo.String{}},
386410
wantErr: true,
387411
wantedErr: tengo.ErrInvalidArgumentType{
388-
Name: "start", Expected: "int", Found: "string"},
412+
Index: 0, Expected: tengo.IntTN, Actual: tengo.StringTN},
389413
},
390414
{name: "invalid stop",
391415
args: []tengo.Object{&tengo.Int{}, &tengo.String{}},
392416
wantErr: true,
393417
wantedErr: tengo.ErrInvalidArgumentType{
394-
Name: "stop", Expected: "int", Found: "string"},
418+
Index: 1, Expected: tengo.IntTN, Actual: tengo.StringTN},
395419
},
396420
{name: "invalid step",
397421
args: []tengo.Object{&tengo.Int{}, &tengo.Int{}, &tengo.String{}},
398422
wantErr: true,
399423
wantedErr: tengo.ErrInvalidArgumentType{
400-
Name: "step", Expected: "int", Found: "string"},
424+
Index: 2, Expected: tengo.IntTN, Actual: tengo.StringTN},
401425
},
402426
{name: "zero step",
403427
args: []tengo.Object{&tengo.Int{}, &tengo.Int{}, &tengo.Int{}}, //must greate than 0

cmd/tengo/main.go

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ func CompileOnly(
9999
modules *tengo.ModuleMap,
100100
data []byte,
101101
inputFile, outputFile string,
102-
) (err error) {
102+
) error {
103103
bytecode, err := compileSrc(modules, data, inputFile)
104104
if err != nil {
105-
return
105+
return err
106106
}
107107

108108
if outputFile == "" {
@@ -111,7 +111,7 @@ func CompileOnly(
111111

112112
out, err := os.OpenFile(outputFile, os.O_CREATE|os.O_WRONLY, os.ModePerm)
113113
if err != nil {
114-
return
114+
return err
115115
}
116116
defer func() {
117117
if err != nil {
@@ -123,39 +123,37 @@ func CompileOnly(
123123

124124
err = bytecode.Encode(out)
125125
if err != nil {
126-
return
126+
return err
127127
}
128128
fmt.Println(outputFile)
129-
return
129+
return err
130130
}
131131

132132
// CompileAndRun compiles the source code and executes it.
133133
func CompileAndRun(
134134
modules *tengo.ModuleMap,
135135
data []byte,
136136
inputFile string,
137-
) (err error) {
137+
) error {
138138
bytecode, err := compileSrc(modules, data, inputFile)
139139
if err != nil {
140-
return
140+
return err
141141
}
142142

143143
machine := tengo.NewVM(bytecode, nil, -1)
144-
err = machine.Run()
145-
return
144+
return machine.Run()
146145
}
147146

148147
// RunCompiled reads the compiled binary from file and executes it.
149-
func RunCompiled(modules *tengo.ModuleMap, data []byte) (err error) {
148+
func RunCompiled(modules *tengo.ModuleMap, data []byte) error {
150149
bytecode := &tengo.Bytecode{}
151-
err = bytecode.Decode(bytes.NewReader(data), modules)
150+
err := bytecode.Decode(bytes.NewReader(data), modules)
152151
if err != nil {
153-
return
152+
return err
154153
}
155154

156155
machine := tengo.NewVM(bytecode, nil, -1)
157-
err = machine.Run()
158-
return
156+
return machine.Run()
159157
}
160158

161159
// RunREPL starts REPL.
@@ -172,19 +170,19 @@ func RunREPL(modules *tengo.ModuleMap, in io.Reader, out io.Writer) {
172170
symbol := symbolTable.Define("__repl_println__")
173171
globals[symbol.Index] = &tengo.UserFunction{
174172
Name: "println",
175-
Value: func(args ...tengo.Object) (ret tengo.Object, err error) {
173+
Value: func(args ...tengo.Object) (tengo.Object, error) {
176174
var printArgs []interface{}
177-
for _, arg := range args {
178-
if _, isUndefined := arg.(*tengo.Undefined); isUndefined {
175+
for i := range args {
176+
if _, isUndefined := args[i].(*tengo.Undefined); isUndefined {
179177
printArgs = append(printArgs, "<undefined>")
180178
} else {
181-
s, _ := tengo.ToString(arg)
179+
s, _ := tengo.ToString(i, args...)
182180
printArgs = append(printArgs, s)
183181
}
184182
}
185183
printArgs = append(printArgs, "\n")
186184
_, _ = fmt.Print(printArgs...)
187-
return
185+
return nil, nil
188186
},
189187
}
190188

compiler_test.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,15 +1296,15 @@ type compileTracer struct {
12961296
Out []string
12971297
}
12981298

1299-
func (o *compileTracer) Write(p []byte) (n int, err error) {
1299+
func (o *compileTracer) Write(p []byte) (int, error) {
13001300
o.Out = append(o.Out, string(p))
13011301
return len(p), nil
13021302
}
13031303

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

@@ -1322,11 +1322,12 @@ func traceCompile(
13221322
c := tengo.NewCompiler(file, symTable, nil, nil, tr)
13231323
parsed, err := p.ParseFile()
13241324
if err != nil {
1325-
return
1325+
return nil, nil, err
13261326
}
13271327

13281328
err = c.Compile(parsed)
1329-
res = c.Bytecode()
1329+
var trace []string
1330+
res := c.Bytecode()
13301331
res.RemoveDuplicates()
13311332
{
13321333
trace = append(trace, fmt.Sprintf("Compiler Trace:\n%s",
@@ -1336,10 +1337,7 @@ func traceCompile(
13361337
trace = append(trace, fmt.Sprintf("Compiled Instructions:\n%s\n",
13371338
strings.Join(res.FormatInstructions(), "\n")))
13381339
}
1339-
if err != nil {
1340-
return
1341-
}
1342-
return
1340+
return res, trace, err
13431341
}
13441342

13451343
func objectsArray(o ...tengo.Object) []tengo.Object {

docs/objects.md

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,12 @@ type StringArray struct {
238238
Value []string
239239
}
240240

241+
const StringArrayTN = "string-array"
242+
243+
func (o *StringArray) TypeName() string {
244+
return StringArrayTN
245+
}
246+
241247
func (o *StringArray) String() string {
242248
return strings.Join(o.Value, ", ")
243249
}
@@ -283,10 +289,6 @@ func (o *StringArray) Copy() tengo.Object {
283289
Value: append([]string{}, o.Value...),
284290
}
285291
}
286-
287-
func (o *StringArray) TypeName() string {
288-
return "string-array"
289-
}
290292
```
291293

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

362-
func (o *StringArray) Call(args ...tengo.Object) (ret tengo.Object, err error) {
363-
if len(args) != 1 {
364-
return nil, tengo.ErrWrongNumArguments
365-
}
366-
367-
s1, ok := tengo.ToString(args[0])
368-
if !ok {
369-
return nil, tengo.ErrInvalidArgumentType{
370-
Name: "first",
371-
Expected: "string",
372-
Found: args[0].TypeName(),
373-
}
374-
}
375-
376-
for i, v := range o.Value {
377-
if v == s1 {
378-
return &tengo.Int{Value: int64(i)}, nil
364+
func (o *StringArray) Call(args ...tengo.Object) (tengo.Object, error) {
365+
return tengo.CheckStrictArgs(func(args ...tengo.Object) (tengo.Object, error){
366+
s1, _ := tengo.ToString(0, args...)
367+
for i, v := range o.Value {
368+
if v == s1 {
369+
return &tengo.Int{Value: int64(i)}, nil
370+
}
379371
}
380-
}
381-
382-
return tengo.UndefinedValue, nil
372+
return tengo.UndefinedValue, nil
373+
}, tengo.StringTN)(args...)
383374
}
384375
```
385376

@@ -414,8 +405,10 @@ type StringArrayIterator struct {
414405
idx int
415406
}
416407

408+
const StringArrayIteratorTN = "string-array-iterator"
409+
417410
func (i *StringArrayIterator) TypeName() string {
418-
return "string-array-iterator"
411+
return StringArrayIteratorTN
419412
}
420413

421414
func (i *StringArrayIterator) Next() bool {

0 commit comments

Comments
 (0)