URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [go/] [ast/] [resolve.go] - Rev 752
Go to most recent revision | Compare with Previous | Blame | View Log
// Copyright 2011 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// This file implements NewPackage.package astimport ("fmt""go/scanner""go/token""strconv")type pkgBuilder struct {scanner.ErrorVectorfset *token.FileSet}func (p *pkgBuilder) error(pos token.Pos, msg string) {p.Error(p.fset.Position(pos), msg)}func (p *pkgBuilder) errorf(pos token.Pos, format string, args ...interface{}) {p.error(pos, fmt.Sprintf(format, args...))}func (p *pkgBuilder) declare(scope, altScope *Scope, obj *Object) {alt := scope.Insert(obj)if alt == nil && altScope != nil {// see if there is a conflicting declaration in altScopealt = altScope.Lookup(obj.Name)}if alt != nil {prevDecl := ""if pos := alt.Pos(); pos.IsValid() {prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", p.fset.Position(pos))}p.error(obj.Pos(), fmt.Sprintf("%s redeclared in this block%s", obj.Name, prevDecl))}}func resolve(scope *Scope, ident *Ident) bool {for ; scope != nil; scope = scope.Outer {if obj := scope.Lookup(ident.Name); obj != nil {ident.Obj = objreturn true}}return false}// An Importer resolves import paths to package Objects.// The imports map records the packages already imported,// indexed by package id (canonical import path).// An Importer must determine the canonical import path and// check the map to see if it is already present in the imports map.// If so, the Importer can return the map entry. Otherwise, the// Importer should load the package data for the given path into// a new *Object (pkg), record pkg in the imports map, and then// return pkg.type Importer func(imports map[string]*Object, path string) (pkg *Object, err error)// NewPackage creates a new Package node from a set of File nodes. It resolves// unresolved identifiers across files and updates each file's Unresolved list// accordingly. If a non-nil importer and universe scope are provided, they are// used to resolve identifiers not declared in any of the package files. Any// remaining unresolved identifiers are reported as undeclared. If the files// belong to different packages, one package name is selected and files with// different package names are reported and then ignored.// The result is a package node and a scanner.ErrorList if there were errors.//func NewPackage(fset *token.FileSet, files map[string]*File, importer Importer, universe *Scope) (*Package, error) {var p pkgBuilderp.fset = fset// complete package scopepkgName := ""pkgScope := NewScope(universe)for _, file := range files {// package names must matchswitch name := file.Name.Name; {case pkgName == "":pkgName = namecase name != pkgName:p.errorf(file.Package, "package %s; expected %s", name, pkgName)continue // ignore this file}// collect top-level file objects in package scopefor _, obj := range file.Scope.Objects {p.declare(pkgScope, nil, obj)}}// package global mapping of imported package ids to package objectsimports := make(map[string]*Object)// complete file scopes with imports and resolve identifiersfor _, file := range files {// ignore file if it belongs to a different package// (error has already been reported)if file.Name.Name != pkgName {continue}// build file scope by processing all importsimportErrors := falsefileScope := NewScope(pkgScope)for _, spec := range file.Imports {if importer == nil {importErrors = truecontinue}path, _ := strconv.Unquote(spec.Path.Value)pkg, err := importer(imports, path)if err != nil {p.errorf(spec.Path.Pos(), "could not import %s (%s)", path, err)importErrors = truecontinue}// TODO(gri) If a local package name != "." is provided,// global identifier resolution could proceed even if the// import failed. Consider adjusting the logic here a bit.// local name overrides imported package namename := pkg.Nameif spec.Name != nil {name = spec.Name.Name}// add import to file scopeif name == "." {// merge imported scope with file scopefor _, obj := range pkg.Data.(*Scope).Objects {p.declare(fileScope, pkgScope, obj)}} else {// declare imported package object in file scope// (do not re-use pkg in the file scope but create// a new object instead; the Decl field is different// for different files)obj := NewObj(Pkg, name)obj.Decl = specobj.Data = pkg.Datap.declare(fileScope, pkgScope, obj)}}// resolve identifiersif importErrors {// don't use the universe scope without correct imports// (objects in the universe may be shadowed by imports;// with missing imports, identifiers might get resolved// incorrectly to universe objects)pkgScope.Outer = nil}i := 0for _, ident := range file.Unresolved {if !resolve(fileScope, ident) {p.errorf(ident.Pos(), "undeclared name: %s", ident.Name)file.Unresolved[i] = identi++}}file.Unresolved = file.Unresolved[0:i]pkgScope.Outer = universe // reset universe scope}return &Package{pkgName, pkgScope, imports, files}, p.GetError(scanner.Sorted)}
Go to most recent revision | Compare with Previous | Blame | View Log
