public override void CompileToDoubleProper(Gen ifProper, Gen ifOther) { if (IsCacheNeeded) { // Call CompileToDoubleOrNan via base class CompileToDoubleProper base.CompileToDoubleProper(ifProper, ifOther); } else { expr.CompileToDoubleProper(ifProper, ifOther); } }
protected void EvalCondCompile(Action compile) { if (evalCond != null) { evalCond.CompileToDoubleProper( new Gen(delegate { Label endLabel = ilg.DefineLabel(); ilg.Emit(OpCodes.Ldc_R8, 0.0); ilg.Emit(OpCodes.Beq, endLabel); compile(); ilg.MarkLabel(endLabel); }), new Gen(delegate { })); } else { compile(); } }
// Generate code to evaluate all argument expressions, including the receiver es[1] // if the method is an instance method, and convert their values to .NET types. private void CompileArgumentsAndApply(CGExpr[] es, Gen ifSuccess, Gen ifOther) { int argCount = es.Length - 1; // The error continuations must pop the arguments computed so far: Gen[] errorCont = new Gen[argCount]; if (argCount > 0) { errorCont[0] = ifOther; } for (int i = 1; i < argCount; i++) { int ii = i; // Capture lvalue -- do NOT inline! errorCont[ii] = new Gen(delegate { ilg.Emit(OpCodes.Pop); errorCont[ii - 1].Generate(ilg); }); } // Generate code, backwards, to evaluate argument expressions and // convert to external method's argument types for (int i = argCount - 1; i >= 0; i--) { // These local vars capture rvalue rather than lvalue -- do NOT inline them! CGExpr ei = es[i + 1]; Gen localSuccess = ifSuccess; int argIndex = i; Type argType = ef.ArgType(i); Gen ifError = errorCont[i]; // First some special cases to avoid boxing: if (argType == typeof(System.Double)) { ifSuccess = new Gen( delegate { ei.CompileToDoubleOrNan(); localSuccess.Generate(ilg); }); } else if (argType == typeof(System.Single)) { ifSuccess = new Gen( delegate { ei.CompileToDoubleOrNan(); ilg.Emit(OpCodes.Conv_R4); localSuccess.Generate(ilg); }); } else if (signed32.Contains(argType)) { ifSuccess = new Gen( delegate { ei.CompileToDoubleProper( new Gen(delegate { ilg.Emit(OpCodes.Conv_I4); localSuccess.Generate(ilg); }), ifError); }); } else if (unsigned32.Contains(argType)) { ifSuccess = new Gen( delegate { ei.CompileToDoubleProper( new Gen(delegate { ilg.Emit(OpCodes.Conv_U4); localSuccess.Generate(ilg); }), ifError); }); } else if (argType == typeof(System.Int64)) { ifSuccess = new Gen( delegate { ei.CompileToDoubleProper( new Gen(delegate { ilg.Emit(OpCodes.Conv_I8); localSuccess.Generate(ilg); }), ifError); }); } else if (argType == typeof(System.UInt64)) { ifSuccess = new Gen( delegate { ei.CompileToDoubleProper( new Gen(delegate { ilg.Emit(OpCodes.Conv_U8); localSuccess.Generate(ilg); }), ifError); }); } else if (argType == typeof(System.Boolean)) { ifSuccess = new Gen( delegate { ei.CompileToDoubleProper( new Gen(delegate { ilg.Emit(OpCodes.Ldc_R8, 0.0); ilg.Emit(OpCodes.Ceq); localSuccess.Generate(ilg); }), ifError); }); } else if (argType == typeof(System.Char)) { ifSuccess = new Gen( delegate { ei.Compile(); ilg.Emit(OpCodes.Call, TextValue.toNakedCharMethod); localSuccess.Generate(ilg); }); } else if (argType == typeof(System.String)) { ifSuccess = new Gen( delegate { ei.Compile(); UnwrapToString(localSuccess, ifError); }); } else // General cases: String[], double[], double[,], ... { ifSuccess = new Gen( delegate { ei.Compile(); ilg.Emit(OpCodes.Call, ef.ArgConverter(argIndex).Method); if (argType.IsValueType) // must unbox wrapped value type, but this is too simple-minded { ilg.Emit(OpCodes.Unbox, argType); } localSuccess.Generate(ilg); }); } } ifSuccess.Generate(ilg); }