1
0
mirror of https://github.com/golang/go synced 2024-11-18 14:04:45 -07:00

go/types: modify Eval, EvalNode to return a TypeAndValue

The new interface makes the functions more useful by allowing clients to
check the various properties that TypeAndValue provides.

Change-Id: I8b41a27316081bea24a18ffe6fa1812e809d6f67
Reviewed-on: https://go-review.googlesource.com/2134
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Peter Collingbourne 2014-12-28 11:35:42 -08:00 committed by Robert Griesemer
parent c1ef9c75bf
commit 6370cd3a8e
3 changed files with 17 additions and 30 deletions

View File

@ -248,13 +248,14 @@ func doOneInput(input, filename string) bool {
continue
}
mainFileScope := mainpkg.Object.Scope().Child(0)
t, _, err = types.EvalNode(prog.Fset, texpr, mainpkg.Object, mainFileScope)
tv, err := types.EvalNode(prog.Fset, texpr, mainpkg.Object, mainFileScope)
if err != nil {
ok = false
// Don't print err since its location is bad.
e.errorf("'%s' is not a valid type: %s", typstr, err)
continue
}
t = tv.Type
}
e.types = append(e.types, t)
}

View File

@ -11,8 +11,6 @@ import (
"go/ast"
"go/parser"
"go/token"
"golang.org/x/tools/go/exact"
)
// New is a convenience function to create a new type from a given
@ -22,11 +20,11 @@ import (
// Position info for objects in the result type is undefined.
//
func New(str string) Type {
typ, _, err := Eval(str, nil, nil)
tv, err := Eval(str, nil, nil)
if err != nil {
panic(err)
}
return typ
return tv.Type
}
// Eval returns the type and, if constant, the value for the
@ -50,10 +48,10 @@ func New(str string) Type {
// level untyped constants will return an untyped type rather then the
// respective context-specific type.
//
func Eval(str string, pkg *Package, scope *Scope) (typ Type, val exact.Value, err error) {
func Eval(str string, pkg *Package, scope *Scope) (TypeAndValue, error) {
node, err := parser.ParseExpr(str)
if err != nil {
return nil, nil, err
return TypeAndValue{}, err
}
// Create a file set that looks structurally identical to the
@ -70,7 +68,7 @@ func Eval(str string, pkg *Package, scope *Scope) (typ Type, val exact.Value, er
// An error is returned if the scope is incorrect
// if the node cannot be evaluated in the scope.
//
func EvalNode(fset *token.FileSet, node ast.Expr, pkg *Package, scope *Scope) (typ Type, val exact.Value, err error) {
func EvalNode(fset *token.FileSet, node ast.Expr, pkg *Package, scope *Scope) (tv TypeAndValue, err error) {
// verify package/scope relationship
if pkg == nil {
scope = Universe
@ -81,7 +79,7 @@ func EvalNode(fset *token.FileSet, node ast.Expr, pkg *Package, scope *Scope) (t
}
// s == nil || s == pkg.scope
if s == nil {
return nil, nil, fmt.Errorf("scope does not belong to package %s", pkg.name)
return TypeAndValue{}, fmt.Errorf("scope does not belong to package %s", pkg.name)
}
}
@ -92,18 +90,6 @@ func EvalNode(fset *token.FileSet, node ast.Expr, pkg *Package, scope *Scope) (t
// evaluate node
var x operand
check.exprOrType(&x, node)
switch x.mode {
case invalid, novalue:
fallthrough
default:
unreachable() // or bailed out with error
case constant:
val = x.val
fallthrough
case typexpr, variable, mapindex, value, commaok:
typ = x.typ
}
return
check.rawExpr(&x, node, nil)
return TypeAndValue{x.mode, x.typ, x.val}, nil
}

View File

@ -18,12 +18,12 @@ import (
)
func testEval(t *testing.T, pkg *Package, scope *Scope, str string, typ Type, typStr, valStr string) {
gotTyp, gotVal, err := Eval(str, pkg, scope)
gotTv, err := Eval(str, pkg, scope)
if err != nil {
t.Errorf("Eval(%q) failed: %s", str, err)
return
}
if gotTyp == nil {
if gotTv.Type == nil {
t.Errorf("Eval(%q) got nil type but no error", str)
return
}
@ -31,13 +31,13 @@ func testEval(t *testing.T, pkg *Package, scope *Scope, str string, typ Type, ty
// compare types
if typ != nil {
// we have a type, check identity
if !Identical(gotTyp, typ) {
t.Errorf("Eval(%q) got type %s, want %s", str, gotTyp, typ)
if !Identical(gotTv.Type, typ) {
t.Errorf("Eval(%q) got type %s, want %s", str, gotTv.Type, typ)
return
}
} else {
// we have a string, compare type string
gotStr := gotTyp.String()
gotStr := gotTv.Type.String()
if gotStr != typStr {
t.Errorf("Eval(%q) got type %s, want %s", str, gotStr, typStr)
return
@ -46,8 +46,8 @@ func testEval(t *testing.T, pkg *Package, scope *Scope, str string, typ Type, ty
// compare values
gotStr := ""
if gotVal != nil {
gotStr = gotVal.String()
if gotTv.Value != nil {
gotStr = gotTv.Value.String()
}
if gotStr != valStr {
t.Errorf("Eval(%q) got value %s, want %s", str, gotStr, valStr)