Пример #1
0
 /// <summary>
 /// Generate code to compute the expression's value and storing it in the IL
 /// local variable; possibly to unwrap to a number variable; and possibly under
 /// the control of an evaluation condition evalCond.
 /// </summary>
 public virtual void Compile()
 {
     EvalCondCompile(delegate {
         if (var != null && var.Type == Typ.Number)
         {
             expr.CompileToDoubleOrNan();
         }
         else
         {
             expr.Compile();
         }
         if (var != null)
         {
             var.EmitStore(ilg);
         }
         if (numberVar != null)
         {
             Debug.Assert(var.Type == Typ.Value);
             var.EmitLoad(ilg);
             UnwrapToDoubleOrNan();
             numberVar.EmitStore(ilg);
         }
     });
 }
Пример #2
0
        // 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;

            // 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 the .NET 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];
                Gen    localSuccess = ifSuccess;
                Typ    argType      = functionInfo.signature.argTypes[i];
                Gen    ifError      = errorCont[i];
                if (argType == Typ.Number)
                {
                    ifSuccess = new Gen(delegate {
                        ei.CompileToDoubleOrNan();
                        localSuccess.Generate(ilg);
                    });
                }
                else if (argType == Typ.Function)
                {
                    ifSuccess = new Gen(delegate {
                        ei.Compile();
                        CheckType(FunctionValue.type, localSuccess, ifError);
                    });
                }
                else if (argType == Typ.Array)
                {
                    ifSuccess = new Gen(delegate {
                        ei.Compile();
                        CheckType(ArrayValue.type, localSuccess, ifError);
                    });
                }
                else if (argType == Typ.Text)
                {
                    ifSuccess = new Gen(delegate {
                        ei.Compile();
                        CheckType(TextValue.type, localSuccess, ifError);
                    });
                }
                else                 // argType.Value -- TODO: neglects to propagate ErrorValue from argument
                {
                    ifSuccess = new Gen(delegate {
                        ei.Compile();
                        localSuccess.Generate(ilg);
                    });
                }
            }
            ifSuccess.Generate(ilg);
        }
Пример #3
0
        // 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);
        }