Refactor gen.go into Generator type.
This commit is contained in:
		
							parent
							
								
									1c3bab0dcc
								
							
						
					
					
						commit
						3329fe75df
					
				
							
								
								
									
										113
									
								
								cmd/pgen/gen.go
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								cmd/pgen/gen.go
									
									
									
									
									
								
							|  | @ -16,15 +16,13 @@ type subspec struct { | |||
| 	s string | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| type Generator struct{ | ||||
| 	firstone bool | ||||
| 	gfset *token.FileSet | ||||
| 	fset *token.FileSet | ||||
| 	fspec, tspec, nspec subspec | ||||
| 	ntspecs []subspec | ||||
| 	nspecs []subspec | ||||
| 	nodes *ast.File | ||||
| ) | ||||
| 
 | ||||
| type gvisit struct{} | ||||
| } | ||||
| 
 | ||||
| func subs(dst *string, specs []subspec) { | ||||
| 	for _,spec := range(specs) { | ||||
|  | @ -38,79 +36,81 @@ func sub(dst *string,spec subspec) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (v *gvisit) Visit(node ast.Node) ast.Visitor { | ||||
| func (g *Generator) Visit(node ast.Node) ast.Visitor { | ||||
| 	switch n := node.(type) { | ||||
| 	case *ast.Ident: | ||||
| 		if n.Obj != nil && n.Obj.Kind == ast.Typ { | ||||
| 			subs(&n.Name,ntspecs) | ||||
| 			subs(&n.Obj.Name,ntspecs) | ||||
| 			subs(&n.Name,g.nspecs) | ||||
| 			subs(&n.Obj.Name,g.nspecs) | ||||
| 		} | ||||
| 	case *ast.TypeSwitchStmt: | ||||
| 		for _,s := range(n.Body.List) { | ||||
| 			cs, ok := s.(*ast.CaseClause); if !ok { continue } | ||||
| 			for _,c := range(cs.List) { | ||||
| 				ci, ok := c.(*ast.Ident); if !ok { continue } | ||||
| 				subs(&ci.Name,ntspecs) | ||||
| 				subs(&ci.Name,g.nspecs) | ||||
| 			} | ||||
| 		} | ||||
| 	case *ast.TypeAssertExpr: | ||||
| 		nt, ok := n.Type.(*ast.Ident); if !ok { return v } | ||||
| 		subs(&nt.Name,ntspecs) | ||||
| 		nt, ok := n.Type.(*ast.Ident); if !ok { return g } | ||||
| 		subs(&nt.Name,g.nspecs) | ||||
| 	case *ast.Ellipsis: | ||||
| 		nt, ok := n.Elt.(*ast.Ident); if !ok { return v } | ||||
| 		subs(&nt.Name,ntspecs) | ||||
| 		nt, ok := n.Elt.(*ast.Ident); if !ok { return g } | ||||
| 		subs(&nt.Name,g.nspecs) | ||||
| 	case *ast.Field: | ||||
| 		nt, ok := n.Type.(*ast.Ident); if !ok { return v } | ||||
| 		subs(&nt.Name,ntspecs) | ||||
| 		nt, ok := n.Type.(*ast.Ident); if !ok { return g } | ||||
| 		subs(&nt.Name,g.nspecs) | ||||
| 	case *ast.StarExpr: | ||||
| 		nt, ok := n.X.(*ast.Ident); if !ok { return v } | ||||
| 		subs(&nt.Name,ntspecs) | ||||
| 	case *ast.TypeSpec: | ||||
| 		//ast.Print(gfset,n)
 | ||||
| 		nt, ok := n.X.(*ast.Ident); if !ok { return g } | ||||
| 		subs(&nt.Name,g.nspecs) | ||||
| 	case *ast.ValueSpec: | ||||
| 		nt, ok := n.Type.(*ast.Ident); if !ok { return v } | ||||
| 		subs(&nt.Name,ntspecs) | ||||
| 		nt, ok := n.Type.(*ast.Ident); if !ok { return g } | ||||
| 		subs(&nt.Name,g.nspecs) | ||||
| 	case *ast.ArrayType: | ||||
| 		nt, ok := n.Elt.(*ast.Ident); if !ok { return v } | ||||
| 		subs(&nt.Name,ntspecs) | ||||
| 		nt, ok := n.Elt.(*ast.Ident); if !ok { return g } | ||||
| 		subs(&nt.Name,g.nspecs) | ||||
| 	case *ast.MapType: | ||||
| 		nt, ok := n.Key.(*ast.Ident); if ok { | ||||
| 			subs(&nt.Name,ntspecs) | ||||
| 			subs(&nt.Name,g.nspecs) | ||||
| 		} | ||||
| 		nt, ok = n.Value.(*ast.Ident); if ok { | ||||
| 			subs(&nt.Name,ntspecs) | ||||
| 			subs(&nt.Name,g.nspecs) | ||||
| 		} | ||||
| 	case *ast.FuncDecl: | ||||
| 		sub(&n.Name.Name,fspec) | ||||
| 		//ast.Print(gfset,n)
 | ||||
| 		sub(&n.Name.Name,g.fspec) | ||||
| 		//ast.Print(g.fset,n)
 | ||||
| 	} | ||||
| 	return v | ||||
| 	return g | ||||
| } | ||||
| 
 | ||||
| func init() { | ||||
| 	firstone = true | ||||
| 	err := os.Remove("pgen.go") | ||||
| 	if err != nil && os.IsExist(err) { | ||||
| 		log.Fatal("Removing pgen.go:",err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func add(newName, typName, typ string) { | ||||
| 	fspec = subspec{regexp.MustCompile("New"), newName} | ||||
| 	nspec = subspec{regexp.MustCompile("_N"), typName} | ||||
| 	tspec = subspec{regexp.MustCompile("_T"), typ} | ||||
| 	ntspecs = []subspec{nspec,tspec} | ||||
| func NewGenerator() *Generator { | ||||
| 	g := &Generator{} | ||||
| 	g.firstone = true | ||||
| 	g.fset = token.NewFileSet() | ||||
| 	return g | ||||
| } | ||||
| 
 | ||||
| 	gfset = token.NewFileSet() | ||||
| 	f, err := parser.ParseFile(gfset, "", template, 0) | ||||
| func (g *Generator) Add(newName, typName, typ string) { | ||||
| 	g.fspec = subspec{regexp.MustCompile("New"), newName} | ||||
| 	g.nspecs = []subspec{ | ||||
| 		subspec{regexp.MustCompile("_N"), typName}, | ||||
| 		subspec{regexp.MustCompile("_T"), typ}} | ||||
| 
 | ||||
| 	f, err := parser.ParseFile(g.fset, "", template, 0) | ||||
| 	if err != nil { | ||||
| 		log.Fatal("Parsing persist/template.T:",err) | ||||
| 	} | ||||
| 	var v = &gvisit{} | ||||
| 	ast.Walk(v,f) | ||||
| 	ast.Walk(g,f) | ||||
| 
 | ||||
| 	if firstone { | ||||
| 		nodes = f | ||||
| 	if g.firstone { | ||||
| 		g.nodes = f | ||||
| 	} else { | ||||
| 		for _,decl := range(f.Decls) { | ||||
| 			imp, ok := decl.(*ast.GenDecl); if ok { | ||||
|  | @ -118,20 +118,27 @@ func add(newName, typName, typ string) { | |||
| 					continue // skip imports
 | ||||
| 				} | ||||
| 			} | ||||
| 			nodes.Decls = append(nodes.Decls,decl) | ||||
| 			g.nodes.Decls = append(g.nodes.Decls,decl) | ||||
| 		} | ||||
| 	} | ||||
| 	firstone = false | ||||
| 	g.firstone = false | ||||
| } | ||||
| 
 | ||||
| func newImportSpec(name string) *ast.ImportSpec { | ||||
| 	path := &ast.BasicLit{ Value: name } | ||||
| 	ret := &ast.ImportSpec{ Path: path } | ||||
| 	return ret | ||||
| func (g *Generator) Import(imports map[string]bool) { | ||||
| 	if g.nodes == nil { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| func gen(wantImps []string) { | ||||
| 	if nodes == nil { | ||||
| 	// strip quotation marks from imports
 | ||||
| 	qexp := regexp.MustCompile(`"`) | ||||
| 	for v := range imports { | ||||
| 		v = qexp.ReplaceAllString(v,"") | ||||
| 		astutil.AddImport(g.fset, g.nodes, v) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (g *Generator) Save() { | ||||
| 	if g.nodes == nil { | ||||
| 		return | ||||
| 	} | ||||
| 	of, err := os.Create("pgen.go") | ||||
|  | @ -139,13 +146,7 @@ func gen(wantImps []string) { | |||
| 		log.Fatal("Cannot open pgen.go") | ||||
| 	} | ||||
| 
 | ||||
| 	qexp := regexp.MustCompile(`"`) | ||||
| 	for _,v := range wantImps { | ||||
| 		v = qexp.ReplaceAllString(v,"") | ||||
| 		astutil.AddImport(gfset, nodes, v) | ||||
| 	} | ||||
| 
 | ||||
| 	err = format.Node(of,gfset,nodes) | ||||
| 	err = format.Node(of,g.fset,g.nodes) | ||||
| 	if err != nil { | ||||
| 		log.Fatal("Generate error:",err) | ||||
| 	} | ||||
|  |  | |||
|  | @ -103,30 +103,26 @@ func init() { | |||
| 
 | ||||
| 	imps = make(map[string]string) | ||||
| 	needImps = make(map[string]bool) | ||||
| 	ts = make(map[string]tps) | ||||
| 	fset = token.NewFileSet() | ||||
| } | ||||
| 
 | ||||
| func main() { | ||||
| 	// In naming imported identifiers, keep only the last part of the
 | ||||
| 	// path to the imported package. This does not take named imports
 | ||||
| 	// into account but should allow the code generator to find the
 | ||||
| 	// right libary to import and generate valid code.
 | ||||
| 
 | ||||
| 	pkgs, err := parser.ParseDir(fset, ".", nil, 0) | ||||
| 	if err != nil { | ||||
| 		log.Fatal("Parse:",err) | ||||
| 	} | ||||
| 	// run type checker on each package
 | ||||
| 	for _,pkg := range pkgs { | ||||
| 		ts = make(map[string]tps) | ||||
| 		chkpkg(pkg) | ||||
| 	} | ||||
| 	addImps := make([]string,0) | ||||
| 	for k := range needImps { | ||||
| 		addImps = append(addImps,imps[k]) | ||||
| 	} | ||||
| 		g := NewGenerator() | ||||
| 		for _,v := range ts { | ||||
| 		add(v.fun, v.name, v.typ) | ||||
| 			g.Add(v.fun, v.name, v.typ) | ||||
| 		} | ||||
| 		g.Import(needImps) | ||||
| 		// process template for each type identified and
 | ||||
| 		// generate output
 | ||||
| 		g.Save() | ||||
| 	} | ||||
| 	gen(addImps) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user