Beispiel #1
0
        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));
        }
Beispiel #3
0
 private static void ProcessRoslynBlockIntoWandaBlock(BlockSyntax roslynBody,
                                                      SimpleCompoundStatement wandaBlock)
 {
     foreach (var statement in roslynBody.Statements)
     {
         ProcessRoslynStatementIntoWandaBlock(statement, wandaBlock);
     }
 }
Beispiel #4
0
        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);
            }
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
 private static void ProcessRoslynSelectionStatementIntoWandaSelectionStatementBlock(
     StatementSyntax innerStatement,
     SimpleCompoundStatement block)
 {
     if (innerStatement is BlockSyntax blockSyntax)
     {
         ProcessRoslynBlockIntoWandaBlock(blockSyntax, block);
     }
     else
     {
         ProcessRoslynStatementIntoWandaBlock(innerStatement, block);
     }
 }
Beispiel #7
0
        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);
            }
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        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));
 }
Beispiel #14
0
        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));
        }
Beispiel #16
0
        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;
            }