...

Source file src/go/types/eval.go

Documentation: go/types

		 1  // Copyright 2013 The Go Authors. All rights reserved.
		 2  // Use of this source code is governed by a BSD-style
		 3  // license that can be found in the LICENSE file.
		 4  
		 5  package types
		 6  
		 7  import (
		 8  	"fmt"
		 9  	"go/ast"
		10  	"go/parser"
		11  	"go/token"
		12  )
		13  
		14  // Eval returns the type and, if constant, the value for the
		15  // expression expr, evaluated at position pos of package pkg,
		16  // which must have been derived from type-checking an AST with
		17  // complete position information relative to the provided file
		18  // set.
		19  //
		20  // The meaning of the parameters fset, pkg, and pos is the
		21  // same as in CheckExpr. An error is returned if expr cannot
		22  // be parsed successfully, or the resulting expr AST cannot be
		23  // type-checked.
		24  func Eval(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (_ TypeAndValue, err error) {
		25  	// parse expressions
		26  	node, err := parser.ParseExprFrom(fset, "eval", expr, 0)
		27  	if err != nil {
		28  		return TypeAndValue{}, err
		29  	}
		30  
		31  	info := &Info{
		32  		Types: make(map[ast.Expr]TypeAndValue),
		33  	}
		34  	err = CheckExpr(fset, pkg, pos, node, info)
		35  	return info.Types[node], err
		36  }
		37  
		38  // CheckExpr type checks the expression expr as if it had appeared at
		39  // position pos of package pkg. Type information about the expression
		40  // is recorded in info.
		41  //
		42  // If pkg == nil, the Universe scope is used and the provided
		43  // position pos is ignored. If pkg != nil, and pos is invalid,
		44  // the package scope is used. Otherwise, pos must belong to the
		45  // package.
		46  //
		47  // An error is returned if pos is not within the package or
		48  // if the node cannot be type-checked.
		49  //
		50  // Note: Eval and CheckExpr should not be used instead of running Check
		51  // to compute types and values, but in addition to Check, as these
		52  // functions ignore the context in which an expression is used (e.g., an
		53  // assignment). Thus, top-level untyped constants will return an
		54  // untyped type rather then the respective context-specific type.
		55  //
		56  func CheckExpr(fset *token.FileSet, pkg *Package, pos token.Pos, expr ast.Expr, info *Info) (err error) {
		57  	// determine scope
		58  	var scope *Scope
		59  	if pkg == nil {
		60  		scope = Universe
		61  		pos = token.NoPos
		62  	} else if !pos.IsValid() {
		63  		scope = pkg.scope
		64  	} else {
		65  		// The package scope extent (position information) may be
		66  		// incorrect (files spread across a wide range of fset
		67  		// positions) - ignore it and just consider its children
		68  		// (file scopes).
		69  		for _, fscope := range pkg.scope.children {
		70  			if scope = fscope.Innermost(pos); scope != nil {
		71  				break
		72  			}
		73  		}
		74  		if scope == nil || debug {
		75  			s := scope
		76  			for s != nil && s != pkg.scope {
		77  				s = s.parent
		78  			}
		79  			// s == nil || s == pkg.scope
		80  			if s == nil {
		81  				return fmt.Errorf("no position %s found in package %s", fset.Position(pos), pkg.name)
		82  			}
		83  		}
		84  	}
		85  
		86  	// initialize checker
		87  	check := NewChecker(nil, fset, pkg, info)
		88  	check.scope = scope
		89  	check.pos = pos
		90  	defer check.handleBailout(&err)
		91  
		92  	// evaluate node
		93  	var x operand
		94  	check.rawExpr(&x, expr, nil)
		95  	check.processDelayed(0) // incl. all functions
		96  	check.recordUntyped()
		97  
		98  	return nil
		99  }
	 100  

View as plain text