protected override object EvaluateExpression(BoundExpression node) { if (node != null) { BoundLiteralExpression boundLiteralExpression; if ((boundLiteralExpression = (node as BoundLiteralExpression)) == null) { BoundVariableExpression boundVariableExpression; if ((boundVariableExpression = (node as BoundVariableExpression)) == null) { BoundAssignmentExpression boundAssignmentExpression; if ((boundAssignmentExpression = (node as BoundAssignmentExpression)) == null) { BoundUnaryExpression boundUnaryExpression; if ((boundUnaryExpression = (node as BoundUnaryExpression)) == null) { BoundBinaryExpression boundBinaryExpression; if ((boundBinaryExpression = (node as BoundBinaryExpression)) != null) { BoundBinaryExpression j = boundBinaryExpression; return(EvaluateBinaryExpression(j)); } return(null); } return(EvaluateUnaryExpression(boundUnaryExpression)); } return(EvaluateAssignmentExpression(boundAssignmentExpression)); } return(EvaluateVariableExpression(boundVariableExpression)); } return(EvaluateLiteralExpression(boundLiteralExpression)); } return(null); }
protected override BoundStatement RewriteForStatement(BoundForStatement node) { /* * { * let upperBound = <UpperBound> * <variable> = <lowerBound> * while <variable> < <UpperBound> * { * <statement> * <variable> = <variable> + 1 * } * } */ var upperBoundSymbol = new VariableSymbol("upperBound", true, node.UpperBound.Type, true); var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound); var upperBoundExpression = new BoundVariableExpression(upperBoundSymbol); var variableDeclaration = new BoundVariableDeclaration(node.Variable, node.LowerBound); // LowerBound shouldn't be rewriten? var variableExpression = new BoundVariableExpression(node.Variable); var conditionOperator = BoundBinaryOperator.Bind(SyntaxKind.LessToken, TypeSymbol.Int, TypeSymbol.Int); var condition = new BoundBinaryExpression(variableExpression, conditionOperator, upperBoundExpression); // UpperBound shouldn't be rewriten? var incrementOperator = BoundBinaryOperator.Bind(SyntaxKind.PlusToken, node.Variable.Type, TypeSymbol.Int); var increment = new BoundBinaryExpression(variableExpression, incrementOperator, new BoundLiteralExpression(1)); var incrementAssignment = new BoundAssignmentExpression(node.Variable, increment); var incrementStatement = new BoundExpressionStatement(incrementAssignment); var whileBlockStatement = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(node.Statement, incrementStatement)); var whileStatement = new BoundWhileStatement(condition, whileBlockStatement); var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(upperBoundDeclaration, variableDeclaration, whileStatement)); return(RewriteStatement(result)); }
private object EvaluateBinaryExpression(BoundBinaryExpression expression) { object left = EvaluateExpression(expression.LeftExpression); object right = EvaluateExpression(expression.RightExpression); var op = expression.Op; switch (op.OperatorType) { case BinaryOperatorType.Addition: return(OperatorEvaluator.EvaluateAddition(left, right, op)); case BinaryOperatorType.Subtraction: return(OperatorEvaluator.EvaluateSubtraction(left, right, op)); case BinaryOperatorType.Multiplication: return(OperatorEvaluator.EvaluateMultiplication(left, right, op)); case BinaryOperatorType.Division: return(OperatorEvaluator.EvaluateDivision(left, right, op)); case BinaryOperatorType.Power: return(OperatorEvaluator.EvaluatePower(left, right, op)); case BinaryOperatorType.Modulus: return((int)left % (int)right); case BinaryOperatorType.Equality: return(OperatorEvaluator.EvaluateEquality(left, right, op)); case BinaryOperatorType.NegatveEquality: return(!OperatorEvaluator.EvaluateEquality(left, right, op)); case BinaryOperatorType.LogicalAnd: return((bool)left && (bool)right); case BinaryOperatorType.LogicalOr: return((bool)left || (bool)right); case BinaryOperatorType.LogicalXOr: return((bool)left ^ (bool)right); case BinaryOperatorType.GreaterThan: return(OperatorEvaluator.EvaluateGreaterThan(left, right, op)); case BinaryOperatorType.LesserThan: return(OperatorEvaluator.EvaluateLesserThan(left, right, op)); case BinaryOperatorType.StrictGreaterThan: return(OperatorEvaluator.EvaluateStrictGreaterThan(left, right, op)); case BinaryOperatorType.StrinLesserThan: return(OperatorEvaluator.EvaluateStrictLesserThan(left, right, op)); case BinaryOperatorType.Concatonate: return(OperatorEvaluator.EvaluateConcatonation(left, right)); default: throw new Exception("Invalid operator"); } }
private void OutputBinaryExpression(BoundBinaryExpression node, string prefix) { builder.AddFragment(new OutputFragment(prefix, DefaultColour)); Output(node.LeftExpression, string.Empty); builder.AddFragment(new OutputFragment($" {node.Op.TokenText} ", DefaultColour)); Output(node.RightExpression, string.Empty); }
private void EmitLogicalOrExpression(BoundBinaryExpression expression) { Debug.Assert(expression.Kind == TokenKind.Or, "Invalid expression kind."); string trySecondLabel = this.GenerateJumpLabel(); string trueLabel = this.GenerateJumpLabel(); string falseLabel = this.GenerateJumpLabel(); string endLabel = this.GenerateJumpLabel(); TextRange expressionRange = expression.Syntax.Range; this.EmitExpression(expression.Left); this.instructions.Add(new TransientConditionalGoToInstruction(trueLabel, trySecondLabel, expressionRange)); this.instructions.Add(new TransientLabelInstruction(trySecondLabel, expressionRange)); this.EmitExpression(expression.Right); this.instructions.Add(new TransientConditionalGoToInstruction(null, falseLabel, expressionRange)); TextRange endOfOperatorRange = this.instructions.Last().Range; this.instructions.Add(new TransientLabelInstruction(trueLabel, endOfOperatorRange)); this.instructions.Add(new PushValueInstruction(new BooleanValue(true), endOfOperatorRange)); this.instructions.Add(new TransientUnconditionalGoToInstruction(endLabel, endOfOperatorRange)); this.instructions.Add(new TransientLabelInstruction(falseLabel, endOfOperatorRange)); this.instructions.Add(new PushValueInstruction(new BooleanValue(false), endOfOperatorRange)); this.instructions.Add(new TransientLabelInstruction(endLabel, endOfOperatorRange)); }
protected override BoundStatement RewriteForStatement(BoundForStatement node) { //For Statements are now all While Statements var variableDeclaration = new BoundVariableDeclaration(node.Variable, node.LowerBound); var variableExpression = new BoundVariableExpression(node.Variable); var upperBoundSymbol = new VariableSymbol("upperBound", true, typeof(int)); var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound); var condition = new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, typeof(int), typeof(int)), new BoundVariableExpression(upperBoundSymbol) ); var increment = new BoundExpressionStatement( new BoundAssignmentExpression( node.Variable, new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.PlusToken, typeof(int), typeof(int)), new BoundLiteralExpression(1) ) ) ); var whileBody = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(node.Body, increment)); var whileStatement = new BoundWhileStatement(condition, whileBody); var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( variableDeclaration, upperBoundDeclaration, whileStatement )); return(RewriteStatement(result)); }
private object EvaluateBinaryExpression(BoundBinaryExpression b) { var left = EvaluateExpression(b.Left); var right = EvaluateExpression(b.Right); switch (b.Op.Kind) { case BoundBinaryOperatorKind.Addition: return((int)left + (int)right); case BoundBinaryOperatorKind.Subtraction: return((int)left - (int)right); case BoundBinaryOperatorKind.Multiplication: return((int)left * (int)right); case BoundBinaryOperatorKind.Division: return((int)left / (int)right); case BoundBinaryOperatorKind.LogicalAnd: return((bool)left && (bool)right); case BoundBinaryOperatorKind.LogicalOr: return((bool)left || (bool)right); case BoundBinaryOperatorKind.Equals: return(Equals(left, right)); case BoundBinaryOperatorKind.NotEquals: return(!Equals(left, right)); default: throw new Exception($"Unexpected binary operator {b.Op}"); } }
protected override BoundExpression RewriteBinaryExpression(BoundBinaryExpression expression) { var op = expression.Op; BoundExpression newLeft = RewriteExpression(expression.LeftExpression); BoundExpression newRight = RewriteExpression(expression.RightExpression); if (newLeft.ValueType != newRight.ValueType) { if (TypeConversionSymbol.TryFind(newLeft.ValueType, newRight.ValueType, out var leftConversion)) { newLeft = new BoundInternalTypeConversion(leftConversion, newLeft); } else if (TypeConversionSymbol.TryFind(newRight.ValueType, newLeft.ValueType, out var rightConversion)) { newRight = new BoundInternalTypeConversion(rightConversion, newRight); } } if (newLeft == expression.LeftExpression && newRight == expression.RightExpression) { return(expression); } return(new BoundBinaryExpression(newLeft, op, newRight)); }
protected override BoundExpression RewriteBinaryExpression(BoundBinaryExpression node) { if (!(node.Constant is null)) { return(node); } if (node.Op == BoundBinaryOperator.LogicalAnd) { return(RewriteLogicalAnd(node)); } if (node.Op == BoundBinaryOperator.LogicalOr) { return(RewriteLogicalOr(node)); } var left = RewriteExpression(node.Left); var right = RewriteExpression(node.Right); var leftType = left.ResultType; var rightType = right.ResultType; var oneLiteral = (BoundLiteralExpression?)null; if (node.Op == BoundBinaryOperator.Root) { oneLiteral = new BoundLiteralExpression(1.0d, TypeSymbol.Float, true); } switch (node.Op, leftType.Name, rightType.Name) {
private object Evaluate(BoundBinaryExpression binaryExpression) { var left = EvaluateExpression(binaryExpression.Left); var right = EvaluateExpression(binaryExpression.Right); switch (binaryExpression.Op.Kind) { case BoundBinaryOperatorKind.Addition: return((int)left + (int)right); case BoundBinaryOperatorKind.Subtraction: return((int)left - (int)right); case BoundBinaryOperatorKind.Multiplication: return((int)left * (int)right); case BoundBinaryOperatorKind.Division: return((int)left / (int)right); case BoundBinaryOperatorKind.LessThan: return((int)left < (int)right); case BoundBinaryOperatorKind.LessThanOrEquals: return((int)left <= (int)right); case BoundBinaryOperatorKind.GreaterThan: return((int)left > (int)right); case BoundBinaryOperatorKind.GreaterThanOrEquals: return((int)left >= (int)right); case BoundBinaryOperatorKind.LogicalAnd: return((bool)left && (bool)right); case BoundBinaryOperatorKind.LogicalOr: return((bool)left || (bool)right); case BoundBinaryOperatorKind.Equals: return(Equals(left, right)); case BoundBinaryOperatorKind.NotEquals: return(!Equals(left, right)); case BoundBinaryOperatorKind.BitwiseAnd: return(BitwiseAnd(left, right)); case BoundBinaryOperatorKind.BitwiseOr: return(BitwiseOr(left, right)); case BoundBinaryOperatorKind.BitwiseXor: return(BitwiseXor(left, right)); default: throw new ArgumentOutOfRangeException(nameof(binaryExpression.Op.Kind), binaryExpression.Op.Kind, null); } }
protected override BoundStatement RewriteForStatement(BoundForStatement node) { /* * for <var> = <lower> to <upper> * <body> * * -----> * { * var <var> = <lower> * let upperBound = <upper> * while (<var> <= <upperBound>) * { * <body> * <var> = <var> + 1 * } * } */ // var <var> = <lower> var variableDeclaration = new BoundVariableDeclaration(node.Variable, node.LowerBound); // let upperBound = <upper> var upperBoundSymbol = new VariableSymbol("upperBound", true, TypeSymbol.Int); var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound); // <var> var variableExpression = new BoundVariableExpression(node.Variable); //<var> <= <upperBound> var condition = new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, TypeSymbol.Int, TypeSymbol.Int), new BoundVariableExpression(upperBoundSymbol) ); // <var> = <var> + 1 var increment = new BoundExpressionStatement( new BoundAssignmentExpression( node.Variable, new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int), new BoundLiteralExpression(1) ) ) ); var whileBlock = new BoundBlockStatement(ImmutableArray.Create(node.Body, increment)); var whileStatement = new BoundWhileStatement(condition, whileBlock); var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( variableDeclaration, upperBoundDeclaration, whileStatement)); return(RewriteStatement(result)); }
protected override BoundStatement RewriteForStatement(BoundForStatement node) { // for <var> = <lower> to <upper> // <body> // // ----> // { // var <var> = <lower> // let upperBound = <upper> // while (<var> <= upperBound) // { // <body> // continue: // <var> = <var> + 1 // } // } var variableDeclaration = new BoundVariableDeclaration(node.Variable, node.LowerBound); var variableExpression = new BoundVariableExpression(node.Variable); var upperBoundSymbol = new LocalVariableSymbol("upperBound", true, TypeSymbol.Int); var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound); var condition = new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, TypeSymbol.Int, TypeSymbol.Int), new BoundVariableExpression(upperBoundSymbol) ); var continueLabelStatement = new BoundLabelStatement(node.ContinueLabel); var increment = new BoundExpressionStatement( new BoundAssignmentExpression( node.Variable, new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int), new BoundLiteralExpression(1) ) ) ); var whileBody = new BoundBlockStatement( ImmutableArray.Create <BoundStatement>( node.Body, continueLabelStatement, increment ) ); var whileStatement = new BoundWhileStatement(condition, whileBody, node.BreakLabel, GenerateLabel()); var result = new BoundBlockStatement( ImmutableArray.Create <BoundStatement>( variableDeclaration, upperBoundDeclaration, whileStatement ) ); return(RewriteStatement(result)); }
protected virtual BoundExpression RewriteBinaryExpression(BoundBinaryExpression expression) { var rewritenLeftExpresson = RewriteExpression(expression.LeftExpression); var rewritenRightExpresson = RewriteExpression(expression.RightExpression); if (rewritenLeftExpresson == expression.LeftExpression && rewritenRightExpresson == expression.RightExpression) { return(expression); } return(new BoundBinaryExpression(rewritenLeftExpresson, expression.Op, rewritenRightExpresson)); }
private object EvaluateBinaryExpression(BoundBinaryExpression b) { var left = EvaluateExpression(b.Left); var right = EvaluateExpression(b.Right); switch (b.Operator.Kind) { case BoundBinaryOperatorKind.Addition: return((int)left + (int)right); case BoundBinaryOperatorKind.Subtraction: return((int)left - (int)right); case BoundBinaryOperatorKind.Multiplication: return((int)left * (int)right); case BoundBinaryOperatorKind.Division: return((int)left / (int)right); case BoundBinaryOperatorKind.LogicalAnd: return((bool)left && (bool)right); case BoundBinaryOperatorKind.LogicalOr: return((bool)left || (bool)right); case BoundBinaryOperatorKind.Equal: return(Equals(left, right)); case BoundBinaryOperatorKind.BangEquals: return(!Equals(left, right)); case BoundBinaryOperatorKind.MathmaticalAnd: return((int)left & (int)right); case BoundBinaryOperatorKind.MathmaticalOr: return((int)left | (int)right); case BoundBinaryOperatorKind.LeftShift: return((int)left << (int)right); case BoundBinaryOperatorKind.RIghtShift: return((int)left >> (int)right); case BoundBinaryOperatorKind.BiggerCompare: return((int)left > (int)right); case BoundBinaryOperatorKind.LessCompare: return((int)left < (int)right); default: throw new Exception($"Error: Unexpected Binary Operator <{b.Operator}>"); } }
protected override BoundExpression RewriteBinaryExpression(BoundBinaryExpression node) { var left = IsSimpleNode(node.Left) ? node.Left : CreateTemporary(node.Left); var right = IsSimpleNode(node.Right) ? node.Right : CreateTemporary(node.Right); var @operator = RewriteBinaryOperator(node.Operator); if (node.Left == left && node.Right == right && node.Operator == @operator) { return(node); } return(new BoundBinaryExpression(node.Syntax, left, @operator, right)); }
public override void VisitAssignmentStatement(AssignmentStatement node) { var left = Bind(node.Left) !; var right = Bind(node.Right) !; if (node.Op != null) { // transform 'left op= right' to 'left = left op right' // TODO: this may cause 'left' to be evaluated twice (e.g. function call that returns a reference) right = new BoundBinaryExpression(left, right, node.Op.Value); } stmts !.Add(new BoundAssignmentStatement(left, right)); }
protected override BoundStatement RewriteForToStatement(BoundForToStatement node) { // for <var> = <lower> to <upper> <body> // --- to ---> // { // var <var> = <lower> // let upperBound = <upper> // while <var> <= upperBound // <body> // continue: // <var> = <var> + 1 // } var variableDeclaration = new BoundVariableDeclarationStatement(node.Variable, node.LowerBound); var upperBoundSymbol = new LocalVariableSymbol("upperBound", true, TypeSymbol.Int); var upperBoundDeclaration = new BoundVariableDeclarationStatement(upperBoundSymbol, node.UpperBound); var upperBoundExpression = new BoundVariableExpression(upperBoundSymbol); var condition = new BoundBinaryExpression( new BoundVariableExpression(node.Variable), BoundBinaryOperator.Bind(Lexing.TokenKind.LessOrEquals, TypeSymbol.Int, TypeSymbol.Int), upperBoundExpression); var increment = new BoundExpressionStatement( new BoundAssignmentExpression( node.Variable, new BoundBinaryExpression( new BoundVariableExpression(node.Variable), BoundBinaryOperator.Bind(Lexing.TokenKind.Plus, TypeSymbol.Int, TypeSymbol.Int), new BoundLiteralExpression(1)))); var whileBlock = new BoundBlockStatement( node.Body, increment); var whileStatement = new BoundWhileStatement(condition, whileBlock, node.BreakLabel, node.ContinueLabel); var result = new BoundBlockStatement( variableDeclaration, upperBoundDeclaration, whileStatement); return(RewriteStatement(result)); }
public void TestBinaryExpression() { const int Left = -5, Right = 3; var expr = new BoundBinaryExpression( new BoundIntLiteralExpression(Left), new BoundIntLiteralExpression(Right), BinaryOperator.Add ); var result = Evaluator.Evaluate(expr); Assert.Single(result); Assert.Equal(Left + Right, result[0].AsInt32); }
public override void VisitBinaryExpression(BoundBinaryExpression node) { var op = SyntaxFacts.GetText(node.Operator.SyntaxKind) ?? throw new Exception("Invalid operator"); var precedence = node.Operator.SyntaxKind.GetBinaryOperatorPrecedence() ?? throw new Exception("Invalid operator"); WriteNestedExpression(node.Left, precedence); _writer.Write(" "); _writer.WritePunctuation(op); _writer.Write(" "); WriteNestedExpression(node.Right, precedence); }
protected override object EvaluateExpression(BoundExpression node) { try { BoundLiteralExpression boundLiteralExpression = (BoundLiteralExpression)node; return(EvaluateLiteralExpression(boundLiteralExpression)); } catch { try { BoundVariableExpression boundVariableExpression = (BoundVariableExpression)node; return(EvaluateVariableExpression(boundVariableExpression)); } catch { try { BoundAssignmentExpression boundAssignmentExpression = (BoundAssignmentExpression)node; return(EvaluateAssignmentExpression(boundAssignmentExpression)); } catch { try { BoundUnaryExpression boundUnaryExpression = (BoundUnaryExpression)node; return(EvaluateUnaryExpression(boundUnaryExpression)); } catch { try { BoundBinaryExpression boundBinaryExpression = (BoundBinaryExpression)node; return(EvaluateBinaryExpression(boundBinaryExpression)); } catch { return(null); } } } } } }
protected override BoundStatement RewriteForStatement(BoundForStatement node) { // for <var> = <lower> to <upper> // <body> // // ----> // // { // var <var> = <lower> // while (<var> <= <upper>) // { // <body> // <var> = <var> + 1 // } // } var variableDeclaration = new BoundVeriableDeclaration(node.Variable, node.LowerBound); var variableExpression = new BoundVariableExpression(node.Variable); var upperBoundSybmle = new VariableSymble("upperBound", true, typeof(int)); var upperBoundDeclaration = new BoundVeriableDeclaration(upperBoundSybmle, node.UpperBound); var condition = new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualToken, typeof(int), typeof(int)), new BoundVariableExpression(upperBoundSybmle) ); var increment = new BoundExpressionStatemnet( new BoundAssignmentExpression( node.Variable, new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.PlusToken, typeof(int), typeof(int)), new BoundLiteralExpression(1) ) ) ); var whileBody = new BoundBlockStatemnet(ImmutableArray.Create <BoundStatement>(node.Body, increment)); var whileStatement = new BoundWhileStatement(condition, whileBody); var result = new BoundBlockStatemnet(ImmutableArray.Create <BoundStatement>( variableDeclaration, upperBoundDeclaration, whileStatement)); return(RewriteStatement(result)); }
private void EmitBinaryExpression(ILProcessor ilProcessor, BoundBinaryExpression node) { if (node.Op.Kind == BoundBinaryOperatorKind.Addition) { if (node.Left.Type == TypeSymbol.String && node.Right.Type == TypeSymbol.String) { EmitExpression(ilProcessor, node.Left); EmitExpression(ilProcessor, node.Right); ilProcessor.Emit(OpCodes.Call, _stringConcatReference); } else { throw new NotImplementedException(); } } else { throw new NotImplementedException(); } }
protected override BoundStatement RewriteForStatement(BoundForStatement node) { // for <var> = <lower> to <upper> // <body> // is rewritten to // { // var <Var> = <lower> // while () // var variableDeclaration = new BoundVariableDeclaration(node.Variable, node.LowerBound); var variableExpression = new BoundVariableExpression(node.Variable); var condition = new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, typeof(int), typeof(int)), node.UpperBound); var increment = new BoundExpressionStatement( new BoundAssignmentExpression( node.Variable, new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind( SyntaxKind.PlusToken, typeof(int), typeof(int)), new BoundLiteralExpression(1) ) ) ); var whileBlock = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(node.Body, increment)); var whileStatement = new BoundWhileStatement(condition, whileBlock); var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(variableDeclaration, whileStatement)); return(RewriteStatement(result)); }
protected override BoundStatement RewriteForStatement(BoundForStatement node) { BoundVariableDeclaration variableDeclaration = new BoundVariableDeclaration(node.Variable, node.LowerBound); BoundVariableExpression variableExpression = new BoundVariableExpression(node.Variable); VariableSymbol upperVariableSymbol = new LocalVariableSymbol("upperBound", true, TypeSymbol.Int); BoundVariableDeclaration upperVariableDeclaration = new BoundVariableDeclaration(upperVariableSymbol, node.UpperBound); BoundBinaryExpression condition = new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, TypeSymbol.Int, TypeSymbol.Int), new BoundVariableExpression(upperVariableSymbol) ); BoundLabelStatement continueLabelStatement = new BoundLabelStatement(node.ContinueLabel); BoundExpressionStatement increment = new BoundExpressionStatement( new BoundAssignmentExpression( node.Variable, new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int), new BoundLiteralExpression(1) ) ) ); BoundBlockStatement whileBody = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( node.Body, continueLabelStatement, increment )); BoundWhileStatement whileStatement = new BoundWhileStatement(condition, whileBody, node.BreakLabel, GenerateLabel()); BoundBlockStatement result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( variableDeclaration, upperVariableDeclaration, whileStatement )); return(RewriteStatement(result)); }
public override void VisitRepeatStatement(RepeatStatement node) { // reduce REPEAT statement to a WHILE statement /* REPEAT n i * block * ENDREPEAT * * i = 0 * WHILE i < n * block * i = i + 1 * ENDWHILE */ var boundLimit = Bind(node.Limit) !; var boundCounter = Bind(node.Counter) !; // i = 0 var zeroCounter = new BoundAssignmentStatement(boundCounter, new BoundIntLiteralExpression(0)); stmts !.Add(zeroCounter); // WHILE i < n var condition = new BoundBinaryExpression(boundCounter, boundLimit, BinaryOperator.Less); var boundWhile = new BoundWhileStatement(condition); stmts !.Add(boundWhile); VisitScope(node.Block, boundWhile.Block); // i = i + 1 var add = new BoundBinaryExpression(boundCounter, new BoundIntLiteralExpression(1), BinaryOperator.Add); var assign = new BoundAssignmentStatement(boundCounter, add); boundWhile.Block.Add(assign); }
private void EmitBinaryExpression(BoundBinaryExpression expression) { BaseInstruction binaryInstruction; switch (expression.Kind) { case TokenKind.Or: this.EmitLogicalOrExpression(expression); return; case TokenKind.And: this.EmitLogicalAndExpression(expression); return; case TokenKind.Equal: binaryInstruction = new EqualInstruction(expression.Syntax.Range); break; case TokenKind.NotEqual: binaryInstruction = new NotEqualInstruction(expression.Syntax.Range); break; case TokenKind.LessThan: binaryInstruction = new LessThanInstruction(expression.Syntax.Range); break; case TokenKind.LessThanOrEqual: binaryInstruction = new LessThanOrEqualInstruction(expression.Syntax.Range); break; case TokenKind.GreaterThan: binaryInstruction = new GreaterThanInstruction(expression.Syntax.Range); break; case TokenKind.GreaterThanOrEqual: binaryInstruction = new GreaterThanOrEqualInstruction(expression.Syntax.Range); break; case TokenKind.Plus: binaryInstruction = new AddInstruction(expression.Syntax.Range); break; case TokenKind.Minus: binaryInstruction = new SubtractInstruction(expression.Syntax.Range); break; case TokenKind.Multiply: binaryInstruction = new MultiplyInstruction(expression.Syntax.Range); break; case TokenKind.Divide: binaryInstruction = new DivideInstruction(expression.Syntax.Range); break; default: throw ExceptionUtilities.UnexpectedValue(expression.Kind); } this.EmitExpression(expression.Left); this.EmitExpression(expression.Right); this.instructions.Add(binaryInstruction); }
private object EvaluateBinaryExpression(BoundBinaryExpression bt) { var left = EvaluateExpression(bt.Left); var right = EvaluateExpression(bt.Right); switch (bt.Op.Kind) { case BoundBinaryOperatorKind.Addition: return((int)left + (int)right); case BoundBinaryOperatorKind.Subtraction: return((int)left - (int)right); case BoundBinaryOperatorKind.Multiplication: return((int)left * (int)right); case BoundBinaryOperatorKind.Division: return((int)left / (int)right); case BoundBinaryOperatorKind.BitwiseAnd: if (bt.Left.Type == typeof(int)) { return((int)left & (int)right); } else { return((bool)left & (bool)right); } case BoundBinaryOperatorKind.BitwiseOr: if (bt.Left.Type == typeof(int)) { return((int)left | (int)right); } else { return((bool)left | (bool)right); } case BoundBinaryOperatorKind.BitwiseXor: if (bt.Left.Type == typeof(int)) { return((int)left ^ (int)right); } else { return((bool)left ^ (bool)right); } case BoundBinaryOperatorKind.LogicalAnd: return((bool)left && (bool)right); case BoundBinaryOperatorKind.LogicalOr: return((bool)left || (bool)right); case BoundBinaryOperatorKind.Equals: return(Equals(left, right)); case BoundBinaryOperatorKind.NotEquals: return(!Equals(left, right)); case BoundBinaryOperatorKind.Less: return((int)left < (int)right); case BoundBinaryOperatorKind.LessOrEquals: return((int)left <= (int)right); case BoundBinaryOperatorKind.Greater: return((int)left > (int)right); case BoundBinaryOperatorKind.GreaterOrEquals: return((int)left >= (int)right); default: throw new Exception($"Expected a binary operator {bt.Op.Kind}"); } }
private object EvaluateBinaryExpression(BoundBinaryExpression b) { var left = EvaluateExpression(b.Left); var right = EvaluateExpression(b.Right); switch (b.Op.Kind) { case BoundBinaryOperatorKind.Addition: return((int)left + (int)right); case BoundBinaryOperatorKind.Subtraction: return((int)left - (int)right); case BoundBinaryOperatorKind.Multiplication: return((int)left * (int)right); case BoundBinaryOperatorKind.Division: return((int)left / (int)right); case BoundBinaryOperatorKind.BitwiseAnd: if (b.Type == TypeSymbol.Int) { return((int)left & (int)right); } else { return((bool)left & (bool)right); } case BoundBinaryOperatorKind.BitwiseOr: if (b.Type == TypeSymbol.Int) { return((int)left | (int)right); } else { return((bool)left | (bool)right); } case BoundBinaryOperatorKind.BitwiseXOr: if (b.Type == TypeSymbol.Int) { return((int)left ^ (int)right); } else { return((bool)left ^ (bool)right); } case BoundBinaryOperatorKind.LogicalAndAlso: return((bool)left && (bool)right); case BoundBinaryOperatorKind.LogicalOrElse: return((bool)left || (bool)right); case BoundBinaryOperatorKind.Equals: return(Equals(left, right)); case BoundBinaryOperatorKind.NotEquals: return(!Equals(left, right)); case BoundBinaryOperatorKind.LessThan: return((int)left < (int)right); case BoundBinaryOperatorKind.LessThanOrEqual: return((int)left <= (int)right); case BoundBinaryOperatorKind.GreaterThan: return((int)left > (int)right); case BoundBinaryOperatorKind.GreaterThanOrEqual: return((int)left >= (int)right); default: throw new Exception($"Unexpected binary operator {b.Op}"); } }
/// <inheritdoc/> protected override BoundStatement RewriteForEllipsisStatement(BoundForEllipsisStatement node) { // for <var> := <lower> ... <upper> // <body> // // ----> // // { // var <var> = <lower> // const upperBound = <upper> // var step = 1 // if <var> greaterthan upperBound { // step = -1 // } // goto start // body: // <body> // continue: // <var> = <var> + step // start: // gotoTrue ((step > 0 && lower < upper) || (step < 0 && lower > upper)) body // break: // } var variableDeclaration = new BoundVariableDeclaration(node.Variable, node.LowerBound); var upperBoundSymbol = new LocalVariableSymbol("upperBound", isReadOnly: true, type: TypeSymbol.Int); var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound); var stepBoundSymbol = new LocalVariableSymbol("step", isReadOnly: false, type: TypeSymbol.Int); var stepBoundDeclaration = new BoundVariableDeclaration( variable: stepBoundSymbol, initializer: new BoundLiteralExpression(1)); var variableExpression = new BoundVariableExpression(node.Variable); var upperBoundExpression = new BoundVariableExpression(upperBoundSymbol); var stepBoundExpression = new BoundVariableExpression(stepBoundSymbol); var ifLowerIsGreaterThanUpperExpression = new BoundBinaryExpression( left: variableExpression, op: BoundBinaryOperator.Bind(SyntaxKind.GreaterToken, TypeSymbol.Int, TypeSymbol.Int), right: upperBoundExpression); var stepBoundAssingment = new BoundExpressionStatement( expression: new BoundAssignmentExpression( variable: stepBoundSymbol, expression: new BoundLiteralExpression(-1))); var ifLowerIsGreaterThanUpperIfStatement = new BoundIfStatement( condition: ifLowerIsGreaterThanUpperExpression, thenStatement: stepBoundAssingment, elseStatement: null); var startLabel = GenerateLabel(); var gotoStart = new BoundGotoStatement(startLabel); var bodyLabel = GenerateLabel(); var bodyLabelStatement = new BoundLabelStatement(bodyLabel); var continueLabelStatement = new BoundLabelStatement(node.ContinueLabel); var increment = new BoundExpressionStatement( expression: new BoundAssignmentExpression( variable: node.Variable, expression: new BoundBinaryExpression( left: variableExpression, op: BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int), right: stepBoundExpression))); var startLabelStatement = new BoundLabelStatement(startLabel); var zeroLiteralExpression = new BoundLiteralExpression(0); var stepGreaterThanZeroExpression = new BoundBinaryExpression( left: stepBoundExpression, op: BoundBinaryOperator.Bind(SyntaxKind.GreaterToken, TypeSymbol.Int, TypeSymbol.Int), right: zeroLiteralExpression); var lowerLessThanUpperExpression = new BoundBinaryExpression( left: variableExpression, op: BoundBinaryOperator.Bind(SyntaxKind.LessToken, TypeSymbol.Int, TypeSymbol.Int), right: upperBoundExpression); var positiveStepAndLowerLessThanUpper = new BoundBinaryExpression( left: stepGreaterThanZeroExpression, op: BoundBinaryOperator.Bind(SyntaxKind.AmpersandAmpersandToken, TypeSymbol.Bool, TypeSymbol.Bool), right: lowerLessThanUpperExpression); var stepLessThanZeroExpression = new BoundBinaryExpression( left: stepBoundExpression, op: BoundBinaryOperator.Bind(SyntaxKind.LessToken, TypeSymbol.Int, TypeSymbol.Int), right: zeroLiteralExpression); var lowerGreaterThanUpperExpression = new BoundBinaryExpression( left: variableExpression, op: BoundBinaryOperator.Bind(SyntaxKind.GreaterToken, TypeSymbol.Int, TypeSymbol.Int), right: upperBoundExpression); var negativeStepAndLowerGreaterThanUpper = new BoundBinaryExpression( left: stepLessThanZeroExpression, op: BoundBinaryOperator.Bind(SyntaxKind.AmpersandAmpersandToken, TypeSymbol.Bool, TypeSymbol.Bool), right: lowerGreaterThanUpperExpression); var condition = new BoundBinaryExpression( positiveStepAndLowerLessThanUpper, BoundBinaryOperator.Bind(SyntaxKind.PipePipeToken, TypeSymbol.Bool, TypeSymbol.Bool), negativeStepAndLowerGreaterThanUpper); var gotoTrue = new BoundConditionalGotoStatement(bodyLabel, condition, jumpIfTrue: true); var breakLabelStatement = new BoundLabelStatement(node.BreakLabel); var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( variableDeclaration, upperBoundDeclaration, stepBoundDeclaration, ifLowerIsGreaterThanUpperIfStatement, gotoStart, bodyLabelStatement, node.Body, continueLabelStatement, increment, startLabelStatement, gotoTrue, breakLabelStatement)); return(RewriteStatement(result)); }
private static void WriteBoundBinaryExpression(this IndentedTextWriter writer, BoundBinaryExpression node) { writer.ColorWrite("("); writer.WriteBoundNode(node.Left); writer.WriteSpace(); writer.ColorWrite(node.Op.GetText()); writer.WriteSpace(); writer.WriteBoundNode(node.Right); writer.ColorWrite(")"); }