func getNewNames(callExpr *ast.CallExpr, funSym *st.FunctionSymbol, destScope map[st.Symbol]bool) map[st.Symbol]ast.Expr { newNames := make(map[st.Symbol]ast.Expr) bt, _ := st.GetBaseType(funSym.FunctionType) ftype := bt.(*st.FunctionTypeSymbol) //Reciever if ftype.Reciever != nil { ftype.Reciever.ForEach(func(sym st.Symbol) { newNames[sym] = getRecieverExpr(callExpr) }) } //Parameters i := 0 ftype.Parameters.ForEach(func(sym st.Symbol) { newNames[sym] = callExpr.Args[i] i++ }) //Locals usedNames := make(map[string]bool) for dest, _ := range destScope { usedNames[dest.Name()] = true } funSym.Locals.ForEach(func(sym st.Symbol) { if _, ok := usedNames[sym.Name()]; ok { j := 0 for { nn := sym.Name() + strconv.Itoa(j) if _, ok := usedNames[nn]; !ok { newNames[sym] = ast.NewIdent(nn) usedNames[nn] = true break } } } }) return newNames }
func (pp *packageParser) openMethodsAndFields(sym st.Symbol) { if pp.checkIsVisited(sym) { return } // fmt.Printf("opening %s %T from %s\n", sym.Name(), sym, func(p *st.Package) string { // if p == nil { // return "nil" // } // return p.AstPackage.Name // }(sym.PackageFrom())) if st.IsPredeclaredIdentifier(sym.Name()) { return } switch t := sym.(type) { case *st.ArrayTypeSymbol: pp.openMethodsAndFields(t.ElemType) case *st.ChanTypeSymbol: pp.openMethodsAndFields(t.ValueType) case *st.FunctionTypeSymbol: if t.Parameters != nil { t.Parameters.ForEachNoLock(func(sym st.Symbol) { v := sym.(*st.VariableSymbol) pp.openMethodsAndFields(v.VariableType) }) } if t.Results != nil { t.Results.ForEachNoLock(func(sym st.Symbol) { v := sym.(*st.VariableSymbol) pp.openMethodsAndFields(v.VariableType) }) } case *st.InterfaceTypeSymbol: if t.Meths != nil { t.Meths.ForEachNoLock(func(sym st.Symbol) { if _, ok := sym.(*st.FunctionSymbol); !ok { //EmbeddedInterface pp.openMethodsAndFields(sym) ts := sym.(*st.InterfaceTypeSymbol) t.Meths.AddOpenedScope(ts.Meths) //Delete functionSymbol which is now useles from interface t.Meths.RemoveSymbol(sym.Name()) } }) } case *st.MapTypeSymbol: pp.openMethodsAndFields(t.KeyType) pp.openMethodsAndFields(t.ValueType) case *st.StructTypeSymbol: // if t.Name() == "Package" { // fmt.Printf("YEAHHH YEAHHH %p\n", t) // } t.Fields.ForEachNoLock(func(variable st.Symbol) { if _, ok := variable.(*st.VariableSymbol); !ok { ts := variable.(st.ITypeSymbol) pp.openMethodsAndFields(ts) //Methods if ts.Methods() != nil { t.Methods().AddOpenedScope(ts.Methods()) } //Fields switch ttt := ts.(type) { case *st.StructTypeSymbol: t.Fields.AddOpenedScope(ttt.Fields) case *st.PointerTypeSymbol: t.Fields.AddOpenedScope(ttt.Fields) } //No longer need in type thumb, replace with var typeVar := st.MakeVariable(ts.Name(), t.Fields, ts) typeVar.Idents = ts.Identifiers() typeVar.Posits = ts.Positions() t.Fields.ReplaceSymbol(ts.Name(), typeVar) //replaces old one } }) case *st.PointerTypeSymbol: //fmt.Printf("%v %T \n", t.BaseType.Name(), t.BaseType) pp.openMethodsAndFields(t.BaseType) switch str := t.BaseType.(type) { case *st.StructTypeSymbol: t.Fields = str.Fields case *st.PointerTypeSymbol: t.Fields = str.Fields } if _, cyc := st.GetBaseType(t); cyc { // fmt.Printf("%s from %s\n", t.Name(), t.PackageFrom().AstPackage.Name) panic("cycle, don't work with that") } if t.BaseType.Methods() != nil { t.Methods().AddOpenedScope(t.BaseType.Methods()) } // if t.BaseType.Name() == "Package" { // fmt.Printf("YEAHHH YEAHHH %p %p\n", t, t.BaseType) // fmt.Println(*t.Methods().String()); // } pp.openMethodsAndFields(t.BaseType) } }
func (mv *methodsVisitor) Visit(node ast.Node) (w ast.Visitor) { w = mv switch f := node.(type) { case *ast.FuncDecl: fft, cyc := st.GetBaseType(mv.Parser.parseTypeSymbol(f.Type)) if cyc { panic("unexpected cycle") } ft := fft.(*st.FunctionTypeSymbol) locals := st.NewSymbolTable(mv.Parser.Package) locals.AddOpenedScope(ft.Parameters) locals.AddOpenedScope(ft.Results) locals.AddOpenedScope(ft.Reciever) var basertype, rtype st.ITypeSymbol if f.Recv != nil { e_count := 0 for _, field := range f.Recv.List { basertype = mv.Parser.parseTypeSymbol(field.Type) if prtype, ok := basertype.(*st.PointerTypeSymbol); ok { rtype = prtype.BaseType } else { rtype = basertype } if mv.Parser.Package.AstPackage.Name == "os" { // fmt.Printf("###@@@### (%s) %s\n", rtype.Name(), f.Name.Name) } if rtype.Methods() == nil { panic("ok, this is a test panic") rtype.SetMethods(st.NewSymbolTable(mv.Parser.Package)) } if len(field.Names) == 0 { toAdd := st.MakeVariable("$unnamed receiver"+strconv.Itoa(e_count), ft.Reciever, basertype) ft.Reciever.AddSymbol(toAdd) e_count += 1 } for _, name := range field.Names { toAdd := st.MakeVariable(name.Name, ft.Reciever, basertype) mv.Parser.registerIdent(toAdd, name) ft.Reciever.AddSymbol(toAdd) } } } toAdd := st.MakeFunction(f.Name.Name, nil, ft) // Scope is set 5 lines down toAdd.Locals = locals mv.Parser.registerIdent(toAdd, f.Name) if f.Recv != nil { rtype.AddMethod(toAdd) toAdd.Scope_ = rtype.Methods() } else { mv.Parser.RootSymbolTable.AddSymbol(toAdd) toAdd.Scope_ = mv.Parser.RootSymbolTable } } return }
func (lv *innerScopeVisitor) parseBlockStmt(node interface{}) (w ast.Visitor) { if node == nil { return nil } w = lv table := st.NewSymbolTable(lv.Parser.Package) // fmt.Printf(" %p %p %p \n", lv.Parser.CurrentSymbolTable, lv.Current, lv.Method.Locals) table.AddOpenedScope(lv.Current) ww := &innerScopeVisitor{lv.Method, table, lv.Parser, nil, lv.LabelsData} temp := lv.Parser.CurrentSymbolTable lv.Parser.CurrentSymbolTable = table defer func() { lv.Parser.CurrentSymbolTable = temp }() switch inNode := node.(type) { case *ast.ForStmt: ww.parseStmt(inNode.Init) ww.Parser.parseExpr(inNode.Cond) ww.parseStmt(inNode.Post) ast.Walk(ww, inNode.Body) w = nil case *ast.IfStmt: ww.parseStmt(inNode.Init) ww.Parser.parseExpr(inNode.Cond) ww1 := &innerScopeVisitor{lv.Method, st.NewSymbolTable(lv.Parser.Package), lv.Parser, nil, lv.LabelsData} ww2 := &innerScopeVisitor{lv.Method, st.NewSymbolTable(lv.Parser.Package), lv.Parser, nil, lv.LabelsData} ww1.Current.AddOpenedScope(ww.Current) ww2.Current.AddOpenedScope(ww.Current) ast.Walk(ww1, inNode.Body) ast.Walk(ww2, inNode.Else) w = nil case *ast.RangeStmt: rangeType := ww.Parser.parseExpr(inNode.X).At(0).(st.ITypeSymbol) // fmt.Printf("range type = %s, %T\n", rangeType.Name(), rangeType) switch inNode.Tok { case token.DEFINE: if rangeType, _ = st.GetBaseType(rangeType); rangeType == nil { panic("unexpected cycle") } var kT, vT st.ITypeSymbol switch rT := rangeType.(type) { case *st.ArrayTypeSymbol: kT = st.PredeclaredTypes["int"] vT = rT.ElemType case *st.MapTypeSymbol: kT = rT.KeyType vT = rT.ValueType case *st.BasicTypeSymbol: //string kT = st.PredeclaredTypes["int"] vT = st.PredeclaredTypes["byte"] case *st.ChanTypeSymbol: kT = rT.ValueType case *st.UnresolvedTypeSymbol: panic("unresolved at range") } iK := inNode.Key.(*ast.Ident) if iK.Name != "_" { toAdd := st.MakeVariable(iK.Name, ww.Current, kT) ww.Parser.registerIdent(toAdd, iK) ww.Current.AddSymbol(toAdd) // fmt.Printf("range key added %s %T\n", toAdd.Name(), toAdd) } if inNode.Value != nil { // not channel, two range vars iV := inNode.Value.(*ast.Ident) if iV.Name != "_" { toAdd := st.MakeVariable(iV.Name, ww.Current, vT) ww.Parser.registerIdent(toAdd, iV) ww.Current.AddSymbol(toAdd) // fmt.Printf("range value added %s %T\n", toAdd.Name(), toAdd) } } case token.ASSIGN: ww.Parser.parseExpr(inNode.Key) if inNode.Value != nil { ww.Parser.parseExpr(inNode.Value) } } ast.Walk(ww, inNode.Body) // fmt.Printf("end of range\n") w = nil case *ast.SelectStmt: w = ww case *ast.SwitchStmt: ww.parseStmt(inNode.Init) ww.Parser.parseExpr(inNode.Tag) ast.Walk(ww, inNode.Body) w = nil case *ast.TypeSwitchStmt: ww.parseStmt(inNode.Init) switch tsT := inNode.Assign.(type) { case *ast.AssignStmt: tsVar := tsT.Lhs[0].(*ast.Ident) tsTypeAss := tsT.Rhs[0].(*ast.TypeAssertExpr) tsType := ww.Parser.parseExpr(tsTypeAss.X).At(0).(st.ITypeSymbol) toAdd := st.MakeVariable(tsVar.Name, ww.Current, tsType) toAdd.IsTypeSwitchVar = true ww.Parser.registerIdent(toAdd, tsVar) ww.Current.AddSymbol(toAdd) case *ast.ExprStmt: tsTypeAss := tsT.X.(*ast.TypeAssertExpr) ww.Parser.parseExpr(tsTypeAss.X) } ast.Walk(ww, inNode.Body) w = nil case *ast.CaseClause: if inNode.List != nil { s := ww.Parser.parseExpr(inNode.List[0]).At(0) _, isTypeSwitch := s.(st.ITypeSymbol) if isTypeSwitch { switch { case len(inNode.List) == 1: tsType := ww.Parser.parseExpr(inNode.List[0]).At(0).(st.ITypeSymbol) if tsVar, ok := lv.Current.FindTypeSwitchVar(); ok { toAdd := st.MakeVariable(tsVar.Name(), ww.Current, tsType) toAdd.Idents = tsVar.Idents toAdd.Posits = tsVar.Posits //No position, just register symbol ww.Current.AddSymbol(toAdd) } case len(inNode.List) > 1: for _, t := range inNode.List { ww.Parser.parseExpr(t) } } } else { for _, v := range inNode.List { ww.Parser.parseExpr(v) } } } for _, stmt := range inNode.Body { ast.Walk(ww, stmt) } w = nil case *ast.CommClause: ww.parseStmt(inNode.Comm) for _, stmt := range inNode.Body { ast.Walk(ww, stmt) } w = nil case *ast.FuncLit: meth := st.MakeFunction("#", ww.Current, lv.Parser.parseTypeSymbol(inNode.Type)) meth.Locals = st.NewSymbolTable(ww.Parser.Package) meth.Locals.AddOpenedScope(lv.Current) if meth.FunctionType.(*st.FunctionTypeSymbol).Parameters != nil { meth.Locals.AddOpenedScope(meth.FunctionType.(*st.FunctionTypeSymbol).Parameters) } if meth.FunctionType.(*st.FunctionTypeSymbol).Results != nil { meth.Locals.AddOpenedScope(meth.FunctionType.(*st.FunctionTypeSymbol).Results) } w = &innerScopeVisitor{meth, meth.Locals, lv.Parser, nil, lv.LabelsData} } return w }