public override void VisitWhileNode(WhileNode w) { var exprTmpName = Gen(w.Expr); var whileHeadLabel = ThreeAddressCodeTmp.GenTmpLabel(); var whileBodyLabel = w.Stat is LabelStatementNode label ? label.Label.Num.ToString() : w.Stat is BlockNode block && block.List.StatChildren[0] is LabelStatementNode labelB ? labelB.Label.Num.ToString() : ThreeAddressCodeTmp.GenTmpLabel(); var exitLabel = ThreeAddressCodeTmp.GenTmpLabel(); Instructions[Instructions.Count - 1].Label = whileHeadLabel; GenCommand("", "ifgoto", exprTmpName, whileBodyLabel, ""); GenCommand("", "goto", exitLabel, "", ""); var instructionIndex = Instructions.Count; w.Stat.Visit(this); Instructions[instructionIndex].Label = whileBodyLabel; GenCommand("", "goto", whileHeadLabel, "", ""); GenCommand(exitLabel, "noop", "", "", ""); }
public override void VisitForNode(ForNode f) { string Id = f.Id.Name; string forHeadLabel = ThreeAddressCodeTmp.GenTmpLabel(); string forBodyLabel = ThreeAddressCodeTmp.GenTmpLabel(); string exitLabel = ThreeAddressCodeTmp.GenTmpLabel(); string fromTmpName = Gen(f.From); GenCommand("", "assign", fromTmpName, "", Id); string toTmpName = Gen(f.To); // Делаем допущение, что for шагает на +1 до границы, не включая ее string condTmpName = ThreeAddressCodeTmp.GenTmpName(); GenCommand(forHeadLabel, "LESS", Id, toTmpName, condTmpName); GenCommand("", "ifgoto", condTmpName, forBodyLabel, ""); GenCommand("", "goto", exitLabel, "", ""); var instructionIndex = Instructions.Count; f.Stat.Visit(this); Instructions[instructionIndex].Label = forBodyLabel; GenCommand("", "PLUS", Id, "1", Id); GenCommand("", "goto", forHeadLabel, "", ""); GenCommand(exitLabel, "noop", "", "", ""); }
public override void VisitIfElseNode(IfElseNode i) { // перевод в трёхадресный код условия var exprTmpName = Gen(i.Expr); var trueLabel = i.TrueStat is LabelStatementNode label ? label.Label.Num.ToString() : i.TrueStat is BlockNode block && block.List.StatChildren[0] is LabelStatementNode labelB ? labelB.Label.Num.ToString() : ThreeAddressCodeTmp.GenTmpLabel(); var falseLabel = ThreeAddressCodeTmp.GenTmpLabel(); GenCommand("", "ifgoto", exprTmpName, trueLabel, ""); // перевод в трёхадресный код false ветки i.FalseStat?.Visit(this); GenCommand("", "goto", falseLabel, "", ""); // перевод в трёхадресный код true ветки var instructionIndex = Instructions.Count; i.TrueStat.Visit(this); Instructions[instructionIndex].Label = trueLabel; GenCommand(falseLabel, "noop", "", "", ""); }
public void Optimization() { // обновление глобальных переменных для корректной работы теста GenTAC(@"var a;"); var expectedTAC = new List <string>() { "1: #t1 = 1 < 2", "7: if #t1 goto L1", "goto L2", "L1: goto 3", "L2: noop", "2: goto 4", "3: a = 0", "4: a = 1", "666: a = False" }; var TAC = new List <Instruction>() { new Instruction("1", "LESS", "1", "2", "#t1"), new Instruction("7", "ifgoto", "#t1", "L1", ""), new Instruction("", "goto", "L2", "", ""), new Instruction("L1", "goto", "3", "", ""), new Instruction("L2", "noop", "", "", ""), new Instruction("2", "goto", "4", "", ""), new Instruction("3", "assign", "0", "", "a"), new Instruction("4", "assign", "1", "", "a"), new Instruction("666", "assign", "False", "", "a") }; ThreeAddressCodeTmp.GenTmpLabel(); // L1 ThreeAddressCodeTmp.GenTmpLabel(); // L2 ThreeAddressCodeTmp.GenTmpName(); // #t1 var expected = new List <string>() { "1: #t1 = 1 < 2", "7: #t2 = !#t1", "if #t2 goto L2", "goto 3", "L2: noop", "2: goto 4", "3: a = 0", "4: a = 1", "666: a = False" }; //CollectionAssert.AreEqual(TAC.Select(instruction => instruction.ToString()), expectedTAC); var optimizations = new List <Optimization> { ThreeAddressCodeRemoveGotoThroughGoto.RemoveGotoThroughGoto }; var actual = ThreeAddressCodeOptimizer.Optimize(TAC, allCodeOptimizations: optimizations) .Select(instruction => instruction.ToString()).ToList(); CollectionAssert.AreEqual(expected, actual); }
public void WithoutOptimizationCorrectIf() { GenTAC(@"var a;"); // // instructions aren't changed var expectedTAC = new List <string>() { "1: #t1 = 1 < 2", "if #t1 goto L1", "goto 4", "a = 5 * 6", "L1: #t2 = 5 * 6", "#t3 = 4 + #t2", "a = #t3", "L2: noop" }; var TAC = new List <Instruction>() { new Instruction("1", "LESS", "1", "2", "#t1"), new Instruction("", "ifgoto", "#t1", "L1", ""), new Instruction("", "goto", "4", "", ""), new Instruction("", "MULT", "5", "6", "a"), new Instruction("L1", "MULT", "5", "6", "#t2"), new Instruction("", "PLUS", "4", "#t2", "#t3"), new Instruction("", "assign", "#t3", "", "a"), new Instruction("L2", "noop", "", "", "") }; ThreeAddressCodeTmp.GenTmpLabel(); // L1 ThreeAddressCodeTmp.GenTmpLabel(); // L2 ThreeAddressCodeTmp.GenTmpName(); // #t1 ThreeAddressCodeTmp.GenTmpName(); // #t2 ThreeAddressCodeTmp.GenTmpName(); // #t3 var expected = new List <string>() { "1: #t1 = 1 < 2", "if #t1 goto L1", "goto 4", "a = 5 * 6", "L1: #t2 = 5 * 6", "#t3 = 4 + #t2", "a = #t3", "L2: noop" }; //CollectionAssert.AreEqual(TAC.Select(instruction => instruction.ToString()), expectedTAC); var optimizations = new List <Optimization> { ThreeAddressCodeRemoveGotoThroughGoto.RemoveGotoThroughGoto }; var actual = ThreeAddressCodeOptimizer.Optimize(TAC, optimizations) .Select(instruction => instruction.ToString()); CollectionAssert.AreEqual(expected, actual); }
public override void VisitIfElseNode(IfElseNode i) { string endLabel, exprTmpName; if (i.FalseStat == null) { var wasInverted = InvertIfExpression(i); exprTmpName = Gen(i.Expr); endLabel = GenEndLabel(i); if (wasInverted) { GenCommand("", "ifgoto", exprTmpName, endLabel, ""); } else { var tmpVar = ThreeAddressCodeTmp.GenTmpName(); GenCommand("", "assign", $"!{exprTmpName}", "", tmpVar); GenCommand("", "ifgoto", tmpVar, endLabel, ""); } i.TrueStat.Visit(this); } else { exprTmpName = Gen(i.Expr); var trueLabel = i.TrueStat is LabelStatementNode label ? label.Label.Num.ToString(CultureInfo.InvariantCulture) : i.TrueStat is BlockNode block && block.List.StatChildren[0] is LabelStatementNode labelB ? labelB.Label.Num.ToString(CultureInfo.InvariantCulture) : ThreeAddressCodeTmp.GenTmpLabel(); GenCommand("", "ifgoto", exprTmpName, trueLabel, ""); i.FalseStat.Visit(this); endLabel = GenEndLabel(i); GenCommand("", "goto", endLabel, "", ""); var instructionIndex = Instructions.Count; i.TrueStat.Visit(this); Instructions[instructionIndex].Label = trueLabel; } if (endLabel.StartsWith("L", System.StringComparison.Ordinal)) { GenCommand(endLabel, "noop", "", "", ""); } }
public void WithoutOptimizationIncorrectIf() { GenTAC(@"var a;"); // // нет false ветки и соотв. goto var expectedTAC = new List <string>() { "1: #t1 = 1 < 2", "if #t1 goto L1", "L1: goto 3", "a = 5 * 6", "L2: noop" }; var TAC = new List <Instruction>() { new Instruction("1", "LESS", "1", "2", "#t1"), new Instruction("", "ifgoto", "#t1", "L1", ""), new Instruction("L1", "goto", "3", "", ""), new Instruction("", "MULT", "5", "6", "a"), new Instruction("L2", "noop", "", "", "") }; ThreeAddressCodeTmp.GenTmpLabel(); // L1 ThreeAddressCodeTmp.GenTmpLabel(); // L2 ThreeAddressCodeTmp.GenTmpName(); // #t1 var expected = new List <string>() { "1: #t1 = 1 < 2", "if #t1 goto L1", "L1: goto 3", "a = 5 * 6", "L2: noop" }; //CollectionAssert.AreEqual(TAC.Select(instruction => instruction.ToString()), expectedTAC); var optimizations = new List <Optimization> { ThreeAddressCodeRemoveGotoThroughGoto.RemoveGotoThroughGoto }; var actual = ThreeAddressCodeOptimizer.Optimize(TAC, allCodeOptimizations: optimizations) .Select(instruction => instruction.ToString()); CollectionAssert.AreEqual(expected, actual); }
public override void VisitWhileNode(WhileNode w) { string exprTmpName = Gen(w.Expr); string whileHeadLabel = ThreeAddressCodeTmp.GenTmpLabel(); string whileBodyLabel = ThreeAddressCodeTmp.GenTmpLabel(); string exitLabel = ThreeAddressCodeTmp.GenTmpLabel(); Instructions[Instructions.Count - 1].Label = whileHeadLabel; GenCommand("", "ifgoto", exprTmpName, whileBodyLabel, ""); GenCommand("", "goto", exitLabel, "", ""); var instructionIndex = Instructions.Count; w.Stat.Visit(this); Instructions[instructionIndex].Label = whileBodyLabel; GenCommand("", "goto", whileHeadLabel, "", ""); GenCommand(exitLabel, "noop", "", "", ""); }
private static string GenEndLabel(IfElseNode i) { Node parent, curNode; if (i.Parent is LabelStatementNode) { parent = i.Parent.Parent; curNode = i.Parent; } else { parent = i.Parent; curNode = i; } var ifIndex = parent.StatChildren.IndexOf(curNode as StatementNode); return(parent.StatChildren.Count > ifIndex + 1 ? // next statement exists (parent.StatChildren[ifIndex + 1] is LabelStatementNode nextLabelNode) ? // next statement has label nextLabelNode.Label.Num.ToString(CultureInfo.InvariantCulture) : ThreeAddressCodeTmp.GenTmpLabel() : ThreeAddressCodeTmp.GenTmpLabel()); }
public override void VisitWhileNode(WhileNode w) { var numStr = Instructions.Count; var exprTmpName = Gen(w.Expr); var whileHeadLabel = ThreeAddressCodeTmp.GenTmpLabel(); var whileBodyLabel = w.Stat is LabelStatementNode label ? label.Label.Num.ToString(CultureInfo.InvariantCulture) : w.Stat is BlockNode block && block.List.StatChildren[0] is LabelStatementNode labelB ? labelB.Label.Num.ToString(CultureInfo.InvariantCulture) : ThreeAddressCodeTmp.GenTmpLabel(); var exitLabel = ThreeAddressCodeTmp.GenTmpLabel(); // Т.е. условие while() - константа if (numStr == Instructions.Count) { GenCommand("", "noop", "", "", ""); } Instructions[^ 1].Label = whileHeadLabel;
public override void VisitIfElseNode(IfElseNode i) { // перевод в трёхадресный код условия string exprTmpName = Gen(i.Expr); string trueLabel = ThreeAddressCodeTmp.GenTmpLabel(); string falseLabel = ThreeAddressCodeTmp.GenTmpLabel(); GenCommand("", "ifgoto", exprTmpName, trueLabel, ""); // перевод в трёхадресный код false ветки i.FalseStat?.Visit(this); GenCommand("", "goto", falseLabel, "", ""); // перевод в трёхадресный код true ветки var instructionIndex = Instructions.Count; i.TrueStat.Visit(this); Instructions[instructionIndex].Label = trueLabel; GenCommand(falseLabel, "noop", "", "", ""); }
public override void VisitForNode(ForNode f) { var Id = f.Id.Name; var forHeadLabel = ThreeAddressCodeTmp.GenTmpLabel(); var exitLabel = ThreeAddressCodeTmp.GenTmpLabel(); var fromTmpName = Gen(f.From); GenCommand("", "assign", fromTmpName, "", Id); var toTmpName = Gen(f.To); // Делаем допущение, что for шагает на +1 до границы, не включая ее var condTmpName = ThreeAddressCodeTmp.GenTmpName(); GenCommand(forHeadLabel, "EQGREATER", Id, toTmpName, condTmpName); GenCommand("", "ifgoto", condTmpName, exitLabel, ""); f.Stat.Visit(this); GenCommand("", "PLUS", Id, "1", Id); GenCommand("", "goto", forHeadLabel, "", ""); GenCommand(exitLabel, "noop", "", "", ""); }
public override void VisitIfElseNode(IfElseNode i) { var exprTmpName = Gen(i.Expr); var endLabel = string.Empty; if (i.FalseStat == null) { var tmpVar = ThreeAddressCodeTmp.GenTmpName(); GenCommand("", "assign", $"!{exprTmpName}", "", tmpVar); endLabel = ThreeAddressCodeTmp.GenTmpLabel(); GenCommand("", "ifgoto", tmpVar, endLabel, ""); i.TrueStat.Visit(this); } else { var trueLabel = i.TrueStat is LabelStatementNode label ? label.Label.Num.ToString() : i.TrueStat is BlockNode block && block.List.StatChildren[0] is LabelStatementNode labelB ? labelB.Label.Num.ToString() : ThreeAddressCodeTmp.GenTmpLabel(); GenCommand("", "ifgoto", exprTmpName, trueLabel, ""); i.FalseStat.Visit(this); endLabel = ThreeAddressCodeTmp.GenTmpLabel(); GenCommand("", "goto", endLabel, "", ""); var instructionIndex = Instructions.Count; i.TrueStat.Visit(this); Instructions[instructionIndex].Label = trueLabel; } GenCommand(endLabel, "noop", "", "", ""); }