logo

class

compiler::TypeDef

sys::Obj
  compiler::Node
    compiler::DefNode
      compiler::TypeDef : compiler::CType
   1  //
   2  // Copyright (c) 2006, Brian Frank and Andy Frank
   3  // Licensed under the Academic Free License version 3.0
   4  //
   5  // History:
   6  //   15 Sep 05  Brian Frank  Creation
   7  //    3 Jun 06  Brian Frank  Ported from Java to Fan - Megan's b-day!
   8  //
   9  
  10  **
  11  ** TypeDef models a type definition for a class, mixin or enum
  12  **
  13  class TypeDef : DefNode, CType
  14  {
  15  
  16  //////////////////////////////////////////////////////////////////////////
  17  // Construction
  18  //////////////////////////////////////////////////////////////////////////
  19  
  20    new make(Namespace ns, Location location, CompilationUnit unit, Str name)
  21      : super(location)
  22    {
  23      this.ns          = ns
  24      this.pod         = unit.pod
  25      this.unit        = unit
  26      this.name        = name
  27      this.qname       = pod.name + "::" + name
  28      this.mixins      = CType[,]
  29      this.enumDefs    = EnumDef[,]
  30      this.slotMap     = Str:CSlot[:]
  31      this.slotDefMap  = Str:SlotDef[:]
  32      this.slotDefList = SlotDef[,]
  33      this.closures    = ClosureExpr[,]
  34    }
  35  
  36  //////////////////////////////////////////////////////////////////////////
  37  // CType
  38  //////////////////////////////////////////////////////////////////////////
  39  
  40    override Str signature() { return qname }
  41  
  42    override Bool isGeneric() { return false }
  43    override Bool isParameterized() { return false }
  44    override Bool isGenericParameter() { return false }
  45  
  46    override ListType toListOf()
  47    {
  48      if (listOf == null) listOf = ListType.make(this)
  49      return listOf
  50    }
  51  
  52  //////////////////////////////////////////////////////////////////////////
  53  // Access
  54  //////////////////////////////////////////////////////////////////////////
  55  
  56    **
  57    ** Return if this type is the anonymous class of a closure
  58    **
  59    Bool isClosure()
  60    {
  61      return closure != null
  62    }
  63  
  64  //////////////////////////////////////////////////////////////////////////
  65  // Slots
  66  //////////////////////////////////////////////////////////////////////////
  67  
  68    **
  69    ** Return all the all slots (inherited and defined)
  70    **
  71    override Str:CSlot slots() { return slotMap }
  72  
  73    **
  74    ** Add a slot to the type definition.  The method is used to add
  75    ** SlotDefs declared by this type as well as slots inherited by
  76    ** this type.
  77    **
  78    Void addSlot(CSlot s, Int slotDefIndex := null)
  79    {
  80      // if MethodDef
  81      m := s as MethodDef
  82      if (m != null)
  83      {
  84        // static initializes are just temporarily added to the
  85        // slotDefList but never into the name map - we just need
  86        // to keep them in declared order until they get collapsed
  87        // and removed in the Normalize step
  88        if (m.isStaticInit)
  89        {
  90          slotDefList.add(m)
  91          return
  92        }
  93  
  94        // field accessors are added only to slotDefList,
  95        // name lookup is always the field itself
  96        if (m.isFieldAccessor)
  97        {
  98          slotDefList.add(m)
  99          return
 100        }
 101      }
 102  
 103      // sanity check
 104      name := s.name
 105      if (hasSlot(name))
 106        throw CompilerErr.make("Internal error: duplicate slot $name", location)
 107  
 108      // add to all slots table
 109      slotMap[name] = s
 110  
 111      // if my own SlotDef
 112      def := s as SlotDef
 113      if (def != null && def.parent === this)
 114      {
 115        // add to my slot definitions
 116        slotDefMap[name] = def
 117        if (slotDefIndex == null)
 118          slotDefList.add(def)
 119        else
 120          slotDefList.insert(slotDefIndex, def)
 121  
 122        // if non-const FieldDef, then add getter/setter methods
 123        if (s is FieldDef)
 124        {
 125          f := (FieldDef)s
 126          if (f.get != null) addSlot(f.get)
 127          if (f.set != null) addSlot(f.set)
 128        }
 129      }
 130    }
 131  
 132    **
 133    ** Replace oldSlot with newSlot in my slot tables.
 134    **
 135    Void replaceSlot(CSlot oldSlot, CSlot newSlot)
 136    {
 137      // sanity checks
 138      if (oldSlot.name != newSlot.name)
 139        throw CompilerErr.make("Not same names: $oldSlot != $newSlot", location)
 140      if (slotMap[oldSlot.name] !== oldSlot)
 141        throw CompilerErr.make("Old slot not mapped: $oldSlot", location)
 142  
 143      // remap in slotMap table
 144      slotMap[oldSlot.name] = newSlot
 145  
 146      // if SlotDef
 147      def := newSlot as SlotDef
 148      if (def != null && def.parent === this)
 149      {
 150        slotDefMap[name] = def
 151        slotDefList.add(def)
 152      }
 153    }
 154  
 155    **
 156    ** If during parse we added any static initializer methods,
 157    ** now is the time to remove them all and replace them with a
 158    ** single collapsed MethodDef (processed in Normalize step)
 159    **
 160    Void normalizeStaticInits(MethodDef m)
 161    {
 162      // remove any temps we had in slotDefList
 163      slotDefList = slotDefList.exclude |SlotDef s->Bool|
 164      {
 165        return MethodDef.isNameStaticInit(s.name)
 166      }
 167  
 168      // fix enclosingMethod of closures used in those temp statics
 169      closures.each |ClosureExpr c|
 170      {
 171        if (c.enclosingMethod.isStaticInit)
 172          c.enclosingMethod = m
 173      }
 174  
 175      // now we add into all slot tables
 176      slotMap[m.name] = m
 177      slotDefMap[m.name] = m
 178      slotDefList.add(m)
 179    }
 180  
 181  //////////////////////////////////////////////////////////////////////////
 182  // SlotDefs
 183  //////////////////////////////////////////////////////////////////////////
 184  
 185    **
 186    ** Return if this class has a slot definition for specified name.
 187    **
 188    Bool hasSlotDef(Str name)
 189    {
 190      return slotDefMap.containsKey(name)
 191    }
 192  
 193    **
 194    ** Return SlotDef for specified name or null.
 195    **
 196    SlotDef slotDef(Str name)
 197    {
 198      return slotDefMap[name]
 199    }
 200  
 201    **
 202    ** Return FieldDef for specified name or null.
 203    **
 204    FieldDef fieldDef (Str name)
 205    {
 206      return (FieldDef)slotDefMap[name]
 207    }
 208  
 209    **
 210    ** Return MethodDef for specified name or null.
 211    **
 212    MethodDef methodDef(Str name)
 213    {
 214      return (MethodDef)slotDefMap[name]
 215    }
 216  
 217    **
 218    ** Get the SlotDefs declared within this TypeDef.
 219    **
 220    SlotDef[] slotDefs()
 221    {
 222      return slotDefList
 223    }
 224  
 225    **
 226    ** Get the FieldDefs declared within this TypeDef.
 227    **
 228    FieldDef[] fieldDefs()
 229    {
 230      return (FieldDef[])slotDefList.findType(FieldDef.type)
 231    }
 232  
 233    **
 234    ** Get the static FieldDefs declared within this TypeDef.
 235    **
 236    FieldDef[] staticFieldDefs()
 237    {
 238      return fieldDefs.findAll |FieldDef f->Bool| { return f.isStatic }
 239    }
 240  
 241    **
 242    ** Get the instance FieldDefs declared within this TypeDef.
 243    **
 244    FieldDef[] instanceFieldDefs()
 245    {
 246      return fieldDefs.findAll |FieldDef f->Bool| { return !f.isStatic }
 247    }
 248  
 249    **
 250    ** Get the MethodDefs declared within this TypeDef.
 251    **
 252    MethodDef[] methodDefs()
 253    {
 254      return (MethodDef[])slotDefList.findType(MethodDef.type)
 255    }
 256  
 257  //////////////////////////////////////////////////////////////////////////
 258  // Enum
 259  //////////////////////////////////////////////////////////////////////////
 260  
 261    **
 262    ** Return EnumDef for specified name or null.
 263    **
 264    public EnumDef enumDef(Str name)
 265    {
 266      return enumDefs.find |EnumDef def->Bool| { return def.name == name }
 267    }
 268  
 269  //////////////////////////////////////////////////////////////////////////
 270  // Tree
 271  //////////////////////////////////////////////////////////////////////////
 272  
 273    Void walk(Visitor v, VisitDepth depth)
 274    {
 275      v.enterTypeDef(this)
 276      walkFacets(v, depth)
 277      if (depth >= VisitDepth.slotDef)
 278      {
 279        slotDefs.each |SlotDef slot| { slot.walk(v, depth) }
 280      }
 281      v.visitTypeDef(this)
 282      v.exitTypeDef(this)
 283    }
 284  
 285  //////////////////////////////////////////////////////////////////////////
 286  // Debug
 287  //////////////////////////////////////////////////////////////////////////
 288  
 289    override Str toStr()
 290    {
 291      return signature()
 292    }
 293  
 294    override Void print(AstWriter out)
 295    {
 296      out.nl
 297      printFacets(out)
 298      if (isMixin)
 299        out.w("mixin $qname").nl
 300      else if (isEnum)
 301        out.w("enum $qname").nl
 302      else
 303        out.w("class $qname").nl
 304  
 305      if (base != null || !mixins.isEmpty)
 306      {
 307        out.w(" : ")
 308        if (base != null) out.w(" $base")
 309        if (!mixins.isEmpty) out.w(", ").w(mixins.join(", ")).nl
 310      }
 311  
 312      out.w("{").nl
 313      out.indent
 314      enumDefs.each |EnumDef e| { e.print(out) }
 315      slotDefs.each |SlotDef s| { s.print(out) }
 316      out.unindent
 317      out.w("}").nl
 318    }
 319  
 320  //////////////////////////////////////////////////////////////////////////
 321  // Fields
 322  //////////////////////////////////////////////////////////////////////////
 323  
 324    override readonly Namespace ns   // compiler's namespace
 325    readonly CompilationUnit unit    // parent unit
 326    override readonly CPod pod       // parent pod
 327    override readonly Str name       // simple class name
 328    override readonly Str qname      // podName::name
 329    Bool baseSpecified := true       // was base assigned from source code
 330    override CType base              // extends class
 331    override CType[] mixins          // mixin types
 332    EnumDef[] enumDefs               // declared enumerated pairs (only if enum)
 333    ClosureExpr[] closures           // closures where I am enclosing type (Parse)
 334    ClosureExpr closure              // if I am a closure anonymous class
 335    private Str:CSlot slotMap        // all slots
 336    private Str:SlotDef slotDefMap   // declared slot definitions
 337    private SlotDef[] slotDefList    // declared slot definitions
 338    private ListType listOf          // lazily created list of
 339    FacetDef[] indexedFacets         // used by WritePod
 340  
 341  }