protected void EmitValue(object value, CljILGen ilg)
{
bool partial = true;
if (value == null)
ilg.Emit(OpCodes.Ldnull);
else if (value is String)
ilg.Emit(OpCodes.Ldstr, (String)value);
else if (value is Boolean)
{
ilg.EmitBoolean((Boolean)value);
ilg.Emit(OpCodes.Box,typeof(bool));
}
else if (value is Int32)
{
ilg.EmitInt((int)value);
ilg.Emit(OpCodes.Box, typeof(int));
}
else if (value is Int64)
{
ilg.EmitLong((long)value);
ilg.Emit(OpCodes.Box, typeof(long));
}
else if (value is Double)
{
ilg.EmitDouble((double)value);
ilg.Emit(OpCodes.Box, typeof(double));
}
else if (value is Char)
{
ilg.EmitChar((char)value);
ilg.Emit(OpCodes.Box,typeof(char));
}
else if (value is Type)
{
Type t = (Type)value;
if (t.IsValueType)
ilg.EmitType(t);
else
{
//ilg.EmitString(Compiler.DestubClassName(((Type)value).FullName));
ilg.EmitString(((Type)value).FullName);
ilg.EmitCall(Compiler.Method_RT_classForName);
}
}
else if (value is Symbol)
{
Symbol sym = (Symbol)value;
if (sym.Namespace == null)
ilg.EmitNull();
else
ilg.EmitString(sym.Namespace);
ilg.EmitString(sym.Name);
ilg.EmitCall(Compiler.Method_Symbol_intern2);
}
else if (value is Keyword)
{
Keyword keyword = (Keyword)value;
if (keyword.Namespace == null)
ilg.EmitNull();
else
ilg.EmitString(keyword.Namespace);
ilg.EmitString(keyword.Name);
ilg.EmitCall(Compiler.Method_RT_keyword);
}
else if (value is Var)
{
Var var = (Var)value;
ilg.EmitString(var.Namespace.Name.ToString());
ilg.EmitString(var.Symbol.Name.ToString());
ilg.EmitCall(Compiler.Method_RT_var2);
}
else if (value is IType)
{
IPersistentVector fields = (IPersistentVector)Reflector.InvokeStaticMethod(value.GetType(), "getBasis", Type.EmptyTypes);
for (ISeq s = RT.seq(fields); s != null; s = s.next())
{
Symbol field = (Symbol)s.first();
Type k = Compiler.TagType(Compiler.TagOf(field));
object val = Reflector.GetInstanceFieldOrProperty(value, Compiler.munge(field.Name));
EmitValue(val, ilg);
if (k.IsPrimitive)
{
ilg.Emit(OpCodes.Castclass, k);
}
}
ConstructorInfo cinfo = value.GetType().GetConstructors()[0];
ilg.EmitNew(cinfo);
}
else if (value is IRecord)
{
//MethodInfo[] minfos = value.GetType().GetMethods(BindingFlags.Static | BindingFlags.Public);
EmitValue(PersistentArrayMap.create((IDictionary)value), ilg);
MethodInfo createMI = value.GetType().GetMethod("create", BindingFlags.Static | BindingFlags.Public, null, CallingConventions.Standard, new Type[] { typeof(IPersistentMap) }, null);
ilg.EmitCall(createMI);
}
else if (value is IPersistentMap)
{
IPersistentMap map = (IPersistentMap)value;
List<object> entries = new List<object>(map.count() * 2);
foreach (IMapEntry entry in map)
{
entries.Add(entry.key());
entries.Add(entry.val());
}
EmitListAsObjectArray(entries, ilg);
ilg.EmitCall(Compiler.Method_RT_map);
}
else if (value is IPersistentVector)
{
IPersistentVector args = (IPersistentVector)value;
if (args.count() <= Tuple.MAX_SIZE)
{
for (int i = 0; i < args.count(); i++)
EmitValue(args.nth(i), ilg);
ilg.Emit(OpCodes.Call, Compiler.Methods_CreateTuple[args.count()]);
}
else
{
EmitListAsObjectArray(value, ilg);
ilg.EmitCall(Compiler.Method_RT_vector);
}
}
else if (value is PersistentHashSet)
{
ISeq vs = RT.seq(value);
if (vs == null)
ilg.EmitFieldGet(Compiler.Method_PersistentHashSet_EMPTY);
else
{
EmitListAsObjectArray(vs, ilg);
ilg.EmitCall(Compiler.Method_PersistentHashSet_create);
}
}
else if (value is ISeq || value is IPersistentList)
{
EmitListAsObjectArray(value, ilg);
ilg.EmitCall(Compiler.Method_PersistentList_create);
}
else if (value is Regex)
{
ilg.EmitString(((Regex)value).ToString());
ilg.EmitNew(Compiler.Ctor_Regex_1);
}
else
{
string cs = null;
try
{
cs = RT.printString(value);
}
catch (Exception)
{
throw new InvalidOperationException(String.Format("Can't embed object in code, maybe print-dup not defined: {0}", value));
}
if (cs.Length == 0)
throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + value));
if (cs.StartsWith("#<"))
throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + cs));
ilg.EmitString(cs);
ilg.EmitCall(Compiler.Method_RT_readString);
partial = false;
}
if (partial)
{
if (value is IObj && RT.count(((IObj)value).meta()) > 0)
{
ilg.Emit(OpCodes.Castclass, typeof(IObj));
Object m = ((IObj)value).meta();
EmitValue(Compiler.ElideMeta(m), ilg);
ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap));
ilg.Emit(OpCodes.Callvirt, Compiler.Method_IObj_withMeta);
}
}
}