IronPython and Generics

posted @ Thursday, October 14, 2004 1:48 AM

 

So lately I have been going through the source in Jim Hugunin's release of IronPython. This has been a really great experience for me as programming language design has always peaked my interest. I just got to thinking as I went through some of his code, how could generics help out when writing this language. So for an example I took a look at the Slot class and just a random method from his CodeGen class. The Slot class looks something like this:

 

public abstract class Slot
{
public abstract void emitGet(CodeGen cg);
public abstract void emitGetAddr(CodeGen cg);

public virtual void emitSet(CodeGen cg, Slot val)
{
val.emitGet(cg);
emitSet(cg);
}

public virtual void emitSet(CodeGen cg)
{
Slot val = cg.getLocalTmp(typeof(object));
val.emitSet(cg);
emitSet(cg, val);
cg.freeLocalTmp(val);
}

public virtual void emitCheck(CodeGen cg)
{
if (Options.CHECK_UNINITIALIZED)
{
cg.ilg.Emit(OpCodes.Dup);
cg.emitCall(typeof(Ops), "CheckInitialized");
}
}

public virtual Type type
{
get
{
throw new NotImplementedException("type");
}
}
}

public class ModuleSlot : Slot
{
public readonly Type _type;

public ModuleSlot(Type type)
{
this._type = type;
}

public override void emitGet(CodeGen cg)
{
cg.emitModuleInstance();
}

public override void emitSet(CodeGen cg)
{
throw new NotSupportedException("setting a module slot");
}

public override void emitGetAddr(CodeGen cg)
{
throw new NotSupportedException("addr of a module slot");
}

public override Type type { get { return _type; } }
}

So obviously there are a series of other classes (i.e., ModuleSlot) that use Slot as their base class. The important part is within the CodeGen class. Jim uses a private ArrayList to maintain free slots. This is simply declaired as such:

 

private ArrayList freeSlots = new ArrayList();

and the CodeGen class has a method I selected at random that is implemented as such:

 

public Slot getLocalTmp(Type type)
{
for (int i=0; i < freeSlots.Count; i++)
{
Slot slot = (Slot)freeSlots[i];
if (slot.type == type)
{
freeSlots.RemoveAt(i);
return slot;
}
}
return new LocalSlot(ilg.DeclareLocal(type));
}

However, with generics, we could do the following:

private LinkedList<Slot> freeSlots = new LinkedList<Slot>();
//...

public Slot getLocalTmp(Type type)
{
LinkedList<Slot>.Enumerator en = freeSlots.GetEnumerator();
while(en.MoveNext())
{
Slot slot = en.Current;
if(slot.type == type)
{
freeSlots.Remove(en.Current);
return slot;
}
}
return new LocalSlot(ilg.DeclareLocal(type));
}

It will be interesting to see if generics gets added to IronPython as we get closer to a RTM version of generics.