#1681 JS: type.slots not fully implemented (no inheritance)

jessevdam Tue 25 Oct 2011

The type.slots function in JS is not fully implmented. I checked in the java version, but it seems the JS code does not have the same structure as the working Java code. I think it would be good if both have exactly the same structure. The only two difference should be the java <-> JS syntax and the loading (from pod <-> code inline).

This would prevent us from doing double work, another option could be an partly implementation of the sys lib in Fantom.

jessevdam Wed 26 Oct 2011

I added some code my self to make code work, it should give the same implementation as in the java version (just copied the code and adapted it to JS)

fan.sys.Type.prototype.buildReflection = function()
{
  // these are working accumulators used to build the
  // data structures of my defined and inherited slots
  var slots = [];
  var nameToSlot  = {};   // String -> Slot
  var nameToIndex = {};   // String -> Int

  // merge in base class and mixin classes
  var mixins = this.mixins();
  for(var i=0; i< mixins.size(); ++i)
    this.mergeType(mixins.get(i), slots, nameToSlot, nameToIndex);
  this.mergeType(this.base(), slots, nameToSlot, nameToIndex);

  for (var i in this.m_slots)
    this.mergeSlot(this.m_slots[i], slots, nameToSlot, nameToIndex);

  // break out into fields and methods
  var fields = [];
  var methods = [];
  for (var i in slots)
  {
    if (slots[i] instanceof fan.sys.Field)
      fields.push(slots[i]);
    else
      methods.push(slots[i]);
  }
  this.m_rslots       = fan.sys.List.make(fan.sys.Slot.$type, slots);
  this.m_rfields      = fan.sys.List.make(fan.sys.Field.$type, fields);
  this.m_rmethods     = fan.sys.List.make(fan.sys.Method.$type, methods);
  //  this.slotsByName = nameToSlot;
  //  this.myFacets    = Facets.mapFacets(pod, ftype.attrs.facets);
  //  this.lineNum    = ftype.attrs.lineNum;
  //  this.sourceFile = ftype.attrs.sourceFile;
}

/**
 * Merge the inherit's slots into my slot maps.
 *  slots:       Slot[] by order
 *  nameToSlot:  String name -> Slot
 *  nameToIndex: String name -> Long index of slots
 */
fan.sys.Type.prototype.mergeType = function(inheritedType, slots, nameToSlot, nameToIndex)
{
  if (inheritedType == null) 
    return;
  var inheritedSlots = inheritedType.slots();
  for(var i=0; i< inheritedSlots.size(); ++i)
    this.mergeSlot(inheritedSlots.get(i), slots, nameToSlot, nameToIndex);
}

/**
 * Merge the inherited slot into my slot maps.  Assume this slot
 * trumps any previous definition (because we process inheritance
 * and my slots in the right order)
 *  slots:       Slot[] by order
 *  nameToSlot:  String name -> Slot
 *  nameToIndex: String name -> Long index of slots
 */
fan.sys.Type.prototype.mergeSlot = function(slot, slots, nameToSlot, nameToIndex)
{
  // skip constructors which aren't mine
  if (slot.isCtor() && slot.parent() != this) return;

  var name = slot.$name();
  var dup = nameToIndex[name];
  if (dup != null)
  {
    // if the slot is inherited from Obj, then we can
    // safely ignore it as an override - the dup is most
    // likely already the same Object method inherited from
    // a mixin; but the dup might actually be a more specific
    // override in which case we definitely don't want to
    // override with the sys::Object version
    if (slot.parent().qname() == "sys::Obj")
      return;

    // if given the choice between two *inherited* slots where
    // one is concrete and abstract, then choose the concrete one
    var dupSlot = slots[dup];
    if (slot.parent() != this && slot.isAbstract() && !dupSlot.isAbstract())
      return;

    // check if this is a Getter or Setter, which we should ignore
    if ((slot.flags() & (fan.sys.FConst.Getter|fan.sys.FConst.Setter)) != 0)
      return

    nameToSlot[name] = slot;
    slots[dup] = slot;
  }
  else
  {
    nameToSlot[name] = slot;
    slots.push(slot);
    nameToIndex[name] = slots.length - 1;
  }
}


fan.sys.Type.prototype.slots = function()
{
  if(this.m_rslots === undefined)
  {
    this.buildReflection()
  }
  return this.m_rslots;
}

fan.sys.Type.prototype.methods = function()
{
  if(this.m_rslots === undefined)
  {
    this.buildReflection();
  }
  return this.m_rmethods;
}

fan.sys.Type.prototype.fields = function()
{
  if(this.m_rslots === undefined)
  {
    this.buildReflection();
  }
  return this.m_rfields;
}

Login or Signup to reply.