protected override BoundStatement RewriteIfStatement(BoundIfStatement node) { if (node.ElseStatement == null) { // if <condition> // <then> // // ----> // gotoIfFalse <condition> end // <then> // end: var endLabel = GenerateLabel(); var gotoFalse = new BoundConditionalGotoStatement(endLabel, node.Condition, false); var endLabelStatement = new BoundLabelStatement(endLabel); var result = new BoundBlockStatement(ImmutableArray.Create(gotoFalse, node.ThenStatement, endLabelStatement)); return(RewriteStatement(result)); } else { // if <condition> // <then> // else // <else> // // ----> // gotoIfFalse <condition> else // <then> // goto end // else: // <else> // end: var elseLabel = GenerateLabel(); var endLabel = GenerateLabel(); var gotoFalse = new BoundConditionalGotoStatement(elseLabel, node.Condition, false); var gotoEndStatement = new BoundGotoStatement(endLabel); var endLabelStatement = new BoundLabelStatement(endLabel); var elseLabelStatement = new BoundLabelStatement(elseLabel); var result = new BoundBlockStatement(ImmutableArray.Create( gotoFalse, node.ThenStatement, gotoEndStatement, elseLabelStatement, node.ElseStatement, endLabelStatement )); return(RewriteStatement(result)); } }
protected override BoundStatement RewriteDoWhileStatement(BoundDoWhileStatement node) { var continueLabelStmt = new BoundLabelStatement(node.ContinueLabel, node.IsValid); var breakLabelStmt = new BoundLabelStatement(node.BreakLabel, node.IsValid); var gotoContinue = new BoundConditionalGotoStatement(node.ContinueLabel, node.Condition, jumpIfFalse: false, node.IsValid); var res = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( continueLabelStmt, node.Body, gotoContinue, breakLabelStmt ), node.IsValid); return(RewriteStatement(res)); }
protected override BoundStatement RewriteIfStatement(BoundIfStatement node) { /* * gotoIfFalse <condition> end * <Then> * end: * * gotoIfFalse <condition> else * <Then> * goto end * else: * <Else> * end: */ BoundBlockStatement result; if (node.ElseClause is null) { result = Create(); } else { result = CreateWithElse(); } return(RewriteStatement(result)); BoundBlockStatement Create() { var endLabelStatement = new BoundLabelStatement(GenerateLabel()); var gotoIfFalseStatement = new BoundConditionalGotoStatement(endLabelStatement.Label, node.Condition, false); return(new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(gotoIfFalseStatement, node.Statement, endLabelStatement))); } BoundBlockStatement CreateWithElse() { var elseLabelStatement = new BoundLabelStatement(GenerateLabel()); var endLabelStatement = new BoundLabelStatement(GenerateLabel()); var gotoIfFalseStatement = new BoundConditionalGotoStatement(elseLabelStatement.Label, node.Condition, false); var gotoEndStatement = new BoundGotoStatement(endLabelStatement.Label); var statements = ImmutableArray.Create <BoundStatement>(gotoIfFalseStatement, node.Statement, gotoEndStatement, elseLabelStatement, node.ElseClause, endLabelStatement); return(new BoundBlockStatement(statements)); } }
protected override BoundStatement RewriteConditionalGotoStatement(BoundConditionalGotoStatement node) { if (!(node.Condition.Constant is null) && node.Condition.Constant.Value is bool val) { val = node.JumpIfFalse ? !val : val; if (val) { return(new BoundGotoStatement(node.Label, node.IsValid)); } else { return(new BoundNopStatement(node.IsValid)); } } return(base.RewriteConditionalGotoStatement(node)); }
protected override BoundStatement RewriteConditionalGotoStatement(BoundConditionalGotoStatement node) { if (node.Condition.ConstantValue != null) { var condition = (bool)node.Condition.ConstantValue.Value; condition = node.JumpIfTrue ? condition : !condition; if (condition) { return(RewriteStatement(Goto(node.Syntax, node.Label))); } else { return(RewriteStatement(Nop(node.Syntax))); } } return(base.RewriteConditionalGotoStatement(node)); }
protected override BoundStatement RewriteWhileStatement(BoundWhileStatement node) { /* * check: * gotoIfFalse <condition> end * <statement> * goto check * end: */ var checkLabelStatement = new BoundLabelStatement(GenerateLabel()); var endLabelStatement = new BoundLabelStatement(GenerateLabel()); var gotoIfFalseStatement = new BoundConditionalGotoStatement(endLabelStatement.Label, node.Condition, false); var gotoCheckStatement = new BoundGotoStatement(checkLabelStatement.Label); var statements = ImmutableArray.Create <BoundStatement>(checkLabelStatement, gotoIfFalseStatement, node.Statement, gotoCheckStatement, endLabelStatement); var result = new BoundBlockStatement(statements); return(RewriteStatement(result)); }
protected override BoundStatement RewriteDoWhileStatement(BoundDoWhileStatement node) { var bodyLabel = GenerateLabel(); var bodyLabelStatement = new BoundLabelStatement(bodyLabel); var continueLabelStatement = new BoundLabelStatement(node.ContinueLabel); var gotoTrue = new BoundConditionalGotoStatement(bodyLabel, node.Condition); var breakLabelStatement = new BoundLabelStatement(node.BreakLabel); var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( bodyLabelStatement, node.Body, continueLabelStatement, gotoTrue, breakLabelStatement )); return(RewriteStatement(result)); }
protected override BoundStatement RewriteBoundConditionalGotoStatement( BoundConditionalGotoStatement node ) { var constant = ConstantFolding.Fold(node.Condition); if (constant == null) { return(base.RewriteBoundConditionalGotoStatement(node)); } var condition = (bool)constant.Value; var condition2 = node.JumpIfTrue ? condition : !condition; if (condition2) { return(new BoundGotoStatement(node.Syntax, node.BoundLabel)); } return(new BoundNopStatement(node.Syntax)); }
protected override BoundStatement RewriteDoWhileStatement(BoundDoWhileStatement node) { BoundLabel bodyLabel = GenerateLabel(); BoundLabel endLabel = new BoundLabel("End"); BoundLabelStatement bodyLabelStatement = new BoundLabelStatement(bodyLabel); BoundLabelStatement continueLabelStatement = new BoundLabelStatement(node.ContinueLabel); BoundConditionalGotoStatement gotoTrue = new BoundConditionalGotoStatement(bodyLabel, node.Condition, true); BoundLabelStatement breakLabelStatement = new BoundLabelStatement(node.BreakLabel); BoundLabelStatement endLabelStatement = new BoundLabelStatement(endLabel); BoundBlockStatement result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( bodyLabelStatement, node.Body, continueLabelStatement, gotoTrue, breakLabelStatement, endLabelStatement )); return(RewriteStatement(result)); }
protected override BoundStatement RewriteConditionalGotoStatement(BoundConditionalGotoStatement node) { var syntax = node.Syntax; if (node.Condition.ConstantValue != null) { var value = (bool)node.Condition.ConstantValue.Value; var condition = node.JumpIfTrue ? value : !value; if (condition) { return(Goto(syntax, node.Label)); } else { return(new BoundNopStatement(syntax)); } } return(base.RewriteConditionalGotoStatement(node)); }
protected override BoundStatement RewriteWhileStatement(BoundWhileStatement node) { // goto check: // continue: // <body> // check: // gotoTrue condition continue: // end: // ------------------------------------------------------- // later try out //- begin //- gotoFalse <condition> end //- <body> //- goto begin //- end var endLabel = GenerateLabel(); var checkLabel = GenerateLabel(); var continueLabel = GenerateLabel(); var gotoCheck = new BoundGotoStatement(checkLabel); var gotoTrue = new BoundConditionalGotoStatement(continueLabel, node.Condition); var continueLabelStatement = new BoundLabelStatement(continueLabel); var checkLabelStatement = new BoundLabelStatement(checkLabel); var endLabelStatement = new BoundLabelStatement(endLabel); var result = new BoundBlockStatement( ImmutableArray.Create <BoundStatement>( gotoCheck, continueLabelStatement, node.Body, checkLabelStatement, gotoTrue, endLabelStatement)); return(RewriteStatement(result)); }
protected override BoundStatement RewriteWhileStatement(BoundWhileStatement node) { // while <condition> // <body> // // -----> // // goto continue // body: // <body> // continue: // gotoTrue <condition> body // break: // var bodyLabel = GenerateLabel(); var gotoContinue = new BoundGotoStatement(node.ContinueLabel); var bodyLabelStatement = new BoundLabelStatement(bodyLabel); var continueLabelStatement = new BoundLabelStatement(node.ContinueLabel); var gotoTrue = new BoundConditionalGotoStatement(bodyLabel, node.Condition); var breakLabelStatement = new BoundLabelStatement(node.BreakLabel); var result = new BoundBlockStatement( ImmutableArray.Create <BoundStatement>( gotoContinue, bodyLabelStatement, node.Body, continueLabelStatement, gotoTrue, breakLabelStatement ) ); return(RewriteStatement(result)); }
protected override BoundStatement RewriteWhileStatement(BoundWhileStatement node) { // while <condition> // <bode> // // -----> // // goto check // continue: // <body> // check: // gotoTrue <condition> continue // end: // var continueLabel = GenerateLabel(); var checkLabel = GenerateLabel(); var endLabel = GenerateLabel(); var gotoCheck = new BoundGotoStatement(checkLabel); var continueLabelStatement = new BoundLabelStatement(continueLabel); var checkLabelStatement = new BoundLabelStatement(checkLabel); var gotoTrue = new BoundConditionalGotoStatement(continueLabel, node.Condition); var endLabelStatement = new BoundLabelStatement(endLabel); var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( gotoCheck, continueLabelStatement, node.Body, checkLabelStatement, gotoTrue, endLabelStatement )); return(RewriteStatement(result)); }
protected override BoundStatement RewriteIfStatement(BoundIfStatement node) { if (node.ElseStatement == null) { var endLabel = GenerateLabel(); var gotoFalse = new BoundConditionalGotoStatement(endLabel, node.Condition, true); var endLabelStatement = new BoundLabelStatement(endLabel); var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(gotoFalse, node.Statement, endLabelStatement)); return(RewriteStatement(result)); } else { var elseLabel = GenerateLabel(); var endLabel = GenerateLabel(); var gotoFalse = new BoundConditionalGotoStatement(elseLabel, node.Condition, true); var gotoEnd = new BoundGotoStatement(endLabel); var elseLabelStatement = new BoundLabelStatement(elseLabel); var endLabelStatement = new BoundLabelStatement(endLabel); var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( gotoFalse, node.Statement, gotoEnd, elseLabelStatement, node.ElseStatement, endLabelStatement)); return(RewriteStatement(result)); } }
private void EmitConditionalGotoStatement(ILProcessor ilProcessor, BoundConditionalGotoStatement node) { throw new NotImplementedException(); }
protected override BoundStatement RewriteForStatement(BoundForStatement node) { /* * * for <decl>, <condition>, <increment> { * <body> * } * * * -----> * * { * <decl> * while <condition>{ * <body> * continue: * <increment> * } * break: * } * * * -----> * * * <decl> * goto check * body: * <body> * continue: * <increment> * check: * goto body if <condtiton> * break: */ var decl = node.VariableDeclaration; var increment = new BoundExpressionStatement(node.Increment, node.IsValid, true); var body = node.Body; var condition = node.Condition; var bodyLabel = CreateLabel(); var continueLabel = node.ContinueLabel; var checkLabel = CreateLabel(); var breakLabel = node.BreakLabel; var bodyLabelStmt = new BoundLabelStatement(bodyLabel, node.IsValid); var continueLabelStmt = new BoundLabelStatement(continueLabel, node.IsValid); var checkLabelStmt = new BoundLabelStatement(checkLabel, node.IsValid); var breakLabelStmt = new BoundLabelStatement(breakLabel, node.IsValid); var gotoCheck = new BoundGotoStatement(checkLabel, node.IsValid); var gotoTrueBody = new BoundConditionalGotoStatement(bodyLabel, node.Condition, jumpIfFalse: false, node.IsValid); var res = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( decl, gotoCheck, bodyLabelStmt, body, continueLabelStmt, increment, checkLabelStmt, gotoTrueBody, breakLabelStmt ), node.IsValid); return(RewriteStatement(res)); }
private object EvaluateStatement(BoundBlockStatement body) { var labelToIndex = new Dictionary <BoundLabel, int>(); for (int i = 0; i < body.Statements.Length; i++) { if (body.Statements[i] is BoundLabelStatement l) { labelToIndex.Add(l.Label, i + 1); } } int index = 0; while (index < body.Statements.Length) { BoundStatement s = body.Statements[index]; switch (s.Kind) { case BoundNodeKind.VariableDeclaration: EvaluateVariableDeclaration((BoundVariableDeclaration)s); index++; break; case BoundNodeKind.ExpressionStatement: EvaluateExpressionStatement((BoundExpressionStatement)s); index++; break; case BoundNodeKind.GotoStatement: BoundGotoStatement gs = (BoundGotoStatement)s; index = labelToIndex[gs.Label]; break; case BoundNodeKind.ConditionalGotoStatement: BoundConditionalGotoStatement cgs = (BoundConditionalGotoStatement)s; bool condition = (bool)EvaluateExpression(cgs.Condition); if (condition == cgs.JumpIfTrue) { index = labelToIndex[cgs.Label]; } else { index++; } break; case BoundNodeKind.LabelStatement: index++; break; case BoundNodeKind.ReturnStatement: BoundReturnStatement rs = (BoundReturnStatement)s; lastValue = rs.Expression == null ? null : EvaluateExpression(rs.Expression); return(lastValue); default: throw new Exception($"Unexpected node <{s.Kind}>"); } } return(lastValue); }
/// <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 WriteBoundConditionalGotoStatement(this IndentedTextWriter writer, BoundConditionalGotoStatement node) { writer.WriteMagentaKeyword("goto"); writer.WriteSpace(); writer.ColorWrite(node.Label.Identifier); writer.WriteSpace(); if (node.JumpIfFalse) { writer.WriteMagentaKeyword("unless"); } else { writer.WriteMagentaKeyword("if"); } writer.WriteSpace(); writer.WriteBoundNode(node.Condition); }
public virtual void VisitConditionalGotoStatement(BoundConditionalGotoStatement node) => this.DefaultVisit(node);