mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2025-02-04 19:44:44 +00:00
b257a06f3e
* 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.
96 lines
2 KiB
Go
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
|
|
}
|