private static ILValue ResolveLValue(this SimpleCompoundStatement block, List <ExpressionBase> expressionQueue, ExpressionSyntax expressionSyntax, bool suppressDummyVariableCreation = false, ILValue replaceCreatedDummyVariableWith = null) { var last = ResolveValueToQueue(block, expressionQueue, expressionSyntax, suppressDummyVariableCreation, replaceCreatedDummyVariableWith); switch (last) { case null: return(null); case ILValue value: return(value); default: Log.Debug("ResolveLValue: {Expression} ({Kind}) → ILValue ({Kind})", expressionSyntax, expressionSyntax.Kind(), last); return(null); } }
private static SubscriptOperator ResolveRoslynElementAccessExpressionToWandaOperator( ElementAccessExpressionSyntax elementAccessExpressionSyntax, List <ExpressionBase> expressionQueue, SimpleCompoundStatement block) { var subscript = block.ResolveLValue(expressionQueue, elementAccessExpressionSyntax.Expression, true); if (subscript == null) { return(null); } var argumentListArguments = elementAccessExpressionSyntax.ArgumentList.Arguments; if (argumentListArguments.Count != 1) { Log.Warning("{ArgumentList}: {Count} elements, not supported", elementAccessExpressionSyntax.ArgumentList, argumentListArguments.Count); return(null); } var argument = block.ResolveValue(expressionQueue, argumentListArguments[0].Expression, true); if (argument == null) { return(null); } return(new SubscriptOperator(subscript, argument)); }
private static void ProcessRoslynBlockIntoWandaBlock(BlockSyntax roslynBody, SimpleCompoundStatement wandaBlock) { foreach (var statement in roslynBody.Statements) { ProcessRoslynStatementIntoWandaBlock(statement, wandaBlock); } }
private static void ProcessVariableDeclarationSyntax(VariableDeclarationSyntax variableDeclarationSyntax, SimpleCompoundStatement wandaBlock) { foreach (var variableDeclaratorSyntax in variableDeclarationSyntax.Variables) { var variable = new Variable { TypeRef = ResolveType(variableDeclarationSyntax.Type), Name = variableDeclaratorSyntax.Identifier.Text }; wandaBlock.LocalVariables.Add(variable); var declaration = new SimpleDeclarationStatement { Variable = variable, ParentBlock = wandaBlock, ParentMethod = wandaBlock.ParentMethod, }; wandaBlock.Body.Add(declaration); if (variableDeclaratorSyntax.Initializer == null) { continue; } var initializerValue = variableDeclaratorSyntax.Initializer.Value; var withWhat = ResolveValueToBlock(wandaBlock, initializerValue, replaceCreatedDummyVariableWith: variable); if (withWhat == variable) { continue; } if (withWhat == null) { Log.Warning("Unable to parse assigned value expression {Expression} for {Variable}, using null", initializerValue, variable.Name); withWhat = NullLiteral.Instance; } var assignment = new SimpleExpressionStatement { Expression = new SimpleAssignment(variable, withWhat), ParentBlock = wandaBlock, ParentMethod = wandaBlock.ParentMethod, // todo: location }; if (withWhat is ILValue value) { variable.TypeRef = value.TypeRef; } wandaBlock.Body.Add(assignment); } }
private static void ProcessWandaExpressionIntoWandaBlock(SimpleCompoundStatement wandaBlock, ExpressionBase wandaExpression) { var simpleExpressionStatement = new SimpleExpressionStatement { Expression = wandaExpression, ParentBlock = wandaBlock, ParentMethod = wandaBlock.ParentMethod //Location = invocationExpressionSyntax.GetLocation() }; wandaBlock.Body.Add(simpleExpressionStatement); }
private static void ProcessRoslynSelectionStatementIntoWandaSelectionStatementBlock( StatementSyntax innerStatement, SimpleCompoundStatement block) { if (innerStatement is BlockSyntax blockSyntax) { ProcessRoslynBlockIntoWandaBlock(blockSyntax, block); } else { ProcessRoslynStatementIntoWandaBlock(innerStatement, block); } }
private void BuildGraphForBlock([NotNull] SimpleCompoundStatement compoundStatement, [NotNull] GraphMethodRoot methodRoot) { var graphNode = new GraphControlFlowBlockNode(methodRoot); methodRoot.Start = graphNode; var(preemptiveExits, next) = AddStatementToGraphNode(compoundStatement, methodRoot, graphNode, null, null); if (next != null) { next.Outgoing = new GraphControlFlowReturnNode(methodRoot, null, true); } }
private static ExpressionBase ResolveValueToBlock(SimpleCompoundStatement block, ExpressionSyntax expressionSyntax, bool suppressDummyVariableCreation = false, ILValue replaceCreatedDummyVariableWith = null) { var expressionQueue = new List <ExpressionBase>(); var last = ResolveValueToQueue(block, expressionQueue, expressionSyntax, suppressDummyVariableCreation, replaceCreatedDummyVariableWith); foreach (var expressionBase in expressionQueue) { ProcessWandaExpressionIntoWandaBlock(block, expressionBase); } return(last); }
private static ExpressionBase ResolveValueToQueue(SimpleCompoundStatement block, List <ExpressionBase> expressionQueue, ExpressionSyntax expressionSyntax, bool suppressDummyVariableCreation = false, ILValue replaceCreatedDummyVariableWith = null) { var expressions = ConvertRoslynExpressionToWandaExpression(block, expressionSyntax)?.ToArray(); if (expressions == null) { Log.Debug("ResolveValueInternal: {Expression} ({Kind}) → null", expressionSyntax, expressionSyntax.Kind()); return(null); } if (expressions.Length == 0) { Log.Debug("ResolveValueInternal: {Expression} ({Kind}) → []", expressionSyntax, expressionSyntax.Kind()); return(null); } switch (expressions[^ 1])
private static IValue ResolveValue(this SimpleCompoundStatement block, List <ExpressionBase> expressionQueue, ExpressionSyntax expressionSyntax, bool suppressDummyVariableCreation = false, ILValue replaceCreatedDummyVariableWith = null) { var last = ResolveValueToQueue(block, expressionQueue, expressionSyntax, suppressDummyVariableCreation, replaceCreatedDummyVariableWith); switch (last) { case null: return(null); case AssignmentBase value: return(value.Left); case IValue value: return(value); default: throw new ApplicationException(); } }
private WhileIterationStatement(SimpleCompoundStatement block, bool tag) { }
public WhileIterationStatement(SimpleCompoundStatement parent) : base(parent) { }
public static WhileIterationStatement FromBlock(SimpleCompoundStatement block) { return(new WhileIterationStatement(block, true)); }
private static void ProcessRoslynStatementIntoWandaBlock(StatementSyntax roslynStatement, SimpleCompoundStatement wandaBlock) { switch (roslynStatement) { case LocalDeclarationStatementSyntax declarationStatement: { ProcessVariableDeclarationSyntax(declarationStatement.Declaration, wandaBlock); break; } case ExpressionStatementSyntax expressionStatementSyntax: { foreach (var expressionBase in ConvertRoslynExpressionToWandaExpression(wandaBlock, expressionStatementSyntax.Expression)) { ProcessWandaExpressionIntoWandaBlock(wandaBlock, expressionBase); } break; } case ForStatementSyntax forStatementSyntax: { if (forStatementSyntax.Declaration != null) { ProcessVariableDeclarationSyntax(forStatementSyntax.Declaration, wandaBlock); } var forIterationStatement = new ForIterationStatement(wandaBlock); foreach (var expressionSyntax in forStatementSyntax.Initializers) { foreach (var expressionBase in ConvertRoslynExpressionToWandaExpression(wandaBlock, expressionSyntax)) { ProcessWandaExpressionIntoWandaBlock(wandaBlock, expressionBase); } } forIterationStatement.Condition.AddRange( ConvertRoslynExpressionToWandaExpression(wandaBlock, forStatementSyntax.Condition)); forIterationStatement.IterationExpression.AddRange(forStatementSyntax.Incrementors .SelectMany(x => ConvertRoslynExpressionToWandaExpression(wandaBlock, x))); ProcessRoslynSelectionStatementIntoWandaSelectionStatementBlock(forStatementSyntax.Statement, forIterationStatement.Block); wandaBlock.Body.Add(forIterationStatement); break; } case WhileStatementSyntax whileStatementSyntax: { var whileIterationStatement = new WhileIterationStatement(wandaBlock); whileIterationStatement.Condition.AddRange( ConvertRoslynExpressionToWandaExpression(wandaBlock, whileStatementSyntax.Condition)); ProcessRoslynSelectionStatementIntoWandaSelectionStatementBlock(whileStatementSyntax.Statement, whileIterationStatement.Block); wandaBlock.Body.Add(whileIterationStatement); break; } case IfStatementSyntax ifStatementSyntax: { var ifStatement = new IfStatement(wandaBlock); ifStatement.Condition.AddRange( ConvertRoslynExpressionToWandaExpression(wandaBlock, ifStatementSyntax.Condition)); ProcessRoslynSelectionStatementIntoWandaSelectionStatementBlock(ifStatementSyntax.Statement, ifStatement.Block); if (ifStatementSyntax.Else != null) { ifStatement.ElseBlock = new SimpleCompoundStatement { ParentBlock = wandaBlock, ParentMethod = wandaBlock.ParentMethod }; ProcessRoslynSelectionStatementIntoWandaSelectionStatementBlock( ifStatementSyntax.Else.Statement, ifStatement.ElseBlock); } wandaBlock.Body.Add(ifStatement); break; } case ReturnStatementSyntax returnStatementSyntax: { var returnStatement = new ReturnStatement(); if (returnStatementSyntax.Expression != null) { returnStatement.What = ResolveValueToBlock(wandaBlock, returnStatementSyntax.Expression, true); } wandaBlock.Body.Add(returnStatement); break; } case ContinueStatementSyntax _: { var continueStatement = new ContinueStatement(); wandaBlock.Body.Add(continueStatement); break; } default: Log.Debug("Roslyn → Wanda Statement: {Statement} ({Kind})", roslynStatement, roslynStatement.Kind()); break; } }
public static Variable ResolveVariableByName(this SimpleCompoundStatement block, string name) { var variable = block.LocalVariables.FirstOrDefault(x => x.Name == name); return(variable ?? block.ParentBlock?.ResolveVariableByName(name)); }
private static List <ExpressionBase> ConvertRoslynExpressionToWandaExpression( SimpleCompoundStatement wandaBlock, ExpressionSyntax expressionSyntax) { var result = new List <ExpressionBase>(); switch (expressionSyntax) { case AssignmentExpressionSyntax assignmentExpressionSyntax: { var left = assignmentExpressionSyntax.Left; var operatorToken = assignmentExpressionSyntax.OperatorToken; var right = assignmentExpressionSyntax.Right; var leftValue = wandaBlock.ResolveLValue(result, left, true); var rightValue = wandaBlock.ResolveValue(result, right, true); AssignmentBase assignment = null; switch (operatorToken.Kind()) { case SyntaxKind.EqualsToken: assignment = new SimpleAssignment(leftValue, rightValue); break; case SyntaxKind.SlashEqualsToken: assignment = new OperatorAssignment(leftValue, rightValue, BinaryDivideOperator.Instance); break; case SyntaxKind.PlusEqualsToken: assignment = new OperatorAssignment(leftValue, rightValue, BinaryAddOperator.Instance); break; case SyntaxKind.MinusEqualsToken: assignment = new OperatorAssignment(leftValue, rightValue, BinarySubtractOperator.Instance); break; case SyntaxKind.AsteriskEqualsToken: assignment = new OperatorAssignment(leftValue, rightValue, BinaryMultiplyOperator.Instance); break; case SyntaxKind.PercentEqualsToken: assignment = new OperatorAssignment(leftValue, rightValue, BinaryRemainderOperator.Instance); break; case SyntaxKind.AmpersandEqualsToken: assignment = new OperatorAssignment(leftValue, rightValue, BinaryBitAndOperator.Instance); break; case SyntaxKind.CaretEqualsToken: assignment = new OperatorAssignment(leftValue, rightValue, BinaryBitXorOperator.Instance); break; case SyntaxKind.BarEqualsToken: assignment = new OperatorAssignment(leftValue, rightValue, BinaryBitOrOperator.Instance); break; case SyntaxKind.LessThanLessThanEqualsToken: assignment = new OperatorAssignment(leftValue, rightValue, BinaryBitShiftLeftOperator.Instance); break; case SyntaxKind.GreaterThanGreaterThanEqualsToken: assignment = new OperatorAssignment(leftValue, rightValue, BinaryBitShiftRightOperator.Instance); break; case SyntaxKind.QuestionQuestionEqualsToken: break; default: throw new ArgumentOutOfRangeException(); } if (assignment != null) { result.Add(assignment); } else { Log.Debug("{Left} {Operator} {Right}", left, operatorToken.Text, right); } break; } case PrefixUnaryExpressionSyntax unaryExpressionSyntax: { var operand = unaryExpressionSyntax.Operand; var leftValue = wandaBlock.ResolveLValue(result, operand, true); AssignmentBase assignment = null; var operatorToken = unaryExpressionSyntax.OperatorToken; switch (operatorToken.Kind()) { case SyntaxKind.PlusToken: case SyntaxKind.MinusToken: case SyntaxKind.TildeToken: case SyntaxKind.ExclamationToken: break; case SyntaxKind.PlusPlusToken: assignment = new OperatorAssignment(leftValue, IntegerLiteral.One, BinaryAddOperator.Instance); break; case SyntaxKind.MinusMinusToken: assignment = new OperatorAssignment(leftValue, IntegerLiteral.One, BinarySubtractOperator.Instance); break; case SyntaxKind.AmpersandToken: case SyntaxKind.AsteriskToken: case SyntaxKind.CaretToken: break; default: throw new ArgumentOutOfRangeException(); } if (assignment != null) { result.Add(assignment); } else { Log.Debug("{Operator} {Right}", operatorToken.Text, unaryExpressionSyntax.Operand); } break; } case PostfixUnaryExpressionSyntax unaryExpressionSyntax: { var operand = unaryExpressionSyntax.Operand; var leftValue = wandaBlock.ResolveLValue(result, operand, true); AssignmentBase assignment = null; var operatorToken = unaryExpressionSyntax.OperatorToken; switch (operatorToken.Kind()) { case SyntaxKind.PlusPlusToken: assignment = new OperatorAssignment(leftValue, IntegerLiteral.One, BinaryAddOperator.Instance); break; case SyntaxKind.MinusMinusToken: assignment = new OperatorAssignment(leftValue, IntegerLiteral.One, BinarySubtractOperator.Instance); break; case SyntaxKind.ExclamationToken: break; default: throw new ArgumentOutOfRangeException(); } if (assignment != null) { // todo: that's not right. The value returned by expression is not as simple result.Add(assignment); } else { Log.Debug("{Left} {Operator}", unaryExpressionSyntax.Operand, operatorToken.Text); } break; } case InvocationExpressionSyntax invocationExpressionSyntax: { var what = invocationExpressionSyntax.Expression.ToString(); FunctionCallParameter Selector(ArgumentSyntax x) { var xRefKindKeyword = x.RefKindKeyword.Kind(); var(isRef, isOut) = ( xRefKindKeyword == SyntaxKind.RefKeyword, xRefKindKeyword == SyntaxKind.OutKeyword); return(new FunctionCallParameter { Value = wandaBlock.ResolveValue(result, x.Expression, true), Out = isOut, Ref = isRef }); } var with = invocationExpressionSyntax.ArgumentList.Arguments.Select(Selector); var functionCallOperator = new FunctionCallOperator { Name = what }; functionCallOperator.Arguments.AddRange(with); result.Add(functionCallOperator); break; } case IdentifierNameSyntax identifierNameSyntax: { result.Add(wandaBlock.ResolveVariableByName(identifierNameSyntax.Identifier.Text)); break; } case LiteralExpressionSyntax literalExpressionSyntax: { result.Add(ResolveLiteral(literalExpressionSyntax)); break; } case ElementAccessExpressionSyntax elementAccessExpressionSyntax: { result.Add( ResolveRoslynElementAccessExpressionToWandaOperator(elementAccessExpressionSyntax, result, wandaBlock)); break; } case BinaryExpressionSyntax binaryExpressionSyntax: { var operatorToken = binaryExpressionSyntax.OperatorToken; PureBase operatorBase = null; LogicBase logicBase = null; switch (operatorToken.Kind()) { case SyntaxKind.PlusToken: operatorBase = BinaryAddOperator.Instance; break; case SyntaxKind.MinusToken: operatorBase = BinarySubtractOperator.Instance; break; case SyntaxKind.AsteriskToken: operatorBase = BinaryMultiplyOperator.Instance; break; case SyntaxKind.SlashToken: operatorBase = BinaryDivideOperator.Instance; break; case SyntaxKind.PercentToken: operatorBase = BinaryRemainderOperator.Instance; break; case SyntaxKind.LessThanLessThanToken: operatorBase = BinaryBitShiftLeftOperator.Instance; break; case SyntaxKind.GreaterThanGreaterThanToken: operatorBase = BinaryBitShiftRightOperator.Instance; break; case SyntaxKind.BarBarToken: logicBase = OrLogic.Instance; break; case SyntaxKind.AmpersandAmpersandToken: logicBase = AndLogic.Instance; break; case SyntaxKind.BarToken: operatorBase = BinaryBitOrOperator.Instance; break; case SyntaxKind.AmpersandToken: operatorBase = BinaryBitAndOperator.Instance; break; case SyntaxKind.CaretToken: operatorBase = BinaryBitXorOperator.Instance; break; case SyntaxKind.EqualsEqualsToken: logicBase = EqualLogic.Instance; break; case SyntaxKind.ExclamationEqualsToken: logicBase = NotEqualLogic.Instance; break; case SyntaxKind.LessThanToken: logicBase = LessLogic.Instance; break; case SyntaxKind.LessThanEqualsToken: logicBase = LessOrEqualLogic.Instance; break; case SyntaxKind.GreaterThanToken: logicBase = GreaterLogic.Instance; break; case SyntaxKind.GreaterThanEqualsToken: logicBase = GreaterOrEqualLogic.Instance; break; case SyntaxKind.IsKeyword: case SyntaxKind.AsKeyword: case SyntaxKind.QuestionQuestionToken: break; default: throw new ArgumentOutOfRangeException(); } switch (operatorBase != null, logicBase != null) { case (true, false): { var left = wandaBlock.ResolveValue(result, binaryExpressionSyntax.Left, true); var right = wandaBlock.ResolveValue(result, binaryExpressionSyntax.Right, true); var dummy = new DummyVariable { TypeRef = ApproximateResultTypeOfBinaryOperator(left, right) }; wandaBlock.LocalVariables.Add(dummy); var assignment = new SimpleAssignment(dummy, left); result.Add(assignment); var operatorAssignment = new OperatorAssignment(dummy, right, operatorBase); result.Add(operatorAssignment); break; } case (false, true): { var left = wandaBlock.ResolveValue(result, binaryExpressionSyntax.Left, true); var right = wandaBlock.ResolveValue(result, binaryExpressionSyntax.Right, true); var operatorAssignment = new BinaryLogicExpression(logicBase, left, right); result.Add(operatorAssignment); break; } case (false, false): { Log.Debug("BINARY: {Left} {Operator} {Right} ({Kind})", binaryExpressionSyntax.Left, operatorToken.Text, binaryExpressionSyntax.Right, operatorToken.Kind()); break; } default: throw new ArgumentOutOfRangeException(); } break; }