Commit e4c69685 authored by Hugo Moreau's avatar Hugo Moreau

Global transform ready

Global are now identified and not mixed with local variables.
funcptr are used to set their values.

 * main.go,
   tests/global.go,
   transform/global.go
   transfrom/global2.go : Here.
parent 35cc819e
Pipeline #26195 failed with stage
in 2 minutes and 14 seconds
......@@ -525,6 +525,7 @@ func main() {
meta := transform.NewMeta(fset, info)
global := &transform.Global{}
res := transform.Apply(node, meta, global)
res = transform.Apply(res, meta, &transform.Global2{ FuncCallToAdd: global.FuncCallToAdd })
err = format.Node(f, fset, res)
if err != nil {
fmt.Println(os.Stderr, err.Error())
......
package main
import (
"fmt"
)
var a = 2
var b int
......@@ -8,6 +13,8 @@ func foo(here, not_here int) {
c, e := 2, 3
d += c + e
a = 42 + c
a, c = a, 2
b = 2
a := 2
a += a
}
......@@ -15,5 +22,7 @@ func foo(here, not_here int) {
func main() {
var t = 1
test := 2
fmt.Println(a, b)
foo(t, test)
fmt.Println(a, b)
}
......@@ -3,9 +3,7 @@ package transform
import (
"fmt"
"go/ast"
"go/printer"
"go/token"
"os"
)
func find(a []string, x string) bool {
......@@ -17,12 +15,23 @@ func find(a []string, x string) bool {
return false
}
func findIdent(a []*ast.Field, x string) bool {
for _, n := range a {
if x == n.Names[0].Name {
return true
}
}
return false
}
type Global struct {
currentFunction *ast.Object
globalVar []string
funcsVar map[string][]string
funcsSetter []*ast.Object
firstFunc string
funcArgToAdd map[string][]*ast.Field
funcsSetter []*ast.FuncDecl
funcsVar map[string][]string
globalVar []string
FuncCallToAdd map[string][]*ast.Ident
}
// Pre traversal applies the transformation
......@@ -32,12 +41,16 @@ func (t *Global) Pre(meta *Meta, v *Visitor) bool {
case *ast.File:
t.funcsVar = make(map[string][]string)
t.funcArgToAdd = make(map[string][]*ast.Field)
t.FuncCallToAdd = make(map[string][]*ast.Ident)
case *ast.FuncDecl:
if t.firstFunc == "" {
t.firstFunc = node.Name.Obj.Name
}
t.currentFunction = node.Name.Obj
t.funcsVar[node.Name.Name] = []string{}
t.funcArgToAdd[node.Name.Name] = []*ast.Field{}
t.FuncCallToAdd[node.Name.Name] = []*ast.Ident{}
for i := 0; i < len(node.Type.Params.List); i++ {
fmt.Println(node.Type.Params.List[i])
for j := 0; j < len(node.Type.Params.List[i].Names); j++ {
t.funcsVar[t.currentFunction.Name] = append(t.funcsVar[t.currentFunction.Name], node.Type.Params.List[i].Names[j].Name)
}
......@@ -70,27 +83,71 @@ func (t *Global) Pre(meta *Meta, v *Visitor) bool {
if find(t.globalVar, lhs.Name) && !find(t.funcsVar[t.currentFunction.Name], lhs.Name) {
fmt.Println("global", "`"+lhs.Name+"`", "is modified in", t.currentFunction.Name+"()")
node.Lhs[i] = ast.NewIdent("_")
ident := ast.NewIdent("G2P_" + lhs.Name + "_set_ptr")
node.Rhs[i] = &ast.CallExpr{
Fun: ast.NewIdent("G2P_" + lhs.Name + "_set"),
Fun: ident,
Args: []ast.Expr{node.Rhs[i]},
}
funcident := ast.NewIdent("G2P_" + lhs.Name + "_set")
if findIdent(t.funcArgToAdd[t.currentFunction.Name], ident.Name) {
return true
}
t.FuncCallToAdd[t.currentFunction.Name] = append(t.FuncCallToAdd[t.currentFunction.Name], funcident)
t.funcArgToAdd[t.currentFunction.Name] = append(t.funcArgToAdd[t.currentFunction.Name], &ast.Field{
Names: []*ast.Ident{ast.NewIdent("G2P_" + lhs.Name + "_set")},
Names: []*ast.Ident{ident},
Type: ast.NewIdent("func(int) int"),
})
value := ast.NewIdent("value")
t.funcsSetter = append(t.funcsSetter, &ast.FuncDecl{
Name: funcident,
Type: &ast.FuncType{
Params: &ast.FieldList{
List: []*ast.Field{
&ast.Field{
Names: []*ast.Ident{value},
Type: ast.NewIdent("int"),
},
},
},
Results: &ast.FieldList{
List: []*ast.Field{
&ast.Field{
Type: ast.NewIdent("int"),
},
},
},
},
Body: &ast.BlockStmt{
List: []ast.Stmt{
&ast.AssignStmt{
Lhs: []ast.Expr{lhs},
Tok: token.ASSIGN,
Rhs: []ast.Expr{value},
},
&ast.ReturnStmt{
Results: []ast.Expr{
ast.NewIdent("1"),
},
},
},
},
})
}
}
}
}
case *ast.CallExpr:
fmt.Print("CallExpr : ")
fset := token.NewFileSet()
printer.Fprint(os.Stdout, fset, c.Node())
fmt.Println()
switch fun := node.Fun.(type) {
case *ast.Ident:
fmt.Println(fun.Name)
}
/*
fmt.Print("CallExpr : ")
fset := token.NewFileSet()
printer.Fprint(os.Stdout, fset, c.Node())
fmt.Println()
switch fun := node.Fun.(type) {
case *ast.Ident:
fmt.Println(fun.Name)
}
*/
}
return true
}
......@@ -100,9 +157,26 @@ func (t *Global) Post(meta *Meta, v *Visitor) bool {
c := v.Cursor()
switch node := c.Node().(type) {
case *ast.File:
fmt.Println("first :", t.firstFunc)
fmt.Println(t.funcsVar)
fmt.Println(t.globalVar)
fmt.Println(t.funcArgToAdd)
fmt.Println(t.FuncCallToAdd)
for i, d := range node.Decls {
if f, ok := d.(*ast.FuncDecl); ok {
if f.Name.Name == t.firstFunc {
newDecls := []ast.Decl{}
for j := 0; j < i; j++ {
newDecls = append(newDecls, node.Decls[j])
}
for j := 0; j < len(t.funcsSetter); j++ {
newDecls = append(newDecls, t.funcsSetter[j])
}
newDecls = append(newDecls, node.Decls[i:]...)
node.Decls = newDecls
}
}
}
for _, d := range node.Decls {
if f, ok := d.(*ast.FuncDecl); ok {
if val, ok2 := t.funcArgToAdd[f.Name.Name]; ok2 {
......
package transform
import (
"go/ast"
)
type Global2 struct {
FuncCallToAdd map[string][]*ast.Ident
}
// Pre traversal applies the transformation
func (t *Global2) Pre(meta *Meta, v *Visitor) bool {
c := v.Cursor()
switch node := c.Node().(type) {
case *ast.File:
if t.FuncCallToAdd == nil {
t.FuncCallToAdd = make(map[string][]*ast.Ident)
}
case *ast.CallExpr:
switch fun := node.Fun.(type) {
case *ast.Ident:
if val, ok := t.FuncCallToAdd[fun.Name]; ok {
for _, elt := range val {
node.Args = append(node.Args, elt)
}
}
}
}
return true
}
// Post traversal applies the transformation
func (t *Global2) Post(meta *Meta, v *Visitor) bool {
return true
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment