neoneo-go/pkg/vm/compiler/func_context.go
Anthony De Meulemeester b257a06f3e
Compiler update (#21)
* added seperate folders for cmd packages.

* Fix netmodes in test + reverse bigint bytes

* glide get deps

* add, sub, mul, div

* booleans

* strings

* binary expressions

* if statements

* function calls

* composite literals (slice, array)

* Added lots of test cases and update readme.
2018-02-15 16:35:49 +01:00

96 lines
2 KiB
Go

package compiler
import (
"go/ast"
"go/types"
"log"
"github.com/CityOfZion/neo-go/pkg/vm"
)
type jumpLabel struct {
offset int
op vm.OpCode
}
// A FuncContext represents details about a function in the program along withs its variables.
type FuncContext struct {
// The declaration tree of this function.
decl *ast.FuncDecl
// Identifier (name of the function in the program).
name string
// The scope of the function.
scope map[string]*VarContext
// Arguments of the function.
args map[string]bool
// Address (label) where the compiler can find this function when someone calls it.
label int16
// Counter for stored local variables.
i int
// This needs refactor along with the (if stmt)
jumpLabels []jumpLabel
}
func (f *FuncContext) addJump(op vm.OpCode, offset int) {
f.jumpLabels = append(f.jumpLabels, jumpLabel{offset, op})
}
func newFuncContext(decl *ast.FuncDecl, label int16) *FuncContext {
return &FuncContext{
decl: decl,
label: int16(label),
name: decl.Name.Name,
scope: map[string]*VarContext{},
args: map[string]bool{},
jumpLabels: []jumpLabel{},
}
}
func (f *FuncContext) newConst(name string, t types.TypeAndValue, needStore bool) *VarContext {
ctx := &VarContext{
name: name,
tinfo: t,
}
if needStore {
f.storeContext(ctx)
}
return ctx
}
func (f *FuncContext) numStackOps() int64 {
ops := 0
ast.Inspect(f.decl, func(n ast.Node) bool {
switch n.(type) {
case *ast.AssignStmt, *ast.ReturnStmt, *ast.IfStmt:
ops++
}
return true
})
numArgs := len(f.decl.Type.Params.List)
return int64(ops + numArgs)
}
func (f *FuncContext) storeContext(ctx *VarContext) {
ctx.pos = f.i
f.scope[ctx.name] = ctx
f.i++
}
func (f *FuncContext) getContext(name string) *VarContext {
ctx, ok := f.scope[name]
if !ok {
log.Fatalf("could not resolve variable %s", name)
}
return ctx
}
func (f *FuncContext) isRegistered(ctx *VarContext) bool {
_, ok := f.scope[ctx.name]
return ok
}
func (f *FuncContext) isArgument(name string) bool {
_, ok := f.args[name]
return ok
}