Skip to content

Commit

Permalink
dry-er type checking
Browse files Browse the repository at this point in the history
  • Loading branch information
0xor1 committed Jul 24, 2021
1 parent ac80580 commit 26cd5e3
Show file tree
Hide file tree
Showing 30 changed files with 2,149 additions and 3,673 deletions.
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

0 comments on commit 26cd5e3

Please sign in to comment.