fix internal package issue (#241)
* fix internal package issue * ExampleSimple -> Example
This commit is contained in:
parent
7cb058b564
commit
a9a233a750
40 changed files with 1187 additions and 1137 deletions
|
@ -121,7 +121,6 @@ each([a, b, c, d], func(x) {
|
||||||
mul := compiled.Get("mul")
|
mul := compiled.Get("mul")
|
||||||
fmt.Println(sum, mul) // "22 288"
|
fmt.Println(sum, mul) // "22 288"
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
24
bytecode.go
24
bytecode.go
|
@ -6,12 +6,12 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/d5/tengo/internal"
|
"github.com/d5/tengo/parser"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bytecode is a compiled instructions and constants.
|
// Bytecode is a compiled instructions and constants.
|
||||||
type Bytecode struct {
|
type Bytecode struct {
|
||||||
FileSet *internal.SourceFileSet
|
FileSet *parser.SourceFileSet
|
||||||
MainFunction *CompiledFunction
|
MainFunction *CompiledFunction
|
||||||
Constants []Object
|
Constants []Object
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func (b *Bytecode) CountObjects() int {
|
||||||
// FormatInstructions returns human readable string representations of
|
// FormatInstructions returns human readable string representations of
|
||||||
// compiled instructions.
|
// compiled instructions.
|
||||||
func (b *Bytecode) FormatInstructions() []string {
|
func (b *Bytecode) FormatInstructions() []string {
|
||||||
return internal.FormatInstructions(b.MainFunction.Instructions, 0)
|
return FormatInstructions(b.MainFunction.Instructions, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FormatConstants returns human readable string representations of
|
// FormatConstants returns human readable string representations of
|
||||||
|
@ -51,7 +51,7 @@ func (b *Bytecode) FormatConstants() (output []string) {
|
||||||
case *CompiledFunction:
|
case *CompiledFunction:
|
||||||
output = append(output, fmt.Sprintf(
|
output = append(output, fmt.Sprintf(
|
||||||
"[% 3d] (Compiled Function|%p)", cidx, &cn))
|
"[% 3d] (Compiled Function|%p)", cidx, &cn))
|
||||||
for _, l := range internal.FormatInstructions(cn.Instructions, 0) {
|
for _, l := range FormatInstructions(cn.Instructions, 0) {
|
||||||
output = append(output, fmt.Sprintf(" %s", l))
|
output = append(output, fmt.Sprintf(" %s", l))
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -239,25 +239,25 @@ func updateConstIndexes(insts []byte, indexMap map[int]int) {
|
||||||
i := 0
|
i := 0
|
||||||
for i < len(insts) {
|
for i < len(insts) {
|
||||||
op := insts[i]
|
op := insts[i]
|
||||||
numOperands := internal.OpcodeOperands[op]
|
numOperands := parser.OpcodeOperands[op]
|
||||||
_, read := internal.ReadOperands(numOperands, insts[i+1:])
|
_, read := parser.ReadOperands(numOperands, insts[i+1:])
|
||||||
|
|
||||||
switch op {
|
switch op {
|
||||||
case internal.OpConstant:
|
case parser.OpConstant:
|
||||||
curIdx := int(insts[i+2]) | int(insts[i+1])<<8
|
curIdx := int(insts[i+2]) | int(insts[i+1])<<8
|
||||||
newIdx, ok := indexMap[curIdx]
|
newIdx, ok := indexMap[curIdx]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Errorf("constant index not found: %d", curIdx))
|
panic(fmt.Errorf("constant index not found: %d", curIdx))
|
||||||
}
|
}
|
||||||
copy(insts[i:], internal.MakeInstruction(op, newIdx))
|
copy(insts[i:], MakeInstruction(op, newIdx))
|
||||||
case internal.OpClosure:
|
case parser.OpClosure:
|
||||||
curIdx := int(insts[i+2]) | int(insts[i+1])<<8
|
curIdx := int(insts[i+2]) | int(insts[i+1])<<8
|
||||||
numFree := int(insts[i+3])
|
numFree := int(insts[i+3])
|
||||||
newIdx, ok := indexMap[curIdx]
|
newIdx, ok := indexMap[curIdx]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Errorf("constant index not found: %d", curIdx))
|
panic(fmt.Errorf("constant index not found: %d", curIdx))
|
||||||
}
|
}
|
||||||
copy(insts[i:], internal.MakeInstruction(op, newIdx, numFree))
|
copy(insts[i:], MakeInstruction(op, newIdx, numFree))
|
||||||
}
|
}
|
||||||
|
|
||||||
i += 1 + read
|
i += 1 + read
|
||||||
|
@ -272,8 +272,8 @@ func inferModuleName(mod *ImmutableMap) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
gob.Register(&internal.SourceFileSet{})
|
gob.Register(&parser.SourceFileSet{})
|
||||||
gob.Register(&internal.SourceFile{})
|
gob.Register(&parser.SourceFile{})
|
||||||
gob.Register(&Array{})
|
gob.Register(&Array{})
|
||||||
gob.Register(&Bool{})
|
gob.Register(&Bool{})
|
||||||
gob.Register(&Bytes{})
|
gob.Register(&Bytes{})
|
||||||
|
|
176
bytecode_test.go
176
bytecode_test.go
|
@ -6,8 +6,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal"
|
"github.com/d5/tengo/parser"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
type srcfile struct {
|
type srcfile struct {
|
||||||
|
@ -23,20 +23,20 @@ func TestBytecode(t *testing.T) {
|
||||||
&tengo.Char{Value: 'y'},
|
&tengo.Char{Value: 'y'},
|
||||||
&tengo.Float{Value: 93.11},
|
&tengo.Float{Value: 93.11},
|
||||||
compiledFunction(1, 0,
|
compiledFunction(1, 0,
|
||||||
internal.MakeInstruction(internal.OpConstant, 3),
|
tengo.MakeInstruction(parser.OpConstant, 3),
|
||||||
internal.MakeInstruction(internal.OpSetLocal, 0),
|
tengo.MakeInstruction(parser.OpSetLocal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetGlobal, 0),
|
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetFree, 0)),
|
tengo.MakeInstruction(parser.OpGetFree, 0)),
|
||||||
&tengo.Float{Value: 39.2},
|
&tengo.Float{Value: 39.2},
|
||||||
&tengo.Int{Value: 192},
|
&tengo.Int{Value: 192},
|
||||||
&tengo.String{Value: "bar"})))
|
&tengo.String{Value: "bar"})))
|
||||||
|
|
||||||
testBytecodeSerialization(t, bytecodeFileSet(
|
testBytecodeSerialization(t, bytecodeFileSet(
|
||||||
concatInsts(
|
concatInsts(
|
||||||
internal.MakeInstruction(internal.OpConstant, 0),
|
tengo.MakeInstruction(parser.OpConstant, 0),
|
||||||
internal.MakeInstruction(internal.OpSetGlobal, 0),
|
tengo.MakeInstruction(parser.OpSetGlobal, 0),
|
||||||
internal.MakeInstruction(internal.OpConstant, 6),
|
tengo.MakeInstruction(parser.OpConstant, 6),
|
||||||
internal.MakeInstruction(internal.OpPop)),
|
tengo.MakeInstruction(parser.OpPop)),
|
||||||
objectsArray(
|
objectsArray(
|
||||||
&tengo.Int{Value: 55},
|
&tengo.Int{Value: 55},
|
||||||
&tengo.Int{Value: 66},
|
&tengo.Int{Value: 66},
|
||||||
|
@ -99,29 +99,29 @@ func TestBytecode(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
compiledFunction(1, 0,
|
compiledFunction(1, 0,
|
||||||
internal.MakeInstruction(internal.OpConstant, 3),
|
tengo.MakeInstruction(parser.OpConstant, 3),
|
||||||
internal.MakeInstruction(internal.OpSetLocal, 0),
|
tengo.MakeInstruction(parser.OpSetLocal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetGlobal, 0),
|
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetFree, 0),
|
tengo.MakeInstruction(parser.OpGetFree, 0),
|
||||||
internal.MakeInstruction(internal.OpBinaryOp, 11),
|
tengo.MakeInstruction(parser.OpBinaryOp, 11),
|
||||||
internal.MakeInstruction(internal.OpGetFree, 1),
|
tengo.MakeInstruction(parser.OpGetFree, 1),
|
||||||
internal.MakeInstruction(internal.OpBinaryOp, 11),
|
tengo.MakeInstruction(parser.OpBinaryOp, 11),
|
||||||
internal.MakeInstruction(internal.OpGetLocal, 0),
|
tengo.MakeInstruction(parser.OpGetLocal, 0),
|
||||||
internal.MakeInstruction(internal.OpBinaryOp, 11),
|
tengo.MakeInstruction(parser.OpBinaryOp, 11),
|
||||||
internal.MakeInstruction(internal.OpReturn, 1)),
|
tengo.MakeInstruction(parser.OpReturn, 1)),
|
||||||
compiledFunction(1, 0,
|
compiledFunction(1, 0,
|
||||||
internal.MakeInstruction(internal.OpConstant, 2),
|
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||||
internal.MakeInstruction(internal.OpSetLocal, 0),
|
tengo.MakeInstruction(parser.OpSetLocal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetFree, 0),
|
tengo.MakeInstruction(parser.OpGetFree, 0),
|
||||||
internal.MakeInstruction(internal.OpGetLocal, 0),
|
tengo.MakeInstruction(parser.OpGetLocal, 0),
|
||||||
internal.MakeInstruction(internal.OpClosure, 4, 2),
|
tengo.MakeInstruction(parser.OpClosure, 4, 2),
|
||||||
internal.MakeInstruction(internal.OpReturn, 1)),
|
tengo.MakeInstruction(parser.OpReturn, 1)),
|
||||||
compiledFunction(1, 0,
|
compiledFunction(1, 0,
|
||||||
internal.MakeInstruction(internal.OpConstant, 1),
|
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||||
internal.MakeInstruction(internal.OpSetLocal, 0),
|
tengo.MakeInstruction(parser.OpSetLocal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetLocal, 0),
|
tengo.MakeInstruction(parser.OpGetLocal, 0),
|
||||||
internal.MakeInstruction(internal.OpClosure, 5, 1),
|
tengo.MakeInstruction(parser.OpClosure, 5, 1),
|
||||||
internal.MakeInstruction(internal.OpReturn, 1))),
|
tengo.MakeInstruction(parser.OpReturn, 1))),
|
||||||
fileSet(srcfile{name: "file1", size: 100},
|
fileSet(srcfile{name: "file1", size: 100},
|
||||||
srcfile{name: "file2", size: 200})))
|
srcfile{name: "file2", size: 200})))
|
||||||
}
|
}
|
||||||
|
@ -133,10 +133,10 @@ func TestBytecode_RemoveDuplicates(t *testing.T) {
|
||||||
&tengo.Char{Value: 'y'},
|
&tengo.Char{Value: 'y'},
|
||||||
&tengo.Float{Value: 93.11},
|
&tengo.Float{Value: 93.11},
|
||||||
compiledFunction(1, 0,
|
compiledFunction(1, 0,
|
||||||
internal.MakeInstruction(internal.OpConstant, 3),
|
tengo.MakeInstruction(parser.OpConstant, 3),
|
||||||
internal.MakeInstruction(internal.OpSetLocal, 0),
|
tengo.MakeInstruction(parser.OpSetLocal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetGlobal, 0),
|
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetFree, 0)),
|
tengo.MakeInstruction(parser.OpGetFree, 0)),
|
||||||
&tengo.Float{Value: 39.2},
|
&tengo.Float{Value: 39.2},
|
||||||
&tengo.Int{Value: 192},
|
&tengo.Int{Value: 192},
|
||||||
&tengo.String{Value: "bar"})),
|
&tengo.String{Value: "bar"})),
|
||||||
|
@ -145,10 +145,10 @@ func TestBytecode_RemoveDuplicates(t *testing.T) {
|
||||||
&tengo.Char{Value: 'y'},
|
&tengo.Char{Value: 'y'},
|
||||||
&tengo.Float{Value: 93.11},
|
&tengo.Float{Value: 93.11},
|
||||||
compiledFunction(1, 0,
|
compiledFunction(1, 0,
|
||||||
internal.MakeInstruction(internal.OpConstant, 3),
|
tengo.MakeInstruction(parser.OpConstant, 3),
|
||||||
internal.MakeInstruction(internal.OpSetLocal, 0),
|
tengo.MakeInstruction(parser.OpSetLocal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetGlobal, 0),
|
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetFree, 0)),
|
tengo.MakeInstruction(parser.OpGetFree, 0)),
|
||||||
&tengo.Float{Value: 39.2},
|
&tengo.Float{Value: 39.2},
|
||||||
&tengo.Int{Value: 192},
|
&tengo.Int{Value: 192},
|
||||||
&tengo.String{Value: "bar"})))
|
&tengo.String{Value: "bar"})))
|
||||||
|
@ -156,63 +156,63 @@ func TestBytecode_RemoveDuplicates(t *testing.T) {
|
||||||
testBytecodeRemoveDuplicates(t,
|
testBytecodeRemoveDuplicates(t,
|
||||||
bytecode(
|
bytecode(
|
||||||
concatInsts(
|
concatInsts(
|
||||||
internal.MakeInstruction(internal.OpConstant, 0),
|
tengo.MakeInstruction(parser.OpConstant, 0),
|
||||||
internal.MakeInstruction(internal.OpConstant, 1),
|
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||||
internal.MakeInstruction(internal.OpConstant, 2),
|
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||||
internal.MakeInstruction(internal.OpConstant, 3),
|
tengo.MakeInstruction(parser.OpConstant, 3),
|
||||||
internal.MakeInstruction(internal.OpConstant, 4),
|
tengo.MakeInstruction(parser.OpConstant, 4),
|
||||||
internal.MakeInstruction(internal.OpConstant, 5),
|
tengo.MakeInstruction(parser.OpConstant, 5),
|
||||||
internal.MakeInstruction(internal.OpConstant, 6),
|
tengo.MakeInstruction(parser.OpConstant, 6),
|
||||||
internal.MakeInstruction(internal.OpConstant, 7),
|
tengo.MakeInstruction(parser.OpConstant, 7),
|
||||||
internal.MakeInstruction(internal.OpConstant, 8),
|
tengo.MakeInstruction(parser.OpConstant, 8),
|
||||||
internal.MakeInstruction(internal.OpClosure, 4, 1)),
|
tengo.MakeInstruction(parser.OpClosure, 4, 1)),
|
||||||
objectsArray(
|
objectsArray(
|
||||||
&tengo.Int{Value: 1},
|
&tengo.Int{Value: 1},
|
||||||
&tengo.Float{Value: 2.0},
|
&tengo.Float{Value: 2.0},
|
||||||
&tengo.Char{Value: '3'},
|
&tengo.Char{Value: '3'},
|
||||||
&tengo.String{Value: "four"},
|
&tengo.String{Value: "four"},
|
||||||
compiledFunction(1, 0,
|
compiledFunction(1, 0,
|
||||||
internal.MakeInstruction(internal.OpConstant, 3),
|
tengo.MakeInstruction(parser.OpConstant, 3),
|
||||||
internal.MakeInstruction(internal.OpConstant, 7),
|
tengo.MakeInstruction(parser.OpConstant, 7),
|
||||||
internal.MakeInstruction(internal.OpSetLocal, 0),
|
tengo.MakeInstruction(parser.OpSetLocal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetGlobal, 0),
|
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetFree, 0)),
|
tengo.MakeInstruction(parser.OpGetFree, 0)),
|
||||||
&tengo.Int{Value: 1},
|
&tengo.Int{Value: 1},
|
||||||
&tengo.Float{Value: 2.0},
|
&tengo.Float{Value: 2.0},
|
||||||
&tengo.Char{Value: '3'},
|
&tengo.Char{Value: '3'},
|
||||||
&tengo.String{Value: "four"})),
|
&tengo.String{Value: "four"})),
|
||||||
bytecode(
|
bytecode(
|
||||||
concatInsts(
|
concatInsts(
|
||||||
internal.MakeInstruction(internal.OpConstant, 0),
|
tengo.MakeInstruction(parser.OpConstant, 0),
|
||||||
internal.MakeInstruction(internal.OpConstant, 1),
|
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||||
internal.MakeInstruction(internal.OpConstant, 2),
|
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||||
internal.MakeInstruction(internal.OpConstant, 3),
|
tengo.MakeInstruction(parser.OpConstant, 3),
|
||||||
internal.MakeInstruction(internal.OpConstant, 4),
|
tengo.MakeInstruction(parser.OpConstant, 4),
|
||||||
internal.MakeInstruction(internal.OpConstant, 0),
|
tengo.MakeInstruction(parser.OpConstant, 0),
|
||||||
internal.MakeInstruction(internal.OpConstant, 1),
|
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||||
internal.MakeInstruction(internal.OpConstant, 2),
|
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||||
internal.MakeInstruction(internal.OpConstant, 3),
|
tengo.MakeInstruction(parser.OpConstant, 3),
|
||||||
internal.MakeInstruction(internal.OpClosure, 4, 1)),
|
tengo.MakeInstruction(parser.OpClosure, 4, 1)),
|
||||||
objectsArray(
|
objectsArray(
|
||||||
&tengo.Int{Value: 1},
|
&tengo.Int{Value: 1},
|
||||||
&tengo.Float{Value: 2.0},
|
&tengo.Float{Value: 2.0},
|
||||||
&tengo.Char{Value: '3'},
|
&tengo.Char{Value: '3'},
|
||||||
&tengo.String{Value: "four"},
|
&tengo.String{Value: "four"},
|
||||||
compiledFunction(1, 0,
|
compiledFunction(1, 0,
|
||||||
internal.MakeInstruction(internal.OpConstant, 3),
|
tengo.MakeInstruction(parser.OpConstant, 3),
|
||||||
internal.MakeInstruction(internal.OpConstant, 2),
|
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||||
internal.MakeInstruction(internal.OpSetLocal, 0),
|
tengo.MakeInstruction(parser.OpSetLocal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetGlobal, 0),
|
tengo.MakeInstruction(parser.OpGetGlobal, 0),
|
||||||
internal.MakeInstruction(internal.OpGetFree, 0)))))
|
tengo.MakeInstruction(parser.OpGetFree, 0)))))
|
||||||
|
|
||||||
testBytecodeRemoveDuplicates(t,
|
testBytecodeRemoveDuplicates(t,
|
||||||
bytecode(
|
bytecode(
|
||||||
concatInsts(
|
concatInsts(
|
||||||
internal.MakeInstruction(internal.OpConstant, 0),
|
tengo.MakeInstruction(parser.OpConstant, 0),
|
||||||
internal.MakeInstruction(internal.OpConstant, 1),
|
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||||
internal.MakeInstruction(internal.OpConstant, 2),
|
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||||
internal.MakeInstruction(internal.OpConstant, 3),
|
tengo.MakeInstruction(parser.OpConstant, 3),
|
||||||
internal.MakeInstruction(internal.OpConstant, 4)),
|
tengo.MakeInstruction(parser.OpConstant, 4)),
|
||||||
objectsArray(
|
objectsArray(
|
||||||
&tengo.Int{Value: 1},
|
&tengo.Int{Value: 1},
|
||||||
&tengo.Int{Value: 2},
|
&tengo.Int{Value: 2},
|
||||||
|
@ -221,11 +221,11 @@ func TestBytecode_RemoveDuplicates(t *testing.T) {
|
||||||
&tengo.Int{Value: 3})),
|
&tengo.Int{Value: 3})),
|
||||||
bytecode(
|
bytecode(
|
||||||
concatInsts(
|
concatInsts(
|
||||||
internal.MakeInstruction(internal.OpConstant, 0),
|
tengo.MakeInstruction(parser.OpConstant, 0),
|
||||||
internal.MakeInstruction(internal.OpConstant, 1),
|
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||||
internal.MakeInstruction(internal.OpConstant, 2),
|
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||||
internal.MakeInstruction(internal.OpConstant, 0),
|
tengo.MakeInstruction(parser.OpConstant, 0),
|
||||||
internal.MakeInstruction(internal.OpConstant, 2)),
|
tengo.MakeInstruction(parser.OpConstant, 2)),
|
||||||
objectsArray(
|
objectsArray(
|
||||||
&tengo.Int{Value: 1},
|
&tengo.Int{Value: 1},
|
||||||
&tengo.Int{Value: 2},
|
&tengo.Int{Value: 2},
|
||||||
|
@ -241,19 +241,19 @@ func TestBytecode_CountObjects(t *testing.T) {
|
||||||
&tengo.Int{Value: 77},
|
&tengo.Int{Value: 77},
|
||||||
&tengo.Int{Value: 88},
|
&tengo.Int{Value: 88},
|
||||||
compiledFunction(1, 0,
|
compiledFunction(1, 0,
|
||||||
internal.MakeInstruction(internal.OpConstant, 3),
|
tengo.MakeInstruction(parser.OpConstant, 3),
|
||||||
internal.MakeInstruction(internal.OpReturn, 1)),
|
tengo.MakeInstruction(parser.OpReturn, 1)),
|
||||||
compiledFunction(1, 0,
|
compiledFunction(1, 0,
|
||||||
internal.MakeInstruction(internal.OpConstant, 2),
|
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||||
internal.MakeInstruction(internal.OpReturn, 1)),
|
tengo.MakeInstruction(parser.OpReturn, 1)),
|
||||||
compiledFunction(1, 0,
|
compiledFunction(1, 0,
|
||||||
internal.MakeInstruction(internal.OpConstant, 1),
|
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||||
internal.MakeInstruction(internal.OpReturn, 1))))
|
tengo.MakeInstruction(parser.OpReturn, 1))))
|
||||||
require.Equal(t, 7, b.CountObjects())
|
require.Equal(t, 7, b.CountObjects())
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileSet(files ...srcfile) *internal.SourceFileSet {
|
func fileSet(files ...srcfile) *parser.SourceFileSet {
|
||||||
fileSet := internal.NewFileSet()
|
fileSet := parser.NewFileSet()
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
fileSet.AddFile(f.name, -1, f.size)
|
fileSet.AddFile(f.name, -1, f.size)
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,7 @@ func fileSet(files ...srcfile) *internal.SourceFileSet {
|
||||||
func bytecodeFileSet(
|
func bytecodeFileSet(
|
||||||
instructions []byte,
|
instructions []byte,
|
||||||
constants []tengo.Object,
|
constants []tengo.Object,
|
||||||
fileSet *internal.SourceFileSet,
|
fileSet *parser.SourceFileSet,
|
||||||
) *tengo.Bytecode {
|
) *tengo.Bytecode {
|
||||||
return &tengo.Bytecode{
|
return &tengo.Bytecode{
|
||||||
FileSet: fileSet,
|
FileSet: fileSet,
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal"
|
"github.com/d5/tengo/parser"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -163,7 +163,7 @@ func runBench(
|
||||||
result tengo.Object,
|
result tengo.Object,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
var astFile *internal.File
|
var astFile *parser.File
|
||||||
parseTime, astFile, err = parse(input)
|
parseTime, astFile, err = parse(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -180,13 +180,13 @@ func runBench(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parse(input []byte) (time.Duration, *internal.File, error) {
|
func parse(input []byte) (time.Duration, *parser.File, error) {
|
||||||
fileSet := internal.NewFileSet()
|
fileSet := parser.NewFileSet()
|
||||||
inputFile := fileSet.AddFile("bench", -1, len(input))
|
inputFile := fileSet.AddFile("bench", -1, len(input))
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
p := internal.NewParser(inputFile, input, nil)
|
p := parser.NewParser(inputFile, input, nil)
|
||||||
file, err := p.ParseFile()
|
file, err := p.ParseFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Since(start), nil, err
|
return time.Since(start), nil, err
|
||||||
|
@ -195,8 +195,8 @@ func parse(input []byte) (time.Duration, *internal.File, error) {
|
||||||
return time.Since(start), file, nil
|
return time.Since(start), file, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func compileFile(file *internal.File) (time.Duration, *tengo.Bytecode, error) {
|
func compileFile(file *parser.File) (time.Duration, *tengo.Bytecode, error) {
|
||||||
symTable := internal.NewSymbolTable()
|
symTable := tengo.NewSymbolTable()
|
||||||
symTable.Define("out")
|
symTable.Define("out")
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal"
|
"github.com/d5/tengo/parser"
|
||||||
"github.com/d5/tengo/stdlib"
|
"github.com/d5/tengo/stdlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -148,9 +148,9 @@ func RunCompiled(modules *tengo.ModuleMap, data []byte) (err error) {
|
||||||
// RunREPL starts REPL.
|
// RunREPL starts REPL.
|
||||||
func RunREPL(modules *tengo.ModuleMap, in io.Reader, out io.Writer) {
|
func RunREPL(modules *tengo.ModuleMap, in io.Reader, out io.Writer) {
|
||||||
stdin := bufio.NewScanner(in)
|
stdin := bufio.NewScanner(in)
|
||||||
fileSet := internal.NewFileSet()
|
fileSet := parser.NewFileSet()
|
||||||
globals := make([]tengo.Object, tengo.GlobalsSize)
|
globals := make([]tengo.Object, tengo.GlobalsSize)
|
||||||
symbolTable := internal.NewSymbolTable()
|
symbolTable := tengo.NewSymbolTable()
|
||||||
for idx, fn := range tengo.GetAllBuiltinFunctions() {
|
for idx, fn := range tengo.GetAllBuiltinFunctions() {
|
||||||
symbolTable.DefineBuiltin(idx, fn.Name)
|
symbolTable.DefineBuiltin(idx, fn.Name)
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ func RunREPL(modules *tengo.ModuleMap, in io.Reader, out io.Writer) {
|
||||||
|
|
||||||
line := stdin.Text()
|
line := stdin.Text()
|
||||||
srcFile := fileSet.AddFile("repl", -1, len(line))
|
srcFile := fileSet.AddFile("repl", -1, len(line))
|
||||||
p := internal.NewParser(srcFile, []byte(line), nil)
|
p := parser.NewParser(srcFile, []byte(line), nil)
|
||||||
file, err := p.ParseFile()
|
file, err := p.ParseFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_, _ = fmt.Fprintln(out, err.Error())
|
_, _ = fmt.Fprintln(out, err.Error())
|
||||||
|
@ -214,10 +214,10 @@ func compileSrc(
|
||||||
src []byte,
|
src []byte,
|
||||||
filename string,
|
filename string,
|
||||||
) (*tengo.Bytecode, error) {
|
) (*tengo.Bytecode, error) {
|
||||||
fileSet := internal.NewFileSet()
|
fileSet := parser.NewFileSet()
|
||||||
srcFile := fileSet.AddFile(filename, -1, len(src))
|
srcFile := fileSet.AddFile(filename, -1, len(src))
|
||||||
|
|
||||||
p := internal.NewParser(srcFile, src, nil)
|
p := parser.NewParser(srcFile, src, nil)
|
||||||
file, err := p.ParseFile()
|
file, err := p.ParseFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -267,23 +267,23 @@ func doHelp() {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
|
|
||||||
func addPrints(file *internal.File) *internal.File {
|
func addPrints(file *parser.File) *parser.File {
|
||||||
var stmts []internal.Stmt
|
var stmts []parser.Stmt
|
||||||
for _, s := range file.Stmts {
|
for _, s := range file.Stmts {
|
||||||
switch s := s.(type) {
|
switch s := s.(type) {
|
||||||
case *internal.ExprStmt:
|
case *parser.ExprStmt:
|
||||||
stmts = append(stmts, &internal.ExprStmt{
|
stmts = append(stmts, &parser.ExprStmt{
|
||||||
Expr: &internal.CallExpr{
|
Expr: &parser.CallExpr{
|
||||||
Func: &internal.Ident{Name: "__repl_println__"},
|
Func: &parser.Ident{Name: "__repl_println__"},
|
||||||
Args: []internal.Expr{s.Expr},
|
Args: []parser.Expr{s.Expr},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
case *internal.AssignStmt:
|
case *parser.AssignStmt:
|
||||||
stmts = append(stmts, s)
|
stmts = append(stmts, s)
|
||||||
|
|
||||||
stmts = append(stmts, &internal.ExprStmt{
|
stmts = append(stmts, &parser.ExprStmt{
|
||||||
Expr: &internal.CallExpr{
|
Expr: &parser.CallExpr{
|
||||||
Func: &internal.Ident{
|
Func: &parser.Ident{
|
||||||
Name: "__repl_println__",
|
Name: "__repl_println__",
|
||||||
},
|
},
|
||||||
Args: s.LHS,
|
Args: s.LHS,
|
||||||
|
@ -293,7 +293,7 @@ func addPrints(file *internal.File) *internal.File {
|
||||||
stmts = append(stmts, s)
|
stmts = append(stmts, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &internal.File{
|
return &parser.File{
|
||||||
InputFile: file.InputFile,
|
InputFile: file.InputFile,
|
||||||
Stmts: stmts,
|
Stmts: stmts,
|
||||||
}
|
}
|
||||||
|
|
465
compiler.go
465
compiler.go
File diff suppressed because it is too large
Load diff
1132
compiler_test.go
1132
compiler_test.go
File diff suppressed because it is too large
Load diff
3
doc.go
Normal file
3
doc.go
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
// tengo is a small, dynamic, fast, secure script language for Go.
|
||||||
|
|
||||||
|
package tengo
|
46
example_test.go
Normal file
46
example_test.go
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package tengo_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/d5/tengo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Example() {
|
||||||
|
// Tengo script code
|
||||||
|
src := `
|
||||||
|
each := func(seq, fn) {
|
||||||
|
for x in seq { fn(x) }
|
||||||
|
}
|
||||||
|
|
||||||
|
sum := 0
|
||||||
|
mul := 1
|
||||||
|
each([a, b, c, d], func(x) {
|
||||||
|
sum += x
|
||||||
|
mul *= x
|
||||||
|
})`
|
||||||
|
|
||||||
|
// create a new Script instance
|
||||||
|
script := tengo.NewScript([]byte(src))
|
||||||
|
|
||||||
|
// set values
|
||||||
|
_ = script.Add("a", 1)
|
||||||
|
_ = script.Add("b", 9)
|
||||||
|
_ = script.Add("c", 8)
|
||||||
|
_ = script.Add("d", 4)
|
||||||
|
|
||||||
|
// run the script
|
||||||
|
compiled, err := script.RunContext(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// retrieve values
|
||||||
|
sum := compiled.Get("sum")
|
||||||
|
mul := compiled.Get("mul")
|
||||||
|
fmt.Println(sum, mul)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 22 288
|
||||||
|
}
|
|
@ -1,10 +1,14 @@
|
||||||
package internal
|
package tengo
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/d5/tengo/parser"
|
||||||
|
)
|
||||||
|
|
||||||
// MakeInstruction returns a bytecode for an opcode and the operands.
|
// MakeInstruction returns a bytecode for an opcode and the operands.
|
||||||
func MakeInstruction(opcode Opcode, operands ...int) []byte {
|
func MakeInstruction(opcode parser.Opcode, operands ...int) []byte {
|
||||||
numOperands := OpcodeOperands[opcode]
|
numOperands := parser.OpcodeOperands[opcode]
|
||||||
|
|
||||||
totalLen := 1
|
totalLen := 1
|
||||||
for _, w := range numOperands {
|
for _, w := range numOperands {
|
||||||
|
@ -36,19 +40,19 @@ func FormatInstructions(b []byte, posOffset int) []string {
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
for i < len(b) {
|
for i < len(b) {
|
||||||
numOperands := OpcodeOperands[b[i]]
|
numOperands := parser.OpcodeOperands[b[i]]
|
||||||
operands, read := ReadOperands(numOperands, b[i+1:])
|
operands, read := parser.ReadOperands(numOperands, b[i+1:])
|
||||||
|
|
||||||
switch len(numOperands) {
|
switch len(numOperands) {
|
||||||
case 0:
|
case 0:
|
||||||
out = append(out, fmt.Sprintf("%04d %-7s",
|
out = append(out, fmt.Sprintf("%04d %-7s",
|
||||||
posOffset+i, OpcodeNames[b[i]]))
|
posOffset+i, parser.OpcodeNames[b[i]]))
|
||||||
case 1:
|
case 1:
|
||||||
out = append(out, fmt.Sprintf("%04d %-7s %-5d",
|
out = append(out, fmt.Sprintf("%04d %-7s %-5d",
|
||||||
posOffset+i, OpcodeNames[b[i]], operands[0]))
|
posOffset+i, parser.OpcodeNames[b[i]], operands[0]))
|
||||||
case 2:
|
case 2:
|
||||||
out = append(out, fmt.Sprintf("%04d %-7s %-5d %-5d",
|
out = append(out, fmt.Sprintf("%04d %-7s %-5d %-5d",
|
||||||
posOffset+i, OpcodeNames[b[i]],
|
posOffset+i, parser.OpcodeNames[b[i]],
|
||||||
operands[0], operands[1]))
|
operands[0], operands[1]))
|
||||||
}
|
}
|
||||||
i += 1 + read
|
i += 1 + read
|
10
objects.go
10
objects.go
|
@ -8,8 +8,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/d5/tengo/internal"
|
"github.com/d5/tengo/parser"
|
||||||
"github.com/d5/tengo/internal/token"
|
"github.com/d5/tengo/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -574,7 +574,7 @@ type CompiledFunction struct {
|
||||||
NumLocals int // number of local variables (including function parameters)
|
NumLocals int // number of local variables (including function parameters)
|
||||||
NumParameters int
|
NumParameters int
|
||||||
VarArgs bool
|
VarArgs bool
|
||||||
SourceMap map[int]internal.Pos
|
SourceMap map[int]parser.Pos
|
||||||
Free []*ObjectPtr
|
Free []*ObjectPtr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,14 +605,14 @@ func (o *CompiledFunction) Equals(_ Object) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SourcePos returns the source position of the instruction at ip.
|
// SourcePos returns the source position of the instruction at ip.
|
||||||
func (o *CompiledFunction) SourcePos(ip int) internal.Pos {
|
func (o *CompiledFunction) SourcePos(ip int) parser.Pos {
|
||||||
for ip >= 0 {
|
for ip >= 0 {
|
||||||
if p, ok := o.SourceMap[ip]; ok {
|
if p, ok := o.SourceMap[ip]; ok {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
ip--
|
ip--
|
||||||
}
|
}
|
||||||
return internal.NoPos
|
return parser.NoPos
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanCall returns whether the Object can be Called.
|
// CanCall returns whether the Object can be Called.
|
||||||
|
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
"github.com/d5/tengo/internal/token"
|
"github.com/d5/tengo/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestObject_TypeName(t *testing.T) {
|
func TestObject_TypeName(t *testing.T) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package internal
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
|
@ -1,14 +1,14 @@
|
||||||
package internal_test
|
package parser_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/d5/tengo/internal"
|
"github.com/d5/tengo/parser"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIdentListString(t *testing.T) {
|
func TestIdentListString(t *testing.T) {
|
||||||
identListVar := &internal.IdentList{
|
identListVar := &parser.IdentList{
|
||||||
List: []*internal.Ident{
|
List: []*parser.Ident{
|
||||||
{Name: "a"},
|
{Name: "a"},
|
||||||
{Name: "b"},
|
{Name: "b"},
|
||||||
{Name: "c"},
|
{Name: "c"},
|
||||||
|
@ -22,8 +22,8 @@ func TestIdentListString(t *testing.T) {
|
||||||
identListVar, expectedVar, str)
|
identListVar, expectedVar, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
identList := &internal.IdentList{
|
identList := &parser.IdentList{
|
||||||
List: []*internal.Ident{
|
List: []*parser.Ident{
|
||||||
{Name: "a"},
|
{Name: "a"},
|
||||||
{Name: "b"},
|
{Name: "b"},
|
||||||
{Name: "c"},
|
{Name: "c"},
|
|
@ -1,9 +1,9 @@
|
||||||
package internal
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/d5/tengo/internal/token"
|
"github.com/d5/tengo/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Expr represents an expression node in the AST.
|
// Expr represents an expression node in the AST.
|
|
@ -1,4 +1,4 @@
|
||||||
package internal
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
|
@ -1,4 +1,4 @@
|
||||||
package internal
|
package parser
|
||||||
|
|
||||||
// Opcode represents a single byte operation code.
|
// Opcode represents a single byte operation code.
|
||||||
type Opcode = byte
|
type Opcode = byte
|
|
@ -1,4 +1,4 @@
|
||||||
package internal
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -6,7 +6,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/d5/tengo/internal/token"
|
"github.com/d5/tengo/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
type bailout struct{}
|
type bailout struct{}
|
||||||
|
@ -20,37 +20,37 @@ var stmtStart = map[token.Token]bool{
|
||||||
token.Export: true,
|
token.Export: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParserError represents a parser error.
|
// Error represents a parser error.
|
||||||
type ParserError struct {
|
type Error struct {
|
||||||
Pos SourceFilePos
|
Pos SourceFilePos
|
||||||
Msg string
|
Msg string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e ParserError) Error() string {
|
func (e Error) Error() string {
|
||||||
if e.Pos.Filename != "" || e.Pos.IsValid() {
|
if e.Pos.Filename != "" || e.Pos.IsValid() {
|
||||||
return fmt.Sprintf("Parse Error: %s\n\tat %s", e.Msg, e.Pos)
|
return fmt.Sprintf("Parse Error: %s\n\tat %s", e.Msg, e.Pos)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("Parse Error: %s", e.Msg)
|
return fmt.Sprintf("Parse Error: %s", e.Msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParserErrorList is a collection of parser errors.
|
// ErrorList is a collection of parser errors.
|
||||||
type ParserErrorList []*ParserError
|
type ErrorList []*Error
|
||||||
|
|
||||||
// Add adds a new parser error to the collection.
|
// Add adds a new parser error to the collection.
|
||||||
func (p *ParserErrorList) Add(pos SourceFilePos, msg string) {
|
func (p *ErrorList) Add(pos SourceFilePos, msg string) {
|
||||||
*p = append(*p, &ParserError{pos, msg})
|
*p = append(*p, &Error{pos, msg})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Len returns the number of elements in the collection.
|
// Len returns the number of elements in the collection.
|
||||||
func (p ParserErrorList) Len() int {
|
func (p ErrorList) Len() int {
|
||||||
return len(p)
|
return len(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p ParserErrorList) Swap(i, j int) {
|
func (p ErrorList) Swap(i, j int) {
|
||||||
p[i], p[j] = p[j], p[i]
|
p[i], p[j] = p[j], p[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p ParserErrorList) Less(i, j int) bool {
|
func (p ErrorList) Less(i, j int) bool {
|
||||||
e := &p[i].Pos
|
e := &p[i].Pos
|
||||||
f := &p[j].Pos
|
f := &p[j].Pos
|
||||||
|
|
||||||
|
@ -67,11 +67,11 @@ func (p ParserErrorList) Less(i, j int) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort sorts the collection.
|
// Sort sorts the collection.
|
||||||
func (p ParserErrorList) Sort() {
|
func (p ErrorList) Sort() {
|
||||||
sort.Sort(p)
|
sort.Sort(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p ParserErrorList) Error() string {
|
func (p ErrorList) Error() string {
|
||||||
switch len(p) {
|
switch len(p) {
|
||||||
case 0:
|
case 0:
|
||||||
return "no errors"
|
return "no errors"
|
||||||
|
@ -82,7 +82,7 @@ func (p ParserErrorList) Error() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Err returns an error.
|
// Err returns an error.
|
||||||
func (p ParserErrorList) Err() error {
|
func (p ErrorList) Err() error {
|
||||||
if len(p) == 0 {
|
if len(p) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ func (p ParserErrorList) Err() error {
|
||||||
// implementation.
|
// implementation.
|
||||||
type Parser struct {
|
type Parser struct {
|
||||||
file *SourceFile
|
file *SourceFile
|
||||||
errors ParserErrorList
|
errors ErrorList
|
||||||
scanner *Scanner
|
scanner *Scanner
|
||||||
pos Pos
|
pos Pos
|
||||||
token token.Token
|
token token.Token
|
|
@ -1,4 +1,4 @@
|
||||||
package internal_test
|
package parser_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -7,20 +7,20 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "github.com/d5/tengo/internal"
|
. "github.com/d5/tengo/parser"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
"github.com/d5/tengo/internal/token"
|
"github.com/d5/tengo/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParserError(t *testing.T) {
|
func TestParserError(t *testing.T) {
|
||||||
err := &ParserError{Pos: SourceFilePos{
|
err := &Error{Pos: SourceFilePos{
|
||||||
Offset: 10, Line: 1, Column: 10,
|
Offset: 10, Line: 1, Column: 10,
|
||||||
}, Msg: "test"}
|
}, Msg: "test"}
|
||||||
require.Equal(t, "Parse Error: test\n\tat 1:10", err.Error())
|
require.Equal(t, "Parse Error: test\n\tat 1:10", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParserErrorList(t *testing.T) {
|
func TestParserErrorList(t *testing.T) {
|
||||||
var list ParserErrorList
|
var list ErrorList
|
||||||
list.Add(SourceFilePos{Offset: 20, Line: 2, Column: 10}, "error 2")
|
list.Add(SourceFilePos{Offset: 20, Line: 2, Column: 10}, "error 2")
|
||||||
list.Add(SourceFilePos{Offset: 30, Line: 3, Column: 10}, "error 3")
|
list.Add(SourceFilePos{Offset: 30, Line: 3, Column: 10}, "error 3")
|
||||||
list.Add(SourceFilePos{Offset: 10, Line: 1, Column: 10}, "error 1")
|
list.Add(SourceFilePos{Offset: 10, Line: 1, Column: 10}, "error 1")
|
|
@ -1,4 +1,4 @@
|
||||||
package internal
|
package parser
|
||||||
|
|
||||||
// Pos represents a position in the file set.
|
// Pos represents a position in the file set.
|
||||||
type Pos int
|
type Pos int
|
|
@ -1,11 +1,11 @@
|
||||||
package internal
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/d5/tengo/internal/token"
|
"github.com/d5/tengo/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
// byte order mark
|
// byte order mark
|
|
@ -1,4 +1,4 @@
|
||||||
package internal_test
|
package parser_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -7,12 +7,12 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/d5/tengo/internal"
|
"github.com/d5/tengo/parser"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
"github.com/d5/tengo/internal/token"
|
"github.com/d5/tengo/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
var testFileSet = internal.NewFileSet()
|
var testFileSet = parser.NewFileSet()
|
||||||
|
|
||||||
type scanResult struct {
|
type scanResult struct {
|
||||||
Token token.Token
|
Token token.Token
|
||||||
|
@ -151,7 +151,7 @@ func TestScanner_Scan(t *testing.T) {
|
||||||
switch tc.token {
|
switch tc.token {
|
||||||
case token.Comment:
|
case token.Comment:
|
||||||
// strip CRs in comments
|
// strip CRs in comments
|
||||||
expectedLiteral = string(internal.StripCR([]byte(tc.literal),
|
expectedLiteral = string(parser.StripCR([]byte(tc.literal),
|
||||||
tc.literal[1] == '*'))
|
tc.literal[1] == '*'))
|
||||||
|
|
||||||
//-style comment literal doesn't contain newline
|
//-style comment literal doesn't contain newline
|
||||||
|
@ -167,7 +167,7 @@ func TestScanner_Scan(t *testing.T) {
|
||||||
// strip CRs in raw string
|
// strip CRs in raw string
|
||||||
expectedLiteral = tc.literal
|
expectedLiteral = tc.literal
|
||||||
if expectedLiteral[0] == '`' {
|
if expectedLiteral[0] == '`' {
|
||||||
expectedLiteral = string(internal.StripCR(
|
expectedLiteral = string(parser.StripCR(
|
||||||
[]byte(expectedLiteral), false))
|
[]byte(expectedLiteral), false))
|
||||||
}
|
}
|
||||||
} else if tc.token.IsKeyword() {
|
} else if tc.token.IsKeyword() {
|
||||||
|
@ -189,9 +189,9 @@ func TestScanner_Scan(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
scanExpect(t, strings.Join(lines, "\n"),
|
scanExpect(t, strings.Join(lines, "\n"),
|
||||||
internal.ScanComments|internal.DontInsertSemis, expected...)
|
parser.ScanComments|parser.DontInsertSemis, expected...)
|
||||||
scanExpect(t, strings.Join(lines, "\n"),
|
scanExpect(t, strings.Join(lines, "\n"),
|
||||||
internal.DontInsertSemis, expectedSkipComments...)
|
parser.DontInsertSemis, expectedSkipComments...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStripCR(t *testing.T) {
|
func TestStripCR(t *testing.T) {
|
||||||
|
@ -210,7 +210,7 @@ func TestStripCR(t *testing.T) {
|
||||||
{"/*\r/\r*\r/*/", "/*/*\r/*/"},
|
{"/*\r/\r*\r/*/", "/*/*\r/*/"},
|
||||||
{"/*\r\r\r\r*/", "/**/"},
|
{"/*\r\r\r\r*/", "/**/"},
|
||||||
} {
|
} {
|
||||||
actual := string(internal.StripCR([]byte(tc.input),
|
actual := string(parser.StripCR([]byte(tc.input),
|
||||||
len(tc.input) >= 2 && tc.input[1] == '*'))
|
len(tc.input) >= 2 && tc.input[1] == '*'))
|
||||||
require.Equal(t, tc.expect, actual)
|
require.Equal(t, tc.expect, actual)
|
||||||
}
|
}
|
||||||
|
@ -219,15 +219,15 @@ func TestStripCR(t *testing.T) {
|
||||||
func scanExpect(
|
func scanExpect(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
input string,
|
input string,
|
||||||
mode internal.ScanMode,
|
mode parser.ScanMode,
|
||||||
expected ...scanResult,
|
expected ...scanResult,
|
||||||
) {
|
) {
|
||||||
testFile := testFileSet.AddFile("test", -1, len(input))
|
testFile := testFileSet.AddFile("test", -1, len(input))
|
||||||
|
|
||||||
s := internal.NewScanner(
|
s := parser.NewScanner(
|
||||||
testFile,
|
testFile,
|
||||||
[]byte(input),
|
[]byte(input),
|
||||||
func(_ internal.SourceFilePos, msg string) { require.Fail(t, msg) },
|
func(_ parser.SourceFilePos, msg string) { require.Fail(t, msg) },
|
||||||
mode)
|
mode)
|
||||||
|
|
||||||
for idx, e := range expected {
|
for idx, e := range expected {
|
|
@ -1,4 +1,4 @@
|
||||||
package internal
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
|
@ -1,9 +1,9 @@
|
||||||
package internal
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/d5/tengo/internal/token"
|
"github.com/d5/tengo/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Stmt represents a statement in the AST.
|
// Stmt represents a statement in the AST.
|
|
@ -11,8 +11,8 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal"
|
"github.com/d5/tengo/parser"
|
||||||
"github.com/d5/tengo/internal/token"
|
"github.com/d5/tengo/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NoError asserts err is not an error.
|
// NoError asserts err is not an error.
|
||||||
|
@ -120,12 +120,12 @@ func Equal(
|
||||||
if expected != actual.(rune) {
|
if expected != actual.(rune) {
|
||||||
failExpectedActual(t, expected, actual, msg...)
|
failExpectedActual(t, expected, actual, msg...)
|
||||||
}
|
}
|
||||||
case *internal.Symbol:
|
case *tengo.Symbol:
|
||||||
if !equalSymbol(expected, actual.(*internal.Symbol)) {
|
if !equalSymbol(expected, actual.(*tengo.Symbol)) {
|
||||||
failExpectedActual(t, expected, actual, msg...)
|
failExpectedActual(t, expected, actual, msg...)
|
||||||
}
|
}
|
||||||
case internal.Pos:
|
case parser.Pos:
|
||||||
if expected != actual.(internal.Pos) {
|
if expected != actual.(parser.Pos) {
|
||||||
failExpectedActual(t, expected, actual, msg...)
|
failExpectedActual(t, expected, actual, msg...)
|
||||||
}
|
}
|
||||||
case token.Token:
|
case token.Token:
|
||||||
|
@ -176,14 +176,14 @@ func Equal(
|
||||||
if !expected.Equals(actual.(tengo.Object)) {
|
if !expected.Equals(actual.(tengo.Object)) {
|
||||||
failExpectedActual(t, expected, actual, msg...)
|
failExpectedActual(t, expected, actual, msg...)
|
||||||
}
|
}
|
||||||
case *internal.SourceFileSet:
|
case *parser.SourceFileSet:
|
||||||
equalFileSet(t, expected, actual.(*internal.SourceFileSet), msg...)
|
equalFileSet(t, expected, actual.(*parser.SourceFileSet), msg...)
|
||||||
case *internal.SourceFile:
|
case *parser.SourceFile:
|
||||||
Equal(t, expected.Name, actual.(*internal.SourceFile).Name, msg...)
|
Equal(t, expected.Name, actual.(*parser.SourceFile).Name, msg...)
|
||||||
Equal(t, expected.Base, actual.(*internal.SourceFile).Base, msg...)
|
Equal(t, expected.Base, actual.(*parser.SourceFile).Base, msg...)
|
||||||
Equal(t, expected.Size, actual.(*internal.SourceFile).Size, msg...)
|
Equal(t, expected.Size, actual.(*parser.SourceFile).Size, msg...)
|
||||||
True(t, equalIntSlice(expected.Lines,
|
True(t, equalIntSlice(expected.Lines,
|
||||||
actual.(*internal.SourceFile).Lines), msg...)
|
actual.(*parser.SourceFile).Lines), msg...)
|
||||||
case error:
|
case error:
|
||||||
if expected != actual.(error) {
|
if expected != actual.(error) {
|
||||||
failExpectedActual(t, expected, actual, msg...)
|
failExpectedActual(t, expected, actual, msg...)
|
||||||
|
@ -253,7 +253,7 @@ func equalStringSlice(a, b []string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func equalSymbol(a, b *internal.Symbol) bool {
|
func equalSymbol(a, b *tengo.Symbol) bool {
|
||||||
return a.Name == b.Name &&
|
return a.Name == b.Name &&
|
||||||
a.Index == b.Index &&
|
a.Index == b.Index &&
|
||||||
a.Scope == b.Scope
|
a.Scope == b.Scope
|
||||||
|
@ -272,7 +272,7 @@ func equalObjectSlice(
|
||||||
|
|
||||||
func equalFileSet(
|
func equalFileSet(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
expected, actual *internal.SourceFileSet,
|
expected, actual *parser.SourceFileSet,
|
||||||
msg ...interface{},
|
msg ...interface{},
|
||||||
) {
|
) {
|
||||||
Equal(t, len(expected.Files), len(actual.Files), msg...)
|
Equal(t, len(expected.Files), len(actual.Files), msg...)
|
||||||
|
@ -303,8 +303,8 @@ func equalCompiledFunction(
|
||||||
expectedT := expected.(*tengo.CompiledFunction)
|
expectedT := expected.(*tengo.CompiledFunction)
|
||||||
actualT := actual.(*tengo.CompiledFunction)
|
actualT := actual.(*tengo.CompiledFunction)
|
||||||
Equal(t,
|
Equal(t,
|
||||||
internal.FormatInstructions(expectedT.Instructions, 0),
|
tengo.FormatInstructions(expectedT.Instructions, 0),
|
||||||
internal.FormatInstructions(actualT.Instructions, 0), msg...)
|
tengo.FormatInstructions(actualT.Instructions, 0), msg...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isNil(v interface{}) bool {
|
func isNil(v interface{}) bool {
|
12
script.go
12
script.go
|
@ -5,7 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/d5/tengo/internal"
|
"github.com/d5/tengo/parser"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Script can simplify compilation and execution of embedded scripts.
|
// Script can simplify compilation and execution of embedded scripts.
|
||||||
|
@ -83,9 +83,9 @@ func (s *Script) Compile() (*Compiled, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fileSet := internal.NewFileSet()
|
fileSet := parser.NewFileSet()
|
||||||
srcFile := fileSet.AddFile("(main)", -1, len(s.input))
|
srcFile := fileSet.AddFile("(main)", -1, len(s.input))
|
||||||
p := internal.NewParser(srcFile, s.input, nil)
|
p := parser.NewParser(srcFile, s.input, nil)
|
||||||
file, err := p.ParseFile()
|
file, err := p.ParseFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -104,7 +104,7 @@ func (s *Script) Compile() (*Compiled, error) {
|
||||||
globalIndexes := make(map[string]int, len(globals))
|
globalIndexes := make(map[string]int, len(globals))
|
||||||
for _, name := range symbolTable.Names() {
|
for _, name := range symbolTable.Names() {
|
||||||
symbol, _, _ := symbolTable.Resolve(name)
|
symbol, _, _ := symbolTable.Resolve(name)
|
||||||
if symbol.Scope == internal.ScopeGlobal {
|
if symbol.Scope == ScopeGlobal {
|
||||||
globalIndexes[name] = symbol.Index
|
globalIndexes[name] = symbol.Index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ func (s *Script) RunContext(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Script) prepCompile() (
|
func (s *Script) prepCompile() (
|
||||||
symbolTable *internal.SymbolTable,
|
symbolTable *SymbolTable,
|
||||||
globals []Object,
|
globals []Object,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
|
@ -161,7 +161,7 @@ func (s *Script) prepCompile() (
|
||||||
names = append(names, name)
|
names = append(names, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
symbolTable = internal.NewSymbolTable()
|
symbolTable = NewSymbolTable()
|
||||||
for idx, fn := range builtinFuncs {
|
for idx, fn := range builtinFuncs {
|
||||||
symbolTable.DefineBuiltin(idx, fn.Name)
|
symbolTable.DefineBuiltin(idx, fn.Name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
"github.com/d5/tengo/internal/token"
|
|
||||||
"github.com/d5/tengo/stdlib"
|
"github.com/d5/tengo/stdlib"
|
||||||
|
"github.com/d5/tengo/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestScript_Add(t *testing.T) {
|
func TestScript_Add(t *testing.T) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
"github.com/d5/tengo/stdlib"
|
"github.com/d5/tengo/stdlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
"github.com/d5/tengo/stdlib/json"
|
"github.com/d5/tengo/stdlib/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReadFile(t *testing.T) {
|
func TestReadFile(t *testing.T) {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRand(t *testing.T) {
|
func TestRand(t *testing.T) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
"github.com/d5/tengo/stdlib"
|
"github.com/d5/tengo/stdlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTimes(t *testing.T) {
|
func TestTimes(t *testing.T) {
|
||||||
|
|
|
@ -1,33 +1,4 @@
|
||||||
package internal
|
package tengo
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// CompilationScope represents a compiled instructions and the last two
|
|
||||||
// instructions that were emitted.
|
|
||||||
type CompilationScope struct {
|
|
||||||
Instructions []byte
|
|
||||||
SymbolInit map[string]bool
|
|
||||||
SourceMap map[int]Pos
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop represents a loop construct that the compiler uses to track the current
|
|
||||||
// loop.
|
|
||||||
type Loop struct {
|
|
||||||
Continues []int
|
|
||||||
Breaks []int
|
|
||||||
}
|
|
||||||
|
|
||||||
// CompilerError represents a compiler error.
|
|
||||||
type CompilerError struct {
|
|
||||||
FileSet *SourceFileSet
|
|
||||||
Node Node
|
|
||||||
Err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *CompilerError) Error() string {
|
|
||||||
filePos := e.FileSet.Position(e.Node.Pos())
|
|
||||||
return fmt.Sprintf("Compile Error: %s\n\tat %s", e.Err.Error(), filePos)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SymbolScope represents a symbol scope.
|
// SymbolScope represents a symbol scope.
|
||||||
type SymbolScope string
|
type SymbolScope string
|
|
@ -1,10 +1,10 @@
|
||||||
package internal_test
|
package tengo_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/d5/tengo/internal"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSymbolTable(t *testing.T) {
|
func TestSymbolTable(t *testing.T) {
|
||||||
|
@ -93,37 +93,37 @@ func TestSymbolTable(t *testing.T) {
|
||||||
|
|
||||||
func symbol(
|
func symbol(
|
||||||
name string,
|
name string,
|
||||||
scope internal.SymbolScope,
|
scope tengo.SymbolScope,
|
||||||
index int,
|
index int,
|
||||||
) *internal.Symbol {
|
) *tengo.Symbol {
|
||||||
return &internal.Symbol{
|
return &tengo.Symbol{
|
||||||
Name: name,
|
Name: name,
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
Index: index,
|
Index: index,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func globalSymbol(name string, index int) *internal.Symbol {
|
func globalSymbol(name string, index int) *tengo.Symbol {
|
||||||
return symbol(name, internal.ScopeGlobal, index)
|
return symbol(name, tengo.ScopeGlobal, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
func localSymbol(name string, index int) *internal.Symbol {
|
func localSymbol(name string, index int) *tengo.Symbol {
|
||||||
return symbol(name, internal.ScopeLocal, index)
|
return symbol(name, tengo.ScopeLocal, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
func freeSymbol(name string, index int) *internal.Symbol {
|
func freeSymbol(name string, index int) *tengo.Symbol {
|
||||||
return symbol(name, internal.ScopeFree, index)
|
return symbol(name, tengo.ScopeFree, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
func symbolTable() *internal.SymbolTable {
|
func symbolTable() *tengo.SymbolTable {
|
||||||
return internal.NewSymbolTable()
|
return tengo.NewSymbolTable()
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveExpect(
|
func resolveExpect(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
symbolTable *internal.SymbolTable,
|
symbolTable *tengo.SymbolTable,
|
||||||
name string,
|
name string,
|
||||||
expectedSymbol *internal.Symbol,
|
expectedSymbol *tengo.Symbol,
|
||||||
expectedDepth int,
|
expectedDepth int,
|
||||||
) {
|
) {
|
||||||
actualSymbol, actualDepth, ok := symbolTable.Resolve(name)
|
actualSymbol, actualDepth, ok := symbolTable.Resolve(name)
|
|
@ -6,16 +6,16 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal"
|
"github.com/d5/tengo/parser"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInstructions_String(t *testing.T) {
|
func TestInstructions_String(t *testing.T) {
|
||||||
assertInstructionString(t,
|
assertInstructionString(t,
|
||||||
[][]byte{
|
[][]byte{
|
||||||
internal.MakeInstruction(internal.OpConstant, 1),
|
tengo.MakeInstruction(parser.OpConstant, 1),
|
||||||
internal.MakeInstruction(internal.OpConstant, 2),
|
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||||
internal.MakeInstruction(internal.OpConstant, 65535),
|
tengo.MakeInstruction(parser.OpConstant, 65535),
|
||||||
},
|
},
|
||||||
`0000 CONST 1
|
`0000 CONST 1
|
||||||
0003 CONST 2
|
0003 CONST 2
|
||||||
|
@ -23,9 +23,9 @@ func TestInstructions_String(t *testing.T) {
|
||||||
|
|
||||||
assertInstructionString(t,
|
assertInstructionString(t,
|
||||||
[][]byte{
|
[][]byte{
|
||||||
internal.MakeInstruction(internal.OpBinaryOp, 11),
|
tengo.MakeInstruction(parser.OpBinaryOp, 11),
|
||||||
internal.MakeInstruction(internal.OpConstant, 2),
|
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||||
internal.MakeInstruction(internal.OpConstant, 65535),
|
tengo.MakeInstruction(parser.OpConstant, 65535),
|
||||||
},
|
},
|
||||||
`0000 BINARYOP 11
|
`0000 BINARYOP 11
|
||||||
0002 CONST 2
|
0002 CONST 2
|
||||||
|
@ -33,10 +33,10 @@ func TestInstructions_String(t *testing.T) {
|
||||||
|
|
||||||
assertInstructionString(t,
|
assertInstructionString(t,
|
||||||
[][]byte{
|
[][]byte{
|
||||||
internal.MakeInstruction(internal.OpBinaryOp, 11),
|
tengo.MakeInstruction(parser.OpBinaryOp, 11),
|
||||||
internal.MakeInstruction(internal.OpGetLocal, 1),
|
tengo.MakeInstruction(parser.OpGetLocal, 1),
|
||||||
internal.MakeInstruction(internal.OpConstant, 2),
|
tengo.MakeInstruction(parser.OpConstant, 2),
|
||||||
internal.MakeInstruction(internal.OpConstant, 65535),
|
tengo.MakeInstruction(parser.OpConstant, 65535),
|
||||||
},
|
},
|
||||||
`0000 BINARYOP 11
|
`0000 BINARYOP 11
|
||||||
0002 GETL 1
|
0002 GETL 1
|
||||||
|
@ -45,15 +45,15 @@ func TestInstructions_String(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeInstruction(t *testing.T) {
|
func TestMakeInstruction(t *testing.T) {
|
||||||
makeInstruction(t, []byte{internal.OpConstant, 0, 0},
|
makeInstruction(t, []byte{parser.OpConstant, 0, 0},
|
||||||
internal.OpConstant, 0)
|
parser.OpConstant, 0)
|
||||||
makeInstruction(t, []byte{internal.OpConstant, 0, 1},
|
makeInstruction(t, []byte{parser.OpConstant, 0, 1},
|
||||||
internal.OpConstant, 1)
|
parser.OpConstant, 1)
|
||||||
makeInstruction(t, []byte{internal.OpConstant, 255, 254},
|
makeInstruction(t, []byte{parser.OpConstant, 255, 254},
|
||||||
internal.OpConstant, 65534)
|
parser.OpConstant, 65534)
|
||||||
makeInstruction(t, []byte{internal.OpPop}, internal.OpPop)
|
makeInstruction(t, []byte{parser.OpPop}, parser.OpPop)
|
||||||
makeInstruction(t, []byte{internal.OpTrue}, internal.OpTrue)
|
makeInstruction(t, []byte{parser.OpTrue}, parser.OpTrue)
|
||||||
makeInstruction(t, []byte{internal.OpFalse}, internal.OpFalse)
|
makeInstruction(t, []byte{parser.OpFalse}, parser.OpFalse)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNumObjects(t *testing.T) {
|
func TestNumObjects(t *testing.T) {
|
||||||
|
@ -123,15 +123,15 @@ func assertInstructionString(
|
||||||
concatted = append(concatted, e...)
|
concatted = append(concatted, e...)
|
||||||
}
|
}
|
||||||
require.Equal(t, expected, strings.Join(
|
require.Equal(t, expected, strings.Join(
|
||||||
internal.FormatInstructions(concatted, 0), "\n"))
|
tengo.FormatInstructions(concatted, 0), "\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeInstruction(
|
func makeInstruction(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
expected []byte,
|
expected []byte,
|
||||||
opcode internal.Opcode,
|
opcode parser.Opcode,
|
||||||
operands ...int,
|
operands ...int,
|
||||||
) {
|
) {
|
||||||
inst := internal.MakeInstruction(opcode, operands...)
|
inst := tengo.MakeInstruction(opcode, operands...)
|
||||||
require.Equal(t, expected, inst)
|
require.Equal(t, expected, inst)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
type VariableTest struct {
|
type VariableTest struct {
|
||||||
|
|
96
vm.go
96
vm.go
|
@ -4,8 +4,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/d5/tengo/internal"
|
"github.com/d5/tengo/parser"
|
||||||
"github.com/d5/tengo/internal/token"
|
"github.com/d5/tengo/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
// frame represents a function call frame.
|
// frame represents a function call frame.
|
||||||
|
@ -22,7 +22,7 @@ type VM struct {
|
||||||
stack [StackSize]Object
|
stack [StackSize]Object
|
||||||
sp int
|
sp int
|
||||||
globals []Object
|
globals []Object
|
||||||
fileSet *internal.SourceFileSet
|
fileSet *parser.SourceFileSet
|
||||||
frames [MaxFrames]frame
|
frames [MaxFrames]frame
|
||||||
framesIndex int
|
framesIndex int
|
||||||
curFrame *frame
|
curFrame *frame
|
||||||
|
@ -99,16 +99,16 @@ func (v *VM) run() {
|
||||||
v.ip++
|
v.ip++
|
||||||
|
|
||||||
switch v.curInsts[v.ip] {
|
switch v.curInsts[v.ip] {
|
||||||
case internal.OpConstant:
|
case parser.OpConstant:
|
||||||
v.ip += 2
|
v.ip += 2
|
||||||
cidx := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
cidx := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
||||||
|
|
||||||
v.stack[v.sp] = v.constants[cidx]
|
v.stack[v.sp] = v.constants[cidx]
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpNull:
|
case parser.OpNull:
|
||||||
v.stack[v.sp] = UndefinedValue
|
v.stack[v.sp] = UndefinedValue
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpBinaryOp:
|
case parser.OpBinaryOp:
|
||||||
v.ip++
|
v.ip++
|
||||||
right := v.stack[v.sp-1]
|
right := v.stack[v.sp-1]
|
||||||
left := v.stack[v.sp-2]
|
left := v.stack[v.sp-2]
|
||||||
|
@ -133,7 +133,7 @@ func (v *VM) run() {
|
||||||
|
|
||||||
v.stack[v.sp-2] = res
|
v.stack[v.sp-2] = res
|
||||||
v.sp--
|
v.sp--
|
||||||
case internal.OpEqual:
|
case parser.OpEqual:
|
||||||
right := v.stack[v.sp-1]
|
right := v.stack[v.sp-1]
|
||||||
left := v.stack[v.sp-2]
|
left := v.stack[v.sp-2]
|
||||||
v.sp -= 2
|
v.sp -= 2
|
||||||
|
@ -143,7 +143,7 @@ func (v *VM) run() {
|
||||||
v.stack[v.sp] = FalseValue
|
v.stack[v.sp] = FalseValue
|
||||||
}
|
}
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpNotEqual:
|
case parser.OpNotEqual:
|
||||||
right := v.stack[v.sp-1]
|
right := v.stack[v.sp-1]
|
||||||
left := v.stack[v.sp-2]
|
left := v.stack[v.sp-2]
|
||||||
v.sp -= 2
|
v.sp -= 2
|
||||||
|
@ -153,15 +153,15 @@ func (v *VM) run() {
|
||||||
v.stack[v.sp] = TrueValue
|
v.stack[v.sp] = TrueValue
|
||||||
}
|
}
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpPop:
|
case parser.OpPop:
|
||||||
v.sp--
|
v.sp--
|
||||||
case internal.OpTrue:
|
case parser.OpTrue:
|
||||||
v.stack[v.sp] = TrueValue
|
v.stack[v.sp] = TrueValue
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpFalse:
|
case parser.OpFalse:
|
||||||
v.stack[v.sp] = FalseValue
|
v.stack[v.sp] = FalseValue
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpLNot:
|
case parser.OpLNot:
|
||||||
operand := v.stack[v.sp-1]
|
operand := v.stack[v.sp-1]
|
||||||
v.sp--
|
v.sp--
|
||||||
if operand.IsFalsy() {
|
if operand.IsFalsy() {
|
||||||
|
@ -170,7 +170,7 @@ func (v *VM) run() {
|
||||||
v.stack[v.sp] = FalseValue
|
v.stack[v.sp] = FalseValue
|
||||||
}
|
}
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpBComplement:
|
case parser.OpBComplement:
|
||||||
operand := v.stack[v.sp-1]
|
operand := v.stack[v.sp-1]
|
||||||
v.sp--
|
v.sp--
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ func (v *VM) run() {
|
||||||
operand.TypeName())
|
operand.TypeName())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case internal.OpMinus:
|
case parser.OpMinus:
|
||||||
operand := v.stack[v.sp-1]
|
operand := v.stack[v.sp-1]
|
||||||
v.sp--
|
v.sp--
|
||||||
|
|
||||||
|
@ -217,14 +217,14 @@ func (v *VM) run() {
|
||||||
operand.TypeName())
|
operand.TypeName())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case internal.OpJumpFalsy:
|
case parser.OpJumpFalsy:
|
||||||
v.ip += 2
|
v.ip += 2
|
||||||
v.sp--
|
v.sp--
|
||||||
if v.stack[v.sp].IsFalsy() {
|
if v.stack[v.sp].IsFalsy() {
|
||||||
pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
||||||
v.ip = pos - 1
|
v.ip = pos - 1
|
||||||
}
|
}
|
||||||
case internal.OpAndJump:
|
case parser.OpAndJump:
|
||||||
v.ip += 2
|
v.ip += 2
|
||||||
if v.stack[v.sp-1].IsFalsy() {
|
if v.stack[v.sp-1].IsFalsy() {
|
||||||
pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
||||||
|
@ -232,7 +232,7 @@ func (v *VM) run() {
|
||||||
} else {
|
} else {
|
||||||
v.sp--
|
v.sp--
|
||||||
}
|
}
|
||||||
case internal.OpOrJump:
|
case parser.OpOrJump:
|
||||||
v.ip += 2
|
v.ip += 2
|
||||||
if v.stack[v.sp-1].IsFalsy() {
|
if v.stack[v.sp-1].IsFalsy() {
|
||||||
v.sp--
|
v.sp--
|
||||||
|
@ -240,15 +240,15 @@ func (v *VM) run() {
|
||||||
pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
||||||
v.ip = pos - 1
|
v.ip = pos - 1
|
||||||
}
|
}
|
||||||
case internal.OpJump:
|
case parser.OpJump:
|
||||||
pos := int(v.curInsts[v.ip+2]) | int(v.curInsts[v.ip+1])<<8
|
pos := int(v.curInsts[v.ip+2]) | int(v.curInsts[v.ip+1])<<8
|
||||||
v.ip = pos - 1
|
v.ip = pos - 1
|
||||||
case internal.OpSetGlobal:
|
case parser.OpSetGlobal:
|
||||||
v.ip += 2
|
v.ip += 2
|
||||||
v.sp--
|
v.sp--
|
||||||
globalIndex := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
globalIndex := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
||||||
v.globals[globalIndex] = v.stack[v.sp]
|
v.globals[globalIndex] = v.stack[v.sp]
|
||||||
case internal.OpSetSelGlobal:
|
case parser.OpSetSelGlobal:
|
||||||
v.ip += 3
|
v.ip += 3
|
||||||
globalIndex := int(v.curInsts[v.ip-1]) | int(v.curInsts[v.ip-2])<<8
|
globalIndex := int(v.curInsts[v.ip-1]) | int(v.curInsts[v.ip-2])<<8
|
||||||
numSelectors := int(v.curInsts[v.ip])
|
numSelectors := int(v.curInsts[v.ip])
|
||||||
|
@ -265,13 +265,13 @@ func (v *VM) run() {
|
||||||
v.err = e
|
v.err = e
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case internal.OpGetGlobal:
|
case parser.OpGetGlobal:
|
||||||
v.ip += 2
|
v.ip += 2
|
||||||
globalIndex := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
globalIndex := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
||||||
val := v.globals[globalIndex]
|
val := v.globals[globalIndex]
|
||||||
v.stack[v.sp] = val
|
v.stack[v.sp] = val
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpArray:
|
case parser.OpArray:
|
||||||
v.ip += 2
|
v.ip += 2
|
||||||
numElements := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
numElements := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
||||||
|
|
||||||
|
@ -290,7 +290,7 @@ func (v *VM) run() {
|
||||||
|
|
||||||
v.stack[v.sp] = arr
|
v.stack[v.sp] = arr
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpMap:
|
case parser.OpMap:
|
||||||
v.ip += 2
|
v.ip += 2
|
||||||
numElements := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
numElements := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
||||||
kv := make(map[string]Object)
|
kv := make(map[string]Object)
|
||||||
|
@ -309,7 +309,7 @@ func (v *VM) run() {
|
||||||
}
|
}
|
||||||
v.stack[v.sp] = m
|
v.stack[v.sp] = m
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpError:
|
case parser.OpError:
|
||||||
value := v.stack[v.sp-1]
|
value := v.stack[v.sp-1]
|
||||||
var e Object = &Error{
|
var e Object = &Error{
|
||||||
Value: value,
|
Value: value,
|
||||||
|
@ -320,7 +320,7 @@ func (v *VM) run() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v.stack[v.sp-1] = e
|
v.stack[v.sp-1] = e
|
||||||
case internal.OpImmutable:
|
case parser.OpImmutable:
|
||||||
value := v.stack[v.sp-1]
|
value := v.stack[v.sp-1]
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case *Array:
|
case *Array:
|
||||||
|
@ -344,7 +344,7 @@ func (v *VM) run() {
|
||||||
}
|
}
|
||||||
v.stack[v.sp-1] = immutableMap
|
v.stack[v.sp-1] = immutableMap
|
||||||
}
|
}
|
||||||
case internal.OpIndex:
|
case parser.OpIndex:
|
||||||
index := v.stack[v.sp-1]
|
index := v.stack[v.sp-1]
|
||||||
left := v.stack[v.sp-2]
|
left := v.stack[v.sp-2]
|
||||||
v.sp -= 2
|
v.sp -= 2
|
||||||
|
@ -368,7 +368,7 @@ func (v *VM) run() {
|
||||||
}
|
}
|
||||||
v.stack[v.sp] = val
|
v.stack[v.sp] = val
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpSliceIndex:
|
case parser.OpSliceIndex:
|
||||||
high := v.stack[v.sp-1]
|
high := v.stack[v.sp-1]
|
||||||
low := v.stack[v.sp-2]
|
low := v.stack[v.sp-2]
|
||||||
left := v.stack[v.sp-3]
|
left := v.stack[v.sp-3]
|
||||||
|
@ -535,7 +535,7 @@ func (v *VM) run() {
|
||||||
v.stack[v.sp] = val
|
v.stack[v.sp] = val
|
||||||
v.sp++
|
v.sp++
|
||||||
}
|
}
|
||||||
case internal.OpCall:
|
case parser.OpCall:
|
||||||
numArgs := int(v.curInsts[v.ip+1])
|
numArgs := int(v.curInsts[v.ip+1])
|
||||||
v.ip++
|
v.ip++
|
||||||
value := v.stack[v.sp-1-numArgs]
|
value := v.stack[v.sp-1-numArgs]
|
||||||
|
@ -576,9 +576,9 @@ func (v *VM) run() {
|
||||||
// test if it's tail-call
|
// test if it's tail-call
|
||||||
if callee == v.curFrame.fn { // recursion
|
if callee == v.curFrame.fn { // recursion
|
||||||
nextOp := v.curInsts[v.ip+1]
|
nextOp := v.curInsts[v.ip+1]
|
||||||
if nextOp == internal.OpReturn ||
|
if nextOp == parser.OpReturn ||
|
||||||
(nextOp == internal.OpPop &&
|
(nextOp == parser.OpPop &&
|
||||||
internal.OpReturn == v.curInsts[v.ip+2]) {
|
parser.OpReturn == v.curInsts[v.ip+2]) {
|
||||||
for p := 0; p < numArgs; p++ {
|
for p := 0; p < numArgs; p++ {
|
||||||
v.stack[v.curFrame.basePointer+p] =
|
v.stack[v.curFrame.basePointer+p] =
|
||||||
v.stack[v.sp-numArgs+p]
|
v.stack[v.sp-numArgs+p]
|
||||||
|
@ -640,7 +640,7 @@ func (v *VM) run() {
|
||||||
v.stack[v.sp] = ret
|
v.stack[v.sp] = ret
|
||||||
v.sp++
|
v.sp++
|
||||||
}
|
}
|
||||||
case internal.OpReturn:
|
case parser.OpReturn:
|
||||||
v.ip++
|
v.ip++
|
||||||
var retVal Object
|
var retVal Object
|
||||||
if int(v.curInsts[v.ip]) == 1 {
|
if int(v.curInsts[v.ip]) == 1 {
|
||||||
|
@ -658,7 +658,7 @@ func (v *VM) run() {
|
||||||
// skip stack overflow check because (newSP) <= (oldSP)
|
// skip stack overflow check because (newSP) <= (oldSP)
|
||||||
v.stack[v.sp-1] = retVal
|
v.stack[v.sp-1] = retVal
|
||||||
//v.sp++
|
//v.sp++
|
||||||
case internal.OpDefineLocal:
|
case parser.OpDefineLocal:
|
||||||
v.ip++
|
v.ip++
|
||||||
localIndex := int(v.curInsts[v.ip])
|
localIndex := int(v.curInsts[v.ip])
|
||||||
sp := v.curFrame.basePointer + localIndex
|
sp := v.curFrame.basePointer + localIndex
|
||||||
|
@ -668,7 +668,7 @@ func (v *VM) run() {
|
||||||
val := v.stack[v.sp-1]
|
val := v.stack[v.sp-1]
|
||||||
v.sp--
|
v.sp--
|
||||||
v.stack[sp] = val
|
v.stack[sp] = val
|
||||||
case internal.OpSetLocal:
|
case parser.OpSetLocal:
|
||||||
localIndex := int(v.curInsts[v.ip+1])
|
localIndex := int(v.curInsts[v.ip+1])
|
||||||
v.ip++
|
v.ip++
|
||||||
sp := v.curFrame.basePointer + localIndex
|
sp := v.curFrame.basePointer + localIndex
|
||||||
|
@ -683,7 +683,7 @@ func (v *VM) run() {
|
||||||
val = obj
|
val = obj
|
||||||
}
|
}
|
||||||
v.stack[sp] = val // also use a copy of popped value
|
v.stack[sp] = val // also use a copy of popped value
|
||||||
case internal.OpSetSelLocal:
|
case parser.OpSetSelLocal:
|
||||||
localIndex := int(v.curInsts[v.ip+1])
|
localIndex := int(v.curInsts[v.ip+1])
|
||||||
numSelectors := int(v.curInsts[v.ip+2])
|
numSelectors := int(v.curInsts[v.ip+2])
|
||||||
v.ip += 2
|
v.ip += 2
|
||||||
|
@ -703,7 +703,7 @@ func (v *VM) run() {
|
||||||
v.err = e
|
v.err = e
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case internal.OpGetLocal:
|
case parser.OpGetLocal:
|
||||||
v.ip++
|
v.ip++
|
||||||
localIndex := int(v.curInsts[v.ip])
|
localIndex := int(v.curInsts[v.ip])
|
||||||
val := v.stack[v.curFrame.basePointer+localIndex]
|
val := v.stack[v.curFrame.basePointer+localIndex]
|
||||||
|
@ -712,12 +712,12 @@ func (v *VM) run() {
|
||||||
}
|
}
|
||||||
v.stack[v.sp] = val
|
v.stack[v.sp] = val
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpGetBuiltin:
|
case parser.OpGetBuiltin:
|
||||||
v.ip++
|
v.ip++
|
||||||
builtinIndex := int(v.curInsts[v.ip])
|
builtinIndex := int(v.curInsts[v.ip])
|
||||||
v.stack[v.sp] = builtinFuncs[builtinIndex]
|
v.stack[v.sp] = builtinFuncs[builtinIndex]
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpClosure:
|
case parser.OpClosure:
|
||||||
v.ip += 3
|
v.ip += 3
|
||||||
constIndex := int(v.curInsts[v.ip-1]) | int(v.curInsts[v.ip-2])<<8
|
constIndex := int(v.curInsts[v.ip-1]) | int(v.curInsts[v.ip-2])<<8
|
||||||
numFree := int(v.curInsts[v.ip])
|
numFree := int(v.curInsts[v.ip])
|
||||||
|
@ -752,24 +752,24 @@ func (v *VM) run() {
|
||||||
}
|
}
|
||||||
v.stack[v.sp] = cl
|
v.stack[v.sp] = cl
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpGetFreePtr:
|
case parser.OpGetFreePtr:
|
||||||
v.ip++
|
v.ip++
|
||||||
freeIndex := int(v.curInsts[v.ip])
|
freeIndex := int(v.curInsts[v.ip])
|
||||||
val := v.curFrame.freeVars[freeIndex]
|
val := v.curFrame.freeVars[freeIndex]
|
||||||
v.stack[v.sp] = val
|
v.stack[v.sp] = val
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpGetFree:
|
case parser.OpGetFree:
|
||||||
v.ip++
|
v.ip++
|
||||||
freeIndex := int(v.curInsts[v.ip])
|
freeIndex := int(v.curInsts[v.ip])
|
||||||
val := *v.curFrame.freeVars[freeIndex].Value
|
val := *v.curFrame.freeVars[freeIndex].Value
|
||||||
v.stack[v.sp] = val
|
v.stack[v.sp] = val
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpSetFree:
|
case parser.OpSetFree:
|
||||||
v.ip++
|
v.ip++
|
||||||
freeIndex := int(v.curInsts[v.ip])
|
freeIndex := int(v.curInsts[v.ip])
|
||||||
*v.curFrame.freeVars[freeIndex].Value = v.stack[v.sp-1]
|
*v.curFrame.freeVars[freeIndex].Value = v.stack[v.sp-1]
|
||||||
v.sp--
|
v.sp--
|
||||||
case internal.OpGetLocalPtr:
|
case parser.OpGetLocalPtr:
|
||||||
v.ip++
|
v.ip++
|
||||||
localIndex := int(v.curInsts[v.ip])
|
localIndex := int(v.curInsts[v.ip])
|
||||||
sp := v.curFrame.basePointer + localIndex
|
sp := v.curFrame.basePointer + localIndex
|
||||||
|
@ -783,7 +783,7 @@ func (v *VM) run() {
|
||||||
}
|
}
|
||||||
v.stack[v.sp] = freeVar
|
v.stack[v.sp] = freeVar
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpSetSelFree:
|
case parser.OpSetSelFree:
|
||||||
v.ip += 2
|
v.ip += 2
|
||||||
freeIndex := int(v.curInsts[v.ip-1])
|
freeIndex := int(v.curInsts[v.ip-1])
|
||||||
numSelectors := int(v.curInsts[v.ip])
|
numSelectors := int(v.curInsts[v.ip])
|
||||||
|
@ -801,7 +801,7 @@ func (v *VM) run() {
|
||||||
v.err = e
|
v.err = e
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case internal.OpIteratorInit:
|
case parser.OpIteratorInit:
|
||||||
var iterator Object
|
var iterator Object
|
||||||
dst := v.stack[v.sp-1]
|
dst := v.stack[v.sp-1]
|
||||||
v.sp--
|
v.sp--
|
||||||
|
@ -817,7 +817,7 @@ func (v *VM) run() {
|
||||||
}
|
}
|
||||||
v.stack[v.sp] = iterator
|
v.stack[v.sp] = iterator
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpIteratorNext:
|
case parser.OpIteratorNext:
|
||||||
iterator := v.stack[v.sp-1]
|
iterator := v.stack[v.sp-1]
|
||||||
v.sp--
|
v.sp--
|
||||||
hasMore := iterator.(Iterator).Next()
|
hasMore := iterator.(Iterator).Next()
|
||||||
|
@ -827,19 +827,19 @@ func (v *VM) run() {
|
||||||
v.stack[v.sp] = FalseValue
|
v.stack[v.sp] = FalseValue
|
||||||
}
|
}
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpIteratorKey:
|
case parser.OpIteratorKey:
|
||||||
iterator := v.stack[v.sp-1]
|
iterator := v.stack[v.sp-1]
|
||||||
v.sp--
|
v.sp--
|
||||||
val := iterator.(Iterator).Key()
|
val := iterator.(Iterator).Key()
|
||||||
v.stack[v.sp] = val
|
v.stack[v.sp] = val
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpIteratorValue:
|
case parser.OpIteratorValue:
|
||||||
iterator := v.stack[v.sp-1]
|
iterator := v.stack[v.sp-1]
|
||||||
v.sp--
|
v.sp--
|
||||||
val := iterator.(Iterator).Value()
|
val := iterator.(Iterator).Value()
|
||||||
v.stack[v.sp] = val
|
v.stack[v.sp] = val
|
||||||
v.sp++
|
v.sp++
|
||||||
case internal.OpSuspend:
|
case parser.OpSuspend:
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
v.err = fmt.Errorf("unknown opcode: %d", v.curInsts[v.ip])
|
v.err = fmt.Errorf("unknown opcode: %d", v.curInsts[v.ip])
|
||||||
|
|
16
vm_test.go
16
vm_test.go
|
@ -11,10 +11,10 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/d5/tengo"
|
"github.com/d5/tengo"
|
||||||
"github.com/d5/tengo/internal"
|
"github.com/d5/tengo/parser"
|
||||||
"github.com/d5/tengo/internal/require"
|
"github.com/d5/tengo/require"
|
||||||
"github.com/d5/tengo/internal/token"
|
|
||||||
"github.com/d5/tengo/stdlib"
|
"github.com/d5/tengo/stdlib"
|
||||||
|
"github.com/d5/tengo/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
const testOut = "out"
|
const testOut = "out"
|
||||||
|
@ -3276,7 +3276,7 @@ func (o *vmTracer) Write(p []byte) (n int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func traceCompileRun(
|
func traceCompileRun(
|
||||||
file *internal.File,
|
file *parser.File,
|
||||||
symbols map[string]tengo.Object,
|
symbols map[string]tengo.Object,
|
||||||
modules *tengo.ModuleMap,
|
modules *tengo.ModuleMap,
|
||||||
maxAllocs int64,
|
maxAllocs int64,
|
||||||
|
@ -3306,7 +3306,7 @@ func traceCompileRun(
|
||||||
|
|
||||||
globals := make([]tengo.Object, tengo.GlobalsSize)
|
globals := make([]tengo.Object, tengo.GlobalsSize)
|
||||||
|
|
||||||
symTable := internal.NewSymbolTable()
|
symTable := tengo.NewSymbolTable()
|
||||||
for name, value := range symbols {
|
for name, value := range symbols {
|
||||||
sym := symTable.Define(name)
|
sym := symTable.Define(name)
|
||||||
|
|
||||||
|
@ -3371,11 +3371,11 @@ func formatGlobals(globals []tengo.Object) (formatted []string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parse(t *testing.T, input string) *internal.File {
|
func parse(t *testing.T, input string) *parser.File {
|
||||||
testFileSet := internal.NewFileSet()
|
testFileSet := parser.NewFileSet()
|
||||||
testFile := testFileSet.AddFile("test", -1, len(input))
|
testFile := testFileSet.AddFile("test", -1, len(input))
|
||||||
|
|
||||||
p := internal.NewParser(testFile, []byte(input), nil)
|
p := parser.NewParser(testFile, []byte(input), nil)
|
||||||
file, err := p.ParseFile()
|
file, err := p.ParseFile()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return file
|
return file
|
||||||
|
|
Loading…
Reference in a new issue