internal void CompileExpr(ILGen il, LocalAccess locals, Stack<Type> st, object lval) { if (lval == null) { il.EmitNull(); st.Push(typeof(System.Object)); } else if (Lisp.IsNode(lval)) { if (lval == Lisp.NIL || lval == Lisp.T) { if (lval == Lisp.NIL) il.EmitNull(); else il.Emit(OpCodes.Ldsfld, typeof(RuntimeOps).GetField("True")); st.Push(typeof(System.Object)); } else if (lval == Lisp.INST) { il.Emit(OpCodes.Ldarg_0); il.EmitPropertyGet(typeof(CompiledLambda), "Engine"); st.Push(typeof(Executive)); } else if (lval == Lisp.ARGV) { il.Emit(OpCodes.Ldarg_2); st.Push(typeof(object[])); } else if (lval == Lisp.MPOOL) { il.Emit(OpCodes.Ldarg_3); st.Push(typeof(MemoryPool)); } else { LocalBuilder localVar = locals.GetLocal(lval); if (localVar != null) { il.Emit(OpCodes.Ldloc, localVar); st.Push(localVar.LocalType); } else { Type type = lval.GetType(); if (type == typeof(Integer)) { il.EmitDecimal((Decimal)((Integer)lval)); il.EmitNew(typeof(Integer).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(Decimal) }, null)); } else if (!il.TryEmitConstant(lval, type)) { il.Emit(OpCodes.Ldarg_1); il.EmitInt(locals.DefineConstant(lval)); il.Emit(OpCodes.Ldelem_Ref); if (type.IsValueType) il.EmitUnbox(type); } st.Push(type); } } } else if (Lisp.IsFunctor(lval)) { object head = Lisp.Car(lval); object[] args = Lisp.ToArray(Lisp.Cdr(lval)); ControlFormBase control; if (m_control.TryGetValue(head, out control)) control.Compile(this, lval, il, locals, st, args); else { foreach (object a in args) CompileExpr(il, locals, st, a); Type[] parameterTypes = new Type[args.Length]; for (int k = args.Length - 1; k >= 0; k--) parameterTypes[k] = st.Pop(); FuncName name = new FuncName(head, parameterTypes); FuncBase body = GetFunc(name, false); if (body == null) { bool successed = false; if (parameterTypes.Length == 2) { Type castType = ValueProxy.GetType(parameterTypes[0], parameterTypes[1]); ValueConverter converter1 = FindConverter(parameterTypes[0], castType); ValueConverter converter2 = FindConverter(parameterTypes[1], castType); body = GetFunc(new FuncName(name.ID, new Type[] { castType, castType }), false); if (body != null && converter1 != null && converter2 != null) { LocalBuilder localVar = il.DeclareLocal(parameterTypes[1]); il.Emit(OpCodes.Stloc, localVar); converter1.Compile(this, il, locals, parameterTypes[0]); il.Emit(OpCodes.Ldloc, localVar); il.FreeLocal(localVar); converter2.Compile(this, il, locals, parameterTypes[1]); successed = true; } } if (!successed) { body = GetFunc(name, true); if (body == null) throw new UnknownFuncCall(name.ToString()); else { LocalBuilder[] localVar = new LocalBuilder[parameterTypes.Length]; for (int k = localVar.Length - 1; k >= 0; k--) { localVar[k] = il.DeclareLocal(parameterTypes[k]); il.Emit(OpCodes.Stloc, localVar[k]); } Type[] new_parameter_types = new Type[parameterTypes.Length]; for (int k = 0; k < localVar.Length; k++) { il.Emit(OpCodes.Ldloc, localVar[k]); if (body.Name.GetParameterType(k) != parameterTypes[k]) { if (parameterTypes[k].IsValueType) il.EmitBoxing(parameterTypes[k]); else if (ValueProxy.IsProxyType(parameterTypes[k])) il.EmitPropertyGet(typeof(ValueProxy), "Value"); new_parameter_types[k] = typeof(System.Object); } else new_parameter_types[k] = parameterTypes[k]; il.FreeLocal(localVar[k]); } parameterTypes = new_parameter_types; } } } Type resType = body.Compile(this, il, locals, parameterTypes); if (resType == typeof(System.Boolean)) { // Implict boolean convertion Label l_false = il.DefineLabel(); Label end = il.DefineLabel(); il.Emit(OpCodes.Brfalse_S, l_false); il.Emit(OpCodes.Ldsfld, typeof(RuntimeOps).GetField("True")); il.Emit(OpCodes.Br_S, end); il.MarkLabel(l_false); il.EmitNull(); il.MarkLabel(end); st.Push(typeof(System.Object)); } else if (resType == typeof(void)) { // assume that all procedures returns t il.Emit(OpCodes.Ldsfld, typeof(RuntimeOps).GetField("True")); st.Push(typeof(System.Object)); } else st.Push(resType); } } else if (Lisp.IsFunctor(Lisp.Car(lval), Lisp.LAMBDA)) { object form = Lisp.Car(lval); object body = Lisp.Car(Lisp.Cddr(form)); object tail = Lisp.Cdr(lval); LambdaExpr lambda = new LambdaExpr(null, CreateParameters(Lisp.Arg1(form)), typeof(System.Object), body); List<Type> parameterTypesList = new List<Type>(); foreach (object a in Lisp.getIterator(tail)) { CompileExpr(il, locals, st, a); parameterTypesList.Add(st.Pop()); } Type[] parameterTypes = parameterTypesList.ToArray(); FuncName name = new FuncName(null, parameterTypes); if (!lambda.Name.Match(name, true)) throw new InvalidOperationException("Lambda parameters does not match"); st.Push(lambda.Compile(this, il, locals, parameterTypes)); } else throw new ArgumentException("Unproperly formated expression"); }