/// <summary>
        /// <para>如果栈顶部是值对象,那么该方法可以将顶部的对象拆箱成<paramref name="type"/>对应的值类型</para>
        /// <para>如果栈顶部是引用对象,那么该方法可以顶部的对象转换成<paramref name="type"/>对应的引用类型</para>
        /// <para>转换后的值会被存储在堆栈上</para>
        /// </summary>
        public MethodGenerator UnboxAny(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            var item = _evalStack.Pop();

            StackAssert.IsAssignable(item, new StackItem(typeof(object), LoadOptions.BoxValues), false);
            _writer.Emit(OpCodes.Unbox_Any, type);
            _evalStack.Push(type);
            return(this);
        }
        /// <summary>
        /// 封装了返回指令
        /// </summary>
        public void Return()
        {
            if (_header.ReturnType != typeof(void))
            {
                StackAssert.IsAssignable(_evalStack.Pop(), new StackItem(_header.ReturnType, LoadOptions.Default), true);
            }

            if (_evalStack.Count > 0)
            {
                throw new InvalidOperationException("在返回代码执行之前,计算堆栈上的所有数据应该已被移除.");
            }

            _writer.Emit(OpCodes.Ret);
        }
            public override void Open()
            {
                var item = Owner._evalStack.Peek();

                StackAssert.AreEqual(item, new StackItem(item.Type, LoadOptions.Default));

                _targetDisposeMethod = UsingTarget.Type.GetBestCallableOverride(_disposeMethod);

                UsingTarget = Owner.Declare(item.Type);
                Owner.Store(UsingTarget);

                base.Open();

                Owner._writer.BeginTry();
            }
        /// <summary>
        /// 三元运算
        /// </summary>
        /// <param name="type"></param>
        /// <param name="options"></param>
        /// <param name="condition"></param>
        /// <param name="trueValue"></param>
        /// <param name="falseValue"></param>
        public void Ternary(Type type, LoadOptions options, Func <LogicOperator> condition, Action trueValue, Action falseValue)
        {
            if (condition == null)
            {
                throw new ArgumentNullException("condition");
            }
            if (trueValue == null)
            {
                throw new ArgumentNullException("trueValue");
            }
            if (falseValue == null)
            {
                throw new ArgumentNullException("falseValue");
            }

            var trueLabel = _writer.DefineLabel();
            var doneLabel = _writer.DefineLabel();

            var c = condition();

            GoToIf(c, trueLabel);
            int count = _evalStack.Count;

            falseValue();
            if (_evalStack.Count != count + 1)
            {
                throw new StackValidationException("The ternary operator expects exactly one more item on the evaluation stack after falseValue completes");
            }
            var falseResult = _evalStack.Pop();

            StackAssert.IsAssignable(falseResult, new StackItem(type, options), true);

            _writer.Emit(OpCodes.Br, doneLabel);
            trueLabel.Mark();
            count = _evalStack.Count();
            trueValue();
            if (_evalStack.Count != count + 1)
            {
                throw new StackValidationException("The ternary operator expects exactly one more item on the evaluation stack after trueValue completes");
            }
            var trueResult = _evalStack.Pop();

            StackAssert.IsAssignable(trueResult, new StackItem(type, options), true);

            doneLabel.Mark();

            _evalStack.Push(type, options);
        }
        /// <summary>
        /// 检查参数合法性,并从模拟计算堆栈中弹出参数
        /// </summary>
        /// <param name="method"></param>
        private void PopAndValidateParams(MethodBase method)
        {
            var parameters = method.GetParameters();

            for (int i = parameters.Length - 1; i >= 0; --i)
            {
                // 验证参数是否合法
                StackAssert.IsAssignable(_evalStack.Pop(), new StackItem(parameters[i].ParameterType, LoadOptions.Default), true);
            }
            if (!method.IsStatic && !method.IsConstructor)
            {
                //如果不是静态方法或者构造方法,那么当前栈顶的数据,应该是this
                //即:方法所声明的类型
                StackAssert.IsAssignable(_evalStack.Pop(), new StackItem(method.DeclaringType, LoadOptions.ValueAsAddress), false);
            }
        }
        public void Convert(Type toType, bool withOverflowCheck)
        {
            var item = _evalStack.Pop();

            StackAssert.IsPrimitive(item);
            OpCode conversionCode;

            if (_conversions.TryGetValue(new ConversionKey(toType, withOverflowCheck), out conversionCode))
            {
                _writer.Emit(conversionCode);
                _evalStack.Push(toType);
                return;
            }

            throw new ArgumentException("不能转换类型 " + toType.Name, "toType");
        }
