Skip to content

Commit 9caceee

Browse files
committed
Flatten builtin opcodes in vm
1 parent 3fe3504 commit 9caceee

File tree

6 files changed

+47
-40
lines changed

6 files changed

+47
-40
lines changed

builtin/builtin.go

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,25 @@ var (
1212
)
1313

1414
type Function struct {
15-
Name string
16-
Func func(args ...interface{}) (interface{}, error)
17-
Types []reflect.Type
18-
Validate func(args []reflect.Type) (reflect.Type, error)
19-
BuiltinId int
15+
Name string
16+
Func func(args ...interface{}) (interface{}, error)
17+
Opcode byte
18+
Types []reflect.Type
19+
Validate func(args []reflect.Type) (reflect.Type, error)
2020
}
2121

2222
const (
23-
Len = iota + 1
23+
Opcode byte = iota + 100
24+
Len
2425
Abs
2526
Int
2627
Float
2728
)
2829

29-
var Builtins = []*Function{
30-
{
31-
Name: "len",
32-
BuiltinId: Len,
30+
var Builtins = map[byte]*Function{
31+
Len: {
32+
Name: "len",
33+
Opcode: Len,
3334
Validate: func(args []reflect.Type) (reflect.Type, error) {
3435
if len(args) != 1 {
3536
return anyType, fmt.Errorf("invalid number of arguments for len (expected 1, got %d)", len(args))
@@ -41,9 +42,9 @@ var Builtins = []*Function{
4142
return anyType, fmt.Errorf("invalid argument for len (type %s)", args[0])
4243
},
4344
},
44-
{
45-
Name: "abs",
46-
BuiltinId: Abs,
45+
Abs: {
46+
Name: "abs",
47+
Opcode: Abs,
4748
Validate: func(args []reflect.Type) (reflect.Type, error) {
4849
if len(args) != 1 {
4950
return anyType, fmt.Errorf("invalid number of arguments for abs (expected 1, got %d)", len(args))
@@ -55,9 +56,9 @@ var Builtins = []*Function{
5556
return anyType, fmt.Errorf("invalid argument for abs (type %s)", args[0])
5657
},
5758
},
58-
{
59-
Name: "int",
60-
BuiltinId: Int,
59+
Int: {
60+
Name: "int",
61+
Opcode: Int,
6162
Validate: func(args []reflect.Type) (reflect.Type, error) {
6263
if len(args) != 1 {
6364
return anyType, fmt.Errorf("invalid number of arguments for int (expected 1, got %d)", len(args))
@@ -73,9 +74,9 @@ var Builtins = []*Function{
7374
return anyType, fmt.Errorf("invalid argument for int (type %s)", args[0])
7475
},
7576
},
76-
{
77-
Name: "float",
78-
BuiltinId: Float,
77+
Float: {
78+
Name: "float",
79+
Opcode: Float,
7980
Validate: func(args []reflect.Type) (reflect.Type, error) {
8081
if len(args) != 1 {
8182
return anyType, fmt.Errorf("invalid number of arguments for float (expected 1, got %d)", len(args))

compiler/compiler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,8 +527,8 @@ func (c *compiler) CallNode(node *ast.CallNode) {
527527
c.compile(arg)
528528
}
529529
if node.Func != nil {
530-
if node.Func.BuiltinId > 0 {
531-
c.emit(OpCallBuiltin, node.Func.BuiltinId)
530+
if node.Func.Opcode > 0 {
531+
c.emit(node.Func.Opcode)
532532
return
533533
}
534534
switch len(node.Arguments) {

conf/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ func CreateNew() *Config {
3131
Functions: make(map[string]*builtin.Function),
3232
Optimize: true,
3333
}
34-
for _, builtin := range builtin.Builtins {
35-
c.Functions[builtin.Name] = builtin
34+
for _, f := range builtin.Builtins {
35+
c.Functions[f.Name] = f
3636
}
3737
return c
3838
}

vm/opcodes.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package vm
22

3-
type Opcode byte
3+
type Opcode = byte
44

55
const (
66
OpPush Opcode = iota
@@ -54,7 +54,6 @@ const (
5454
OpCallN
5555
OpCallFast
5656
OpCallTyped
57-
OpCallBuiltin
5857
OpArray
5958
OpMap
6059
OpLen

vm/program.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"strings"
77

88
"github.com/antonmedv/expr/ast"
9+
"github.com/antonmedv/expr/builtin"
910
"github.com/antonmedv/expr/file"
1011
"github.com/antonmedv/expr/vm/runtime"
1112
)
@@ -60,6 +61,15 @@ func (program *Program) Disassemble() string {
6061
out += fmt.Sprintf("%v\t%v\t%v\t%v\n", pp, label, arg, c)
6162
}
6263

64+
if op > builtin.Opcode {
65+
f, ok := builtin.Builtins[op]
66+
if !ok {
67+
panic(fmt.Sprintf("unknown builtin %v", op))
68+
}
69+
out += fmt.Sprintf("%v\t%v\t%v\n", pp, "OpBuiltin", f.Name)
70+
continue
71+
}
72+
6373
switch op {
6474
case OpPush:
6575
constant("OpPush")
@@ -214,9 +224,6 @@ func (program *Program) Disassemble() string {
214224
case OpCallTyped:
215225
argument("OpCallTyped")
216226

217-
case OpCallBuiltin:
218-
argument("OpCallBuiltin")
219-
220227
case OpArray:
221228
code("OpArray")
222229

vm/vm.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -367,18 +367,6 @@ func (vm *VM) Run(program *Program, env interface{}) (_ interface{}, err error)
367367
out := vm.call(fn, arg)
368368
vm.push(out)
369369

370-
case OpCallBuiltin:
371-
switch arg {
372-
case builtin.Len:
373-
vm.push(runtime.Len(vm.pop()))
374-
case builtin.Abs:
375-
vm.push(runtime.Abs(vm.pop()))
376-
case builtin.Int:
377-
vm.push(runtime.ToInt(vm.pop()))
378-
case builtin.Float:
379-
vm.push(runtime.ToFloat64(vm.pop()))
380-
}
381-
382370
case OpArray:
383371
size := vm.pop().(int)
384372
array := make([]interface{}, size)
@@ -454,6 +442,18 @@ func (vm *VM) Run(program *Program, env interface{}) (_ interface{}, err error)
454442
case OpEnd:
455443
vm.scopes = vm.scopes[:len(vm.scopes)-1]
456444

445+
case builtin.Len:
446+
vm.push(runtime.Len(vm.pop()))
447+
448+
case builtin.Abs:
449+
vm.push(runtime.Abs(vm.pop()))
450+
451+
case builtin.Int:
452+
vm.push(runtime.ToInt(vm.pop()))
453+
454+
case builtin.Float:
455+
vm.push(runtime.ToFloat64(vm.pop()))
456+
457457
default:
458458
panic(fmt.Sprintf("unknown bytecode %#x", op))
459459
}

0 commit comments

Comments
 (0)