Fan

 

class

compilerJs::JsTypeRef

sys::Obj
  compilerJs::JsNode
    compilerJs::JsTypeRef
//
// Copyright (c) 2009, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
//   9 Jul 09  Andy Frank  Creation
//

using compiler

**
** JsType
**
class JsType : JsNode
{
  new make(TypeDef def)
  {
    this.base        = JsTypeRef(def.base)
    this.qname       = qnameToJs(def)
    this.pod         = def.pod.name
    this.name        = def.name
    this.peer        = findPeer(def)
    this.isMixin     = def.isMixin
    this.isSynthetic = def.isSynthetic
    this.mixins      = def.mixins.map |TypeRef r->JsTypeRef| { JsTypeRef(r) }
    this.methods     = def.methodDefs.map |MethodDef m->JsMethod| { JsMethod(m) }
    this.fields      = def.fieldDefs.map |FieldDef f->JsField| { JsField(f) }
    if (def.staticInit != null) this.staticInit = def.staticInit.name
  }

  static JsTypeRef? findPeer(CType def)
  {
    CType? t := def
    while (t != null)
    {
      slot := t.slots.find |s| { s.isNative && s.parent.qname == t.qname }
      if (slot != null) return JsTypeRef(slot.parent)
      t = t.base
    }
    return null
  }

  override Void write(JsWriter out)
  {
    // class/mixin
    if (isMixin) out.w("$qname = function() {}").nl
    else out.w("$qname = fan.sys.Obj.\$extend($base.qname);").nl
    mixins.each |m| { copyMixin(m, out) }

    // ctor
    out.w("${qname}.prototype.\$ctor = function() {")
    if (peer != null) out.w(" this.peer = new ${peer.qname}Peer(this); ")
    out.w("}").nl

    // cache type
    if (!isSynthetic)
    {
      out.w("${qname}.\$type = fan.sys.Type.find(\"$pod::$name\");").nl
      out.w("${qname}.prototype.type = function() { return ${qname}.\$type; }").nl
    }

    // slots
    methods.each |m| { m.write(out) }
    fields.each |f| { f.write(out) }

    // static init
    if (staticInit != null) out.w("${qname}.$staticInit();").nl
  }

  Void copyMixin(JsTypeRef ref, JsWriter out)
  {
    ref.slots.each |s|
    {
      if (s.parent == "fan.sys.Obj") return
      if (s.isAbstract) return
      if (s.isStatic) return
      out.w("${qname}.prototype.${s.name} = ${s.parent}.prototype.${s.name};").nl
    }
  }

  JsTypeRef base      // base type qname
  Str qname           // type qname
  Str pod             // pod name for type
  Str name            // simple type name
  Bool isMixin        // is this type a mixin
  Bool isSynthetic    // is type synthetic
  JsTypeRef? peer     // peer type if has one
  JsTypeRef[] mixins  // mixins for this type
  JsMethod[] methods  // methods
  JsField[] fields    // fields
  Str? staticInit     // name of static initializer if has one
}

**************************************************************************
** JsTypeRef
**************************************************************************

**
** JsTypeRef
**
class JsTypeRef : JsNode
{
  new make(CType ref)
  {
    this.qname = qnameToJs(ref)
    this.pod   = ref.pod.name
    this.name  = ref.name
    this.sig   = ref.signature
    this.slots = ref.slots.values.map |CSlot s->JsSlotRef| { JsSlotRef(s) }
    this.isSynthetic = ref.isSynthetic
  }

  override Void write(JsWriter out)
  {
    out.w(qname)
  }

  Str qname          // qname of type ref
  Str pod            // pod name for type
  Str name           // simple type name
  Str sig            // full type signature
  JsSlotRef[] slots  // slots
  Bool isSynthetic   // is type synthetic
}