void Map() { IType type = (IType)_sharedLocalsClass.Entity; InternalLocal locals = CodeBuilder.DeclareLocal(_currentMethod, "___locals", type); foreach (ReferenceExpression reference in _references) { IField mapped = (IField)_mappings[reference.Entity]; if (null != mapped) { reference.ParentNode.Replace( reference, CodeBuilder.CreateMemberReference( CodeBuilder.CreateReference(locals), mapped)); } } Block initializationBlock = new Block(); initializationBlock.Add(CodeBuilder.CreateAssignment( CodeBuilder.CreateReference(locals), CodeBuilder.CreateConstructorInvocation(type.GetConstructors()[0]))); InitializeSharedParameters(initializationBlock, locals); _currentMethod.Body.Statements.Insert(0, initializationBlock); foreach (IEntity entity in _mappings.Keys) { _currentMethod.Locals.RemoveByEntity(entity); } }
public InternalLabel ProxyReturnIfNeeded( Method containingMethod, Node valueOpt, out InternalLocal retVal) { retVal = null; // no need to proxy returns at the root if (IsRoot()) { return(null); } var returnProxy = returnProxyLabel; if (returnProxy == null) { returnProxyLabel = returnProxy = _builder.CreateLabel(valueOpt ?? containingMethod, "returnProxy", _tryDepth); } if (valueOpt != null) { retVal = returnValue; if (retVal == null) { Debug.Assert(_tryStatementOpt != null); returnValue = retVal = _builder.DeclareTempLocal( containingMethod, ((ITypedEntity)valueOpt.Entity).Type); } } return(returnProxy); }
private Block PendBranches( AwaitFinallyFrame frame, InternalLocal pendingBranchVar, InternalLabel finallyLabel) { var bodyStatements = new Block(); // handle proxy labels if have any var proxiedLabels = frame.proxiedLabels; var proxyLabels = frame.proxyLabels; // skip 0 - it means we took no explicit branches int i = 1; if (proxiedLabels != null) { for (int cnt = proxiedLabels.Count; i <= cnt; i++) { var proxied = proxiedLabels[i - 1]; var proxy = proxyLabels[proxied]; PendBranch(bodyStatements, proxy, i, pendingBranchVar, finallyLabel); } } var returnProxy = frame.returnProxyLabel; if (returnProxy != null) { PendBranch(bodyStatements, returnProxy, i, pendingBranchVar, finallyLabel); } return(bodyStatements); }
private void AddToMoveNextMethod(Local local) { var newLocal = new InternalLocal(local, _methodToStateMachineMapper.MapType(((InternalLocal)local.Entity).Type)); _entityMapper.Add(local.Entity, newLocal); local.Entity = newLocal; _moveNext.Method.Locals.Add(local); }
public AwaitCatchFrame(TypeSystemServices tss, BooCodeBuilder builder, Method currentMethod) { pendingCaughtException = builder.DeclareTempLocal(currentMethod, tss.ObjectType); pendingCatch = builder.DeclareTempLocal(currentMethod, tss.IntType); handlers = new List <Block>(); _hoistedLocals = new Dictionary <InternalLocal, InternalLocal>(); _orderedHoistedLocals = new List <InternalLocal>(); _currentMethod = currentMethod; }
private bool IsExceptionHandlerVariable(InternalLocal local) { Declaration originalDeclaration = local.OriginalDeclaration; if (originalDeclaration == null) { return(false); } return(originalDeclaration.ParentNode is ExceptionHandler); }
private Block GenerateAwaitForIncompleteTask(InternalLocal awaiterTemp) { var stateNumber = _labels.Count; var resumeLabel = CreateLabel(awaiterTemp.Node); IType awaiterFieldType = awaiterTemp.Type.IsVerifierReference() ? TypeSystemServices.ObjectType : awaiterTemp.Type; Field awaiterField = GetAwaiterField(awaiterFieldType); var blockBuilder = new Block(); // this.state = _cachedState = stateForLabel blockBuilder.Add(new ExpressionStatement(SetStateTo(stateNumber))); blockBuilder.Add( // this.<>t__awaiter = $awaiterTemp CodeBuilder.CreateFieldAssignment( awaiterField, awaiterField.Type == awaiterTemp.Type ? CodeBuilder.CreateLocalReference(awaiterTemp) : CodeBuilder.CreateCast(awaiterFieldType, CodeBuilder.CreateLocalReference(awaiterTemp)))); blockBuilder.Add(GenerateAwaitOnCompleted(awaiterTemp.Type, awaiterTemp)); blockBuilder.Add(GenerateReturn()); blockBuilder.Add(resumeLabel); AstAnnotations.SetTryBlockDepth(resumeLabel, blockBuilder.GetAncestors <TryStatement>().Count()); var awaiterFieldRef = CodeBuilder.CreateMemberReference( CodeBuilder.CreateSelfReference(_stateMachineClass.Entity), (IField)awaiterField.Entity); blockBuilder.Add( // $awaiterTemp = this.<>t__awaiter or $awaiterTemp = (AwaiterType)this.<>t__awaiter // $this.<>t__awaiter = null; CodeBuilder.CreateAssignment( CodeBuilder.CreateLocalReference(awaiterTemp), awaiterTemp.Type == awaiterField.Type ? awaiterFieldRef : CodeBuilder.CreateCast(awaiterTemp.Type, awaiterFieldRef))); blockBuilder.Add( CodeBuilder.CreateFieldAssignment( awaiterField, CodeBuilder.CreateDefaultInvocation(LexicalInfo.Empty, ((ITypedEntity)awaiterField.Entity).Type))); // this.state = _cachedState = NotStartedStateMachine blockBuilder.Add(new ExpressionStatement(SetStateTo(StateMachineStates.NotStartedStateMachine))); return(blockBuilder); }
void CheckUnusedLocals(Method node) { foreach (Local local in node.Locals) { InternalLocal entity = (InternalLocal)local.Entity; if (!entity.IsPrivateScope && !entity.IsUsed) { Warnings.Add(CompilerWarningFactory.UnusedLocalVariable(local, local.Name)); } } }
public Block PrepareEvaluationContextInitialization(IType evaluationContextType) { this._evaluationContextLocal = this.CodeBuilder.DeclareTempLocal(this.CurrentMethodNode, evaluationContextType); Block block = new Block(); block.Add(this.CodeBuilder.CreateAssignment(this.CreateEvaluationContextReference(), this.CodeBuilder.CreateConstructorInvocation(UtilitiesModule.ConstructorTakingNArgumentsFor(evaluationContextType, 1), this.EvaluationDomainProviderReference()))); foreach (ParameterDeclaration declaration in this.CurrentMethodNode.Parameters) { block.Add(this.CodeBuilder.CreateAssignment(this.CreateEvaluationContextFieldReference(this.GetEvaluationContextField(declaration)), this.CodeBuilder.CreateReference(declaration))); } return(block); }
public void AddLocal(InternalLocal local) { if (_locals == null) { _locals = new List <InternalLocal>(); } if (local.Type.IsRestrictedType()) { CompilerContext.Current.Errors.Add( CompilerErrorFactory.RestrictedAwaitType(local.Local, local.Type)); } _locals.Add(local); }
void ProcessAssignmentToSpecialMember(BinaryExpression node) { MemberReferenceExpression memberRef = (MemberReferenceExpression)node.Left; List chain = WalkMemberChain(memberRef); if (null == chain || 0 == chain.Count) { return; } MethodInvocationExpression eval = CodeBuilder.CreateEvalInvocation(node.LexicalInfo); // right hand side should always be executed before // left hand side InternalLocal value = DeclareTempLocal(GetExpressionType(node.Right)); eval.Arguments.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateReference(value), node.Right)); foreach (ChainItem item in chain) { item.Local = DeclareTempLocal(item.Container.ExpressionType); BinaryExpression tempInitialization = CodeBuilder.CreateAssignment( node.LexicalInfo, CodeBuilder.CreateReference(item.Local), item.Container.CloneNode()); item.Container.ParentNode.Replace(item.Container, CodeBuilder.CreateReference(item.Local)); eval.Arguments.Add(tempInitialization); } eval.Arguments.Add( CodeBuilder.CreateAssignment(node.LexicalInfo, node.Left, CodeBuilder.CreateReference(value))); PropagateChanges(eval, chain); if (NodeType.ExpressionStatement != node.ParentNode.NodeType) { eval.Arguments.Add(CodeBuilder.CreateReference(value)); BindExpressionType(eval, value.Type); } ReplaceCurrentNode(eval); }
void InitializeSharedParameters(Block block, InternalLocal locals) { foreach (Node node in _currentMethod.Parameters) { InternalParameter param = (InternalParameter)node.Entity; if (param.IsShared) { block.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateMemberReference( CodeBuilder.CreateReference(locals), (IField)_mappings[param]), CodeBuilder.CreateReference(param))); } } }
void CheckUnusedLocals(Method node) { foreach (Local local in node.Locals) { // _ is a commonly accepted dummy variable for unused items if (local.Name == "_") { continue; } InternalLocal entity = (InternalLocal)local.Entity; if (!entity.IsPrivateScope && !entity.IsUsed) { Warnings.Add(CompilerWarningFactory.UnusedLocalVariable(local, local.Name)); } } }
void CreateMoveNext() { Method generator = _generator.Method; BooMethodBuilder mn = _enumerator.AddVirtualMethod("MoveNext", TypeSystemServices.BoolType); mn.Method.LexicalInfo = this.LexicalInfo; _moveNext = mn.Entity; foreach (Local local in generator.Locals) { InternalLocal entity = (InternalLocal)local.Entity; Field field = _enumerator.AddField("___" + entity.Name + _context.AllocIndex(), entity.Type); field.Modifiers |= TypeMemberModifiers.Internal; _mapping[entity] = field.Entity; } generator.Locals.Clear(); foreach (ParameterDeclaration parameter in generator.Parameters) { InternalParameter entity = (InternalParameter)parameter.Entity; if (entity.IsUsed) { Field field = DeclareFieldInitializedFromConstructorParameter(_enumerator, _enumeratorConstructor, entity.Name, entity.Type); _mapping[entity] = field.Entity; } } mn.Body.Add(CreateLabel(generator)); mn.Body.Add(generator.Body); generator.Body.Clear(); Visit(mn.Body); mn.Body.Add(CreateYieldInvocation(null)); mn.Body.Add(CreateLabel(generator)); mn.Body.Insert(0, CodeBuilder.CreateSwitch( this.LexicalInfo, CodeBuilder.CreateMemberReference(_state), _labels)); }
private void PendBranch( Block bodyStatements, InternalLabel proxy, int i, InternalLocal pendingBranchVar, InternalLabel finallyLabel) { // branch lands here bodyStatements.Add(proxy.LabelStatement); // pend the branch bodyStatements.Add(_F.CreateAssignment( _F.CreateLocalReference(pendingBranchVar), _F.CreateIntegerLiteral(i))); // skip other proxies bodyStatements.Add(_F.CreateGoto(finallyLabel, _tryDepth)); }
public override void OnDeclaration(Declaration node) { if (node.Entity == null) { return; } var catchFrame = _currentAwaitCatchFrame; InternalLocal hoistedLocal = null; if (catchFrame == null || !catchFrame.TryGetHoistedLocal((InternalLocal)node.Entity, out hoistedLocal)) { base.OnDeclaration(node); } ReplaceCurrentNode(new Declaration(node.Name, _F.CreateTypeReference(hoistedLocal.Type)) { Entity = hoistedLocal }); }
public static void UnpackEnumerable(BooCodeBuilder codeBuilder, Method method, Block block, Expression expression, DeclarationCollection declarations) { TypeSystemServices tss = codeBuilder.TypeSystemServices; InternalLocal local = codeBuilder.DeclareTempLocal(method, tss.IEnumeratorType); IType expressionType = expression.ExpressionType; if (expressionType.IsSubclassOf(codeBuilder.TypeSystemServices.IEnumeratorType)) { block.Add( codeBuilder.CreateAssignment( codeBuilder.CreateReference(local), expression)); } else { if (!expressionType.IsSubclassOf(codeBuilder.TypeSystemServices.IEnumerableType)) { expression = codeBuilder.CreateMethodInvocation( RuntimeServices_GetEnumerable, expression); } block.Add( codeBuilder.CreateAssignment( block.LexicalInfo, codeBuilder.CreateReference(local), codeBuilder.CreateMethodInvocation( expression, IEnumerable_GetEnumerator))); } for (int i = 0; i < declarations.Count; ++i) { Declaration declaration = declarations[i]; block.Add( codeBuilder.CreateAssignment( codeBuilder.CreateReference(declaration.Entity), codeBuilder.CreateMethodInvocation(RuntimeServices_MoveNext, codeBuilder.CreateReference(local)))); } }
public void HoistLocal(InternalLocal local, BooCodeBuilder F) { if (!_hoistedLocals.Keys.Any(l => l.Name == local.Name && l.Type == local.Type)) { _hoistedLocals.Add(local, local); _orderedHoistedLocals.Add(local); return; } // code uses "await" in two sibling catches with exception filters // locals with same names and types may cause problems if they are lifted // and become fields with identical signatures. // To avoid such problems we will mangle the name of the second local. // This will only affect debugging of this extremely rare case. var newLocal = F.DeclareTempLocal(_currentMethod, local.Type); _hoistedLocals.Add(local, newLocal); _orderedHoistedLocals.Add(newLocal); }
public override void OnBlock(Block node) { try { if (node.Statements.Count == 0 || node.Statements[0].NodeType != NodeType.Block) { return; } var innerBlock = (Block)node.Statements[0]; ExpressionStatement firstStatement; if (!IsSwitchStatementWithOnlyDefault(innerBlock, out firstStatement)) { return; } var binaryExp = (BinaryExpression)firstStatement.Expression; if (binaryExp.Operator != BinaryOperatorType.Assign || binaryExp.Left.NodeType != NodeType.ReferenceExpression || !binaryExp.Left.ToCodeString().Contains("$switch$")) { return; } var originalLocal = ((InternalLocal)binaryExp.Left.Entity).Local; var varName = originalLocal.Name.Replace("$", "_"); var local = new Local(varName, true); var internalLocal = new InternalLocal(local, binaryExp.ExpressionType); local.Entity = internalLocal; internalLocal.OriginalDeclaration = new Declaration(varName, CodeBuilder.CreateTypeReference(internalLocal.Type)); // we need a DeclarationStatment as the parent of the "OriginalDeclaration" var ds = new DeclarationStatement(internalLocal.OriginalDeclaration, binaryExp.Right); innerBlock.Statements.RemoveAt(0); var parentMethod = node.GetAncestor <Method>(); parentMethod.Locals.Replace(originalLocal, internalLocal.Local); } finally { base.OnBlock(node); } }
public void AddLocalVariablesAsFields(BooClassBuilder builder) { Field field; foreach (Local local in this.CurrentMethodNode.Locals) { InternalLocal entity = (InternalLocal)this.GetEntity(local); if (!entity.IsPrivateScope) { field = builder.AddPublicField(entity.Name, entity.Type); this.SetEvaluationContextField(local, (InternalField)this.GetEntity(field)); } } foreach (ParameterDeclaration declaration in this.CurrentMethodNode.Parameters) { InternalParameter parameter = (InternalParameter)this.GetEntity(declaration); field = builder.AddPublicField(parameter.Name, parameter.Type); this.SetEvaluationContextField(declaration, (InternalField)this.GetEntity(field)); } }
public override void OnReturnStatement(ReturnStatement node) { Statement result = CodeBuilder.CreateGoto(_exprReturnLabel, _tryStatementStack.Count + 1); if (node.Expression != null) { Debug.Assert(_isGenericTask || node.Expression.ExpressionType == TypeSystemServices.TaskType); if (_exprRetValue == null) { _exprRetValue = CodeBuilder.DeclareTempLocal(_moveNext.Method, TypeSystemServices.TaskType); } result = new Block( new ExpressionStatement( CodeBuilder.CreateAssignment( CodeBuilder.CreateLocalReference(_exprRetValue), Visit(node.Expression))), result); } ReplaceCurrentNode(result); }
public override void OnWhileStatement(WhileStatement node) { if (node.OrBlock == null) { return; } InternalLocal enteredLoop = CodeBuilder().DeclareTempLocal(_currentMethod, BoolType()); IfStatement orPart = new IfStatement( node.OrBlock.LexicalInfo, CodeBuilder().CreateNotExpression(CodeBuilder().CreateReference(enteredLoop)), node.OrBlock, null); node.OrBlock = orPart.ToBlock(); node.Block.Insert(0, CodeBuilder().CreateAssignment( CreateReference(enteredLoop), CreateTrueLiteral())); }
public void TransformIteration(ForStatement node) { string[] components = new string[] { "iterator" }; InternalLocal local = this.CodeBuilder.DeclareLocal(this.CurrentMethod, base._context.GetUniqueName(components), this.TypeSystemServices.IEnumeratorType); local.IsUsed = true; Block newNode = new Block(node.LexicalInfo); newNode.Add(this.CodeBuilder.CreateAssignment(node.LexicalInfo, this.CodeBuilder.CreateReference(local), node.Iterator)); WhileStatement stmt = new WhileStatement(node.LexicalInfo) { Condition = this.CodeBuilder.CreateMethodInvocation(this.CodeBuilder.CreateReference(local), this.IEnumerator_MoveNext) }; MethodInvocationExpression rhs = this.CodeBuilder.CreateMethodInvocation(this.CodeBuilder.CreateReference(local), this.IEnumerator_get_Current); InternalLocal entity = (InternalLocal)TypeSystemServices.GetEntity(node.Declarations[0]); stmt.Block.Add(this.CodeBuilder.CreateAssignment(node.LexicalInfo, this.CodeBuilder.CreateReference(entity), rhs)); stmt.Block.Add(node.Block); new LoopVariableUpdater(this, base._context, local, entity).Visit(node); newNode.Add(stmt); node.ParentNode.Replace(node, newNode); }
private Statement GenerateAwaitOnCompleted(IType loweredAwaiterType, InternalLocal awaiterTemp) { // this.builder.AwaitOnCompleted<TAwaiter,TSM>(ref $awaiterTemp, ref this) // or // this.builder.AwaitOnCompleted<TAwaiter,TSM>(ref $awaiterArrayTemp[0], ref this) var localEntity = MapNestedType(_stateMachineClass.Entity); InternalLocal selfTemp = _stateMachineClass.Entity.IsValueType ? null : CodeBuilder.DeclareTempLocal(_moveNext.Method, _stateMachineClass.Entity); var useUnsafeOnCompleted = loweredAwaiterType.IsAssignableFrom(ICriticalNotifyCompletionType); var onCompleted = (useUnsafeOnCompleted ? _asyncMethodBuilderMemberCollection.AwaitUnsafeOnCompleted : _asyncMethodBuilderMemberCollection.AwaitOnCompleted) .GenericInfo.ConstructMethod(loweredAwaiterType, localEntity); var result = CodeBuilder.CreateMethodInvocation( CodeBuilder.CreateMemberReference( CodeBuilder.CreateSelfReference(localEntity), (IField)_asyncMethodBuilderField.Entity), onCompleted, CodeBuilder.CreateLocalReference(awaiterTemp), selfTemp != null ? CodeBuilder.CreateLocalReference(selfTemp) : (Expression)CodeBuilder.CreateSelfReference(localEntity)); if (selfTemp != null) { result = CodeBuilder.CreateEvalInvocation( LexicalInfo.Empty, CodeBuilder.CreateAssignment( CodeBuilder.CreateLocalReference(selfTemp), CodeBuilder.CreateSelfReference(localEntity)), result); } return(new ExpressionStatement(result)); }
private Statement UnpendException(InternalLocal pendingExceptionLocal) { // create a temp. // pendingExceptionLocal will certainly be captured, no need to access it over and over. InternalLocal obj = _F.DeclareTempLocal(_containingMethod, _tss.ObjectType); var objInit = _F.CreateAssignment(_F.CreateLocalReference(obj), _F.CreateLocalReference(pendingExceptionLocal)); // throw pendingExceptionLocal; Statement rethrow = Rethrow(obj); return(new Block( new ExpressionStatement(objInit), new IfStatement( pendingExceptionLocal.Local.LexicalInfo, _F.CreateBoundBinaryExpression( _tss.BoolType, BinaryOperatorType.ReferenceInequality, _F.CreateLocalReference(obj), new NullLiteralExpression()), new Block(rethrow), null))); }
private Statement Rethrow(InternalLocal obj) { // conservative rethrow Statement rethrow = new RaiseStatement(_F.CreateLocalReference(obj)); // if these helpers are available, we can rethrow with original stack info // as long as it derives from Exception if (_exceptionDispatchInfoCapture != null && _exceptionDispatchInfoThrow != null) { var ex = _F.DeclareTempLocal(_containingMethod, _tss.ExceptionType); var assignment = _F.CreateAssignment( _F.CreateLocalReference(ex), _F.CreateAsCast(ex.Type, _F.CreateLocalReference(obj))); // better rethrow rethrow = new Block( new ExpressionStatement(assignment), new IfStatement( _F.CreateBoundBinaryExpression( _tss.BoolType, BinaryOperatorType.ReferenceEquality, _F.CreateLocalReference(ex), new NullLiteralExpression()), new Block(rethrow), null), // ExceptionDispatchInfo.Capture(pendingExceptionLocal).Throw() new ExpressionStatement( _F.CreateMethodInvocation( _F.CreateMethodInvocation( _exceptionDispatchInfoCapture, _F.CreateLocalReference(ex)), _exceptionDispatchInfoThrow)) ); } return(rethrow); }
private Expression CreateSideEffectAwareSlicingOperation(LexicalInfo lexicalInfo, BinaryOperatorType binaryOperator, SlicingExpression lvalue, Expression rvalue, InternalLocal returnValue) { MethodInvocationExpression eval = CodeBuilder.CreateEvalInvocation(lexicalInfo); if (HasSideEffect(lvalue.Target)) { InternalLocal temp = AddInitializedTempLocal(eval, lvalue.Target); lvalue.Target = CodeBuilder.CreateReference(temp); } foreach (Slice slice in lvalue.Indices) { Expression index = slice.Begin; if (HasSideEffect(index)) { InternalLocal temp = AddInitializedTempLocal(eval, index); slice.Begin = CodeBuilder.CreateReference(temp); } } BinaryExpression addition = CodeBuilder.CreateBoundBinaryExpression( GetExpressionType(lvalue), binaryOperator, CloneOrAssignToTemp(returnValue, lvalue), rvalue); Expression expansion = CodeBuilder.CreateAssignment( lvalue.CloneNode(), addition); // Resolve operator overloads if any BindArithmeticOperator(addition); if (eval.Arguments.Count > 0 || null != returnValue) { eval.Arguments.Add(expansion); if (null != returnValue) { eval.Arguments.Add(CodeBuilder.CreateReference(returnValue)); } BindExpressionType(eval, GetExpressionType(lvalue)); expansion = eval; } return expansion; }
override public void LeaveForStatement(ForStatement node) { _iteratorNode = node.Iterator; CurrentEnumeratorType = GetExpressionType(node.Iterator); if (null == CurrentBestEnumeratorType) { return; //error } DeclarationCollection declarations = node.Declarations; Block body = new Block(node.LexicalInfo); InternalLocal iterator = CodeBuilder.DeclareLocal(_current, Context.GetUniqueName("iterator"), CurrentBestEnumeratorType); if (CurrentBestEnumeratorType == CurrentEnumeratorType) { //$iterator = <node.Iterator> body.Add( CodeBuilder.CreateAssignment( node.LexicalInfo, CodeBuilder.CreateReference(iterator), node.Iterator)); } else { //$iterator = <node.Iterator>.GetEnumerator() body.Add( CodeBuilder.CreateAssignment( node.LexicalInfo, CodeBuilder.CreateReference(iterator), CodeBuilder.CreateMethodInvocation(node.Iterator, CurrentBestGetEnumerator))); } // while __iterator.MoveNext(): if (null == CurrentBestMoveNext) { return; //error } WhileStatement ws = new WhileStatement(node.LexicalInfo); ws.Condition = CodeBuilder.CreateMethodInvocation( CodeBuilder.CreateReference(iterator), CurrentBestMoveNext); if (null == CurrentBestGetCurrent) { return; //error } Expression current = CodeBuilder.CreateMethodInvocation( CodeBuilder.CreateReference(iterator), CurrentBestGetCurrent); if (1 == declarations.Count) { // item = __iterator.Current ws.Block.Add( CodeBuilder.CreateAssignment( node.LexicalInfo, CodeBuilder.CreateReference((InternalLocal)declarations[0].Entity), current)); } else { UnpackExpression(ws.Block, CodeBuilder.CreateCast( CurrentEnumeratorItemType, current), node.Declarations); } ws.Block.Add(node.Block); ws.OrBlock = node.OrBlock; ws.ThenBlock = node.ThenBlock; // try: // while... // ensure: // d = iterator as IDisposable // d.Dispose() unless d is null if (IsAssignableFrom(TypeSystemServices.IDisposableType, CurrentBestEnumeratorType)) { TryStatement tryStatement = new TryStatement(); tryStatement.ProtectedBlock.Add(ws); tryStatement.EnsureBlock = new Block(); CastExpression castExpression = new CastExpression(); castExpression.Type = CodeBuilder.CreateTypeReference(TypeSystemServices.IDisposableType); castExpression.Target = CodeBuilder.CreateReference(iterator); castExpression.ExpressionType = TypeSystemServices.IDisposableType; tryStatement.EnsureBlock.Add( CodeBuilder.CreateMethodInvocation(castExpression, IDisposable_Dispose)); body.Add(tryStatement); } else { body.Add(ws); } ReplaceCurrentNode(body); }
private ReferenceExpression CreateReference(InternalLocal enteredLoop) { return(CodeBuilder().CreateReference(enteredLoop)); }
void SetLocal(BinaryExpression node, InternalLocal tag, bool leaveValueOnStack) { if (AstUtil.IsIndirection(node.Left)) _il.Emit(OpCodes.Ldloc, tag.LocalBuilder); node.Right.Accept(this); // leaves type on stack IType typeOnStack = null; if (leaveValueOnStack) { typeOnStack = PeekTypeOnStack(); _il.Emit(OpCodes.Dup); } else { typeOnStack = PopType(); } if (!AstUtil.IsIndirection(node.Left)) EmitAssignment(tag, typeOnStack); else EmitIndirectAssignment(tag, typeOnStack); }
void LoadLocal(InternalLocal local, bool byAddress) { _il.Emit(IsByAddress(local.Type) ? OpCodes.Ldloca : OpCodes.Ldloc, local.LocalBuilder); PushType(local.Type); _currentLocal = local.LocalBuilder; }
void LoadLocal(InternalLocal local) { LoadLocal(local, false); }
public ReferenceExpression CreateReference(InternalLocal local) { return CreateLocalReference(local.Name, local); }
public Expression CreateInitValueType(LexicalInfo li, InternalLocal local) { return CreateInitValueType(li, CreateReference(local)); }
protected virtual IEntity DeclareLocal(Node sourceNode, string name, IType localType, bool privateScope) { ClearResolutionCacheFor(name); var local = new Local(name, privateScope); local.LexicalInfo = sourceNode.LexicalInfo; var entity = new InternalLocal(local, localType); local.Entity = entity; CurrentMethod.Locals.Add(local); return entity; }
private void AddInternalFieldFor(InternalLocal entity) { Field field = _enumerator.AddInternalField(UniqueName(entity.Name), entity.Type); _mapping[entity] = field.Entity; }
void EmitIndirectAssignment(InternalLocal local, IType typeOnStack) { var elementType = local.Type.ElementType; EmitCastIfNeeded(elementType, typeOnStack); var code = GetStoreRefParamCode(elementType); if (code == OpCodes.Stobj) _il.Emit(code, GetSystemType(elementType)); else _il.Emit(code); }
public Block PrepareEvaluationContextInitialization(IType evaluationContextType) { this._evaluationContextLocal = this.get_CodeBuilder().DeclareTempLocal(this.CurrentMethodNode, evaluationContextType); Block block = new Block(); block.Add(this.get_CodeBuilder().CreateAssignment(this.CreateEvaluationContextReference(), this.get_CodeBuilder().CreateConstructorInvocation(UtilitiesModule.ConstructorTakingNArgumentsFor(evaluationContextType, 1), this.EvaluationDomainProviderReference()))); foreach (ParameterDeclaration declaration in this.CurrentMethodNode.get_Parameters()) { block.Add(this.get_CodeBuilder().CreateAssignment(this.CreateEvaluationContextFieldReference(this.GetEvaluationContextField(declaration)), this.get_CodeBuilder().CreateReference(declaration))); } return block; }
void ImplementByRefICallableCall( Method call, InternalCallableType type, ClassDefinition node, CallableSignature signature, int byRefCount) { MethodInvocationExpression mie = CreateInvokeInvocation(type); IParameter[] parameters = signature.Parameters; ReferenceExpression args = CodeBuilder.CreateReference(call.Parameters[0]); InternalLocal[] temporaries = new InternalLocal[byRefCount]; int byRefIndex = 0; for (int i=0; i<parameters.Length; ++i) { SlicingExpression slice = CodeBuilder.CreateSlicing(args.CloneNode(), i); IParameter parameter = parameters[i]; if (parameter.IsByRef) { IType tempType = parameter.Type; if (tempType.IsByRef) { tempType = tempType.ElementType; } temporaries[byRefIndex] = CodeBuilder.DeclareLocal(call, "__temp_" + parameter.Name, tempType); call.Body.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateReference(temporaries[byRefIndex]), CodeBuilder.CreateCast( tempType, slice))); mie.Arguments.Add( CodeBuilder.CreateReference( temporaries[byRefIndex])); ++byRefIndex; } else { mie.Arguments.Add(slice); } } if (TypeSystemServices.VoidType == signature.ReturnType) { call.Body.Add(mie); PropagateByRefParameterChanges(call, parameters, temporaries); } else { InternalLocal invokeReturnValue = CodeBuilder.DeclareLocal(call, "__returnValue", signature.ReturnType); call.Body.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateReference(invokeReturnValue), mie)); PropagateByRefParameterChanges(call, parameters, temporaries); call.Body.Add( new ReturnStatement( CodeBuilder.CreateReference(invokeReturnValue))); } }
private bool IsExceptionHandlerVariable(InternalLocal local) { Declaration originalDeclaration = local.OriginalDeclaration; if (originalDeclaration == null) return false; return originalDeclaration.ParentNode is ExceptionHandler; }
Expression CloneOrAssignToTemp(InternalLocal temp, Expression operand) { return null == temp ? operand.CloneNode() : CodeBuilder.CreateAssignment( CodeBuilder.CreateReference(temp), operand.CloneNode()); }
private ReferenceExpression CreateReference(InternalLocal enteredLoop) { return CodeBuilder().CreateReference(enteredLoop); }
public Expression CreateDefaultInitializer(LexicalInfo li, InternalLocal local) { return CreateDefaultInitializer(li, CreateReference(local), local.Type); }
void EmitAssignment(InternalLocal tag, IType typeOnStack) { // todo: assignment result must be type on the left in the // case of casting LocalBuilder local = tag.LocalBuilder; EmitCastIfNeeded(tag.Type, typeOnStack); _il.Emit(OpCodes.Stloc, local); }
public ReferenceExpression CreateLocalReference(string name, InternalLocal entity) { return CreateTypedReference(name, entity); }
void EmitIndirectAssignment(InternalLocal tag, IType typeOnStack) { IType et = tag.Type.ElementType; EmitCastIfNeeded(et, typeOnStack); OpCode code = GetStoreRefParamCode(et); if (code == OpCodes.Stobj) _il.Emit(code, GetSystemType(et)); else _il.Emit(code); }
public InternalLocal DeclareLocal(Method node, string name, IType type) { Local local = new Local(node.LexicalInfo, name); InternalLocal entity = new InternalLocal(local, type); local.Entity = entity; node.Locals.Add(local); return entity; }
void LoadIndirectLocal(InternalLocal local) { LoadLocal(local); IType et = local.Type.ElementType; PopType(); PushType(et); OpCode code = GetLoadRefParamCode(et); if (code == OpCodes.Ldobj) _il.Emit(code, GetSystemType(et)); else _il.Emit(code); }
private void AddInternalFieldFor(InternalLocal entity) { Field field = _stateMachineClass.AddInternalField(UniqueName(entity.Name), _methodToStateMachineMapper.MapType(entity.Type)); _mapping[entity] = (InternalField)field.Entity; }
void PropagateByRefParameterChanges(Method call, IParameter[] parameters, InternalLocal[] temporaries) { int byRefIndex = 0; for (int i=0; i<parameters.Length; ++i) { if (!parameters[i].IsByRef) continue; SlicingExpression slice = CodeBuilder.CreateSlicing( CodeBuilder.CreateReference(call.Parameters[0]), i); call.Body.Add( CodeBuilder.CreateAssignment( slice, CodeBuilder.CreateReference(temporaries[byRefIndex]))); ++byRefIndex; } }