private void EmitReturnStatement(ILProcessor ilProcessor, BoundReturnStatement node) { if (node.Expression != null) { EmitExpression(ilProcessor, node.Expression); } ilProcessor.Emit(OpCodes.Ret); }
private object EvaluateReturnStatement(BoundReturnStatement returnStatement) { if (returnStatement.ReturnExpression == null) { return(null); } return(EvaluateExpression(returnStatement.ReturnExpression)); }
private void OutputReturn(BoundReturnStatement node, string prefix) { builder.AddFragment(new OutputFragment(prefix, DefaultColour)); builder.AddFragment(new OutputFragment("return ", StatementColour)); if (node.ReturnExpression != null) { Output(node.ReturnExpression, string.Empty); } }
internal void Parse(BoundReturnStatement boundReturnStatement) { if (boundReturnStatement == null) { throw new ArgumentNullException(); } if (boundReturnStatement.ExpressionOpt != null) { this.ExpressionOpt = Deserialize(boundReturnStatement.ExpressionOpt) as Expression; } }
private BoundStatement RewriteReturnStatement(BoundReturnStatement statement) { if (statement.ReturnExpression == null) { return(statement); } var exprRewrite = RewriteExpression(statement.ReturnExpression); if (exprRewrite == statement.ReturnExpression) { return(statement); } return(new BoundReturnStatement(exprRewrite, statement.EndLabel)); }
public override T VisitReturn(BoundReturnStatement x) { if (_routine.Syntax is MethodDecl m) { if (m.Name.Name.IsToStringName) { // __tostring() allows only strings to be returned if (x.Returned == null || !IsAllowedToStringReturnType(x.Returned.TypeRefMask)) { var span = (x.PhpSyntax != null ? x.PhpSyntax.Span : m.HeadingSpan).ToTextSpan(); // span of return expression OR span of routine header _diagnostics.Add(_routine, span, ErrorCode.WRN_ToStringMustReturnString, _routine.ContainingType.PhpQualifiedName().ToString()); } } } if (_routine.SyntaxReturnType != null) { // "void" return type hint ? if (_routine.SyntaxReturnType.IsVoid() && x.Returned != null) { // A void function must not return a value _diagnostics.Add(_routine, x.PhpSyntax, ErrorCode.ERR_VoidFunctionCannotReturnValue); } if (_routine.SyntaxReturnType.IsNever()) { _diagnostics.Add(_routine, x.PhpSyntax ?? _routine.SyntaxReturnType, ErrorCode.ERR_NeverReturningFunctionCannotReturn); } if (x.Returned == null) { if (!_routine.SyntaxReturnType.IsVoid()) { // CONSIDER: Err or silently return NULL } } else if (x.Returned.ConstantValue.IsNull() && !_routine.SyntaxReturnType.CanBeNull()) { // not nullable return type // Cannot convert {0} to {1} _diagnostics.Add(_routine, x.Returned.PhpSyntax, ErrorCode.ERR_TypeMismatch, "NULL", _routine.SyntaxReturnType.ToString()); } } // return(base.VisitReturn(x)); }
public override object VisitReturn(BoundReturnStatement x) { return(x.Update((BoundExpression)Accept(x.Returned))); }
private EEMethodSymbol GetTypeVariablesMethod(EENamedTypeSymbol container, string methodName, NamedTypeSymbol typeVariablesType) { var syntax = SyntaxFactory.IdentifierName(SyntaxFactory.MissingToken(SyntaxKind.IdentifierToken)); return this.CreateMethod(container, methodName, syntax, (method, diagnostics) => { var type = method.TypeMap.SubstituteNamedType(typeVariablesType); var expression = new BoundObjectCreationExpression(syntax, type.InstanceConstructors[0]); var statement = new BoundReturnStatement(syntax, expression) { WasCompilerGenerated = true }; return statement; }); }
// private static T <Factory>(object[] submissionArray) // { // var submission = new Submission#N(submissionArray); // return submission.<Initialize>(); // } internal override BoundBlock CreateBody() { var syntax = this.GetSyntax(); var ctor = _containingType.GetScriptConstructor(); Debug.Assert(ctor.ParameterCount == 1); var initializer = _containingType.GetScriptInitializer(); Debug.Assert(initializer.ParameterCount == 0); var submissionArrayParameter = new BoundParameter(syntax, _parameters[0]) { WasCompilerGenerated = true }; var submissionLocal = new BoundLocal( syntax, new SynthesizedLocal(this, _containingType, SynthesizedLocalKind.LoweringTemp), null, _containingType) { WasCompilerGenerated = true }; // var submission = new Submission#N(submissionArray); var submissionAssignment = new BoundExpressionStatement( syntax, new BoundAssignmentOperator( syntax, submissionLocal, new BoundObjectCreationExpression( syntax, ctor, ImmutableArray.Create<BoundExpression>(submissionArrayParameter), default(ImmutableArray<string>), default(ImmutableArray<RefKind>), false, default(ImmutableArray<int>), null, null, _containingType) { WasCompilerGenerated = true }, _containingType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // return submission.<Initialize>(); var initializeResult = CreateParameterlessCall( syntax, submissionLocal, initializer); Debug.Assert(initializeResult.Type == _returnType); var returnStatement = new BoundReturnStatement( syntax, RefKind.None, initializeResult) { WasCompilerGenerated = true }; return new BoundBlock(syntax, ImmutableArray.Create<LocalSymbol>(submissionLocal.LocalSymbol), ImmutableArray<LocalFunctionSymbol>.Empty, ImmutableArray.Create<BoundStatement>(submissionAssignment, returnStatement)) { WasCompilerGenerated = true }; }
private void EmitReturnStatement(BoundReturnStatement boundReturnStatement) { var expressionOpt = boundReturnStatement.ExpressionOpt; if (boundReturnStatement.RefKind == RefKind.None) { this.EmitExpression(expressionOpt, true); } else { this.EmitAddress(expressionOpt, AddressKind.Writeable); } if (ShouldUseIndirectReturn()) { if (expressionOpt != null) { _builder.EmitLocalStore(LazyReturnTemp); } if (_indirectReturnState != IndirectReturnState.Emitted && CanHandleReturnLabel(boundReturnStatement)) { HandleReturn(); } else { _builder.EmitBranch(ILOpCode.Br, s_returnLabel); if (_indirectReturnState == IndirectReturnState.NotNeeded) { _indirectReturnState = IndirectReturnState.Needed; } } } else { if (_indirectReturnState == IndirectReturnState.Needed && CanHandleReturnLabel(boundReturnStatement)) { if (expressionOpt != null) { _builder.EmitLocalStore(LazyReturnTemp); } HandleReturn(); } else { if (expressionOpt != null) { // Ensure the return type has been translated. (Necessary // for cases of untranslated anonymous types.) var returnType = expressionOpt.Type; var byRefType = returnType as ByRefReturnErrorTypeSymbol; if ((object)byRefType != null) { returnType = byRefType.ReferencedType; } _module.Translate(returnType, boundReturnStatement.Syntax, _diagnostics); } _builder.EmitRet(expressionOpt == null); } } }
private void EmitReturnStatement(BoundReturnStatement boundReturnStatement) { this.EmitExpression(boundReturnStatement.ExpressionOpt, true); if (ShouldUseIndirectReturn()) { if (boundReturnStatement.ExpressionOpt != null) { builder.EmitLocalStore(LazyReturnTemp); } if (this.indirectReturnState != IndirectReturnState.Emitted && CanHandleReturnLabel(boundReturnStatement)) { HandleReturn(); } else { builder.EmitBranch(ILOpCode.Br, ReturnLabel); if (this.indirectReturnState == IndirectReturnState.NotNeeded) { this.indirectReturnState = IndirectReturnState.Needed; } } } else { if (this.indirectReturnState == IndirectReturnState.Needed && CanHandleReturnLabel(boundReturnStatement)) { if (boundReturnStatement.ExpressionOpt != null) { builder.EmitLocalStore(LazyReturnTemp); } HandleReturn(); } else { builder.EmitRet(boundReturnStatement.ExpressionOpt == null); } } }
protected override void VisitReturnStatement(BoundReturnStatement node) { base.VisitReturnStatement(node); _containsReturnStatement = true; }
private object EvaluateStatement(BoundBlockStatement body) { var labelToIndex = new Dictionary <BoundLabel, int>(); for (int i = 0; i < body.Statements.Length; i++) { if (body.Statements[i] is BoundLabelStatement l) { labelToIndex.Add(l.Label, i + 1); } } int index = 0; while (index < body.Statements.Length) { BoundStatement s = body.Statements[index]; switch (s.Kind) { case BoundNodeKind.VariableDeclaration: EvaluateVariableDeclaration((BoundVariableDeclaration)s); index++; break; case BoundNodeKind.ExpressionStatement: EvaluateExpressionStatement((BoundExpressionStatement)s); index++; break; case BoundNodeKind.GotoStatement: BoundGotoStatement gs = (BoundGotoStatement)s; index = labelToIndex[gs.Label]; break; case BoundNodeKind.ConditionalGotoStatement: BoundConditionalGotoStatement cgs = (BoundConditionalGotoStatement)s; bool condition = (bool)EvaluateExpression(cgs.Condition); if (condition == cgs.JumpIfTrue) { index = labelToIndex[cgs.Label]; } else { index++; } break; case BoundNodeKind.LabelStatement: index++; break; case BoundNodeKind.ReturnStatement: BoundReturnStatement rs = (BoundReturnStatement)s; lastValue = rs.Expression == null ? null : EvaluateExpression(rs.Expression); return(lastValue); default: throw new Exception($"Unexpected node <{s.Kind}>"); } } return(lastValue); }
// private static T <Factory>(object[] submissionArray) // { // var submission = new Submission#N(submissionArray); // return submission.<Initialize>(); // } internal override BoundBlock CreateBody() { var syntax = this.GetSyntax(); var ctor = _containingType.GetScriptConstructor(); Debug.Assert(ctor.ParameterCount == 1); var initializer = _containingType.GetScriptInitializer(); Debug.Assert(initializer.ParameterCount == 0); var submissionArrayParameter = new BoundParameter(syntax, _parameters[0]) { WasCompilerGenerated = true }; var submissionLocal = new BoundLocal( syntax, new SynthesizedLocal(this, _containingType, SynthesizedLocalKind.LoweringTemp), null, _containingType) { WasCompilerGenerated = true }; // var submission = new Submission#N(submissionArray); var submissionAssignment = new BoundExpressionStatement( syntax, new BoundAssignmentOperator( syntax, submissionLocal, new BoundObjectCreationExpression( syntax, ctor, ImmutableArray.Create <BoundExpression>(submissionArrayParameter), default(ImmutableArray <string>), default(ImmutableArray <RefKind>), false, default(ImmutableArray <int>), null, null, _containingType) { WasCompilerGenerated = true }, _containingType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // return submission.<Initialize>(); BoundExpression initializeResult = new BoundCall( syntax, submissionLocal, initializer, ImmutableArray <BoundExpression> .Empty, default(ImmutableArray <string>), default(ImmutableArray <RefKind>), isDelegateCall: false, expanded: false, invokedAsExtensionMethod: false, argsToParamsOpt: default(ImmutableArray <int>), resultKind: LookupResultKind.Viable, type: initializer.ReturnType) { WasCompilerGenerated = true }; if (initializeResult.Type.IsStructType() && (_returnType.SpecialType == SpecialType.System_Object)) { initializeResult = new BoundConversion(syntax, initializeResult, Conversion.Boxing, false, true, ConstantValue.NotAvailable, _returnType) { WasCompilerGenerated = true }; } var returnStatement = new BoundReturnStatement( syntax, initializeResult) { WasCompilerGenerated = true }; return(new BoundBlock(syntax, ImmutableArray.Create <LocalSymbol>(submissionLocal.LocalSymbol), ImmutableArray.Create <BoundStatement>(submissionAssignment, returnStatement)) { WasCompilerGenerated = true }); }
// private static T <Factory>(object[] submissionArray) // { // var submission = new Submission#N(submissionArray); // return submission.<Initialize>(); // } internal override BoundBlock CreateBody() { var syntax = this.GetSyntax(); var ctor = _containingType.GetScriptConstructor(); Debug.Assert(ctor.ParameterCount == 1); var initializer = _containingType.GetScriptInitializer(); Debug.Assert(initializer.ParameterCount == 0); var submissionArrayParameter = new BoundParameter(syntax, _parameters[0]) { WasCompilerGenerated = true }; var submissionLocal = new BoundLocal( syntax, new SynthesizedLocal(this, _containingType, SynthesizedLocalKind.LoweringTemp), null, _containingType) { WasCompilerGenerated = true }; // var submission = new Submission#N(submissionArray); var submissionAssignment = new BoundExpressionStatement( syntax, new BoundAssignmentOperator( syntax, submissionLocal, new BoundObjectCreationExpression( syntax, ctor, ImmutableArray.Create <BoundExpression>(submissionArrayParameter), default(ImmutableArray <string>), default(ImmutableArray <RefKind>), false, default(ImmutableArray <int>), null, null, _containingType) { WasCompilerGenerated = true }, _containingType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // return submission.<Initialize>(); var initializeResult = CreateParameterlessCall( syntax, submissionLocal, initializer); Debug.Assert(initializeResult.Type == _returnType); var returnStatement = new BoundReturnStatement( syntax, RefKind.None, initializeResult) { WasCompilerGenerated = true }; return(new BoundBlock(syntax, ImmutableArray.Create <LocalSymbol>(submissionLocal.LocalSymbol), ImmutableArray.Create <BoundStatement>(submissionAssignment, returnStatement)) { WasCompilerGenerated = true }); }
// compiler generated return mapped to a block is very likely the synthetic return // that was added at the end of the last block of a void method by analysis. // This is likely to be the last return in the method, // so if we have not yet emitted return sequence, it is convenient to do it right here (if we can). private bool CanHandleReturnLabel(BoundReturnStatement boundReturnStatement) { return boundReturnStatement.WasCompilerGenerated && (boundReturnStatement.Syntax.Kind == SyntaxKind.Block || (((object)this.method != null) && this.method.IsImplicitConstructor)) && !builder.InExceptionHandler; }
// private static T <Factory>(object[] submissionArray) // { // var submission = new Submission#N(submissionArray); // return submission.<Initialize>(); // } internal override BoundBlock CreateBody() { var syntax = this.GetSyntax(); var ctor = _containingType.GetScriptConstructor(); Debug.Assert(ctor.ParameterCount == 1); var initializer = _containingType.GetScriptInitializer(); Debug.Assert(initializer.ParameterCount == 0); var submissionArrayParameter = new BoundParameter(syntax, _parameters[0]) { WasCompilerGenerated = true }; var submissionLocal = new BoundLocal( syntax, new SynthesizedLocal(this, _containingType, SynthesizedLocalKind.LoweringTemp), null, _containingType) { WasCompilerGenerated = true }; // var submission = new Submission#N(submissionArray); var submissionAssignment = new BoundExpressionStatement( syntax, new BoundAssignmentOperator( syntax, submissionLocal, new BoundObjectCreationExpression( syntax, ctor, ImmutableArray.Create<BoundExpression>(submissionArrayParameter), default(ImmutableArray<string>), default(ImmutableArray<RefKind>), false, default(ImmutableArray<int>), null, null, _containingType) { WasCompilerGenerated = true }, _containingType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // return submission.<Initialize>(); BoundExpression initializeResult = new BoundCall( syntax, submissionLocal, initializer, ImmutableArray<BoundExpression>.Empty, default(ImmutableArray<string>), default(ImmutableArray<RefKind>), isDelegateCall: false, expanded: false, invokedAsExtensionMethod: false, argsToParamsOpt: default(ImmutableArray<int>), resultKind: LookupResultKind.Viable, type: initializer.ReturnType) { WasCompilerGenerated = true }; if (initializeResult.Type.IsStructType() && (_returnType.SpecialType == SpecialType.System_Object)) { initializeResult = new BoundConversion(syntax, initializeResult, Conversion.Boxing, false, true, ConstantValue.NotAvailable, _returnType) { WasCompilerGenerated = true }; } var returnStatement = new BoundReturnStatement( syntax, initializeResult) { WasCompilerGenerated = true }; return new BoundBlock(syntax, ImmutableArray.Create<LocalSymbol>(submissionLocal.LocalSymbol), ImmutableArray.Create<BoundStatement>(submissionAssignment, returnStatement)) { WasCompilerGenerated = true }; }
// Compiler generated return mapped to a block is very likely the synthetic return // that was added at the end of the last block of a void method by analysis. // This is likely to be the last return in the method, so if we have not yet // emitted return sequence, it is convenient to do it right here (if we can). private bool CanHandleReturnLabel(BoundReturnStatement boundReturnStatement) { return boundReturnStatement.WasCompilerGenerated && (boundReturnStatement.Syntax.IsKind(SyntaxKind.Block) || _method?.IsImplicitConstructor == true) && !_builder.InExceptionHandler; }
internal override BoundBlock CreateBody(DiagnosticBag diagnostics) { var syntax = DummySyntax(); var ctor = _containingType.GetScriptConstructor(); Debug.Assert(ctor.ParameterCount == 1); var initializer = _containingType.GetScriptInitializer(); Debug.Assert(initializer.ParameterCount == 0); var submissionArrayParameter = new BoundParameter(syntax, _parameters[0]) { WasCompilerGenerated = true }; var submissionLocal = new BoundLocal( syntax, new SynthesizedLocal(this, TypeWithAnnotations.Create(_containingType), SynthesizedLocalKind.LoweringTemp), null, _containingType) { WasCompilerGenerated = true }; // var submission = new Submission#N(submissionArray); var submissionAssignment = new BoundExpressionStatement( syntax, new BoundAssignmentOperator( syntax, submissionLocal, new BoundObjectCreationExpression( syntax, ctor, ImmutableArray.Create <BoundExpression>(submissionArrayParameter), argumentNamesOpt: default(ImmutableArray <string>), argumentRefKindsOpt: default(ImmutableArray <RefKind>), expanded: false, argsToParamsOpt: default(ImmutableArray <int>), defaultArguments: default(BitVector), constantValueOpt: null, initializerExpressionOpt: null, type: _containingType) { WasCompilerGenerated = true }, _containingType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // return submission.<Initialize>(); var initializeResult = CreateParameterlessCall( syntax, submissionLocal, initializer); Debug.Assert(TypeSymbol.Equals(initializeResult.Type, _returnType.Type, TypeCompareKind.ConsiderEverything2)); var returnStatement = new BoundReturnStatement( syntax, RefKind.None, initializeResult) { WasCompilerGenerated = true }; return(new BoundBlock(syntax, ImmutableArray.Create <LocalSymbol>(submissionLocal.LocalSymbol), ImmutableArray.Create <BoundStatement>(submissionAssignment, returnStatement)) { WasCompilerGenerated = true }); }
public override BoundNode VisitReturnStatement(BoundReturnStatement node) { BoundExpression expressionOpt = (BoundExpression)this.Visit(node.ExpressionOpt); // must not have locals on stack when returning EnsureOnlyEvalStack(); return node.Update(expressionOpt); }
private static void WriteBoundReturnStatement(this IndentedTextWriter writer, BoundReturnStatement node) { writer.WriteMagentaKeyword("return"); writer.WriteSpace(); if (node.Expression is null) { writer.WriteBlueKeyword("void"); } else { writer.WriteBoundNode(node.Expression); } }