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 (
const debug = false
const trace = false
// TODO(gri) eventually assert and unimplemented should disappear.
func assert(p bool) {
if !p {
panic("assertion failed")
......@@ -33,19 +34,36 @@ func 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
func (check *checker) dump(format string, args ...interface{}) {
if n := len(format); n > 0 && format[n-1] != '\n' {
format += "\n"
}
check.convertArgs(args)
fmt.Printf(format, args...)
fmt.Println(check.formatMsg(format, args))
}
func (check *checker) errorf(pos token.Pos, format string, args ...interface{}) {
check.convertArgs(args)
msg := fmt.Sprintf(format, args...)
check.errors.Add(check.fset.Position(pos), msg)
msg := check.formatMsg(format, args)
if check.firsterr == nil {
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{}) {
......@@ -60,21 +78,6 @@ func (check *checker) invalidOp(pos token.Pos, format string, args ...interface{
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.
func exprString(expr ast.Expr) string {
var buf bytes.Buffer
......
......@@ -40,7 +40,8 @@ func FindPkg(path, srcDir string) (filename, id string) {
switch {
default:
// "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 == "" {
return
}
......
......@@ -41,10 +41,9 @@ func compile(t *testing.T, dirname, filename string) string {
cmd.Dir = dirname
out, err := cmd.CombinedOutput()
if err != nil {
t.Logf("%s", out)
t.Fatalf("%s %s failed: %s", gcPath, filename, err)
return ""
}
t.Logf("%s", string(out))
archCh, _ := build.ArchChar(runtime.GOARCH)
// filename should end with ".go"
return filepath.Join(dirname, filename[:len(filename)-2]+archCh)
......
......@@ -15,21 +15,16 @@ import (
"sort"
)
// Check typechecks the given package pkg and augments the AST by
// assigning types to all ast.Objects. Check can be used in two
// different modes:
// Check typechecks a package pkg. It returns the first error, or nil.
//
// 1) If a nil types map is provided, Check typechecks the entire
// package. If no error is returned, the package source code has
// no type errors.
// Check augments the AST by assigning types to ast.Objects. It
// calls err with the error position and message for each error.
// 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
// mode 1) but also records the types for all expressions in the
// 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)
func Check(fset *token.FileSet, pkg *ast.Package, err func(token.Pos, string), f func(ast.Expr, Type)) error {
return check(fset, pkg, err, f)
}
// 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