Improve creation of local vars. Change handling package state and metadata (in progress)

This commit is contained in:
Marc Vertes
2018-07-20 10:19:31 +02:00
parent 595e2f3b02
commit 915d976d12
7 changed files with 61 additions and 14 deletions

View File

@@ -5,3 +5,7 @@ import "fmt"
func Foo() {
fmt.Println("Hello from Foo")
}
func F1() {
fmt.Println("SomeString:", SomeString)
}

View File

@@ -2,6 +2,10 @@ package provider
import "fmt"
const (
SomeString = "constant string"
)
type T1 struct {
Name string
}

10
_test/src4.go Normal file
View File

@@ -0,0 +1,10 @@
package main
import "github.com/containous/gi/_test/provider"
func main() {
provider.F1()
}
// Output:
// Hello from Foo

View File

@@ -262,13 +262,8 @@ func (a Action) String() string {
// Ast parses src string containing Go code and generates the corresponding AST.
// The AST root node is returned.
func (interp *Interpreter) Ast(src string, pre *NodeMap) (*Node, *NodeMap) {
var def NodeMap
if pre == nil {
def = make(map[string]*Node)
} else {
def = *pre
}
func (interp *Interpreter) Ast(src string) (*Node, *NodeMap) {
def := NodeMap{}
fset := token.NewFileSet() // positions are relative to fset
f, err := parser.ParseFile(fset, "sample.go", src, 0)
if err != nil {
@@ -280,6 +275,7 @@ func (interp *Interpreter) Ast(src string, pre *NodeMap) (*Node, *NodeMap) {
var st nodestack
var nbAssign int
var typeSpec bool
var pkgName string
addChild := func(root **Node, anc *Node, index *int, kind Kind, action Action) *Node {
*index++
@@ -467,6 +463,7 @@ func (interp *Interpreter) Ast(src string, pre *NodeMap) (*Node, *NodeMap) {
st.push(addChild(&root, anc, &index, FieldList, Nop))
case *ast.File:
pkgName = a.Name.Name
st.push(addChild(&root, anc, &index, File, Nop))
case *ast.ForStmt:

View File

@@ -41,12 +41,18 @@ func (s *Scope) lookup(ident string) (*Symbol, int, bool) {
return nil, 0, false
}
// FrameIndex type defines metadata for Tracking frame index for variables in function context
// FrameIndex type stores informations to allocate frame space for variables
type FrameIndex struct {
anc *FrameIndex // Ancestor upper frame
max int // The highest index in frame
}
// PkgContext type stores current state of a package during compiling
type PkgContext struct {
frameIndex *FrameIndex
nodeMap *NodeMap
}
// Cfg generates a control flow graph (CFG) from AST (wiring successors in AST)
// and pre-compute frame sizes and indexes for all un-named (temporary) and named
// variables. A list of nodes of init functions is returned.
@@ -66,6 +72,7 @@ func (interp *Interpreter) Cfg(root *Node, sdef *NodeMap) []*Node {
for name, node := range *sdef {
scope.sym[name] = &Symbol{node: node, index: -1}
}
log.Println(interp.srcPkg["provider"])
root.Walk(func(n *Node) bool {
// Pre-order processing
@@ -600,6 +607,8 @@ func (interp *Interpreter) Cfg(root *Node, sdef *NodeMap) []*Node {
case Ident:
if n.anc.kind == File || (n.anc.kind == SelectorExpr && n.anc.child[0] != n) {
// skip symbol creation/lookup for idents used as key
} else if n.ident == "nil" {
n.kind = BasicLit
} else if n.ident == "false" {
n.val = false
n.typ = defaultTypes["bool"]
@@ -630,10 +639,28 @@ func (interp *Interpreter) Cfg(root *Node, sdef *NodeMap) []*Node {
n.kind = node.kind
n.findex = node.findex
} else {
//log.Println(n.index, n.ident, n.anc.kind, "unresolved, create new")
frameIndex.max++
scope.sym[n.ident] = &Symbol{index: frameIndex.max}
n.findex = frameIndex.max
if n.ident == "_" || n.anc.kind == Define || n.anc.kind == DefineX || n.anc.kind == Field || n.anc.kind == RangeStmt || n.anc.kind == ValueSpec {
// Create a new local symbol for func argument or local var definition
frameIndex.max++
scope.sym[n.ident] = &Symbol{index: frameIndex.max}
n.findex = frameIndex.max
} else {
// symbol may be defined globally elsewhere later, add an entry at pkg level
symFrameIndex := frameIndex
symScope := scope
level := 0
for symFrameIndex.anc != nil {
level++
symScope = symScope.anc
symFrameIndex = symFrameIndex.anc
}
symFrameIndex.max++
symScope.sym[n.ident] = &Symbol{index: symFrameIndex.max}
(*sdef)[n.ident] = n
n.findex = symFrameIndex.max
n.level = level
log.Println(n.index, n.ident, n.anc.kind, "unresolved, create new at pkg level", n.findex, level)
}
}
case If0: // if cond {}
@@ -869,6 +896,7 @@ func (interp *Interpreter) Cfg(root *Node, sdef *NodeMap) []*Node {
}
}
})
log.Println(sdef)
return initNodes
}

View File

@@ -118,7 +118,7 @@ func (i *Interpreter) ImportBin(pkg *map[string]*map[string]interface{}) {
// current interpreted package exported symbols
func (i *Interpreter) Eval(src string) (string, *NodeMap) {
// Parse source to AST
root, sdef := i.Ast(src, nil)
root, sdef := i.Ast(src)
if i.AstDot {
root.AstDot(DotX())
}

View File

@@ -2,6 +2,7 @@ package interp
import (
"fmt"
"log"
"reflect"
"time"
)
@@ -127,7 +128,7 @@ func value(n *Node, f *Frame) interface{} {
case Rvalue:
return n.rval
default:
//log.Println(n.index, n.findex, n.level, f)
//log.Println(n.index, n.ident, n.findex, n.level, f)
for level := n.level; level > 0; level-- {
f = f.anc
}
@@ -139,6 +140,7 @@ func value(n *Node, f *Frame) interface{} {
}
func addrValue(n *Node, f *Frame) *interface{} {
log.Println(n.index, n.ident, n.kind, n.level, n.findex)
switch n.kind {
case BasicLit, FuncDecl, Rvalue:
return &n.val
@@ -392,6 +394,7 @@ func callBin(n *Node, f *Frame) {
}
}
fun := value(n.child[0], f).(reflect.Value)
log.Println("in:", in)
v := fun.Call(in)
for i := 0; i < n.fsize; i++ {
f.data[n.findex+i] = v[i].Interface()
@@ -717,6 +720,7 @@ func slice(n *Node, f *Frame) {
// slice expression, no low value
func slice0(n *Node, f *Frame) {
log.Println(n.index, n.child[0].ident, value(n.child[0], f))
a := value(n.child[0], f).([]interface{})
switch len(n.child) {
case 1: