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:
parent
c1ef9c75bf
commit
6370cd3a8e
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user