Пример #7
0
        /// <summary>
        /// <para>开始加载数组元素</para>
        /// <para>请在执行该方法之后,加载索引:</para>
        /// <code>
        /// g.BeginLoadElement();
        ///	{
        ///		g.Load(i);
        ///	}
        /// g.EndLoadElement();
        /// </code>
        /// </summary>
        private void BeginLoadElement()
        {
            _delayedInstructions.Push(() =>
            {
                //需要加载的成员的索引值
                var item = _evalStack.Pop();
                StackAssert.IsAssignable(item, new StackItem(typeof(int)), false);//检查索引值是否为int型
                //目标数组
                //此处是模拟弹出,用于效验
                item = _evalStack.Pop();
                StackAssert.IsAssignable(item, new StackItem(typeof(Array)), false);//检查弹出的项是否为array

                //var elementType = item.Type.GetElementType();
                var elementType = item.Type.ResolveElementType();
                _writer.EmitLdelem(elementType);//将指定数组索引中的元素加载到计算堆栈的顶部。
                _evalStack.Push(elementType);
            });
        }
Пример #8
0
        /// <summary>
        /// <para>开始创建新的数组</para>
        /// <para>请在此方法时候,调用加载数组长度的方法,例如:</para>
        /// <code>
        /// g.BeginNewArray(_elementType);
        ///	{
        ///		g.Load(count);
        ///	}
        ///	g.EndNewArray();
        /// </code>
        /// </summary>
        /// <param name="elementType">数组的成员类型</param>
        /// <param name="rank">维数</param>
        private void BeginNewArray(Type elementType, int rank)
        {
            if (elementType == null)
            {
                throw new ArgumentNullException("elementType");
            }
            if (rank < 1)
            {
                throw new ArgumentOutOfRangeException("rank", "数组维度不能小于1");
            }

            var arrayType = rank == 1 ? elementType.MakeArrayType() : elementType.MakeArrayType(rank);

            _delayedInstructions.Push(() =>
            {
                for (int i = 0; i < rank; ++i)
                {
                    StackAssert.AreEqual(_evalStack.Pop(), typeof(int));
                }

                if (rank == 1)
                {
                    //创建一维数组
                    //将对新的从零开始的一维数组(其元素属于特定类型)的对象引用推送到计算堆栈上
                    _writer.Emit(OpCodes.Newarr, elementType);
                }
                else
                {
                    var paramTypes = new Type[rank];
                    for (int i = 0; i < paramTypes.Length; ++i)
                    {
                        paramTypes[i] = typeof(int);
                    }
                    //创建多维数组
                    //利用多维数组的构造函数,创建多维数组对象
                    _writer.Emit(OpCodes.Newobj, arrayType.GetConstructor(paramTypes));
                }
                _evalStack.Push(arrayType);
            });
        }
Пример #9
0
        /// <summary>
        /// <para>开始将值存入数组指定的索引处</para>
        /// <para>示例代码:</para>
        /// <code>
        /// g.Load(context.Member);
        /// g.BeginStoreElement();
        ///	{
        ///		g.Load(i);
        ///		g.Load(element);
        ///	}
        ///	g.EndStoreElement();
        /// </code>
        /// </summary>
        /// <remarks>
        /// 注意:由于BeginStoreElement前后,分为三步:
        /// 1.将对数组 array 的对象引用推送到堆栈上。
        /// 2.将 array 中元素的索引值 index 推送到堆栈上。
        /// 3.将指令中指定类型的值推送到堆栈上。
        /// 因此,以下代码,要反向验证,即:堆栈顶部的数据为:
        /// 1.需要存储的值
        /// 2.索引值 index
        /// 3.数组 array 的对象引用
        /// </remarks>
        private void BeginStoreElement()
        {
            _delayedInstructions.Push(() =>
            {
                //需要存储的值
                var valueItem = _evalStack.Pop();

                //验证索引值为int型
                StackAssert.IsAssignable(_evalStack.Pop(), typeof(int), false);

                //将对数组 array 的对象引用推送到堆栈上。
                var arrayItem = _evalStack.Pop();
                //检查是否为array类型
                StackAssert.IsAssignable(arrayItem, typeof(Array), false);

                Debug.Assert(arrayItem.Type.IsArray, "项必须存储在数组类型上");

                var elementType = arrayItem.Type.GetElementType();

                StackAssert.IsAssignable(valueItem, new StackItem(elementType, LoadOptions.Default), true);

                _writer.EmitStelem(elementType);
            });
        }