}
int unit = size;
List<TemplateAttribute> result = new ArrayList<TemplateAttribute>(size);
for (int i = 0; i < size; i++) {
result.add(new TemplateAttribute(new IRubyObject[args.size()]));
}
for (int i = 0; i < args.size(); i++) {
Collection<IRubyObject> c = args.get(i);
Iterator<IRubyObject> ite = c.iterator();
int k = 0, n = c.size();
int newUnit = unit / n;
IRubyObject v = ite.next();
for (int j = 0; j < size; j++) {
result.get(j).setArg(i, v);
if (++k == newUnit) {
k = 0;
if (!ite.hasNext()) {
ite = c.iterator();
}
v = ite.next();
}
}
unit = newUnit;
}
// handle receiver polymorphic and data polymorphic
int resultSize = result.size();
for (int i = 0; i < resultSize; i++) {
TemplateAttribute base = result.get(i);
boolean first = true;
for (IRubyObject recv : receivers) {
base.setReceiver(recv);
base.setBlock(block);
if (recv instanceof PolymorphicObject) {
for (PolymorphicObject mrecv : ((PolymorphicObject) recv).generateMonomorphicObjects()) {
base.setReceiver(mrecv);
if (!first) {
result.add(base);
}
first = false;
base = base.clone();
}
} else {
if (!first) {
result.add(base);
}
first = false;
base = base.clone();
}
}
}
// handle arguments data polymorphic
for (int i = 0; i < args.size(); i++) {
resultSize = result.size();
for (int j = 0; j < resultSize; j++) {
TemplateAttribute base = result.get(j);
IRubyObject arg = base.getArg(i);
if (arg instanceof PolymorphicObject) {
boolean first = true;
for (PolymorphicObject marg : ((PolymorphicObject) arg).generateMonomorphicObjects()) {
base.setArg(i, marg);
if (!first) {
result.add(base);
}
first = false;
base = base.clone();
}
}
}
}