logo

class

compiler::FType

sys::Obj
  compiler::FType : 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  //   26 Dec 05  Brian Frank  Creation
   7  //   19 Aug 06  Brian Frank  Ported from Java to Fan
   8  //
   9  
  10  **
  11  ** FType is the read/write fcode representation of sys::Type.
  12  **
  13  class FType : CType
  14  {
  15  
  16  //////////////////////////////////////////////////////////////////////////
  17  // Constructor
  18  //////////////////////////////////////////////////////////////////////////
  19  
  20    new make(FPod fpod)
  21    {
  22      this.fpod = fpod
  23      this.fattrs = FAttr[,]
  24    }
  25  
  26  //////////////////////////////////////////////////////////////////////////
  27  // CType
  28  //////////////////////////////////////////////////////////////////////////
  29  
  30    override Namespace ns() { return fpod.ns }
  31    override FPod pod() { return fpod }
  32    override Str name() { return fpod.n(fpod.typeRef(self).typeName) }
  33    override Str qname() { return "${fpod.name}::${name}" }
  34    override Str signature() { return qname }
  35    override Str toStr() { return signature }
  36  
  37    override CType base
  38    {
  39      get
  40      {
  41        if (@base == null) @base = fpod.toType(fbase)
  42        return @base
  43      }
  44    }
  45  
  46    override CType[] mixins
  47    {
  48      get
  49      {
  50        if (@mixins == null) @mixins = fpod.resolveTypes(fmixins)
  51        return @mixins
  52      }
  53    }
  54  
  55    override Str:CSlot slots
  56    {
  57      get
  58      {
  59        if (@slots == null) reflect
  60        return @slots
  61      }
  62    }
  63  
  64    override Bool isGeneric()
  65    {
  66      return fpod.name == "sys" && (name == "List" || name == "Map" || name == "Func")
  67    }
  68  
  69    override Bool isParameterized() { return false }
  70  
  71    override Bool isGenericParameter()
  72    {
  73      return fpod.name == "sys" && name.size == 1
  74    }
  75  
  76    override ListType toListOf()
  77    {
  78      if (listOf == null) listOf = ListType.make(this)
  79      return listOf
  80    }
  81  
  82  //////////////////////////////////////////////////////////////////////////
  83  // Reflection
  84  //////////////////////////////////////////////////////////////////////////
  85  
  86    private Void reflect()
  87    {
  88      // lazy read from the pod file
  89      read
  90  
  91      // map all the declared fields and methods
  92      @slots = Str:CSlot[:]
  93      ffields.each  |FField f|  { slots[f.name] = f }
  94      fmethods.each |FMethod m|
  95      {
  96        f := (FField)slots[m.name]
  97        if (f != null)
  98        {
  99          // if already mapped to field must be getter/setter
 100          if ((m.flags & FConst.Getter) != 0)
 101            f.getter = m
 102          else if ((m.flags & FConst.Setter) != 0)
 103            f.setter = m
 104          else
 105            throw Err.make("Conflicting slots: $f and $m")
 106        }
 107        else
 108        {
 109          slots[m.name] = m
 110        }
 111      }
 112  
 113      // inherited slots
 114      if (base != null) inherit(base)
 115      mixins.each |CType t| { inherit(t) }
 116    }
 117  
 118    private Void inherit(CType t)
 119    {
 120      t.slots.each |CSlot newSlot|
 121      {
 122        // if slot already mapped, skip it
 123        if (@slots[newSlot.name] != null) return
 124  
 125        // we never inherit constructors, private slots,
 126        // or internal slots outside of the pod
 127        if (newSlot.isCtor || newSlot.isPrivate ||
 128            (newSlot.isInternal && newSlot.parent.pod != t.pod))
 129          return
 130  
 131        // inherit it
 132        @slots[newSlot.name] = newSlot
 133      }
 134    }
 135  
 136  //////////////////////////////////////////////////////////////////////////
 137  // Meta IO
 138  //////////////////////////////////////////////////////////////////////////
 139  
 140    Void writeMeta(OutStream out)
 141    {
 142      out.writeI2(self)
 143      out.writeI2(fbase)
 144      out.writeI2(fmixins.size)
 145      fmixins.each |Int m| { out.writeI2(m) }
 146      out.writeI4(flags & FConst.FlagsMask)
 147    }
 148  
 149    FType readMeta(InStream in)
 150    {
 151      self    = in.readU2
 152      fbase   = in.readU2
 153      fmixins = Int[,]
 154      in.readU2.times |,| { fmixins.add(in.readU2) }
 155      flags   = in.readU4
 156      return this
 157    }
 158  
 159  //////////////////////////////////////////////////////////////////////////
 160  // Body IO
 161  //////////////////////////////////////////////////////////////////////////
 162  
 163    Uri uri()
 164    {
 165      return Uri.fromStr("/" + fpod.n(fpod.typeRef(self).typeName) + ".fcode")
 166    }
 167  
 168    Void write()
 169    {
 170      out := fpod.out(uri)
 171  
 172      out.writeI2(ffields.size)
 173      ffields.each |FField f| { f.write(out) }
 174  
 175      out.writeI2(fmethods.size)
 176      fmethods.each |FMethod m| { m.write(out) }
 177  
 178      out.writeI2(fattrs.size)
 179      fattrs.each |FAttr a| { a.write(out) }
 180  
 181      out.close
 182    }
 183  
 184    Void read()
 185    {
 186      in := fpod.in(uri)
 187  
 188      ffields = FField[,]
 189      in.readU2.times |,| { ffields.add(FField.make(this).read(in)) }
 190  
 191      fmethods = FMethod[,]
 192      in.readU2.times |,| { fmethods.add(FMethod.make(this).read(in)) }
 193  
 194      fattrs = FAttr[,]
 195      in.readU2.times |,| { fattrs.add(FAttr.make.read(in)) }
 196  
 197      in.close
 198    }
 199  
 200  //////////////////////////////////////////////////////////////////////////
 201  // Fields
 202  //////////////////////////////////////////////////////////////////////////
 203  
 204    override Int flags    // bitmask
 205    Bool hollow := true   // have we only read meta-data
 206    FPod fpod             // parent pod
 207    Int self              // self typeRef index
 208    Int fbase             // base typeRef index
 209    Int[] fmixins         // mixin typeRef indexes
 210    FField[] ffields      // fields
 211    FMethod[] fmethods    // methods
 212    FAttr[] fattrs        // type attributes
 213    ListType listOf       // CType.listOf cache
 214  
 215  }