logo
class

compiler::ParameterizedMethodParam

sys::Obj
  compiler::ParameterizedMethodParam

Mixin: compiler::CParam
   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 Jul 06  Brian Frank  Creation
   7  //
   8  
   9  **
  10  ** GenericType models a parameterized generic type: List, Map, or Func
  11  **
  12  abstract class GenericType : CType
  13  {
  14  
  15  //////////////////////////////////////////////////////////////////////////
  16  // Construction
  17  //////////////////////////////////////////////////////////////////////////
  18  
  19    new make(CType base)
  20    {
  21      this.base = base
  22    }
  23  
  24  //////////////////////////////////////////////////////////////////////////
  25  // CType
  26  //////////////////////////////////////////////////////////////////////////
  27  
  28    override Namespace ns()  { return base.ns }
  29    override CPod pod()      { return ns.sysPod }
  30    override Str name()      { return base.name }
  31    override Str qname()     { return base.qname }
  32    override Int flags()  { return 0 }
  33  
  34    override Bool isGeneric() { return false }
  35    override Bool isParameterized() { return true }
  36  
  37    override ListType toListOf()
  38    {
  39      if (listOf == null) listOf = ListType.make(this)
  40      return listOf
  41    }
  42  
  43    override CType[] mixins() { return CType[,] }
  44  
  45    override Str:CSlot slots
  46    {
  47      get
  48      {
  49        if (@slots == null) @slots = parameterizeSlots()
  50        return @slots
  51      }
  52    }
  53  
  54    override Str toStr() { return signature() }
  55  
  56  //////////////////////////////////////////////////////////////////////////
  57  // Parameterize
  58  //////////////////////////////////////////////////////////////////////////
  59  
  60    private Str:CSlot parameterizeSlots()
  61    {
  62      s := Str:CSlot[:]
  63      base.slots.map(s) |CSlot slot->Obj| { return parameterizeSlot(slot) }
  64      return s
  65    }
  66  
  67    private CSlot parameterizeSlot(CSlot slot)
  68    {
  69      m := slot as CMethod
  70      if (m == null) return slot
  71      if (!m.isGeneric) return slot
  72      return ParameterizedMethod.make(this, m)
  73    }
  74  
  75    internal CType parameterize(CType t)
  76    {
  77      if (!t.isGenericParameter) return t
  78      if (is ListType) return parameterizeListType((ListType)t)
  79      if (is FuncType) return parameterizeFuncType((FuncType)t)
  80      if (t.name.size != 1) throw CompilerErr.make("Cannot parameterize $t.qname"null)
  81      return doParameterize(t.name[0])
  82    }
  83  
  84    private CType parameterizeListType(ListType t)
  85    {
  86      return parameterize(t.v).toListOf
  87    }
  88  
  89    private CType parameterizeFuncType(FuncType t)
  90    {
  91      params := (CType[])t.params.map(CType[,]) |CType p->CType| { return parameterize(p) }
  92      ret := parameterize(t.ret)
  93      return FuncType.make(params, t.names, ret)
  94    }
  95  
  96    abstract CType doParameterize(Int ch)
  97  
  98  //////////////////////////////////////////////////////////////////////////
  99  // Fields
 100  //////////////////////////////////////////////////////////////////////////
 101  
 102    override readonly CType base
 103    private ListType listOf
 104  }
 105  
 106  **************************************************************************
 107  ** ListType
 108  **************************************************************************
 109  
 110  **
 111  ** ListType models a parameterized List type.
 112  **
 113  class ListType : GenericType
 114  {
 115    new make(CType v)
 116      : super(v.ns.listType)
 117    {
 118      this.v = v
 119      this.signature = "${v.signature}[]"
 120    }
 121  
 122    override Bool isGenericParameter()
 123    {
 124      return v.isGenericParameter
 125    }
 126  
 127    override Bool fits(CType t)
 128    {
 129      if (this == t) return true
 130      if (t.signature == "sys::List") return true
 131      if (t.isObj) return true
 132      if (t.name.size == 1 && t.pod.name == "sys") return true
 133  
 134      that := t.deref as ListType
 135      if (that == null) return false
 136  
 137      return v.fits(that.v)
 138    }
 139  
 140    override CType doParameterize(Int ch)
 141    {
 142      switch (ch)
 143      {
 144        case 'V'return v
 145        case 'L'return this
 146        default:  throw Err.make(ch.toChar)
 147      }
 148    }
 149  
 150    readonly CType v         // value type
 151    override readonly Str signature   // v[]
 152  
 153  }
 154  
 155  **************************************************************************
 156  ** MapType
 157  **************************************************************************
 158  
 159  **
 160  ** MapType models a parameterized Map type.
 161  **
 162  class MapType : GenericType
 163  {
 164    new make(CType k, CType v)
 165      : super(k.ns.mapType)
 166    {
 167      this.k = k
 168      this.v = v
 169      this.signature = "[${k.signature}:${v.signature}]"
 170    }
 171  
 172    override Bool isGenericParameter()
 173    {
 174      return k.isGenericParameter || v.isGenericParameter
 175    }
 176  
 177    override Bool fits(CType t)
 178    {
 179      if (this == t) return true
 180      if (t.signature == "sys::Map") return true
 181      if (t.isObj) return true
 182      if (t.name.size == 1 && t.pod.name == "sys") return true
 183  
 184      that := t.deref as MapType
 185      if (that == null) return false
 186  
 187      return k.fits(that.k) && v.fits(that.v)
 188    }
 189  
 190    override CType doParameterize(Int ch)
 191    {
 192      switch (ch)
 193      {
 194        case 'K'return k
 195        case 'V'return v
 196        case 'M'return this
 197        default:  throw Err.make(ch.toChar)
 198      }
 199    }
 200  
 201    readonly CType k         // keytype
 202    readonly CType v         // value type
 203    override readonly Str signature   // [k:v]
 204  
 205  }
 206  
 207  **************************************************************************
 208  ** FuncType
 209  **************************************************************************
 210  
 211  **
 212  ** FuncType models a parameterized Func type.
 213  **
 214  class FuncType : GenericType
 215  {
 216    new make(CType[] params, Str[] names, CType ret)
 217      : super(ret.ns.funcType)
 218    {
 219      this.params = params
 220      this.names  = names
 221      this.ret    = ret
 222      this.isGenericParameter = ret.isGenericParameter
 223  
 224      s := StrBuf.make.add("|")
 225      params.each |CType p, Int i|
 226      {
 227        isGenericParameter |= p.isGenericParameter
 228        if (i > 0) s.add(","); s.add(p.signature)
 229      }
 230      s.add("->").add(ret.signature).add("|")
 231      this.signature = s.toStr
 232    }
 233  
 234    override Bool fits(CType t)
 235    {
 236      if (this == t) return true
 237      if (t.signature == "sys::Func") return true
 238      if (t.isObj) return true
 239      if (t.name.size == 1 && t.pod.name == "sys") return true
 240  
 241      that := t.deref as FuncType
 242      if (that == null) return false
 243  
 244      // match return type (if void is needed, anything matches)
 245      if (!that.ret.isVoid && !ret.fits(that.ret)) return false
 246  
 247      // match params - it is ok for me to have less than
 248      // the type params (if I want to ignore them), but I
 249      // must have no more
 250      if (params.size > that.params.size) return false
 251      for (i:=0; i<params.size; ++i)
 252        if (!that.params[i].fits(params[i])) return false
 253  
 254      // this method works for the specified method type
 255      return true;
 256    }
 257  
 258    ParamDef[] toParamDefs(Location loc)
 259    {
 260      p := ParamDef[,]
 261      p.size = params.size
 262      for (i:=0; i<params.size; ++i)
 263      {
 264        p[i] = ParamDef.make(loc, params[i], names[i])
 265      }
 266      return p
 267    }
 268  
 269    override CType doParameterize(Int ch)
 270    {
 271      if ('A' <= ch && ch <= 'H')
 272      {
 273        index := ch - 'A'
 274        if (index < params.size) return params[index]
 275        return ns.objType
 276      }
 277  
 278      switch (ch)
 279      {
 280        case 'R'return ret
 281        default:  throw Err.make(ch.toChar)
 282      }
 283    }
 284  
 285    readonly CType[] params  // a, b, c ...
 286    readonly Str[] names     // parameter names
 287    readonly CType ret       // return type
 288    override readonly Str signature   // |a,b..n->r|
 289    override readonly Bool isGenericParameter
 290  }
 291  
 292  **************************************************************************
 293  ** GenericParameterType
 294  **************************************************************************
 295  
 296  **
 297  ** GenericParameterType models the generic parameter types
 298  ** sys::V, sys::K, etc.
 299  **
 300  class GenericParameterType : CType
 301  {
 302    new make(Namespace ns, Str name)
 303    {
 304      this.ns = ns
 305      this.name = name
 306      this.qname = "sys::$name"
 307    }
 308  
 309    override Namespace ns
 310    override CPod pod() { return ns.sysPod }
 311    override Str name
 312    override Str qname
 313    override Str signature() { return qname }
 314    override Int flags() { return 0 }
 315    override Bool isGeneric() { return false }
 316    override Bool isParameterized() { return false }
 317    override Bool isGenericParameter() { return true }
 318    override ListType toListOf() { if (listOf == null) listOf = ListType.make(this)return listOf }
 319    override CType base() { return ns.objType }
 320    override CType[] mixins() { return CType[,] }
 321    override Str:CSlot slots() { throw UnsupportedErr.make }
 322    override Str toStr() { return qname }
 323    private ListType listOf
 324  }
 325  
 326  **************************************************************************
 327  ** ParameterizedMethod
 328  **************************************************************************
 329  
 330  **
 331  ** ParameterizedMethod models a parameterized CMethod
 332  **
 333  class ParameterizedMethod : CMethod
 334  {
 335    new make(GenericType parent, CMethod generic)
 336    {
 337      this.parent = parent
 338      this.generic = generic
 339  
 340      this.returnType = parent.parameterize(generic.returnType)
 341      generic.params.map(this.params = CParam[,]) |CParam p->Obj|
 342      {
 343        return ParameterizedMethodParam.make(parent, p)
 344      }
 345  
 346      signature = "$returnType $name(" + params.join(", ") + ")"
 347    }
 348  
 349    override Str name()  { return generic.name }
 350    override Str qname() { return generic.qname }
 351    override Int flags() { return generic.flags }
 352    override Str toStr() { return signature }
 353  
 354    override Bool isParameterized()  { return true }
 355  
 356    override CType inheritedReturnType()  { return generic.inheritedReturnType }
 357  
 358    override readonly CType parent
 359    override readonly Str signature
 360    override readonly CMethod generic
 361    override readonly CType returnType
 362    override readonly CParam[] params
 363  }
 364  
 365  **************************************************************************
 366  ** ParameterizedMethodParam
 367  **************************************************************************
 368  
 369  class ParameterizedMethodParam : CParam
 370  {
 371    new make(GenericType parent, CParam generic)
 372    {
 373      this.generic = generic
 374      this.paramType = parent.parameterize(generic.paramType)
 375    }
 376  
 377    override Str name() { return generic.name }
 378    override Bool hasDefault() { return generic.hasDefault }
 379    override Str toStr() { return "$paramType $name" }
 380  
 381    override readonly CType paramType
 382    readonly CParam generic
 383  }