github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/go/types/ordering.go (about)

     1  // Copyright 2014 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  // This file implements resolveOrder.
     6  
     7  package types
     8  
     9  import (
    10  	"go/ast"
    11  	"sort"
    12  )
    13  
    14  // resolveOrder computes the order in which package-level objects
    15  // must be type-checked.
    16  //
    17  // Interface types appear first in the list, sorted topologically
    18  // by dependencies on embedded interfaces that are also declared
    19  // in this package, followed by all other objects sorted in source
    20  // order.
    21  //
    22  // TODO(gri) Consider sorting all types by dependencies here, and
    23  // in the process check _and_ report type cycles. This may simplify
    24  // the full type-checking phase.
    25  //
    26  func (check *Checker) resolveOrder() []Object {
    27  	var ifaces, others []Object
    28  
    29  	// collect interface types with their dependencies, and all other objects
    30  	for obj := range check.objMap {
    31  		if ityp := check.interfaceFor(obj); ityp != nil {
    32  			ifaces = append(ifaces, obj)
    33  			// determine dependencies on embedded interfaces
    34  			for _, f := range ityp.Methods.List {
    35  				if len(f.Names) == 0 {
    36  					// Embedded interface: The type must be a (possibly
    37  					// qualified) identifier denoting another interface.
    38  					// Imported interfaces are already fully resolved,
    39  					// so we can ignore qualified identifiers.
    40  					if ident, _ := f.Type.(*ast.Ident); ident != nil {
    41  						embedded := check.pkg.scope.Lookup(ident.Name)
    42  						if check.interfaceFor(embedded) != nil {
    43  							check.objMap[obj].addDep(embedded)
    44  						}
    45  					}
    46  				}
    47  			}
    48  		} else {
    49  			others = append(others, obj)
    50  		}
    51  	}
    52  
    53  	// final object order
    54  	var order []Object
    55  
    56  	// sort interface types topologically by dependencies,
    57  	// and in source order if there are no dependencies
    58  	sort.Sort(inSourceOrder(ifaces))
    59  	if debug {
    60  		for _, obj := range ifaces {
    61  			assert(check.objMap[obj].mark == 0)
    62  		}
    63  	}
    64  	for _, obj := range ifaces {
    65  		check.appendInPostOrder(&order, obj)
    66  	}
    67  
    68  	// sort everything else in source order
    69  	sort.Sort(inSourceOrder(others))
    70  
    71  	return append(order, others...)
    72  }
    73  
    74  // interfaceFor returns the AST interface denoted by obj, or nil.
    75  func (check *Checker) interfaceFor(obj Object) *ast.InterfaceType {
    76  	tname, _ := obj.(*TypeName)
    77  	if tname == nil {
    78  		return nil // not a type
    79  	}
    80  	d := check.objMap[obj]
    81  	if d == nil {
    82  		check.dump("%s: %s should have been declared", obj.Pos(), obj.Name())
    83  		unreachable()
    84  	}
    85  	if d.typ == nil {
    86  		return nil // invalid AST - ignore (will be handled later)
    87  	}
    88  	ityp, _ := d.typ.(*ast.InterfaceType)
    89  	return ityp
    90  }
    91  
    92  func (check *Checker) appendInPostOrder(order *[]Object, obj Object) {
    93  	d := check.objMap[obj]
    94  	if d.mark != 0 {
    95  		// We've already seen this object; either because it's
    96  		// already added to order, or because we have a cycle.
    97  		// In both cases we stop. Cycle errors are reported
    98  		// when type-checking types.
    99  		return
   100  	}
   101  	d.mark = 1
   102  
   103  	for _, obj := range orderedSetObjects(d.deps) {
   104  		check.appendInPostOrder(order, obj)
   105  	}
   106  
   107  	*order = append(*order, obj)
   108  }
   109  
   110  func orderedSetObjects(set map[Object]bool) []Object {
   111  	list := make([]Object, len(set))
   112  	i := 0
   113  	for obj := range set {
   114  		// we don't care about the map element value
   115  		list[i] = obj
   116  		i++
   117  	}
   118  	sort.Sort(inSourceOrder(list))
   119  	return list
   120  }
   121  
   122  // inSourceOrder implements the sort.Sort interface.
   123  type inSourceOrder []Object
   124  
   125  func (a inSourceOrder) Len() int           { return len(a) }
   126  func (a inSourceOrder) Less(i, j int) bool { return a[i].order() < a[j].order() }
   127  func (a inSourceOrder) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }