Compiler (#23)

* implemented add, mul, div, sub assign for identifiers.

* Implemented struct field initialization.

* Implemented imports

* Implemented storage VM API (interop layer) + additional bug fixes when encountered.

* Bumped version 0.12.0

* fixed double point extension on compiled output file.

* Fixed bug where callExpr in returns where added to voidCall

* fixed binExpr compare equal

* Check the env for the gopath first

* removed travis.yml

* custom types + implemented general declarations.

* commented out the storage test to make the build pass
This commit is contained in:
Anthony De Meulemeester 2018-02-24 10:06:48 +01:00 committed by GitHub
parent bebdabab9f
commit 23cfebf621
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 798 additions and 117 deletions

View file

@ -2,6 +2,7 @@ package compiler
import (
"go/ast"
"go/types"
"log"
)
@ -14,36 +15,75 @@ type funcScope struct {
// The declaration of the function in the AST
decl *ast.FuncDecl
// program label of the function
// Program label of the function
label int
// local scope of the function
// Local scope of the function
scope map[string]int
// mapping of structs positions with their scope
// A mapping of structs positions with their scope
structs map[int]*structScope
// voidCalls are basically functions that return their value
// into nothing. The stack has their return value but there
// is nothing that consumes it. We need to keep track of
// these functions so we can cleanup (drop) the returned
// value from the stack. We also need to add every voidCall
// return value to the stack size.
voidCalls map[*ast.CallExpr]bool
// local variable counter
i int
}
func newFuncScope(decl *ast.FuncDecl, label int) *funcScope {
return &funcScope{
name: decl.Name.Name,
decl: decl,
label: label,
scope: map[string]int{},
structs: map[int]*structScope{},
i: -1,
name: decl.Name.Name,
decl: decl,
label: label,
scope: map[string]int{},
structs: map[int]*structScope{},
voidCalls: map[*ast.CallExpr]bool{},
i: -1,
}
}
// analyzeVoidCalls will check for functions that are not assigned
// and therefore we need to cleanup the return value from the stack.
func (c *funcScope) analyzeVoidCalls(node ast.Node) bool {
switch n := node.(type) {
case *ast.AssignStmt:
for i := 0; i < len(n.Rhs); i++ {
switch n.Rhs[i].(type) {
case *ast.CallExpr:
return false
}
}
case *ast.ReturnStmt:
switch n.Results[0].(type) {
case *ast.CallExpr:
return false
}
case *ast.CallExpr:
c.voidCalls[n] = true
}
return true
}
func (c *funcScope) stackSize() int64 {
size := 0
ast.Inspect(c.decl, func(n ast.Node) bool {
switch n.(type) {
switch n := n.(type) {
case *ast.AssignStmt, *ast.ReturnStmt, *ast.IfStmt:
size++
// This handles the inline GenDecl like "var x = 2"
case *ast.GenDecl:
switch t := n.Specs[0].(type) {
case *ast.ValueSpec:
if len(t.Values) > 0 {
size++
}
}
}
return true
})
@ -53,11 +93,11 @@ func (c *funcScope) stackSize() int64 {
if c.decl.Recv != nil {
numArgs += len(c.decl.Recv.List)
}
return int64(size + numArgs)
return int64(size + numArgs + len(c.voidCalls))
}
func (c *funcScope) newStruct() *structScope {
strct := newStructScope()
func (c *funcScope) newStruct(t *types.Struct) *structScope {
strct := newStructScope(t)
c.structs[len(c.scope)] = strct
return strct
}