}
@SuppressWarnings("unchecked") // Because Java implemented generics stupidly
public void compose(ThreadContext tc, STable st, SixModelObject repr_info_hash) {
/* Get attribute part of the protocol from the hash. */
SixModelObject repr_info = repr_info_hash.at_key_boxed(tc, "attribute");
/* Go through MRO and find all classes with attributes and build up
* mapping info hashes. Note, reverse order so indexes will match
* those in parent types. */
int curAttr = 0;
boolean mi = false;
List<SixModelObject> classHandles = new ArrayList<SixModelObject>();
List<HashMap<String, Integer>> attrIndexes = new ArrayList<HashMap<String, Integer>>();
List<SixModelObject> autoVivs = new ArrayList<SixModelObject>();
List<STable> flattenedSTables = new ArrayList<STable>();
List<AttrInfo> attrInfoList = new ArrayList<AttrInfo>();
long mroLength = repr_info.elems(tc);
for (long i = mroLength - 1; i >= 0; i--) {
SixModelObject entry = repr_info.at_pos_boxed(tc, i);
SixModelObject type = entry.at_pos_boxed(tc, 0);
SixModelObject attrs = entry.at_pos_boxed(tc, 1);
SixModelObject parents = entry.at_pos_boxed(tc, 2);
/* If it has any attributes, give them each indexes and put them
* in the list to add to the layout. */
long numAttrs = attrs.elems(tc);
if (numAttrs > 0) {
HashMap<String, Integer> indexes = new HashMap<String, Integer>();
for (long j = 0; j < numAttrs; j++) {
SixModelObject attrHash = attrs.at_pos_boxed(tc, j);
String attrName = attrHash.at_key_boxed(tc, "name").get_str(tc);
SixModelObject attrType = attrHash.at_key_boxed(tc, "type");
if (attrType == null)
attrType = tc.gc.KnowHOW;
indexes.put(attrName, curAttr);
AttrInfo info = new AttrInfo();
info.st = attrType.st;
if (attrType.st.REPR.get_storage_spec(tc, attrType.st).inlineable == StorageSpec.INLINED)
flattenedSTables.add(attrType.st);
else
flattenedSTables.add(null);
info.boxTarget = attrHash.exists_key(tc, "box_target") != 0;
SixModelObject autoViv = attrHash.at_key_boxed(tc, "auto_viv_container");
autoVivs.add(autoViv);
if (autoViv != null)
info.hasAutoVivContainer = true;
info.posDelegate = attrHash.exists_key(tc, "positional_delegate") != 0;
info.assDelegate = attrHash.exists_key(tc, "associative_delegate") != 0;