vm: use BinWriter instead of Buffered version
In the future we could reuse emit interface without buf better
This commit is contained in:
parent
f5e2401984
commit
b08387efdb
2 changed files with 104 additions and 104 deletions
|
@ -64,17 +64,17 @@ func (c *codegen) emitLoadConst(t types.TypeAndValue) {
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
case types.Int, types.UntypedInt, types.Uint:
|
case types.Int, types.UntypedInt, types.Uint:
|
||||||
val, _ := constant.Int64Val(t.Value)
|
val, _ := constant.Int64Val(t.Value)
|
||||||
emitInt(c.prog, val)
|
emitInt(c.prog.BinWriter, val)
|
||||||
case types.String, types.UntypedString:
|
case types.String, types.UntypedString:
|
||||||
val := constant.StringVal(t.Value)
|
val := constant.StringVal(t.Value)
|
||||||
emitString(c.prog, val)
|
emitString(c.prog.BinWriter, val)
|
||||||
case types.Bool, types.UntypedBool:
|
case types.Bool, types.UntypedBool:
|
||||||
val := constant.BoolVal(t.Value)
|
val := constant.BoolVal(t.Value)
|
||||||
emitBool(c.prog, val)
|
emitBool(c.prog.BinWriter, val)
|
||||||
case types.Byte:
|
case types.Byte:
|
||||||
val, _ := constant.Int64Val(t.Value)
|
val, _ := constant.Int64Val(t.Value)
|
||||||
b := byte(val)
|
b := byte(val)
|
||||||
emitBytes(c.prog, []byte{b})
|
emitBytes(c.prog.BinWriter, []byte{b})
|
||||||
default:
|
default:
|
||||||
c.prog.Err = fmt.Errorf("compiler doesn't know how to convert this basic type: %v", t)
|
c.prog.Err = fmt.Errorf("compiler doesn't know how to convert this basic type: %v", t)
|
||||||
return
|
return
|
||||||
|
@ -95,34 +95,34 @@ func (c *codegen) emitLoadLocal(name string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *codegen) emitLoadLocalPos(pos int) {
|
func (c *codegen) emitLoadLocalPos(pos int) {
|
||||||
emitOpcode(c.prog, vm.DUPFROMALTSTACK)
|
emitOpcode(c.prog.BinWriter, vm.DUPFROMALTSTACK)
|
||||||
emitInt(c.prog, int64(pos))
|
emitInt(c.prog.BinWriter, int64(pos))
|
||||||
emitOpcode(c.prog, vm.PICKITEM)
|
emitOpcode(c.prog.BinWriter, vm.PICKITEM)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *codegen) emitStoreLocal(pos int) {
|
func (c *codegen) emitStoreLocal(pos int) {
|
||||||
emitOpcode(c.prog, vm.DUPFROMALTSTACK)
|
emitOpcode(c.prog.BinWriter, vm.DUPFROMALTSTACK)
|
||||||
|
|
||||||
if pos < 0 {
|
if pos < 0 {
|
||||||
c.prog.Err = fmt.Errorf("invalid position to store local: %d", pos)
|
c.prog.Err = fmt.Errorf("invalid position to store local: %d", pos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
emitInt(c.prog, int64(pos))
|
emitInt(c.prog.BinWriter, int64(pos))
|
||||||
emitInt(c.prog, 2)
|
emitInt(c.prog.BinWriter, 2)
|
||||||
emitOpcode(c.prog, vm.ROLL)
|
emitOpcode(c.prog.BinWriter, vm.ROLL)
|
||||||
emitOpcode(c.prog, vm.SETITEM)
|
emitOpcode(c.prog.BinWriter, vm.SETITEM)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *codegen) emitLoadField(i int) {
|
func (c *codegen) emitLoadField(i int) {
|
||||||
emitInt(c.prog, int64(i))
|
emitInt(c.prog.BinWriter, int64(i))
|
||||||
emitOpcode(c.prog, vm.PICKITEM)
|
emitOpcode(c.prog.BinWriter, vm.PICKITEM)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *codegen) emitStoreStructField(i int) {
|
func (c *codegen) emitStoreStructField(i int) {
|
||||||
emitInt(c.prog, int64(i))
|
emitInt(c.prog.BinWriter, int64(i))
|
||||||
emitOpcode(c.prog, vm.ROT)
|
emitOpcode(c.prog.BinWriter, vm.ROT)
|
||||||
emitOpcode(c.prog, vm.SETITEM)
|
emitOpcode(c.prog.BinWriter, vm.SETITEM)
|
||||||
}
|
}
|
||||||
|
|
||||||
// convertGlobals traverses the AST and only converts global declarations.
|
// convertGlobals traverses the AST and only converts global declarations.
|
||||||
|
@ -162,9 +162,9 @@ func (c *codegen) convertFuncDecl(file ast.Node, decl *ast.FuncDecl) {
|
||||||
|
|
||||||
// All globals copied into the scope of the function need to be added
|
// All globals copied into the scope of the function need to be added
|
||||||
// to the stack size of the function.
|
// to the stack size of the function.
|
||||||
emitInt(c.prog, f.stackSize()+countGlobals(file))
|
emitInt(c.prog.BinWriter, f.stackSize()+countGlobals(file))
|
||||||
emitOpcode(c.prog, vm.NEWARRAY)
|
emitOpcode(c.prog.BinWriter, vm.NEWARRAY)
|
||||||
emitOpcode(c.prog, vm.TOALTSTACK)
|
emitOpcode(c.prog.BinWriter, vm.TOALTSTACK)
|
||||||
|
|
||||||
// We need to handle methods, which in Go, is just syntactic sugar.
|
// We need to handle methods, which in Go, is just syntactic sugar.
|
||||||
// The method receiver will be passed in as first argument.
|
// The method receiver will be passed in as first argument.
|
||||||
|
@ -202,9 +202,9 @@ func (c *codegen) convertFuncDecl(file ast.Node, decl *ast.FuncDecl) {
|
||||||
|
|
||||||
// If this function returns the void (no return stmt) we will cleanup its junk on the stack.
|
// If this function returns the void (no return stmt) we will cleanup its junk on the stack.
|
||||||
if !hasReturnStmt(decl) {
|
if !hasReturnStmt(decl) {
|
||||||
emitOpcode(c.prog, vm.FROMALTSTACK)
|
emitOpcode(c.prog.BinWriter, vm.FROMALTSTACK)
|
||||||
emitOpcode(c.prog, vm.DROP)
|
emitOpcode(c.prog.BinWriter, vm.DROP)
|
||||||
emitOpcode(c.prog, vm.RET)
|
emitOpcode(c.prog.BinWriter, vm.RET)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,9 +295,9 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
ast.Walk(c, n.Results[0])
|
ast.Walk(c, n.Results[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
emitOpcode(c.prog, vm.FROMALTSTACK)
|
emitOpcode(c.prog.BinWriter, vm.FROMALTSTACK)
|
||||||
emitOpcode(c.prog, vm.DROP) // Cleanup the stack.
|
emitOpcode(c.prog.BinWriter, vm.DROP) // Cleanup the stack.
|
||||||
emitOpcode(c.prog, vm.RET)
|
emitOpcode(c.prog.BinWriter, vm.RET)
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case *ast.IfStmt:
|
case *ast.IfStmt:
|
||||||
|
@ -307,13 +307,13 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
|
|
||||||
if n.Cond != nil {
|
if n.Cond != nil {
|
||||||
ast.Walk(c, n.Cond)
|
ast.Walk(c, n.Cond)
|
||||||
emitJmp(c.prog, vm.JMPIFNOT, int16(lElse))
|
emitJmp(c.prog.BinWriter, vm.JMPIFNOT, int16(lElse))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.setLabel(lIf)
|
c.setLabel(lIf)
|
||||||
ast.Walk(c, n.Body)
|
ast.Walk(c, n.Body)
|
||||||
if n.Else != nil {
|
if n.Else != nil {
|
||||||
emitJmp(c.prog, vm.JMP, int16(lElseEnd))
|
emitJmp(c.prog.BinWriter, vm.JMP, int16(lElseEnd))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.setLabel(lElse)
|
c.setLabel(lElse)
|
||||||
|
@ -358,8 +358,8 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
for i := ln - 1; i >= 0; i-- {
|
for i := ln - 1; i >= 0; i-- {
|
||||||
c.emitLoadConst(c.typeInfo.Types[n.Elts[i]])
|
c.emitLoadConst(c.typeInfo.Types[n.Elts[i]])
|
||||||
}
|
}
|
||||||
emitInt(c.prog, int64(ln))
|
emitInt(c.prog.BinWriter, int64(ln))
|
||||||
emitOpcode(c.prog, vm.PACK)
|
emitOpcode(c.prog.BinWriter, vm.PACK)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,13 +374,13 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case token.LAND:
|
case token.LAND:
|
||||||
ast.Walk(c, n.X)
|
ast.Walk(c, n.X)
|
||||||
emitJmp(c.prog, vm.JMPIFNOT, int16(len(c.l)-1))
|
emitJmp(c.prog.BinWriter, vm.JMPIFNOT, int16(len(c.l)-1))
|
||||||
ast.Walk(c, n.Y)
|
ast.Walk(c, n.Y)
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case token.LOR:
|
case token.LOR:
|
||||||
ast.Walk(c, n.X)
|
ast.Walk(c, n.X)
|
||||||
emitJmp(c.prog, vm.JMPIF, int16(len(c.l)-3))
|
emitJmp(c.prog.BinWriter, vm.JMPIF, int16(len(c.l)-3))
|
||||||
ast.Walk(c, n.Y)
|
ast.Walk(c, n.Y)
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
@ -405,24 +405,24 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
case n.Op == token.ADD:
|
case n.Op == token.ADD:
|
||||||
// VM has separate opcodes for number and string concatenation
|
// VM has separate opcodes for number and string concatenation
|
||||||
if isStringType(tinfo.Type) {
|
if isStringType(tinfo.Type) {
|
||||||
emitOpcode(c.prog, vm.CAT)
|
emitOpcode(c.prog.BinWriter, vm.CAT)
|
||||||
} else {
|
} else {
|
||||||
emitOpcode(c.prog, vm.ADD)
|
emitOpcode(c.prog.BinWriter, vm.ADD)
|
||||||
}
|
}
|
||||||
case n.Op == token.EQL:
|
case n.Op == token.EQL:
|
||||||
// VM has separate opcodes for number and string equality
|
// VM has separate opcodes for number and string equality
|
||||||
if isStringType(c.typeInfo.Types[n.X].Type) {
|
if isStringType(c.typeInfo.Types[n.X].Type) {
|
||||||
emitOpcode(c.prog, vm.EQUAL)
|
emitOpcode(c.prog.BinWriter, vm.EQUAL)
|
||||||
} else {
|
} else {
|
||||||
emitOpcode(c.prog, vm.NUMEQUAL)
|
emitOpcode(c.prog.BinWriter, vm.NUMEQUAL)
|
||||||
}
|
}
|
||||||
case n.Op == token.NEQ:
|
case n.Op == token.NEQ:
|
||||||
// VM has separate opcodes for number and string equality
|
// VM has separate opcodes for number and string equality
|
||||||
if isStringType(c.typeInfo.Types[n.X].Type) {
|
if isStringType(c.typeInfo.Types[n.X].Type) {
|
||||||
emitOpcode(c.prog, vm.EQUAL)
|
emitOpcode(c.prog.BinWriter, vm.EQUAL)
|
||||||
emitOpcode(c.prog, vm.NOT)
|
emitOpcode(c.prog.BinWriter, vm.NOT)
|
||||||
} else {
|
} else {
|
||||||
emitOpcode(c.prog, vm.NUMNOTEQUAL)
|
emitOpcode(c.prog.BinWriter, vm.NUMNOTEQUAL)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
c.convertToken(n.Op)
|
c.convertToken(n.Op)
|
||||||
|
@ -478,14 +478,14 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
// Do not swap for builtin functions.
|
// Do not swap for builtin functions.
|
||||||
if !isBuiltin {
|
if !isBuiltin {
|
||||||
if numArgs == 2 {
|
if numArgs == 2 {
|
||||||
emitOpcode(c.prog, vm.SWAP)
|
emitOpcode(c.prog.BinWriter, vm.SWAP)
|
||||||
} else if numArgs == 3 {
|
} else if numArgs == 3 {
|
||||||
emitInt(c.prog, 2)
|
emitInt(c.prog.BinWriter, 2)
|
||||||
emitOpcode(c.prog, vm.XSWAP)
|
emitOpcode(c.prog.BinWriter, vm.XSWAP)
|
||||||
} else {
|
} else {
|
||||||
for i := 1; i < numArgs; i++ {
|
for i := 1; i < numArgs; i++ {
|
||||||
emitInt(c.prog, int64(i))
|
emitInt(c.prog.BinWriter, int64(i))
|
||||||
emitOpcode(c.prog, vm.ROLL)
|
emitOpcode(c.prog.BinWriter, vm.ROLL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -499,7 +499,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
case isSyscall(f):
|
case isSyscall(f):
|
||||||
c.convertSyscall(f.selector.Name, f.name)
|
c.convertSyscall(f.selector.Name, f.name)
|
||||||
default:
|
default:
|
||||||
emitCall(c.prog, vm.CALL, int16(f.label))
|
emitCall(c.prog.BinWriter, vm.CALL, int16(f.label))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -529,11 +529,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
case token.ADD:
|
case token.ADD:
|
||||||
// +10 == 10, no need to do anything in this case
|
// +10 == 10, no need to do anything in this case
|
||||||
case token.SUB:
|
case token.SUB:
|
||||||
emitOpcode(c.prog, vm.NEGATE)
|
emitOpcode(c.prog.BinWriter, vm.NEGATE)
|
||||||
case token.NOT:
|
case token.NOT:
|
||||||
emitOpcode(c.prog, vm.NOT)
|
emitOpcode(c.prog.BinWriter, vm.NOT)
|
||||||
case token.XOR:
|
case token.XOR:
|
||||||
emitOpcode(c.prog, vm.INVERT)
|
emitOpcode(c.prog.BinWriter, vm.INVERT)
|
||||||
default:
|
default:
|
||||||
c.prog.Err = fmt.Errorf("invalid unary operator: %s", n.Op)
|
c.prog.Err = fmt.Errorf("invalid unary operator: %s", n.Op)
|
||||||
return nil
|
return nil
|
||||||
|
@ -565,7 +565,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
c.emitLoadField(int(val))
|
c.emitLoadField(int(val))
|
||||||
default:
|
default:
|
||||||
ast.Walk(c, n.Index)
|
ast.Walk(c, n.Index)
|
||||||
emitOpcode(c.prog, vm.PICKITEM) // just pickitem here
|
emitOpcode(c.prog.BinWriter, vm.PICKITEM) // just pickitem here
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
@ -583,14 +583,14 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
ast.Walk(c, n.Cond)
|
ast.Walk(c, n.Cond)
|
||||||
|
|
||||||
// Jump if the condition is false
|
// Jump if the condition is false
|
||||||
emitJmp(c.prog, vm.JMPIFNOT, int16(fend))
|
emitJmp(c.prog.BinWriter, vm.JMPIFNOT, int16(fend))
|
||||||
|
|
||||||
// Walk body followed by the iterator (post stmt).
|
// Walk body followed by the iterator (post stmt).
|
||||||
ast.Walk(c, n.Body)
|
ast.Walk(c, n.Body)
|
||||||
ast.Walk(c, n.Post)
|
ast.Walk(c, n.Post)
|
||||||
|
|
||||||
// Jump back to condition.
|
// Jump back to condition.
|
||||||
emitJmp(c.prog, vm.JMP, int16(fstart))
|
emitJmp(c.prog.BinWriter, vm.JMP, int16(fstart))
|
||||||
c.setLabel(fend)
|
c.setLabel(fend)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -612,11 +612,11 @@ func (c *codegen) convertSyscall(api, name string) {
|
||||||
c.prog.Err = fmt.Errorf("unknown VM syscall api: %s", name)
|
c.prog.Err = fmt.Errorf("unknown VM syscall api: %s", name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
emitSyscall(c.prog, api)
|
emitSyscall(c.prog.BinWriter, api)
|
||||||
|
|
||||||
// This NOP instruction is basically not needed, but if we do, we have a
|
// This NOP instruction is basically not needed, but if we do, we have a
|
||||||
// one to one matching avm file with neo-python which is very nice for debugging.
|
// one to one matching avm file with neo-python which is very nice for debugging.
|
||||||
emitOpcode(c.prog, vm.NOP)
|
emitOpcode(c.prog.BinWriter, vm.NOP)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
||||||
|
@ -633,32 +633,32 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
||||||
arg := expr.Args[0]
|
arg := expr.Args[0]
|
||||||
typ := c.typeInfo.Types[arg].Type
|
typ := c.typeInfo.Types[arg].Type
|
||||||
if isStringType(typ) {
|
if isStringType(typ) {
|
||||||
emitOpcode(c.prog, vm.SIZE)
|
emitOpcode(c.prog.BinWriter, vm.SIZE)
|
||||||
} else {
|
} else {
|
||||||
emitOpcode(c.prog, vm.ARRAYSIZE)
|
emitOpcode(c.prog.BinWriter, vm.ARRAYSIZE)
|
||||||
}
|
}
|
||||||
case "append":
|
case "append":
|
||||||
arg := expr.Args[0]
|
arg := expr.Args[0]
|
||||||
typ := c.typeInfo.Types[arg].Type
|
typ := c.typeInfo.Types[arg].Type
|
||||||
if isByteArrayType(typ) {
|
if isByteArrayType(typ) {
|
||||||
emitOpcode(c.prog, vm.CAT)
|
emitOpcode(c.prog.BinWriter, vm.CAT)
|
||||||
} else {
|
} else {
|
||||||
emitOpcode(c.prog, vm.SWAP)
|
emitOpcode(c.prog.BinWriter, vm.SWAP)
|
||||||
emitOpcode(c.prog, vm.DUP)
|
emitOpcode(c.prog.BinWriter, vm.DUP)
|
||||||
emitOpcode(c.prog, vm.PUSH2)
|
emitOpcode(c.prog.BinWriter, vm.PUSH2)
|
||||||
emitOpcode(c.prog, vm.XSWAP)
|
emitOpcode(c.prog.BinWriter, vm.XSWAP)
|
||||||
emitOpcode(c.prog, vm.APPEND)
|
emitOpcode(c.prog.BinWriter, vm.APPEND)
|
||||||
}
|
}
|
||||||
case "SHA256":
|
case "SHA256":
|
||||||
emitOpcode(c.prog, vm.SHA256)
|
emitOpcode(c.prog.BinWriter, vm.SHA256)
|
||||||
case "SHA1":
|
case "SHA1":
|
||||||
emitOpcode(c.prog, vm.SHA1)
|
emitOpcode(c.prog.BinWriter, vm.SHA1)
|
||||||
case "Hash256":
|
case "Hash256":
|
||||||
emitOpcode(c.prog, vm.HASH256)
|
emitOpcode(c.prog.BinWriter, vm.HASH256)
|
||||||
case "Hash160":
|
case "Hash160":
|
||||||
emitOpcode(c.prog, vm.HASH160)
|
emitOpcode(c.prog.BinWriter, vm.HASH160)
|
||||||
case "Equals":
|
case "Equals":
|
||||||
emitOpcode(c.prog, vm.EQUAL)
|
emitOpcode(c.prog.BinWriter, vm.EQUAL)
|
||||||
case "FromAddress":
|
case "FromAddress":
|
||||||
// We can be sure that this is a ast.BasicLit just containing a simple
|
// We can be sure that this is a ast.BasicLit just containing a simple
|
||||||
// address string. Note that the string returned from calling Value will
|
// address string. Note that the string returned from calling Value will
|
||||||
|
@ -671,7 +671,7 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bytes := uint160.Bytes()
|
bytes := uint160.Bytes()
|
||||||
emitBytes(c.prog, bytes)
|
emitBytes(c.prog.BinWriter, bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,7 +682,7 @@ func (c *codegen) convertByteArray(lit *ast.CompositeLit) {
|
||||||
val, _ := constant.Int64Val(t.Value)
|
val, _ := constant.Int64Val(t.Value)
|
||||||
buf[i] = byte(val)
|
buf[i] = byte(val)
|
||||||
}
|
}
|
||||||
emitBytes(c.prog, buf)
|
emitBytes(c.prog.BinWriter, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *codegen) convertStruct(lit *ast.CompositeLit) {
|
func (c *codegen) convertStruct(lit *ast.CompositeLit) {
|
||||||
|
@ -694,10 +694,10 @@ func (c *codegen) convertStruct(lit *ast.CompositeLit) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
emitOpcode(c.prog, vm.NOP)
|
emitOpcode(c.prog.BinWriter, vm.NOP)
|
||||||
emitInt(c.prog, int64(strct.NumFields()))
|
emitInt(c.prog.BinWriter, int64(strct.NumFields()))
|
||||||
emitOpcode(c.prog, vm.NEWSTRUCT)
|
emitOpcode(c.prog.BinWriter, vm.NEWSTRUCT)
|
||||||
emitOpcode(c.prog, vm.TOALTSTACK)
|
emitOpcode(c.prog.BinWriter, vm.TOALTSTACK)
|
||||||
|
|
||||||
// We need to locally store all the fields, even if they are not initialized.
|
// We need to locally store all the fields, even if they are not initialized.
|
||||||
// We will initialize all fields to their "zero" value.
|
// We will initialize all fields to their "zero" value.
|
||||||
|
@ -730,55 +730,55 @@ func (c *codegen) convertStruct(lit *ast.CompositeLit) {
|
||||||
c.emitLoadConst(typeAndVal)
|
c.emitLoadConst(typeAndVal)
|
||||||
c.emitStoreLocal(i)
|
c.emitStoreLocal(i)
|
||||||
}
|
}
|
||||||
emitOpcode(c.prog, vm.FROMALTSTACK)
|
emitOpcode(c.prog.BinWriter, vm.FROMALTSTACK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *codegen) convertToken(tok token.Token) {
|
func (c *codegen) convertToken(tok token.Token) {
|
||||||
switch tok {
|
switch tok {
|
||||||
case token.ADD_ASSIGN:
|
case token.ADD_ASSIGN:
|
||||||
emitOpcode(c.prog, vm.ADD)
|
emitOpcode(c.prog.BinWriter, vm.ADD)
|
||||||
case token.SUB_ASSIGN:
|
case token.SUB_ASSIGN:
|
||||||
emitOpcode(c.prog, vm.SUB)
|
emitOpcode(c.prog.BinWriter, vm.SUB)
|
||||||
case token.MUL_ASSIGN:
|
case token.MUL_ASSIGN:
|
||||||
emitOpcode(c.prog, vm.MUL)
|
emitOpcode(c.prog.BinWriter, vm.MUL)
|
||||||
case token.QUO_ASSIGN:
|
case token.QUO_ASSIGN:
|
||||||
emitOpcode(c.prog, vm.DIV)
|
emitOpcode(c.prog.BinWriter, vm.DIV)
|
||||||
case token.ADD:
|
case token.ADD:
|
||||||
emitOpcode(c.prog, vm.ADD)
|
emitOpcode(c.prog.BinWriter, vm.ADD)
|
||||||
case token.SUB:
|
case token.SUB:
|
||||||
emitOpcode(c.prog, vm.SUB)
|
emitOpcode(c.prog.BinWriter, vm.SUB)
|
||||||
case token.MUL:
|
case token.MUL:
|
||||||
emitOpcode(c.prog, vm.MUL)
|
emitOpcode(c.prog.BinWriter, vm.MUL)
|
||||||
case token.QUO:
|
case token.QUO:
|
||||||
emitOpcode(c.prog, vm.DIV)
|
emitOpcode(c.prog.BinWriter, vm.DIV)
|
||||||
case token.LSS:
|
case token.LSS:
|
||||||
emitOpcode(c.prog, vm.LT)
|
emitOpcode(c.prog.BinWriter, vm.LT)
|
||||||
case token.LEQ:
|
case token.LEQ:
|
||||||
emitOpcode(c.prog, vm.LTE)
|
emitOpcode(c.prog.BinWriter, vm.LTE)
|
||||||
case token.GTR:
|
case token.GTR:
|
||||||
emitOpcode(c.prog, vm.GT)
|
emitOpcode(c.prog.BinWriter, vm.GT)
|
||||||
case token.GEQ:
|
case token.GEQ:
|
||||||
emitOpcode(c.prog, vm.GTE)
|
emitOpcode(c.prog.BinWriter, vm.GTE)
|
||||||
case token.EQL:
|
case token.EQL:
|
||||||
emitOpcode(c.prog, vm.NUMEQUAL)
|
emitOpcode(c.prog.BinWriter, vm.NUMEQUAL)
|
||||||
case token.NEQ:
|
case token.NEQ:
|
||||||
emitOpcode(c.prog, vm.NUMNOTEQUAL)
|
emitOpcode(c.prog.BinWriter, vm.NUMNOTEQUAL)
|
||||||
case token.DEC:
|
case token.DEC:
|
||||||
emitOpcode(c.prog, vm.DEC)
|
emitOpcode(c.prog.BinWriter, vm.DEC)
|
||||||
case token.INC:
|
case token.INC:
|
||||||
emitOpcode(c.prog, vm.INC)
|
emitOpcode(c.prog.BinWriter, vm.INC)
|
||||||
case token.NOT:
|
case token.NOT:
|
||||||
emitOpcode(c.prog, vm.NOT)
|
emitOpcode(c.prog.BinWriter, vm.NOT)
|
||||||
case token.AND:
|
case token.AND:
|
||||||
emitOpcode(c.prog, vm.AND)
|
emitOpcode(c.prog.BinWriter, vm.AND)
|
||||||
case token.OR:
|
case token.OR:
|
||||||
emitOpcode(c.prog, vm.OR)
|
emitOpcode(c.prog.BinWriter, vm.OR)
|
||||||
case token.SHL:
|
case token.SHL:
|
||||||
emitOpcode(c.prog, vm.SHL)
|
emitOpcode(c.prog.BinWriter, vm.SHL)
|
||||||
case token.SHR:
|
case token.SHR:
|
||||||
emitOpcode(c.prog, vm.SHR)
|
emitOpcode(c.prog.BinWriter, vm.SHR)
|
||||||
case token.XOR:
|
case token.XOR:
|
||||||
emitOpcode(c.prog, vm.XOR)
|
emitOpcode(c.prog.BinWriter, vm.XOR)
|
||||||
default:
|
default:
|
||||||
c.prog.Err = fmt.Errorf("compiler could not convert token: %s", tok)
|
c.prog.Err = fmt.Errorf("compiler could not convert token: %s", tok)
|
||||||
return
|
return
|
||||||
|
|
|
@ -12,18 +12,18 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// emit a VM Instruction with data to the given buffer.
|
// emit a VM Instruction with data to the given buffer.
|
||||||
func emit(w *io.BufBinWriter, instr vm.Instruction, b []byte) {
|
func emit(w *io.BinWriter, instr vm.Instruction, b []byte) {
|
||||||
emitOpcode(w, instr)
|
emitOpcode(w, instr)
|
||||||
w.WriteBytes(b)
|
w.WriteBytes(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// emitOpcode emits a single VM Instruction the given buffer.
|
// emitOpcode emits a single VM Instruction the given buffer.
|
||||||
func emitOpcode(w *io.BufBinWriter, instr vm.Instruction) {
|
func emitOpcode(w *io.BinWriter, instr vm.Instruction) {
|
||||||
w.WriteLE(byte(instr))
|
w.WriteLE(byte(instr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// emitBool emits a bool type the given buffer.
|
// emitBool emits a bool type the given buffer.
|
||||||
func emitBool(w *io.BufBinWriter, ok bool) {
|
func emitBool(w *io.BinWriter, ok bool) {
|
||||||
if ok {
|
if ok {
|
||||||
emitOpcode(w, vm.PUSHT)
|
emitOpcode(w, vm.PUSHT)
|
||||||
return
|
return
|
||||||
|
@ -32,7 +32,7 @@ func emitBool(w *io.BufBinWriter, ok bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// emitInt emits a int type to the given buffer.
|
// emitInt emits a int type to the given buffer.
|
||||||
func emitInt(w *io.BufBinWriter, i int64) {
|
func emitInt(w *io.BinWriter, i int64) {
|
||||||
switch {
|
switch {
|
||||||
case i == -1:
|
case i == -1:
|
||||||
emitOpcode(w, vm.PUSHM1)
|
emitOpcode(w, vm.PUSHM1)
|
||||||
|
@ -52,12 +52,12 @@ func emitInt(w *io.BufBinWriter, i int64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// emitString emits a string to the given buffer.
|
// emitString emits a string to the given buffer.
|
||||||
func emitString(w *io.BufBinWriter, s string) {
|
func emitString(w *io.BinWriter, s string) {
|
||||||
emitBytes(w, []byte(s))
|
emitBytes(w, []byte(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
// emitBytes emits a byte array to the given buffer.
|
// emitBytes emits a byte array to the given buffer.
|
||||||
func emitBytes(w *io.BufBinWriter, b []byte) {
|
func emitBytes(w *io.BinWriter, b []byte) {
|
||||||
n := len(b)
|
n := len(b)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
@ -84,7 +84,7 @@ func emitBytes(w *io.BufBinWriter, b []byte) {
|
||||||
|
|
||||||
// emitSyscall emits the syscall API to the given buffer.
|
// emitSyscall emits the syscall API to the given buffer.
|
||||||
// Syscall API string cannot be 0.
|
// Syscall API string cannot be 0.
|
||||||
func emitSyscall(w *io.BufBinWriter, api string) {
|
func emitSyscall(w *io.BinWriter, api string) {
|
||||||
if len(api) == 0 {
|
if len(api) == 0 {
|
||||||
w.Err = errors.New("syscall api cannot be of length 0")
|
w.Err = errors.New("syscall api cannot be of length 0")
|
||||||
return
|
return
|
||||||
|
@ -96,12 +96,12 @@ func emitSyscall(w *io.BufBinWriter, api string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// emitCall emits a call Instruction with label to the given buffer.
|
// emitCall emits a call Instruction with label to the given buffer.
|
||||||
func emitCall(w *io.BufBinWriter, instr vm.Instruction, label int16) {
|
func emitCall(w *io.BinWriter, instr vm.Instruction, label int16) {
|
||||||
emitJmp(w, instr, label)
|
emitJmp(w, instr, label)
|
||||||
}
|
}
|
||||||
|
|
||||||
// emitJmp emits a jump Instruction along with label to the given buffer.
|
// emitJmp emits a jump Instruction along with label to the given buffer.
|
||||||
func emitJmp(w *io.BufBinWriter, instr vm.Instruction, label int16) {
|
func emitJmp(w *io.BinWriter, instr vm.Instruction, label int16) {
|
||||||
if !isInstrJmp(instr) {
|
if !isInstrJmp(instr) {
|
||||||
w.Err = fmt.Errorf("opcode %s is not a jump or call type", instr)
|
w.Err = fmt.Errorf("opcode %s is not a jump or call type", instr)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue