public override void BuildMethod() { AddStatement.DeclareInterceptedType(field.ContainingType.ResolvedType); Context.Log.WriteTrace(" Adding: var interceptedField = interceptedType.GetField('{0}');", field.Name.Value); Context.Block.Statements.Add( Declare.Variable<FieldInfo>("interceptedField").As( Call.VirtualMethod("GetField", typeof (string)).ThatReturns<FieldInfo>().WithArguments( Constant.Of(field.Name.Value)).On("interceptedType")) ); AddStatement.DeclareArgumentsList(); var funcT = SharpMockTypes.Functions[0]; var funcActualT = new GenericTypeInstanceReference(); funcActualT.GenericType = funcT; funcActualT.GenericArguments.Add(field.Type); var accessor = new AnonymousDelegate(); accessor.Type = funcActualT; accessor.ReturnType = field.Type; accessor.CallingConvention = CallingConvention.HasThis; var accessorBody = new BlockStatement(); var returnActualField = new ReturnStatement(); var actualField = new BoundExpression(); actualField.Type = field.Type; actualField.Definition = field; returnActualField.Expression = actualField; accessorBody.Statements.Add(returnActualField); accessor.Body = accessorBody; Context.Block.Statements.Add( Declare.Variable("local_0", funcActualT).As(accessor) ); AddStatement.DeclareRegistryInterceptor(); AddStatement.DeclareInvocation(); AddStatement.SetArgumentsOnInvocation(); AddStatement.SetOriginalCallOnInvocation(); AddStatement.SetTargetOnInvocationToNull(); Context.Block.Statements.Add( Do(Call.PropertySetter<MemberInfo>("OriginalCallInfo").WithArguments("interceptedField").On("invocation")) ); AddStatement.CallShouldInterceptOnInterceptor(); AddStatement.CallInterceptOnInterceptor(); Context.Block.Statements.Add( Declare.Variable("interceptionResult", field.Type).As( ChangeType.Convert(Call.PropertyGetter<object>("Return").On("invocation")).To(field.Type)) ); Context.Block.Statements.Add(Return.Variable(Locals["interceptionResult"])); }
private bool ReplaceReturnViaGotoInVoidMethods(BlockStatement b) { Contract.Requires(b != null); if (!this.isVoidMethod) return false; if (this.labelOfFinalReturn == null) return false; bool replacedPattern = false; var statements = b.Statements; for (int i = 1; i < b.Statements.Count - 1; i++) { var gotoStatement = statements[i] as GotoStatement; if (gotoStatement == null) continue; if (gotoStatement.TargetStatement.Label != this.labelOfFinalReturn) continue; var gotos = this.gotosThatTarget[(uint)gotoStatement.TargetStatement.Label.UniqueKey]; if (gotos != null) gotos.Remove(gotoStatement); statements[i] = new ReturnStatement(); replacedPattern = true; } return replacedPattern; }
private bool ReplaceReturnViaGoto(BlockStatement b) { Contract.Requires(b != null); if (this.returnValueTemp == null) return false; bool replacedPattern = false; var statements = b.Statements; for (int i = 1; i < b.Statements.Count-1; i++) { var expressionStatement = statements[i] as ExpressionStatement; if (expressionStatement == null) continue; var assign = expressionStatement.Expression as Assignment; if (assign == null) continue; if (assign.Target.Definition != this.returnValueTemp) continue; var gotoStatement = statements[i+1] as GotoStatement; if (gotoStatement == null) continue; if (gotoStatement.TargetStatement.Label != this.labelOfFinalReturn) continue; var gotos = this.gotosThatTarget[(uint)gotoStatement.TargetStatement.Label.UniqueKey]; if (gotos != null) gotos.Remove(gotoStatement); statements[i] = new ReturnStatement() { Expression = assign.Source }; this.numberOfAssignmentsToLocal[this.returnValueTemp]--; statements.RemoveAt(i+1); replacedPattern = true; } return replacedPattern; }
public FieldAccessorReplacementFactory(FieldReference field, ReturnStatement firstStatement, ReplacementRegistry registry) { this.field = field; this.firstStatement = firstStatement; this.registry = registry; }
public override IStatement Visit(ReturnStatement returnStatement) { if (returnStatement.Expression != null) { returnStatement.Expression = this.Visit(returnStatement.Expression); } if (this.sourceMethodBody.MethodDefinition.Type.TypeCode == PrimitiveTypeCode.Boolean) { CompileTimeConstant/*?*/ cc = returnStatement.Expression as CompileTimeConstant; if (cc != null) { if (ExpressionHelper.IsIntegralZero(cc)) cc.Value = false; else cc.Value = true; cc.Type = this.containingType.PlatformType.SystemBoolean; } } return returnStatement; }
/// <summary> /// Rewrites the children of the return statement. /// </summary> public virtual void RewriteChildren(ReturnStatement returnStatement) { this.RewriteChildren((Statement)returnStatement); if (returnStatement.Expression != null) returnStatement.Expression = this.Rewrite(returnStatement.Expression); }
/// <summary> /// Build the state machine. /// /// We start from state 0. For each yield return, we assign a unique state, which we call continueing state. For a yield return /// assigned with state x, we move the state machine from the previous state to x. Whenever we see a yield break, we transit /// the state to -1. /// /// When we return from state x, we jump to a label that is inserted right after the previous yield return (that is assigned with state x). /// </summary> private BlockStatement BuildStateMachine(IteratorClosureInformation iteratorClosure, BlockStatement oldBody, Dictionary<int, ILabeledStatement> stateEntries) { // Switch on cases. StateEntries, which have been computed previously, map a state number (for initial and continuing states) to a label that has been inserted // right after the associated yield return. BlockStatement result = new BlockStatement(); var returnFalse = new ReturnStatement() { Expression = new CompileTimeConstant() { Value = false, Type = this.host.PlatformType.SystemBoolean } }; var returnFalseLabel = new LabeledStatement() { Label = this.host.NameTable.GetNameFor("return false"), Statement = returnFalse }; List<ISwitchCase> cases = new List<ISwitchCase>(); foreach (int i in stateEntries.Keys) { SwitchCase c = new SwitchCase() { Expression = new CompileTimeConstant() { Type = this.host.PlatformType.SystemInt32, Value = i }, Body = new List<IStatement>(), }; c.Body.Add(new GotoStatement() { TargetStatement = stateEntries[i] }); cases.Add(c); } // Default case. SwitchCase defaultCase = new SwitchCase(); defaultCase.Body.Add(new GotoStatement() { TargetStatement = returnFalseLabel }); cases.Add(defaultCase); SwitchStatement switchStatement = new SwitchStatement() { Cases = cases, Expression = new BoundExpression() { Type = this.host.PlatformType.SystemInt32, Instance = new ThisReference(), Definition = iteratorClosure.StateFieldReference } }; result.Statements.Add(switchStatement); result.Statements.Add(oldBody); result.Statements.Add(returnFalseLabel); return result; }
private Statement ParseReturn() { ReturnStatement result = new ReturnStatement(); if (this.MethodDefinition.Type.TypeCode != PrimitiveTypeCode.Void) { result.Expression = TypeInferencer.Convert(this.PopOperandStack(), this.MethodDefinition.Type); } return result; }
/// <summary> /// Replace a (yield return exp)with a new block of the form: /// { /// Fresh_Label:; /// this.current = exp; /// state = Fresh_state; /// return true; /// } /// and associate the newly generated Fresh_state with its entry point: Fresh_label. /// </summary> public override IStatement Rewrite(IYieldReturnStatement yieldReturnStatement) { BlockStatement blockStatement = new BlockStatement(); int state = this.stateNumber++; ExpressionStatement thisDotStateEqState = new ExpressionStatement() { Expression = new Assignment() { Source = new CompileTimeConstant() { Value = state, Type = this.host.PlatformType.SystemInt32 }, Target = new TargetExpression() { Definition = this.iteratorClosure.StateFieldReference, Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32 }, Type = this.host.PlatformType.SystemInt32, }, Locations = IteratorHelper.EnumerableIsEmpty(yieldReturnStatement.Locations) ? null : new List<ILocation>(yieldReturnStatement.Locations) }; blockStatement.Statements.Add(thisDotStateEqState); ExpressionStatement thisDotCurrentEqReturnExp = new ExpressionStatement() { Expression = new Assignment() { Source = yieldReturnStatement.Expression, Target = new TargetExpression() { Definition = this.iteratorClosure.CurrentFieldReference, Instance = new ThisReference(), Type = this.iteratorClosure.CurrentFieldReference.Type }, Type = this.iteratorClosure.CurrentFieldReference.Type } }; blockStatement.Statements.Add(thisDotCurrentEqReturnExp); ReturnStatement returnTrue = new ReturnStatement() { Expression = new CompileTimeConstant() { Value = true, Type = this.host.PlatformType.SystemBoolean } }; blockStatement.Statements.Add(returnTrue); LabeledStatement labeledStatement = new LabeledStatement() { Label = this.host.NameTable.GetNameFor("Label"+state), Statement = new EmptyStatement() }; blockStatement.Statements.Add(labeledStatement); this.stateEntries.Add(state, labeledStatement); return blockStatement; }
/// <summary> /// Replace a yield break with: /// { /// this.state = -2; /// return; /// } /// </summary> /// <param name="yieldBreakStatement"></param> /// <returns></returns> public override IStatement Rewrite(IYieldBreakStatement yieldBreakStatement) { BlockStatement blockStatement = new BlockStatement(); ExpressionStatement thisDotStateEqMinus2 = new ExpressionStatement() { Expression = new Assignment() { Source = new CompileTimeConstant() { Value = -2, Type = this.host.PlatformType.SystemInt32 }, Target = new TargetExpression() { Definition = iteratorClosure.StateFieldReference, Type = this.host.PlatformType.SystemInt32, Instance = new ThisReference() }, Type = this.host.PlatformType.SystemInt32, } }; blockStatement.Statements.Add(thisDotStateEqMinus2); ReturnStatement returnFalse = new ReturnStatement() { Expression = new CompileTimeConstant() { Value = false, Type = this.host.PlatformType.SystemBoolean } }; blockStatement.Statements.Add(returnFalse); return blockStatement; }
/// <summary> /// Create two properties: object Current and T Current as the closure class implements both the /// generic and non-generic version of ienumerator. /// /// Current Implementation generates getters, but not the property. /// </summary> /// <param name="iteratorClosure">Information about the closure created when compiling the current iterator method</param> private void CreateIteratorClosureProperties(IteratorClosureInformation iteratorClosure) { // Non-generic version of the get_Current, which returns the generic version of get_Current. MethodDefinition getterNonGenericCurrent = new MethodDefinition() { Attributes = new List<ICustomAttribute>(1), InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("System.Collections.IEnumerator.get_Current") }; CustomAttribute debuggerHiddenAttribute = new CustomAttribute(); debuggerHiddenAttribute.Constructor = this.DebuggerHiddenCtor; getterNonGenericCurrent.Attributes.Add(debuggerHiddenAttribute); getterNonGenericCurrent.CallingConvention |= CallingConvention.HasThis; getterNonGenericCurrent.Visibility |= TypeMemberVisibility.Public; getterNonGenericCurrent.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; getterNonGenericCurrent.Type = this.host.PlatformType.SystemObject; getterNonGenericCurrent.IsSpecialName = true; getterNonGenericCurrent.IsVirtual = true; getterNonGenericCurrent.IsNewSlot = true; getterNonGenericCurrent.IsHiddenBySignature = true; getterNonGenericCurrent.IsSealed = true; iteratorClosure.NonGenericGetCurrent = getterNonGenericCurrent; IMethodReference originalMethod = Dummy.MethodReference; foreach (ITypeMemberReference tref in iteratorClosure.NonGenericIEnumeratorInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("get_Current"), false)) { originalMethod = tref as IMethodReference; if (originalMethod != null) break; } // assert originalMethod != Dummy MethodImplementation getterImplementation = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementingMethod = getterNonGenericCurrent, ImplementedMethod = originalMethod }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(getterImplementation); List<IStatement> statements = new List<IStatement>(); IFieldReference currentField = iteratorClosure.CurrentFieldReference; BoundExpression thisDotCurr = new BoundExpression() { Definition = currentField, Instance = new ThisReference(), Locations = iteratorClosure.ClosureDefinition.Locations, Type = currentField.Type }; IExpression returnExpression; if (!iteratorClosure.ElementType.IsValueType && TypeHelper.TypesAreAssignmentCompatible(iteratorClosure.ElementType.ResolvedType, this.host.PlatformType.SystemObject.ResolvedType)) { returnExpression = thisDotCurr; } else { Conversion convertion = new Conversion() { CheckNumericRange = false, Type = this.host.PlatformType.SystemObject, TypeAfterConversion = getterNonGenericCurrent.Type, ValueToConvert = thisDotCurr }; returnExpression = convertion; } ReturnStatement returnCurrent = new ReturnStatement() { Expression = returnExpression, Locations = iteratorClosure.ClosureDefinition.Locations }; statements.Add(returnCurrent); BlockStatement block = new BlockStatement() { Statements = statements }; SourceMethodBody body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.IsNormalized = true; body.LocalsAreZeroed = true; body.Block = block; body.MethodDefinition = getterNonGenericCurrent; getterNonGenericCurrent.Body = body; // Create generic version of get_Current, the body of which is simply returning this.current. MethodDefinition getterGenericCurrent = new MethodDefinition() { Attributes = new List<ICustomAttribute>(1), InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("System.Collections.Generic.IEnumerator<" + iteratorClosure.ElementType.ToString() +">.get_Current") }; getterGenericCurrent.Attributes.Add(debuggerHiddenAttribute); getterGenericCurrent.CallingConvention |= CallingConvention.HasThis; getterGenericCurrent.Visibility |= TypeMemberVisibility.Public; getterGenericCurrent.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; getterGenericCurrent.Type = iteratorClosure.ElementType; getterGenericCurrent.IsSpecialName = true; getterGenericCurrent.IsVirtual = true; getterGenericCurrent.IsNewSlot = true; getterGenericCurrent.IsHiddenBySignature = true; getterGenericCurrent.IsSealed = true; iteratorClosure.GenericGetCurrent = getterGenericCurrent; originalMethod = Dummy.MethodReference; foreach (ITypeMemberReference tref in iteratorClosure.GenericIEnumeratorInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("get_Current"), false)) { originalMethod = tref as IMethodReference; if (originalMethod != null) break; } MethodImplementation getterImplementation2 = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementingMethod = getterGenericCurrent, ImplementedMethod = originalMethod }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(getterImplementation2); statements = new List<IStatement>(); currentField = iteratorClosure.CurrentFieldReference; BoundExpression thisDotCurrent = new BoundExpression() { Definition = currentField, Instance = new ThisReference(), Locations = iteratorClosure.ClosureDefinition.Locations, Type = currentField.Type }; returnCurrent = new ReturnStatement() { Expression = thisDotCurrent, Locations = iteratorClosure.ClosureDefinition.Locations }; statements.Add(returnCurrent); block = new BlockStatement() { Statements = statements }; body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.LocalsAreZeroed = true; body.Block = block; body.MethodDefinition = getterGenericCurrent; getterGenericCurrent.Body = body; }
private IModule CreateNewDll(string assemblyName) { var host = new PeReader.DefaultHost(); var core = host.LoadAssembly(host.CoreAssemblySymbolicIdentity); var assembly = new Assembly(); assembly.Name = host.NameTable.GetNameFor(assemblyName); assembly.ModuleName = host.NameTable.GetNameFor(assemblyName + ".dll"); assembly.Kind = ModuleKind.DynamicallyLinkedLibrary; assembly.PlatformType = host.PlatformType; assembly.TargetRuntimeVersion = core.TargetRuntimeVersion; assembly.AssemblyReferences.Add(core); foreach (var referencePath in model.ReferencePaths) { assembly.AssemblyReferences.Add(host.LoadUnitFrom(referencePath) as IAssembly); } var root = new RootUnitNamespace(); root.Unit = assembly; assembly.UnitNamespaceRoot = root; var module = new NamespaceTypeDefinition(); module.Name = host.NameTable.GetNameFor("<Module>"); module.IsClass = true; module.InternFactory = host.InternFactory; module.ContainingUnitNamespace = root; assembly.AllTypes.Add(module); var rootTypeNamespace = new NestedUnitNamespace(); rootTypeNamespace.Name = host.NameTable.GetNameFor(assembly.Name.Value); root.Members.Add(rootTypeNamespace); foreach (var classConfiguration in model.Classes) { var newClass = new NamespaceTypeDefinition(); newClass.IsAbstract = classConfiguration.IsAbstract; newClass.IsClass = true; newClass.BaseClasses = new List<ITypeReference>{ host.PlatformType.SystemObject }; newClass.IsPublic = true; if (classConfiguration.IsStatic) { newClass.IsStatic = true; newClass.IsAbstract = true; newClass.IsSealed = true; } if (!String.IsNullOrEmpty(classConfiguration.Namespace)) { NestedUnitNamespace classContainer = rootTypeNamespace; var namespaceNames = classConfiguration.Namespace.Split('.'); foreach (var namespaceName in namespaceNames) { var existingMembers = classContainer.GetMembersNamed(host.NameTable.GetNameFor(namespaceName), false); var nestedNamespace = new NestedUnitNamespace(); foreach (var existing in existingMembers) { if (existing as NestedUnitNamespace != null) { nestedNamespace = existing as NestedUnitNamespace; break; } } nestedNamespace.Name = host.NameTable.GetNameFor(namespaceName); nestedNamespace.ContainingUnitNamespace = classContainer; classContainer.Members.Add(nestedNamespace); classContainer = nestedNamespace; } newClass.ContainingUnitNamespace = classContainer; } else { newClass.ContainingUnitNamespace = rootTypeNamespace; } newClass.InternFactory = host.InternFactory; newClass.Name = host.NameTable.GetNameFor(classConfiguration.Name); newClass.Methods = new List<IMethodDefinition>(classConfiguration.Methods.Count); newClass.Fields = new List<IFieldDefinition>(classConfiguration.Fields.Count); foreach (var methodConfiguration in classConfiguration.Methods) { var newMethod = new MethodDefinition(); newMethod.Name = host.NameTable.GetNameFor(methodConfiguration.Name); newMethod.IsStatic = methodConfiguration.IsStatic; newMethod.ContainingTypeDefinition = newClass; newMethod.IsCil = true; newMethod.IsHiddenBySignature = true; newMethod.InternFactory = host.InternFactory; newMethod.Visibility = TypeMemberVisibility.Public; newMethod.Type = host.PlatformType.SystemVoid; var newMethodParameters = new List<IParameterDefinition>(); foreach (var param in methodConfiguration.Parameters) { var newMethodParameter = new ParameterDefinition(); newMethodParameter.ContainingSignature = newMethod; newMethodParameter.Index = (ushort)methodConfiguration.Parameters.IndexOf(param); newMethodParameter.Name = host.NameTable.GetNameFor(param.Key); newMethodParameter.Type = new UnitReflector(host).Get(param.Value); newMethodParameters.Add(newMethodParameter); } newMethod.Parameters = newMethodParameters; var methodBody = new SourceMethodBody(host, null); methodBody.MethodDefinition = newMethod; methodBody.LocalsAreZeroed = true; var block = new BlockStatement(); var returnStatement = new ReturnStatement(); if (methodConfiguration.ReturnType != null) { newMethod.Type = new UnitReflector(host).Get(methodConfiguration.ReturnType); returnStatement.Expression = new CompileTimeConstant(); } if (methodConfiguration.MethodBody != null) { var codeBuilder = new CodeBuilder(host, newMethod.Parameters); methodConfiguration.MethodBody(codeBuilder); foreach (var statement in codeBuilder.Statements) { block.Statements.Add(statement); } } // "Stack must be empty on return from a void method" //returnStatement.Expression = new CompileTimeConstant(); //block.Statements.Add(returnStatement); methodBody.Block = block; newMethod.Body = methodBody; newClass.Methods.Add(newMethod); } foreach (var field in classConfiguration.Fields) { var fieldDefinition = new FieldDefinition(); fieldDefinition.ContainingTypeDefinition = newClass; fieldDefinition.InternFactory = host.InternFactory; fieldDefinition.IsReadOnly = field.IsReadonly; fieldDefinition.IsStatic = field.IsStatic; fieldDefinition.Name = host.NameTable.GetNameFor(field.Name); fieldDefinition.Type = new UnitReflector(host).Get(field.FieldType); fieldDefinition.Visibility = field.Accessibility.ToTypeMemberVisibility(); newClass.Fields.Add(fieldDefinition); } assembly.AllTypes.Add(newClass); } using (var dll = File.Create(assemblyName + ".dll")) { PeWriter.WritePeToStream(assembly, host, dll); dll.Close(); } return assembly; }
/// <summary> /// Visits the specified return statement. /// </summary> /// <param name="returnStatement">The return statement.</param> /// <returns></returns> public virtual IStatement Visit(ReturnStatement returnStatement) { if (returnStatement.Expression != null) returnStatement.Expression = Visit(returnStatement.Expression); return returnStatement; }
/// <summary> /// Visits the specified return statement. /// </summary> /// <param name="returnStatement">The return statement.</param> /// <returns></returns> protected virtual IStatement DeepCopy(ReturnStatement returnStatement) { if (returnStatement.Expression != null) returnStatement.Expression = this.Substitute(returnStatement.Expression); return returnStatement; }
/// <summary> /// Create the Reset method. Like in CSC, this method contains nothing. /// </summary> private void CreateResetMethod(IteratorClosureInformation iteratorClosure) { // System.Collections.IEnumerator.Reset: Simply throws an exception MethodDefinition reset = new MethodDefinition() { Attributes = new List<ICustomAttribute>(1), InternFactory = this.host.InternFactory, Name = this.host.NameTable.GetNameFor("Reset") }; CustomAttribute debuggerHiddenAttribute = new CustomAttribute() { Constructor = this.DebuggerHiddenCtor }; reset.Attributes.Add(debuggerHiddenAttribute); reset.CallingConvention |= CallingConvention.HasThis; reset.Visibility = TypeMemberVisibility.Private; reset.ContainingTypeDefinition = iteratorClosure.ClosureDefinition; reset.Type = this.host.PlatformType.SystemVoid; reset.IsVirtual = true; reset.IsNewSlot = true; reset.IsHiddenBySignature = true; reset.IsSealed = true; iteratorClosure.Reset = reset; // explicitly state that this reset method implements IEnumerator's reset method. IMethodReference resetImplemented = Dummy.MethodReference; foreach (var memref in iteratorClosure.NonGenericIEnumeratorInterface.ResolvedType.GetMembersNamed(this.host.NameTable.GetNameFor("Reset"), false)) { IMethodReference mref = memref as IMethodReference; if (mref != null) { resetImplemented = mref; break; } } MethodImplementation resetImp = new MethodImplementation() { ContainingType = iteratorClosure.ClosureDefinition, ImplementedMethod = resetImplemented, ImplementingMethod = reset }; iteratorClosure.ClosureDefinition.ExplicitImplementationOverrides.Add(resetImp); List<IStatement> statements = new List<IStatement>(); ReturnStatement returnCurrent = new ReturnStatement() { Expression = null, Locations = iteratorClosure.ClosureDefinition.Locations }; statements.Add(returnCurrent); BlockStatement block = new BlockStatement() { Statements = statements }; SourceMethodBody body = new SourceMethodBody(this.host, this.sourceLocationProvider); body.LocalsAreZeroed = true; body.IsNormalized = true; body.Block = block; body.MethodDefinition = reset; reset.Body = body; }
/// <summary> /// Visits the specified return statement. /// </summary> /// <param name="returnStatement">The return statement.</param> public override void Visit(IReturnStatement returnStatement) { ReturnStatement mutableReturnStatement = new ReturnStatement(returnStatement); this.resultStatement = this.myCodeCopier.DeepCopy(mutableReturnStatement); }
/// <summary> /// Create the body of the generic version of GetEnumerator for the iterator closure class. /// /// The body's pseudo code. /// { /// if (Thread.CurrentThread.ManagedThreadId == this.l_initialThreadId AND this.state == -2) { /// this.state = 0; /// return this; /// } /// else { /// return a new copy of the iterator instance with state being zero. /// } /// } /// </summary> private BlockStatement GetBodyOfGenericGetEnumerator(IteratorClosureInformation iteratorClosure) { var thisDotState = new BoundExpression() { Definition = iteratorClosure.StateFieldReference, Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32 }; var thisDotThreadId = new BoundExpression() { Definition = iteratorClosure.InitThreadIdFieldReference, Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32 }; var currentThreadId = new MethodCall() { MethodToCall = ThreadDotManagedThreadId.Getter, ThisArgument = ThreadDotCurrentThread, Type = this.host.PlatformType.SystemInt32 }; var stateEqMinus2 = new Equality() { LeftOperand = thisDotState, RightOperand = new CompileTimeConstant() { Type = this.host.PlatformType.SystemInt32, Value = -2 }, Type = this.host.PlatformType.SystemBoolean }; var threadIdEqCurrentThreadId = new Equality { LeftOperand = thisDotThreadId, RightOperand = currentThreadId, Type = this.host.PlatformType.SystemBoolean }; var thisDotStateEq0 = new ExpressionStatement() { Expression = new Assignment() { Source = new CompileTimeConstant() { Type = this.host.PlatformType.SystemInt32, Value = 0 }, Target = new TargetExpression() { Definition = iteratorClosure.StateFieldReference, Instance = new ThisReference(), Type = this.host.PlatformType.SystemInt32 }, Type = this.host.PlatformType.SystemInt32 }, }; var returnThis = new BlockStatement(); returnThis.Statements.Add(thisDotStateEq0); returnThis.Statements.Add(new ReturnStatement() { Expression = new ThisReference() }); var returnNew = new BlockStatement(); var args = new List<IExpression>(); args.Add(new CompileTimeConstant() { Value = 0, Type = this.host.PlatformType.SystemInt32 }); var closureInstanceLocalDecl = new LocalDeclarationStatement() { LocalVariable = new LocalDefinition() { Name = this.host.NameTable.GetNameFor("local0"), Type = iteratorClosure.ClosureDefinitionReference }, InitialValue = new CreateObjectInstance() { MethodToCall = iteratorClosure.ConstructorReference, Arguments = args, Type = iteratorClosure.ClosureDefinitionReference } }; var returnNewClosureInstance = new ReturnStatement() { Expression = new BoundExpression() { Instance = null, Type = iteratorClosure.ClosureDefinitionReference, Definition = closureInstanceLocalDecl.LocalVariable } }; returnNew.Statements.Add(closureInstanceLocalDecl); if (!method.IsStatic) { ExpressionStatement assignThisDotThisToNewClosureDotThis = new ExpressionStatement() { Expression = new Assignment() { Source = new BoundExpression() { Definition = iteratorClosure.ThisFieldReference, Instance = new ThisReference(), Type = iteratorClosure.ClosureDefinitionReference }, Type = iteratorClosure.ClosureDefinition, Target = new TargetExpression() { Instance = new BoundExpression() { Instance = null, Definition = closureInstanceLocalDecl.LocalVariable, Type = iteratorClosure.ClosureDefinitionReference }, Definition = iteratorClosure.ThisFieldReference, Type = iteratorClosure.ClosureDefinitionReference } } }; returnNew.Statements.Add(assignThisDotThisToNewClosureDotThis); } returnNew.Statements.Add(returnNewClosureInstance); ConditionalStatement returnThisOrNew = new ConditionalStatement() { Condition = new Conditional() { Condition = stateEqMinus2, ResultIfTrue = threadIdEqCurrentThreadId, ResultIfFalse = new CompileTimeConstant() { Type = this.host.PlatformType.SystemBoolean, Value = false }, Type = this.host.PlatformType.SystemBoolean }, TrueBranch = returnThis, FalseBranch = returnNew }; BlockStatement block = new BlockStatement(); block.Statements.Add(returnThisOrNew); return block; }
private Statement ParseReturn() { ReturnStatement result = new ReturnStatement(); if (this.MethodDefinition.Type.TypeCode != PrimitiveTypeCode.Void) result.Expression = this.PopOperandStack(); return result; }
/// <summary> /// Visits the specified return statement. /// </summary> /// <param name="returnStatement">The return statement.</param> public override void Visit(IReturnStatement returnStatement) { ReturnStatement mutableReturnStatement = returnStatement as ReturnStatement; if (alwaysMakeACopy || mutableReturnStatement == null) mutableReturnStatement = new ReturnStatement(returnStatement); this.resultStatement = this.myCodeMutator.Visit(mutableReturnStatement); }