internal override void WriteTo(CCodeWriterBase c) { // Finish it properly var localImpl = new LocalImpl { Name = "__ConditionalAccess", Type = Type }; var local = new Local { LocalSymbol = localImpl }; var block = new Block(); block.Statements.Add(new VariableDeclaration { Local = local }); block.Statements.Add( new ExpressionStatement { Expression = new AssignmentOperator { Left = local, Right = this.Receiver } }); // prepare access expression; Expression access = new Access { ReceiverOpt = local, Expression = this.WhenNotNull }; var call = this.WhenNotNull as Call; if (call != null) { access = call; call.ReceiverOpt = local; } var fieldAccess = this.WhenNotNull as FieldAccess; if (fieldAccess != null) { access = fieldAccess; fieldAccess.ReceiverOpt = local; } block.Statements.Add( new ReturnStatement { ExpressionOpt = new ConditionalOperator { Condition = new BinaryOperator { Left = (Type.TypeKind == TypeKind.TypeParameter) ? (Expression) new Cast { Constrained = true, Operand = local, Type = new TypeImpl { SpecialType = SpecialType.System_Object } } : local, Right = new Literal { Value = ConstantValue.Create(null) }, OperatorKind = BinaryOperatorKind.NotEqual }, Consequence = access, Alternative = new Literal { Value = ConstantValue.Create(null) } } }); new LambdaCall { Lambda = new LambdaExpression { Statements = block, Type = Type } }.WriteTo(c); // clean up if (call != null) { call.ReceiverOpt = null; } if (fieldAccess != null) { fieldAccess.ReceiverOpt = null; } }
internal static Base Deserialize(BoundNode boundBody, IMethodSymbol methodSymbol = null, SpecialCases specialCase = SpecialCases.None) { // method var boundStatementList = boundBody as BoundStatementList; if (boundStatementList != null) { if (methodSymbol != null || boundStatementList.Syntax.Green is MethodDeclarationSyntax) { var methodBody = new MethodBody(methodSymbol); methodBody.Parse(boundStatementList); return(methodBody); } if (boundStatementList.Syntax.Green is VariableDeclarationSyntax) { var variableDeclaration = new VariableDeclaration(); variableDeclaration.Parse(boundStatementList); return(variableDeclaration); } if (boundStatementList.Syntax.Green is IfStatementSyntax) { var ifStatement = new IfStatement(); if (ifStatement.Parse(boundStatementList)) { return(ifStatement); } } if (boundStatementList.Syntax.Green is ForStatementSyntax) { var forStatement = new ForStatement(); if (forStatement.Parse(boundStatementList)) { return(forStatement); } } if (boundStatementList.Syntax.Green is WhileStatementSyntax) { var whileStatement = new WhileStatement(); if (whileStatement.Parse(boundStatementList)) { return(whileStatement); } } if (boundStatementList.Syntax.Green is DoStatementSyntax) { var doStatement = new DoStatement(); if (doStatement.Parse(boundStatementList)) { return(doStatement); } } var forEachStatementSyntax = boundStatementList.Syntax.Green as ForEachStatementSyntax; if (forEachStatementSyntax != null) { if (specialCase != SpecialCases.ForEachBody) { var forEachSimpleArrayStatement = new ForEachSimpleArrayStatement(); if (forEachSimpleArrayStatement.Parse(boundStatementList)) { return(forEachSimpleArrayStatement); } var forEachIteratorStatement = new ForEachIteratorStatement(); if (forEachIteratorStatement.Parse(boundStatementList)) { return(forEachIteratorStatement); } } } // try to detect 'if' var ifStatementNoHint = new IfStatement(); if (ifStatementNoHint.Parse(boundStatementList)) { return(ifStatementNoHint); } var whileStatementNoHint = new WhileStatement(); if (whileStatementNoHint.Parse(boundStatementList)) { return(whileStatementNoHint); } var block = new Block(); block.Parse(boundStatementList, specialCase); return(block); } var boundConversion = boundBody as BoundConversion; if (boundConversion != null) { var conversion = new Conversion(); conversion.Parse(boundConversion); return(conversion); } var boundTypeExpression = boundBody as BoundTypeExpression; if (boundTypeExpression != null) { var typeExpression = new TypeExpression(); typeExpression.Parse(boundTypeExpression); return(typeExpression); } var boundThisReference = boundBody as BoundThisReference; if (boundThisReference != null) { var thisReference = new ThisReference(); thisReference.Parse(boundThisReference); return(thisReference); } var boundBaseReference = boundBody as BoundBaseReference; if (boundBaseReference != null) { var baseReference = new BaseReference(); baseReference.Parse(boundBaseReference); return(baseReference); } var boundFieldAccess = boundBody as BoundFieldAccess; if (boundFieldAccess != null) { var fieldAccess = new FieldAccess(); fieldAccess.Parse(boundFieldAccess); return(fieldAccess); } var boundParameter = boundBody as BoundParameter; if (boundParameter != null) { var parameter = new Parameter(); parameter.Parse(boundParameter); return(parameter); } var boundLocal = boundBody as BoundLocal; if (boundLocal != null) { var local = new Local(); local.Parse(boundLocal); return(local); } var boundLiteral = boundBody as BoundLiteral; if (boundLiteral != null) { var literal = new Literal(); literal.Parse(boundLiteral); return(literal); } var boundExpressionStatement = boundBody as BoundExpressionStatement; if (boundExpressionStatement != null) { var expressionStatement = new ExpressionStatement(); expressionStatement.Parse(boundExpressionStatement); return(expressionStatement); } var boundSequence = boundBody as BoundSequence; if (boundSequence != null) { if (boundSequence.Syntax.Green is PrefixUnaryExpressionSyntax) { var prefixUnaryExpression = new PrefixUnaryExpression(); if (prefixUnaryExpression.Parse(boundSequence)) { return(prefixUnaryExpression); } } if (boundSequence.Syntax.Green is PostfixUnaryExpressionSyntax) { var postfixUnaryExpression = new PostfixUnaryExpression(); if (postfixUnaryExpression.Parse(boundSequence)) { return(postfixUnaryExpression); } } var sideEffectsAsLambdaCallExpression = new SideEffectsAsLambdaCallExpression(); if (sideEffectsAsLambdaCallExpression.Parse(boundSequence)) { return(sideEffectsAsLambdaCallExpression); } } var boundCall = boundBody as BoundCall; if (boundCall != null) { var call = new Call(); call.Parse(boundCall); return(call); } var boundBinaryOperator = boundBody as BoundBinaryOperator; if (boundBinaryOperator != null) { var binaryOperator = new BinaryOperator(); binaryOperator.Parse(boundBinaryOperator); return(binaryOperator); } var boundAssignmentOperator = boundBody as BoundAssignmentOperator; if (boundAssignmentOperator != null) { var unaryAssignmentOperator = new UnaryAssignmentOperator(); if (unaryAssignmentOperator.Parse(boundAssignmentOperator)) { return(unaryAssignmentOperator); } var assignmentOperator = new AssignmentOperator(); assignmentOperator.Parse(boundAssignmentOperator); return(assignmentOperator); } var boundObjectCreationExpression = boundBody as BoundObjectCreationExpression; if (boundObjectCreationExpression != null) { var objectCreationExpression = new ObjectCreationExpression(); objectCreationExpression.Parse(boundObjectCreationExpression); return(objectCreationExpression); } var boundUnaryOperator = boundBody as BoundUnaryOperator; if (boundUnaryOperator != null) { var unaryOperator = new UnaryOperator(); unaryOperator.Parse(boundUnaryOperator); return(unaryOperator); } var boundConditionalOperator = boundBody as BoundConditionalOperator; if (boundConditionalOperator != null) { var conditionalOperator = new ConditionalOperator(); conditionalOperator.Parse(boundConditionalOperator); return(conditionalOperator); } var boundNullCoalescingOperator = boundBody as BoundNullCoalescingOperator; if (boundNullCoalescingOperator != null) { var nullCoalescingOperator = new NullCoalescingOperator(); nullCoalescingOperator.Parse(boundNullCoalescingOperator); return(nullCoalescingOperator); } var boundArrayCreation = boundBody as BoundArrayCreation; if (boundArrayCreation != null) { var arrayCreation = new ArrayCreation(); arrayCreation.Parse(boundArrayCreation); return(arrayCreation); } var boundArrayInitialization = boundBody as BoundArrayInitialization; if (boundArrayInitialization != null) { var arrayInitialization = new ArrayInitialization(); arrayInitialization.Parse(boundArrayInitialization); return(arrayInitialization); } var boundArrayAccess = boundBody as BoundArrayAccess; if (boundArrayAccess != null) { var arrayAccess = new ArrayAccess(); arrayAccess.Parse(boundArrayAccess); return(arrayAccess); } var boundArrayLength = boundBody as BoundArrayLength; if (boundArrayLength != null) { var arrayLength = new ArrayLength(); arrayLength.Parse(boundArrayLength); return(arrayLength); } var boundStackAllocArrayCreation = boundBody as BoundStackAllocArrayCreation; if (boundStackAllocArrayCreation != null) { var stackAllocArrayCreation = new StackAllocArrayCreation(); stackAllocArrayCreation.Parse(boundStackAllocArrayCreation); return(stackAllocArrayCreation); } var boundDefaultOperator = boundBody as BoundDefaultOperator; if (boundDefaultOperator != null) { var defaultOperator = new DefaultOperator(); defaultOperator.Parse(boundDefaultOperator); return(defaultOperator); } var boundReturnStatement = boundBody as BoundReturnStatement; if (boundReturnStatement != null) { var returnStatement = new ReturnStatement(); returnStatement.Parse(boundReturnStatement); return(returnStatement); } var boundDelegateCreationExpression = boundBody as BoundDelegateCreationExpression; if (boundDelegateCreationExpression != null) { var delegateCreationExpression = new DelegateCreationExpression(); delegateCreationExpression.Parse(boundDelegateCreationExpression); return(delegateCreationExpression); } var boundThrowStatement = boundBody as BoundThrowStatement; if (boundThrowStatement != null) { var throwStatement = new ThrowStatement(); throwStatement.Parse(boundThrowStatement); return(throwStatement); } var boundThrowExpression = boundBody as BoundThrowExpression; if (boundThrowExpression != null) { var throwExpression = new ThrowExpression(); throwExpression.Parse(boundThrowExpression); return(throwExpression); } var boundTryStatement = boundBody as BoundTryStatement; if (boundTryStatement != null) { var tryStatement = new TryStatement(); tryStatement.Parse(boundTryStatement); return(tryStatement); } var boundCatchBlock = boundBody as BoundCatchBlock; if (boundCatchBlock != null) { var catchBlock = new CatchBlock(); catchBlock.Parse(boundCatchBlock); return(catchBlock); } var boundGotoStatement = boundBody as BoundGotoStatement; if (boundGotoStatement != null) { if (boundGotoStatement.Syntax.Green is ContinueStatementSyntax) { var continueStatement = new ContinueStatement(); continueStatement.Parse(boundGotoStatement); return(continueStatement); } if (boundGotoStatement.Syntax.Green is BreakStatementSyntax) { var breakStatement = new BreakStatement(); breakStatement.Parse(boundGotoStatement); return(breakStatement); } ////var continueStatementNoHint = new ContinueStatement(); ////if (continueStatementNoHint.Parse(boundGotoStatement)) ////{ //// return continueStatementNoHint; ////} ////var breakStatementNoHint = new BreakStatement(); ////if (breakStatementNoHint.Parse(boundGotoStatement)) ////{ //// return breakStatementNoHint; ////} var gotoStatement = new GotoStatement(); gotoStatement.Parse(boundGotoStatement); return(gotoStatement); } var boundLabelStatement = boundBody as BoundLabelStatement; if (boundLabelStatement != null) { var labelStatement = new LabelStatement(); labelStatement.Parse(boundLabelStatement); return(labelStatement); } var boundMethodGroup = boundBody as BoundMethodGroup; if (boundMethodGroup != null) { var methodGroup = new MethodGroup(); methodGroup.Parse(boundMethodGroup); return(methodGroup); } var boundConditionalGoto = boundBody as BoundConditionalGoto; if (boundConditionalGoto != null) { var conditionalGoto = new ConditionalGoto(); conditionalGoto.Parse(boundConditionalGoto); return(conditionalGoto); } var boundAsOperator = boundBody as BoundAsOperator; if (boundAsOperator != null) { var asOperator = new AsOperator(); asOperator.Parse(boundAsOperator); return(asOperator); } var boundIsOperator = boundBody as BoundIsOperator; if (boundIsOperator != null) { var isOperator = new IsOperator(); isOperator.Parse(boundIsOperator); return(isOperator); } var boundTypeOfOperator = boundBody as BoundTypeOfOperator; if (boundTypeOfOperator != null) { var typeOfOperator = new TypeOfOperator(); typeOfOperator.Parse(boundTypeOfOperator); return(typeOfOperator); } var boundSwitchStatement = boundBody as BoundSwitchStatement; if (boundSwitchStatement != null) { var switchStatement = new SwitchStatement(); switchStatement.Parse(boundSwitchStatement); return(switchStatement); } var boundAddressOfOperator = boundBody as BoundAddressOfOperator; if (boundAddressOfOperator != null) { var addressOfOperator = new AddressOfOperator(); addressOfOperator.Parse(boundAddressOfOperator); return(addressOfOperator); } var boundPointerIndirectionOperator = boundBody as BoundPointerIndirectionOperator; if (boundPointerIndirectionOperator != null) { if (boundPointerIndirectionOperator.Syntax.Green is ElementAccessExpressionSyntax) { var elementAccessExpression = new ElementAccessExpression(); if (elementAccessExpression.Parse(boundPointerIndirectionOperator)) { return(elementAccessExpression); } } var pointerIndirectionOperator = new PointerIndirectionOperator(); pointerIndirectionOperator.Parse(boundPointerIndirectionOperator); return(pointerIndirectionOperator); } var boundMakeRefOperator = boundBody as BoundMakeRefOperator; if (boundMakeRefOperator != null) { var makeRefOperator = new MakeRefOperator(); makeRefOperator.Parse(boundMakeRefOperator); return(makeRefOperator); } var boundRefValueOperator = boundBody as BoundRefValueOperator; if (boundRefValueOperator != null) { var refValueOperator = new RefValueOperator(); refValueOperator.Parse(boundRefValueOperator); return(refValueOperator); } var boundRefTypeOperator = boundBody as BoundRefTypeOperator; if (boundRefTypeOperator != null) { var refTypeOperator = new RefTypeOperator(); refTypeOperator.Parse(boundRefTypeOperator); return(refTypeOperator); } var boundSizeOfOperator = boundBody as BoundSizeOfOperator; if (boundSizeOfOperator != null) { var sizeOfOperator = new SizeOfOperator(); sizeOfOperator.Parse(boundSizeOfOperator); return(sizeOfOperator); } var boundNoOpStatement = boundBody as BoundNoOpStatement; if (boundNoOpStatement != null) { var noOpStatement = new NoOpStatement(); noOpStatement.Parse(boundNoOpStatement); return(noOpStatement); } var boundIteratorScope = boundBody as BoundStateMachineScope; if (boundIteratorScope != null) { var stateMachineScope = new StateMachineScope(); stateMachineScope.Parse(boundIteratorScope); return(stateMachineScope); } var boundArgList = boundBody as BoundArgList; if (boundArgList != null) { var argList = new ArgList(); argList.Parse(boundArgList); return(argList); } var boundArgListOperator = boundBody as BoundArgListOperator; if (boundArgListOperator != null) { var argListOperator = new ArgListOperator(); argListOperator.Parse(boundArgListOperator); return(argListOperator); } var boundLoweredConditionalAccess = boundBody as BoundLoweredConditionalAccess; if (boundLoweredConditionalAccess != null) { var loweredConditionalAccess = new LoweredConditionalAccess(); loweredConditionalAccess.Parse(boundLoweredConditionalAccess); return(loweredConditionalAccess); } var boundConditionalReceiver = boundBody as BoundConditionalReceiver; if (boundConditionalReceiver != null) { var conditionalReceiver = new ConditionalReceiver(); conditionalReceiver.Parse(boundConditionalReceiver); return(conditionalReceiver); } var statemnentOrExpression = Unwrap(boundBody); if (statemnentOrExpression == null) { throw new NotImplementedException(); } return(Deserialize(statemnentOrExpression)); }
internal override void WriteTo(CCodeWriterBase c) { Local localCase = null; if (this.stringEquality != null) { c.OpenBlock(); var localImpl = new LocalImpl { Name = "__SwitchExpression", Type = this.expression.Type }; var local = new Local { LocalSymbol = localImpl }; var localImplCase = new LocalImpl { Name = "__SwitchCase", Type = new TypeImpl { SpecialType = SpecialType.System_Int32 } }; localCase = new Local { LocalSymbol = localImplCase }; new VariableDeclaration { Statements = { new ExpressionStatement { Expression = new AssignmentOperator { TypeDeclaration = true, Type = new TypeImpl { SpecialType = SpecialType.System_Int32 }, Left = localCase, Right = new Literal{ Value = ConstantValue.Create(0) } } } } }.WriteTo(c); new VariableDeclaration { Statements = { new ExpressionStatement { Expression = new AssignmentOperator { TypeDeclaration = true, Type = new TypeImpl { SpecialType = SpecialType.System_String }, Left = local, Right = this.expression } } } }.WriteTo(c); // first if IfStatement first = null; IfStatement last = null; var caseIndex = 0; foreach (var switchSection in this.switchCases) { foreach (var label in switchSection.Labels) { if (label.Value == null) { // default case; continue; } caseIndex++; // compare var callEqual = new Call() { Method = this.stringEquality }; callEqual.Arguments.Add(local); callEqual.Arguments.Add(new Literal { Value = label.Value }); // set value var setExpr = new ExpressionStatement { Expression = new AssignmentOperator { Left = localCase, Right = new Literal { Value = ConstantValue.Create(caseIndex) } } }; var ifStatement = new IfStatement { Condition = callEqual, IfStatements = setExpr }; first = first ?? ifStatement; if (last != null) { last.ElseStatementsOpt = ifStatement; } last = ifStatement; // remap case value label.Value = ConstantValue.Create(caseIndex); } } if (first != null) { first.WriteTo(c); } c.Separate(); } foreach (var statement in this.statements) { statement.WriteTo(c); } c.TextSpan("switch"); c.WhiteSpace(); c.TextSpan("("); if (this.stringEquality != null) { localCase.WriteTo(c); } else { this.expression.WriteTo(c); } c.TextSpan(")"); c.NewLine(); c.OpenBlock(); foreach (var switchSection in this.switchCases) { switchSection.WriteTo(c); } c.EndBlock(); if (this.stringEquality != null) { c.EndBlock(); } c.Separate(); }
internal override void WriteTo(CCodeWriterBase c) { Local localCase = null; if (this.stringEquality != null) { c.OpenBlock(); var localImpl = new LocalImpl { Name = "__SwitchExpression", Type = this.expression.Type }; var local = new Local { LocalSymbol = localImpl, MethodOwner = MethodOwner }; var localImplCase = new LocalImpl { Name = "__SwitchCase", Type = SpecialType.System_Int32.ToType() }; localCase = new Local { LocalSymbol = localImplCase, MethodOwner = MethodOwner }; new VariableDeclaration { Statements = { new ExpressionStatement { Expression = new AssignmentOperator { TypeDeclaration = true, Type = SpecialType.System_Int32.ToType(), Left = localCase, Right = new Literal { Value = ConstantValue.Create(0) }, MethodOwner = MethodOwner }, MethodOwner = MethodOwner } }, MethodOwner = MethodOwner }.WriteTo(c); new VariableDeclaration { Statements = { new ExpressionStatement { Expression = new AssignmentOperator { TypeDeclaration = true, Type = SpecialType.System_String.ToType(), Left = local, Right = this.expression, MethodOwner = MethodOwner }, MethodOwner = MethodOwner } }, MethodOwner = MethodOwner }.WriteTo(c); // first if IfStatement first = null; IfStatement last = null; var caseIndex = 0; foreach (var switchSection in this.switchCases) { foreach (var label in switchSection.Labels) { if (label.Value == null) { // default case; continue; } caseIndex++; // compare var callEqual = new Call() { Method = this.stringEquality }; callEqual.Arguments.Add(local); callEqual.Arguments.Add(new Literal { Value = label.Value }); // set value var setExpr = new ExpressionStatement { Expression = new AssignmentOperator { Left = localCase, Right = new Literal { Value = ConstantValue.Create(caseIndex) } } }; var ifStatement = new IfStatement { Condition = callEqual, IfStatements = setExpr }; first = first ?? ifStatement; if (last != null) { last.ElseStatementsOpt = ifStatement; } last = ifStatement; // remap case value label.Value = ConstantValue.Create(caseIndex); } } if (first != null) { first.WriteTo(c); } c.Separate(); } foreach (var statement in this.statements) { statement.WriteTo(c); } var generateDefaultLabel = this.isNullableType; if (this.isNullableType) { var nullCase = this.switchCases.FirstOrDefault(sc => sc.Labels.Any(l => l.Value != null && l.Value.IsNull)); if (nullCase != null) { generateDefaultLabel = false; } var nullCaseOrDefault = nullCase ?? this.switchCases.FirstOrDefault(sc => sc.Labels.Any(l => l.Value == null)); if (nullCaseOrDefault != null) { var effectiveExpression = this.expression; var callExpression = this.expression as Call; if (callExpression != null) { effectiveExpression = new UnaryOperator { OperatorKind = UnaryOperatorKind.LogicalNegation, Operand = new Call { ReceiverOpt = callExpression.ReceiverOpt, Method = new MethodImpl { Name = "get_HasValue", Parameters = ImmutableArray <IParameterSymbol> .Empty } } }; } // we need to insert nullable goto; var ifStatement = new IfStatement { Condition = effectiveExpression, IfStatements = new GotoStatement { Label = nullCaseOrDefault.Labels.First(l => l.Value == null || l.Value.IsNull) } }; ifStatement.WriteTo(c); } } c.TextSpan("switch"); c.WhiteSpace(); c.TextSpan("("); if (this.stringEquality != null) { localCase.WriteTo(c); } else { this.expression.WriteTo(c); } c.TextSpan(")"); c.NewLine(); c.OpenBlock(); foreach (var switchSection in this.switchCases) { if (!generateDefaultLabel && switchSection.Labels.Any(l => l.Value == null)) { switchSection.IsNullableType = false; } switchSection.WriteTo(c); } c.EndBlock(); if (this.stringEquality != null) { c.EndBlock(); } c.Separate(); }