logo

class

compiler::OrderByInheritance

sys::Obj
  compiler::CompilerSupport
    compiler::CompilerStep
      compiler::OrderByInheritance
  1  //
  2  // Copyright (c) 2006, Brian Frank and Andy Frank
  3  // Licensed under the Academic Free License version 3.0
  4  //
  5  // History:
  6  //   23 Sep 06  Brian Frank  Creation
  7  //
  8  
  9  **
 10  ** OrderByInheritance orders the list of TypeDefs from top to bottom
 11  ** such that any inherited types are guaranteed to be positioned first
 12  ** in the types list.  During this process we check for duplicate type
 13  ** names and cyclic inheritance.
 14  **
 15  class OrderByInheritance : CompilerStep
 16  {
 17  
 18  //////////////////////////////////////////////////////////////////////////
 19  // Constructor
 20  //////////////////////////////////////////////////////////////////////////
 21  
 22    new make(Compiler compiler)
 23      : super(compiler)
 24    {
 25    }
 26  
 27  //////////////////////////////////////////////////////////////////////////
 28  // Run
 29  //////////////////////////////////////////////////////////////////////////
 30  
 31    override Void run()
 32    {
 33      log.debug("OrderByInheritance")
 34      ordered = TypeDef[,]
 35      ordered.capacity = types.size
 36      processing = Str:TypeDef[:]
 37  
 38      // create the todo map which is our working input,
 39      // check for duplicate type names in this loop
 40      todo = Str:TypeDef[:]
 41      types.each |TypeDef t|
 42      {
 43        todo[t.qname] = t
 44      }
 45      bombIfErr
 46  
 47      // process each type in order
 48      types.each |TypeDef t| { process(t) }
 49      bombIfErr
 50  
 51      // use ordered types for rest of pipeline
 52      if (ordered.size != compiler.types.size) throw Err.make("Internal error")
 53      compiler.types = ordered
 54    }
 55  
 56  //////////////////////////////////////////////////////////////////////////
 57  // Process
 58  //////////////////////////////////////////////////////////////////////////
 59  
 60    private Void process(CType t)
 61    {
 62      // check that this type is still in the todo
 63      // list, otherwise we've already processed it
 64      // or it is imported from another pod
 65      def := todo[t.qname]
 66      if (def == null) return
 67  
 68      // check if this guy is in the processing queue,
 69      // in which case we have cyclic inheritance
 70      if (processing.containsKey(def.qname))
 71      {
 72        err("Cyclic inheritance for '$def.name'", def.location)
 73        return
 74      }
 75      processing[def.qname] = def
 76  
 77      // process inheritance
 78      if (def.base != null) process(def.base)
 79      def.mixins.each |CType m| { process(m) }
 80  
 81      // now that is has been processed, removed it the
 82      // todo map and add it to the ordered result list
 83      processing.remove(def.qname)
 84      todo.remove(def.qname)
 85      ordered.add(def)
 86    }
 87  
 88  //////////////////////////////////////////////////////////////////////////
 89  // Fields
 90  //////////////////////////////////////////////////////////////////////////
 91  
 92    Str:TypeDef processing  // map of qname to typse being processed
 93    Str:TypeDef todo        // map of qname to types left to process
 94    TypeDef[] ordered       // ordered result list
 95  }