Commit 0d947420 authored by Robert Griesemer's avatar Robert Griesemer

exp/types/staging: more flexible API, cleanups

- Changed Check signature to take function parameters for
  more flexibility: Now a client can interrupt type checking
  early (via panic in one the upcalls) once the desired
  type information or number of errors is reached. Default
  use is still simple.

- Cleaned up main typechecking loops. Now does not neglect
  _ declarations anymore.

- Various other cleanups.

R=golang-dev, r, rsc
CC=golang-dev
https://golang.org/cl/6612049
parent 52248750
This diff is collapsed.
...@@ -17,6 +17,7 @@ import ( ...@@ -17,6 +17,7 @@ import (
const debug = false const debug = false
const trace = false const trace = false
// TODO(gri) eventually assert and unimplemented should disappear.
func assert(p bool) { func assert(p bool) {
if !p { if !p {
panic("assertion failed") panic("assertion failed")
...@@ -33,19 +34,36 @@ func unreachable() { ...@@ -33,19 +34,36 @@ func unreachable() {
panic("unreachable") panic("unreachable")
} }
func (check *checker) formatMsg(format string, args []interface{}) string {
for i, arg := range args {
switch a := arg.(type) {
case token.Pos:
args[i] = check.fset.Position(a)
case ast.Expr:
args[i] = exprString(a)
case Type:
args[i] = typeString(a)
case operand:
panic("internal error: should always pass *operand")
}
}
return fmt.Sprintf(format, args...)
}
// dump is only needed for debugging // dump is only needed for debugging
func (check *checker) dump(format string, args ...interface{}) { func (check *checker) dump(format string, args ...interface{}) {
if n := len(format); n > 0 && format[n-1] != '\n' { fmt.Println(check.formatMsg(format, args))
format += "\n"
}
check.convertArgs(args)
fmt.Printf(format, args...)
} }
func (check *checker) errorf(pos token.Pos, format string, args ...interface{}) { func (check *checker) errorf(pos token.Pos, format string, args ...interface{}) {
check.convertArgs(args) msg := check.formatMsg(format, args)
msg := fmt.Sprintf(format, args...) if check.firsterr == nil {
check.errors.Add(check.fset.Position(pos), msg) check.firsterr = fmt.Errorf("%s: %s", check.fset.Position(pos), msg)
}
if check.errh == nil {
panic(bailout{}) // report only first error
}
check.errh(pos, msg)
} }
func (check *checker) invalidAST(pos token.Pos, format string, args ...interface{}) { func (check *checker) invalidAST(pos token.Pos, format string, args ...interface{}) {
...@@ -60,21 +78,6 @@ func (check *checker) invalidOp(pos token.Pos, format string, args ...interface{ ...@@ -60,21 +78,6 @@ func (check *checker) invalidOp(pos token.Pos, format string, args ...interface{
check.errorf(pos, "invalid operation: "+format, args...) check.errorf(pos, "invalid operation: "+format, args...)
} }
func (check *checker) convertArgs(args []interface{}) {
for i, arg := range args {
switch a := arg.(type) {
case token.Pos:
args[i] = check.fset.Position(a)
case ast.Expr:
args[i] = exprString(a)
case Type:
args[i] = typeString(a)
case operand:
panic("internal error: should always pass *operand")
}
}
}
// exprString returns a (simplified) string representation for an expression. // exprString returns a (simplified) string representation for an expression.
func exprString(expr ast.Expr) string { func exprString(expr ast.Expr) string {
var buf bytes.Buffer var buf bytes.Buffer
......
...@@ -40,7 +40,8 @@ func FindPkg(path, srcDir string) (filename, id string) { ...@@ -40,7 +40,8 @@ func FindPkg(path, srcDir string) (filename, id string) {
switch { switch {
default: default:
// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
bp, _ := build.Import(path, srcDir, build.FindOnly) // Don't require the source files to be present.
bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
if bp.PkgObj == "" { if bp.PkgObj == "" {
return return
} }
......
...@@ -41,10 +41,9 @@ func compile(t *testing.T, dirname, filename string) string { ...@@ -41,10 +41,9 @@ func compile(t *testing.T, dirname, filename string) string {
cmd.Dir = dirname cmd.Dir = dirname
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {
t.Logf("%s", out)
t.Fatalf("%s %s failed: %s", gcPath, filename, err) t.Fatalf("%s %s failed: %s", gcPath, filename, err)
return ""
} }
t.Logf("%s", string(out))
archCh, _ := build.ArchChar(runtime.GOARCH) archCh, _ := build.ArchChar(runtime.GOARCH)
// filename should end with ".go" // filename should end with ".go"
return filepath.Join(dirname, filename[:len(filename)-2]+archCh) return filepath.Join(dirname, filename[:len(filename)-2]+archCh)
......
...@@ -15,21 +15,16 @@ import ( ...@@ -15,21 +15,16 @@ import (
"sort" "sort"
) )
// Check typechecks the given package pkg and augments the AST by // Check typechecks a package pkg. It returns the first error, or nil.
// assigning types to all ast.Objects. Check can be used in two
// different modes:
// //
// 1) If a nil types map is provided, Check typechecks the entire // Check augments the AST by assigning types to ast.Objects. It
// package. If no error is returned, the package source code has // calls err with the error position and message for each error.
// no type errors. // It calls f with each valid AST expression and corresponding
// type. If err == nil, Check terminates as soon as the first error
// is found. If f is nil, it is not invoked.
// //
// 2) If a non-nil types map is provided, Check operates like in func Check(fset *token.FileSet, pkg *ast.Package, err func(token.Pos, string), f func(ast.Expr, Type)) error {
// mode 1) but also records the types for all expressions in the return check(fset, pkg, err, f)
// map. Pre-existing expression types in the map are replaced if
// the expression appears in the AST.
//
func Check(fset *token.FileSet, pkg *ast.Package, types map[ast.Expr]Type) error {
return check(fset, pkg, types)
} }
// All types implement the Type interface. // All types implement the Type interface.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment