Permalink
Browse files

improvements. entire GoDCCP compile correctly now

  • Loading branch information...
1 parent b779b3a commit 6c6877cf390d825834a6c613e8e7addf170675f1 Petar Maymounkov committed May 27, 2012
Showing with 59 additions and 22 deletions.
  1. +0 −1 vrewrite/TODO
  2. +2 −5 vrewrite/call.go
  3. +3 −4 vrewrite/fix.go
  4. +21 −12 vrewrite/rewrite.go
  5. +33 −0 vrewrite/selectorexpr.go
View
@@ -1,5 +1,4 @@
-* Remove "time" import if not used after rewrite
* Which is correct? Does it matter?
Go()
View
@@ -8,15 +8,14 @@ import (
"go/ast"
)
-func rewriteTimeCalls(file *ast.File) (needVtime, needTime bool) {
+func rewriteTimeCalls(file *ast.File) (needVtime bool) {
v := &callVisitor{}
ast.Walk(v, file)
- return v.NeedPkgVtime, v.NeedPkgTime
+ return v.NeedPkgVtime
}
type callVisitor struct {
NeedPkgVtime bool
- NeedPkgTime bool // True if after rewriting invokations to time.Sleep and time.Now, other references to pkg "time" remain
}
func (v *callVisitor) Visit(x ast.Node) ast.Visitor {
@@ -38,8 +37,6 @@ func (v *callVisitor) Visit(x ast.Node) ast.Visitor {
if sexpr.Sel.Name == "Now" || sexpr.Sel.Name == "Sleep" {
sx.Name = "vtime"
v.NeedPkgVtime = true
- } else {
- v.NeedPkgTime = true
}
return v
}
View
@@ -17,18 +17,17 @@ func RewriteFile(fileSet *token.FileSet, file *ast.File) error {
// rewriteTimeCalls will rewrite time.Now and time.Sleep to
// vtime.Now and vtime.Sleep
- needVtime, needTime := rewriteTimeCalls(file)
+ needVtime := rewriteTimeCalls(file) || rewriteChanOps(fileSet, file)
if !needVtime {
removeImport(file, "github.com/petar/vitamix/vtime")
}
- if !needTime {
+ // If there are no left references to pkg time, remove the import
+ if !ExistSelectorFor(file, "time") {
removeImport(file, "time")
}
- rewriteChanOps(fileSet, file)
-
return nil
}
View
@@ -11,41 +11,40 @@ import (
"os"
)
-// XXX: Make sure label statements produce an error
-// XXX: Take care of label statements
-// XXX: Check imports for newline printing insights
-// XXX: Remove import for time if all use cases are rewritten to vtime
// XXX: Cannot fix invokations to Now and Sleep, if not in the form time.Now and time.Sleep
-func rewriteChanOps(fset *token.FileSet, file *ast.File) {
- if err := rewrite(fset, file); err != nil {
+func rewriteChanOps(fset *token.FileSet, file *ast.File) bool {
+ needVtime, err := rewrite(fset, file)
+ if err != nil {
//fmt.Fprintf(os.Stderr, "Rewrite errors parsing '%s':\n%s\n", file.Name.Name, err)
fmt.Fprintf(os.Stderr, "—— Encountered errors while parsing\n")
}
+ return needVtime
}
// Rewrite creates a new rewriting frame
-func rewrite(fset *token.FileSet, node ast.Node) error {
+func rewrite(fset *token.FileSet, node ast.Node) (bool, error) {
rwv := &rewriteVisitor{}
rwv.frame.Init(fset)
ast.Walk(rwv, node)
- return rwv.Error()
+ return rwv.NeedPkgVtime, rwv.Error()
}
// recurseRewrite creates a new rewriting frame as a callee from the frame caller
-func recurseRewrite(caller framed, node ast.Node) error {
+func recurseRewrite(caller framed, node ast.Node) (bool, error) {
rwv := &rewriteVisitor{}
rwv.frame.InitRecurse(caller)
ast.Walk(rwv, node)
- return rwv.Error()
+ return rwv.NeedPkgVtime, rwv.Error()
}
// rewriteVisitor is an AST frame that traverses down the AST until it hits a block
// statement, within which it rewrites the statement-level channel operations.
// This visitor itself does not traverse below the statements of the block statement.
// It does however call another visitor type to continue below those statements.
type rewriteVisitor struct {
+ NeedPkgVtime bool
frame
}
@@ -72,17 +71,25 @@ func (t *rewriteVisitor) Visit(node ast.Node) ast.Visitor {
for _, stmt := range bstmt.List {
switch q := stmt.(type) {
case *ast.SelectStmt:
+ t.NeedPkgVtime = true
list = append(list, t.rewriteSelectStmt(q)...)
case *ast.SendStmt:
+ t.NeedPkgVtime = true
list = append(list, t.rewriteSendStmt(q)...)
case *ast.GoStmt:
+ t.NeedPkgVtime = true
list = append(list, t.rewriteGoStmt(q)...)
default:
if filterRecvStmt(stmt) != nil {
+ t.NeedPkgVtime = true
list = append(list, t.rewriteRecvStmt(stmt)...)
} else {
// Continue the walk recursively below this stmt
- recurseRewrite(t, stmt)
+ needVtime, err := recurseRewrite(t, stmt)
+ if err != nil {
+ t.errs.Add(err)
+ }
+ t.NeedPkgVtime = t.NeedPkgVtime || needVtime
list = append(list, stmt)
}
}
@@ -176,9 +183,11 @@ func (t *rewriteVisitor) rewriteSendStmt(sendstmt *ast.SendStmt) []ast.Stmt {
func (t *rewriteVisitor) rewriteSelectStmt(selstmt *ast.SelectStmt) []ast.Stmt {
// Rewrite the comm clauses
for _, commclause := range selstmt.Body.List {
- if err := recurseRewrite(t, commclause); err != nil {
+ needVtime, err := recurseRewrite(t, commclause);
+ if err != nil {
t.errs.Add(err)
}
+ t.NeedPkgVtime = t.NeedPkgVtime || needVtime
}
// Place a call to Unblock immediately after each case and default
View
@@ -0,0 +1,33 @@
+// Copyright 2012 Petar Maymounkov. All rights reserved.
+// Use of this source code is governed by a
+// license that can be found in the LICENSE file.
+
+package vrewrite
+
+import (
+ "go/ast"
+)
+
+func ExistSelectorFor(file *ast.File, sel string) bool {
+ v := &selectorVisitor{ X: sel }
+ ast.Walk(v, file)
+ return v.Exists
+}
+
+type selectorVisitor struct {
+ X string
+ Exists bool
+}
+
+func (v *selectorVisitor) Visit(x ast.Node) ast.Visitor {
+ se, ok := x.(*ast.SelectorExpr)
+ if !ok || se.X == nil {
+ return v
+ }
+ id, ok := se.X.(*ast.Ident)
+ if !ok || id.Name != v.X {
+ return v
+ }
+ v.Exists = true
+ return nil
+}

0 comments on commit 6c6877c

Please sign in to comment.