protected void addSlotTrait(ObjectValue obj, ObjectList<ByteList> traits, String name, Qualifiers quals)
{
Builder bui = obj.builder;
IntList namespaces = new IntList(quals.size()); // will be (*it)->namespaces
int prev_var_index = -1;
int var_index = -1;
int flags = 0;
Slot prev_slot = null;
Iterator<Map.Entry<ObjectValue, Integer>> i = quals.entrySet().iterator();
Map.Entry<ObjectValue, Integer> qual_it = i.hasNext() ? i.next() : null;
while( qual_it != null )
{
// accumulate namespaces for names that point to the same slot
int slot_index;
Slot slot;
namespaces.clear(); // new multiname
var_index = -1;
ObjectValue ns = qual_it.getKey();
slot_index = obj.getSlotIndex(cx,GET_TOKEN,name,ns);
slot = obj.getSlot(cx,slot_index);
var_index = slot.getVarIndex()+bui.var_offset+1 /*zero is special*/;
if( slot.declaredBy != obj ) // if it is inherited, then skip it
{
qual_it = i.hasNext() ? i.next() : null;
continue;
}
/*
Get the api version the binding was introduced and mark the
namespace with that version.
*/
while( true )
{
if( ns != null )
{
int ns_index;
if (doingAPIVersioning) {
TreeSet<Integer> versions = apiVersionsOfSlot(slot, name, ns);
ns_index = makeVersionedNamespaceSet(ns, versions);
}
else {
ns_index = addNamespace(ns);
}
namespaces.add(ns_index);
}
else
{
cx.internalError(pos, "internal error: non object value for namespace");
}
qual_it = i.hasNext() ? i.next() : null;
if( qual_it == null )
{
break;
}
prev_var_index = var_index;
prev_slot = slot;
ns = qual_it.getKey();
slot_index = obj.getSlotIndex(cx,GET_TOKEN,name,ns);
if(slot_index <= 0)
continue;
slot = obj.getSlot(cx,slot_index);
var_index = slot.getVarIndex()+bui.var_offset+1; // zero is special
flags &= slot.isFinal() ?TRAIT_FLAG_final:0/*virtual*/;
flags &= slot.isOverride() ?TRAIT_FLAG_override:0/*new*/;
if( var_index < 0 || var_index != prev_var_index || slot.declaredBy != prev_slot.declaredBy )
{
var_index = prev_var_index;
slot = prev_slot;
break; // not an alias of the previous name
}
}
int name_index = ab.addUtf8Constant(bytecodeFactory.ConstantUtf8Info(name));
int qname_index;
if (doingAPIVersioning) {
qname_index = ab.addMultiNameConstant(bytecodeFactory.ConstantMultiname(name_index,namespaces.back(),false));
}
else {
qname_index = ab.addMultiNameConstant(bytecodeFactory.ConstantQualifiedName(name_index,namespaces.back(),false));
}
// Using the last namespace, get the slot for the name
ObjectValue objval = slot.getInitializerValue();
int value_index = 0;
byte value_kind = 0;
int kind;
int info;
if( objval != null && ((objval.builder instanceof ClassBuilder) ? objval.builder : null) != null )
{
kind = TRAIT_Class;
info = GetClassInfo(objval.builder.classname);
}
//#if 0 // ISSUE: this almost works, but the compiler needs to be smarter about multiple definitions
// else
// if( objval && dynamic_cast<FunctionBuilder*>(objval->builder) )
// {
// kind = TRAIT_Function;
// info = GetMethodInfo(objval->name);
// }
//#endif
else
{
kind = slot.isConst() ? TRAIT_Const : TRAIT_Var;
if( objval != null )
{
value_index = getValueIndex(objval);
value_kind = getValueKind(objval);
}
{
QName type_name = slot.getType().getName(cx); //slot->type->name;
info = addClassName(type_name);
}
}
IntList metaDataIndices = addMetadata(slot);
traits.push_back(allocBytes());
ab.addBytesToTable(traits,bytecodeFactory.TraitInfo(traits.back(),qname_index,kind, obj.canEarlyBind() ? var_index : 0,info,value_index,value_kind,metaDataIndices));
}
}