예제 #1
0
파일: Test.cs 프로젝트: qinfengzhu/gremit
        public void TestLdDec()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(decimal), Type.EmptyTypes);

            using (var il = new GroboIL(method))
            {
                il.LdDec(-12.3m);
                il.LdDec(34.5m);
                il.Call(typeof(decimal).GetMethod("Add", new[] { typeof(decimal), typeof(decimal) }));
                il.Ret();
                Console.WriteLine(il.GetILCode());
            }

            var compiledMethod = (Func <decimal>)method.CreateDelegate(typeof(Func <decimal>));

            Assert.That(compiledMethod(), Is.EqualTo(22.2m));
        }
        private static void EmitValue(GroboIL il, object value)
        {
            //value.GetType() is the "real" type, only all pointers are UIntPtr and nullables are BoxedNullable
            //It can be:
            //Boolean, Char, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Enum, IntPtr, UIntPtr
            //Or their nullable equivalents
            //Or string
            switch (value)
            {
            case bool boolean: il.Ldc_I4(boolean ? 1 : 0); break;

            case char character: il.Ldc_I4(character); break;

            case sbyte int8: il.Ldc_I4(int8); break;

            case byte uint8: il.Ldc_I4(uint8); break;

            case short int16: il.Ldc_I4(int16); break;

            case ushort uint16: il.Ldc_I4(uint16); break;

            case int int32: il.Ldc_I4(int32); break;

            case uint uint32: il.Ldc_I4((int)uint32); break;

            case long int64: il.Ldc_I8(int64); break;

            case ulong uint64: il.Ldc_I8((long)uint64); break;

            case float float32: il.Ldc_R4(float32); break;

            case double float64: il.Ldc_R8(float64); break;

            case decimal decimal128: il.LdDec(decimal128); break;

            case DateTime dateTime:
                var local = il.DeclareLocal(typeof(DateTime));
                il.Ldloca(local);
                il.Ldc_I8(dateTime.Ticks);
                il.Ldc_I4((int)dateTime.Kind);
                il.Call(typeof(DateTime).GetConstructor(new[] { typeof(long), typeof(DateTimeKind) }));
                il.Ldloc(local);
                break;

            case UIntPtr unint: il.Ldc_IntPtr(Unsafe.As <UIntPtr, IntPtr>(ref unint)); break;

            case IntPtr nint: il.Ldc_IntPtr(nint); break;

            case Enum enumeration:
                var underlyingType  = Enum.GetUnderlyingType(enumeration.GetType());
                var underlyingValue = Convert.ChangeType(enumeration, underlyingType);
                EmitValue(il, underlyingValue);
                break;

            case BoxedNullable boxedNullable:
                EmitValue(il, boxedNullable.UnderlyingValue);
                il.Newobj(boxedNullable.NullableType.GetConstructor(new[] { boxedNullable.UnderlyingType }));
                break;

            case string str: il.Ldstr(str); break;

            default: throw new ArgumentException($"Value {value} of type {value.GetType()} is not supported by the emitter.");
            }
        }