logo

mixin

compiler::CType

sys::Obj
  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  //   4 Jun 06  Brian Frank  Creation
   7  //
   8  
   9  **
  10  ** CType is a "compiler type" which is class used for representing
  11  ** the Fan type system in the compiler.  CTypes map to types within
  12  ** the compilation units themsevles as TypeDef and TypeRef or to
  13  ** precompiled types in imported pods via ReflectType or FType.
  14  **
  15  mixin CType
  16  {
  17  
  18  //////////////////////////////////////////////////////////////////////////
  19  // Naming
  20  //////////////////////////////////////////////////////////////////////////
  21  
  22    **
  23    ** Associated namespace for this type representation
  24    **
  25    abstract Namespace ns()
  26  
  27    **
  28    ** Parent pod which defines this type.
  29    **
  30    abstract CPod pod()
  31  
  32    **
  33    ** Simple name of the type such as "Str".
  34    **
  35    abstract Str name()
  36  
  37    **
  38    ** Qualified name such as "sys:Str".
  39    **
  40    abstract Str qname()
  41  
  42    **
  43    ** This is the full signature of the type.
  44    **
  45    abstract Str signature()
  46  
  47    **
  48    ** If this is a TypeRef, return what it references
  49    **
  50    virtual CType deref() { return this }
  51  
  52  //////////////////////////////////////////////////////////////////////////
  53  // Generics
  54  //////////////////////////////////////////////////////////////////////////
  55  
  56    **
  57    ** A generic type means that one or more of my slots contain signatures
  58    ** using a generic parameter (such as V or K).  Fan supports three built-in
  59    ** generic types: List, Map, and Func.  A generic instance (such as Str[])
  60    ** is NOT a generic type (all of its generic parameters have been filled in).
  61    ** User defined generic types are not supported in Fan.
  62    **
  63    abstract Bool isGeneric()
  64  
  65    **
  66    ** A parameterized type is a type which has parameterized a generic type
  67    ** and replaced all the generic parameter types with generic argument
  68    ** types.  The type Str[] is a parameterized type of the generic type
  69    ** List (V is replaced with Str).  A parameterized type always has a
  70    ** signature which is different from the qname.
  71    **
  72    abstract Bool isParameterized()
  73  
  74    **
  75    ** Return if this type is a generic parameter (such as V or K) in a
  76    ** generic type (List, Map, or Method).  Generic parameters serve
  77    ** as place holders for the parameterization of the generic type.
  78    ** Fan has a predefined set of generic parameters which are always
  79    ** defined in the sys pod with a one character name.
  80    **
  81    abstract Bool isGenericParameter()
  82  
  83    **
  84    ** Create a parameterized List of this type.
  85    **
  86    abstract ListType toListOf()
  87  
  88    **
  89    ** If this type is a generic parameter (V, L, etc), then return
  90    ** the actual type for the native implementation.  For example V
  91    ** is Obj, and L is List.  This is the type we actually use when
  92    ** constructing a signature for the invoke opcode.
  93    **
  94    CType raw()
  95    {
  96      // if not generic parameter, always use this type
  97      if (!isGenericParameter) return this
  98  
  99      // it's possible that this type is a generic unparameterized
 100      // instance of Method (such as List.each), in which case
 101      // we should use this type itself
 102      if (name.size != 1) return this
 103  
 104      switch (name[0])
 105      {
 106        case 'L': return ns.listType
 107        case 'M': return ns.mapType
 108        default:  return ns.objType
 109      }
 110    }
 111  
 112  //////////////////////////////////////////////////////////////////////////
 113  // Inheritance
 114  //////////////////////////////////////////////////////////////////////////
 115  
 116    **
 117    ** The direct super class of this type (null for Obj).
 118    **
 119    abstract CType base()
 120  
 121    **
 122    ** Return the mixins directly implemented by this type.
 123    **
 124    abstract CType[] mixins()
 125  
 126    **
 127    ** Hash on signature.
 128    **
 129    override Int hash()
 130    {
 131      return signature.hash
 132    }
 133  
 134    **
 135    ** Equality based on signature.
 136    **
 137    override Bool equals(Obj t)
 138    {
 139      if (this === t) return true
 140      that := t as CType
 141      if (that == null) return false
 142      return signature == that.signature
 143    }
 144  
 145    **
 146    ** Does this type implement the specified type.  If true, then
 147    ** this type is assignable to the specified type (although the
 148    ** converse is not necessarily true).  All types (including
 149    ** mixin types) fit sys::Obj.
 150    **
 151    virtual Bool fits(CType t)
 152    {
 153      // short circuit if myself
 154      if (this == t) return true
 155  
 156      // recurse extends
 157      if (base != null && base.fits(t)) return true
 158  
 159      // recuse mixins
 160      for (i:=0; i<mixins.size; ++i)
 161        if (mixins[i].fits(t)) return true
 162  
 163      // let anything fit unparameterized generic parameters like
 164      // V, K (in case we are using List, Map, or Method directly)
 165      if (t.name.size == 1 && t.pod.name == "sys")
 166        return true
 167  
 168      // no fit
 169      return false
 170    }
 171  
 172    **
 173    ** Return if this type fits any of the types in the specified list.
 174    **
 175    Bool fitsAny(CType[] types)
 176    {
 177      return types.any |CType t->Bool| { return this.fits(t) }
 178    }
 179  
 180    **
 181    ** Given a list of types, compute the most specific type which they
 182    ** all share, or at worst return sys::Obj.  This method does not take
 183    ** into account mixins, only extends class inheritance.
 184    **
 185    public static CType common(Namespace ns, CType[] types)
 186    {
 187      if (types.isEmpty) return ns.objType
 188      best := types[0]
 189      for (Int i:=1; i<types.size; ++i)
 190      {
 191        t := types[i]
 192        while (!t.fits(best))
 193        {
 194          best = best.base
 195          if (best == null) return ns.objType
 196        }
 197      }
 198      return best
 199    }
 200  
 201  //////////////////////////////////////////////////////////////////////////
 202  // Flags
 203  //////////////////////////////////////////////////////////////////////////
 204  
 205    **
 206    ** Get the flags bitmask.
 207    **
 208    abstract Int flags()
 209  
 210    **
 211    ** Return if this Type is a class (as opposed to enum or mixin)
 212    **
 213    Bool isClass() { return !isMixin && !isEnum }
 214  
 215    **
 216    ** Return if this Type is a mixin type and cannot be instantiated.
 217    **
 218    Bool isMixin() { return flags & FConst.Mixin != 0 }
 219  
 220    **
 221    ** Return if this Type is an sys::Enum
 222    **
 223    Bool isEnum() { return flags & FConst.Enum != 0 }
 224  
 225    **
 226    ** Return if this Type is abstract and cannot be instantiated.  This
 227    ** method will always return true if the type is a mixin.
 228    **
 229    Bool isAbstract() { return flags & FConst.Abstract != 0 }
 230  
 231    **
 232    ** Return if this Type is const and immutable.
 233    **
 234    Bool isConst() { return flags & FConst.Const != 0 }
 235  
 236    **
 237    ** Return if this Type is final and cannot be subclassed.
 238    **
 239    Bool isFinal() { return flags & FConst.Final != 0 }
 240  
 241    **
 242    ** Is this a public scoped class
 243    **
 244    Bool isPublic() { return flags & FConst.Public != 0 }
 245  
 246    **
 247    ** Is this an internally scoped class
 248    **
 249    Bool isInternal() { return flags & FConst.Internal != 0 }
 250  
 251    **
 252    ** Is this a compiler generated synthetic class
 253    **
 254    Bool isSynthetic() { return flags & FConst.Synthetic != 0 }
 255  
 256  //////////////////////////////////////////////////////////////////////////
 257  // Conveniences
 258  //////////////////////////////////////////////////////////////////////////
 259  
 260    Bool isObj()    { return qname == "sys::Obj" }
 261    Bool isBool()   { return qname == "sys::Bool" }
 262    Bool isInt()    { return qname == "sys::Int" }
 263    Bool isFloat()  { return qname == "sys::Float" }
 264    Bool isRange()  { return qname == "sys::Range" }
 265    Bool isStr()    { return qname == "sys::Str" }
 266    Bool isType()   { return qname == "sys::Type" }
 267    Bool isVoid()   { return qname == "sys::Void" }
 268  
 269  //////////////////////////////////////////////////////////////////////////
 270  // Slots
 271  //////////////////////////////////////////////////////////////////////////
 272  
 273    **
 274    ** Map of the all defined slots, both fields and
 275    ** methods (including inherited slots).
 276    **
 277    abstract Str:CSlot slots()
 278  
 279    **
 280    ** Return if this type contains a slot by the specified name.
 281    **
 282    Bool hasSlot(Str name) { return slots.containsKey(name) }
 283  
 284    **
 285    ** Lookup a slot by name.  If the slot doesn't exist then return null.
 286    **
 287    virtual CSlot slot(Str name) { return slots[name] }
 288  
 289    **
 290    ** Lookup a field by name.
 291    **
 292    CField field(Str name) { return (CField)slot(name) }
 293  
 294    **
 295    ** Lookup a method by name.
 296    **
 297    CMethod method(Str name) { return (CMethod)slot(name) }
 298  
 299    **
 300    ** List of the all defined fields (including inherited fields).
 301    **
 302    CField[] fields() { return (CField[])slots.values.findType(CField.type) }
 303  
 304    **
 305    ** List of the all defined methods (including inherited methods).
 306    **
 307    CMethod[] methods() { return (CMethod[])slots.values.findType(CMethod.type) }
 308  
 309    **
 310    ** List of the all constructors.
 311    **
 312    CMethod[] ctors() { return methods.findAll |CMethod m->Bool| { return m.isCtor } }
 313  
 314  }