public void Or() { StackAssert.IsAssignable(_evalStack.Pop(), new StackItem(typeof(bool)), false); StackAssert.IsAssignable(_evalStack.Pop(), new StackItem(typeof(bool)), false); _writer.Emit(OpCodes.Or); _evalStack.Push(typeof(bool)); }
public void Sub <T>() { StackAssert.IsAssignable(_evalStack.Pop(), typeof(T), false); StackAssert.IsAssignable(_evalStack.Pop(), typeof(T), false); _writer.Emit(OpCodes.Sub); _evalStack.Push(typeof(T)); }
private void BeginAssign(FieldInfo field) { if (field == null) { throw new ArgumentNullException("field"); } StackItem target = default(StackItem); if (!field.IsStatic) { target = _evalStack.Peek(); StackAssert.IsAssignable(target, new StackItem(field.DeclaringType, LoadOptions.ValueAsAddress), false); } _delayedInstructions.Push(() => { _evalStack.Pop(); // 稍后做验证 if (field.IsStatic) { _writer.Emit(OpCodes.Stsfld, field); } else { var item = _evalStack.Pop(); if (target != item) { throw new InvalidOperationException("BeginAssign/EndAssign 不匹配."); } _writer.Emit(OpCodes.Stfld, field); } }); }
/// <summary> /// 抛出异常 /// </summary> public void Throw() { var item = _evalStack.Pop(); StackAssert.IsAssignable(item, typeof(Exception), false); _writer.Emit(OpCodes.Throw); }
public override void Open() { var item = Owner._evalStack.Peek(); StackAssert.IsAssignable(item, new StackItem(typeof(IEnumerable), LoadOptions.ValueAsAddress), false); Initialize(item); Owner.BeginAssign(_enumerator); Owner.Call(_getEnumerator); Owner.EndAssign(); base.Open(); Owner._writer.BeginTry(); _iterateLabel = Owner._writer.DefineLabel(); Owner._writer.Emit(OpCodes.Br, _iterateLabel); _loopBlockLabel = Owner._writer.DefineLabel(); _loopBlockLabel.Mark(); Owner.BeginAssign(_current); { Owner.Load(_enumerator); Owner.BeginCall(_getCurrent); Owner.EndCall(); if (ElementType.IsValueType && _getCurrent.ReturnType == typeof(object)) { Owner.UnboxAny(ElementType); } } Owner.EndAssign(); }
public void LoadField(FieldInfo field, LoadOptions mode) { if (field == null) { throw new ArgumentNullException("field"); } OpCode opCode; if (ShouldLoadAddress(field.FieldType, mode)) { opCode = field.IsStatic ? OpCodes.Ldsflda : OpCodes.Ldflda; } else { opCode = field.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld; } if (!field.IsStatic) { StackAssert.IsAssignable(_evalStack.Pop(), new StackItem(field.DeclaringType, LoadOptions.ValueAsAddress), false); } _writer.Emit(opCode, field); _evalStack.Push(field.FieldType, mode); return; }
public void EndAssign() { StackAssert.IsAssignable( _owner._evalStack.Pop(), new StackItem(Type, LoadOptions.Default), true); _innerParameter.EndAssign(); }
public void Store() { StackAssert.IsAssignable( //判断pop出的类型,是否可以存入该参数 _owner._evalStack.Pop(), new StackItem(Type, LoadOptions.Default), true); _innerParameter.Store();//如果类型安全,那么就存储 }
public void Store() { StackAssert.IsAssignable( _owner._evalStack.Pop(), new StackItem(Type, LoadOptions.Default), true); _innerVariable.Store(); }
private void Decrement() { var item = _evalStack.Pop(); StackAssert.IsAssignable(item, typeof(int), false); _writer.EmitLdcI4(1); _writer.Emit(OpCodes.Sub); _evalStack.Push(typeof(int)); }
/// <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); }
/// <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); } }
/// <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); }); }
/// <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); }); }