Improve creation of local vars. Change handling package state and metadata (in progress)
This commit is contained in:
@@ -5,3 +5,7 @@ import "fmt"
|
||||
func Foo() {
|
||||
fmt.Println("Hello from Foo")
|
||||
}
|
||||
|
||||
func F1() {
|
||||
fmt.Println("SomeString:", SomeString)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@ package provider
|
||||
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
SomeString = "constant string"
|
||||
)
|
||||
|
||||
type T1 struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
10
_test/src4.go
Normal file
10
_test/src4.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
import "github.com/containous/gi/_test/provider"
|
||||
|
||||
func main() {
|
||||
provider.F1()
|
||||
}
|
||||
|
||||
// Output:
|
||||
// Hello from Foo
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user