func (pp *packageParser) tParseInterfaceType(t *ast.InterfaceType) (result *st.InterfaceTypeSymbol) { result = st.MakeInterfaceType(st.NO_NAME, pp.CurrentSymbolTable) if len(t.Methods.List) > 0 { for _, method := range t.Methods.List { if len(method.Names) == 0 { //Embeded interface ft := pp.parseTypeSymbol(method.Type) result.AddMethod(ft) } for _, name := range method.Names { ft := pp.parseTypeSymbol(method.Type).(*st.FunctionTypeSymbol) toAdd := st.MakeFunction(name.Name, result.Methods(), ft) toAdd.IsInterfaceMethod = true pp.registerIdent(toAdd, name) result.AddMethod(toAdd) } } } return }
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 }