//ast.Visitor.Visit(). Looks for ast.TypeSpec nodes of ast.Tree to register new types func (tv *typesVisitor) Visit(node ast.Node) (w ast.Visitor) { if tsp, ok := node.(*ast.TypeSpec); ok { ts := tv.Parser.parseTypeSymbol(tsp.Type) if ts.Name() == st.NO_NAME { //No such symbol in CurrentSymbolTable ts.SetName(tsp.Name.Name) } else { //There is an equal type symbol with different name => create alias ts = st.MakeAliasType(tsp.Name.Name, tv.Parser.CurrentSymbolTable, ts) } tv.Parser.registerIdent(ts, tsp.Name) tv.Parser.RootSymbolTable.AddSymbol(ts) } return tv }
func (lv *innerScopeVisitor) parseStmt(node interface{}) (w ast.Visitor) { if node == nil { return nil } w = lv // fmt.Printf("ps %p %p %p %T ", lv.Parser.CurrentSymbolTable, lv.Current, lv.Method.Locals, node) // if id, ok := node.(*ast.Ident); ok { // fmt.Printf("%s ", id.Name) // } // println() temp := lv.Parser.CurrentSymbolTable lv.Parser.CurrentSymbolTable = lv.Current defer func() { lv.Parser.CurrentSymbolTable = temp }() switch s := node.(type) { case *ast.GenDecl: var IotaType st.ITypeSymbol = nil if len(s.Specs) > 0 { if vs, ok := s.Specs[0].(*ast.ValueSpec); ok { switch { case vs.Type != nil: ts := lv.Parser.parseTypeSymbol(vs.Type) if _, ok := ts.(*st.UnresolvedTypeSymbol); (ts == nil) || ok { panic("unresolved type at locals scope: " + ts.Name()) } IotaType = ts case vs.Values != nil && len(vs.Values) > 0: ts := lv.Parser.parseExpr(vs.Values[0]).At(0).(st.ITypeSymbol) IotaType = ts default: panic("decl without either type or value????") } } } w = &innerScopeVisitor{lv.Method, lv.Current, lv.Parser, IotaType, lv.LabelsData} case *ast.ValueSpec: //Specify a new variable ts := lv.Parser.parseTypeSymbol(s.Type) if ts == nil { ts = lv.IotaType } valuesTypes := lv.getValuesTypesValSpec(s) for i, n := range s.Names { curTs := ts if ts == nil { curTs = valuesTypes.At(i).(st.ITypeSymbol) } toAdd := st.MakeVariable(n.Name, lv.Current, curTs) lv.Parser.registerIdent(toAdd, n) lv.Parser.CurrentSymbolTable.AddSymbol(toAdd) } case *ast.AssignStmt: valuesTypes := lv.getValuesTypesAss(s) switch s.Tok { case token.DEFINE: //Specify a new variable for i, nn := range s.Lhs { n := nn.(*ast.Ident) if n.Name != "_" { toAdd := st.MakeVariable(n.Name, lv.Current, valuesTypes.At(i).(st.ITypeSymbol)) lv.Parser.registerIdent(toAdd, n) lv.Current.AddSymbol(toAdd) // fmt.Printf("DEFINED %s\n", toAdd.Name()) } } case token.ASSIGN: //Pos for _, nn := range s.Lhs { // fmt.Printf("<!>") lv.Parser.parseExpr(nn) } w = nil } case *ast.TypeSpec: //Specify a new type ts := lv.Parser.parseTypeSymbol(s.Type) switch ts.(type) { case *st.PointerTypeSymbol, *st.ArrayTypeSymbol, *st.StructTypeSymbol, *st.InterfaceTypeSymbol, *st.MapTypeSymbol, *st.ChanTypeSymbol, *st.FunctionTypeSymbol: if ts.Name() == st.NO_NAME { //No such symbol in CurrentSymbolTable ts.SetName(s.Name.Name) } else { //There is an equal type symbol with different name => create alias ts = st.MakeAliasType(s.Name.Name, lv.Current, ts) } lv.Parser.registerIdent(ts, s.Name) lv.Current.AddSymbol(ts) default: panic("no type symbol returned") } case *ast.ExprStmt: lv.Parser.parseExpr(s.X) case *ast.DeferStmt: lv.Parser.parseExpr(s.Call) case *ast.GoStmt: lv.Parser.parseExpr(s.Call) case *ast.IncDecStmt: lv.Parser.parseExpr(s.X) //labels beg case *ast.LabeledStmt: l := st.MakeLabel(s.Label.Name, lv.Current) for id, _ := range lv.LabelsData { if id.Name == s.Label.Name { lv.Parser.registerIdent(l, id) } } for id, _ := range l.Idents { lv.LabelsData[id] = false, false } lv.Parser.registerIdent(l, s.Label) lv.Current.AddSymbol(l) ast.Walk(lv, s.Stmt) w = nil //prevent from usual ident registration case *ast.BranchStmt: if s.Label != nil { if l, ok := lv.Current.LookUpLabel(s.Label.Name); ok { lv.Parser.registerIdent(l, s.Label) } else { lv.LabelsData[s.Label] = true } } w = nil //prevent from usual ident registration //labels end case *ast.ReturnStmt: if s.Results != nil { //mb not needed for _, exp := range s.Results { lv.Parser.parseExpr(exp) } } case *ast.SendStmt: lv.Parser.parseExpr(s.Chan) lv.Parser.parseExpr(s.Value) case *ast.SwitchStmt, *ast.IfStmt, *ast.ForStmt, *ast.RangeStmt, *ast.FuncLit, *ast.SelectStmt, *ast.TypeSwitchStmt, *ast.CaseClause, *ast.CommClause: w = lv.parseBlockStmt(node) } return }