Esempio n. 1
0
        string Gen(ExprNode ex)
        {
            if (ex.GetType() == typeof(BinOpNode))
            {
                var    bin       = (BinOpNode)ex;
                string argument1 = Gen(bin.Left);
                string argument2 = Gen(bin.Right);
                string result    = ThreeAddressCodeTmp.GenTmpName();
                GenCommand("", bin.Op.ToString(), argument1, argument2, result);
                return(result);
            }
            else if (ex.GetType() == typeof(IdNode))
            {
                var id = (IdNode)ex;
                return(id.Name);
            }
            else if (ex.GetType() == typeof(IntNumNode))
            {
                var id = (IntNumNode)ex;
                return(id.Num.ToString());
            }
            else if (ex.GetType() == typeof(BoolValNode))
            {
                var bl = (BoolValNode)ex;
                return(bl.Val.ToString());
            }

            return(null);
        }
Esempio n. 2
0
        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", "", "", "");
        }
Esempio n. 3
0
        private string Gen(ExprNode ex)
        {
            if (ex is BinOpNode binOp)
            {
                var argument1 = Gen(binOp.Left);
                var argument2 = Gen(binOp.Right);
                var result    = ThreeAddressCodeTmp.GenTmpName();
                GenCommand("", binOp.Op.ToString(), argument1, argument2, result);
                return(result);
            }
            else if (ex is UnOpNode unOp)
            {
                var argument1 = Gen(unOp.Expr);
                var result    = ThreeAddressCodeTmp.GenTmpName();
                GenCommand("", unOp.Op.ToString(), argument1, "", result);
                return(result);
            }
            else if (ex is IdNode id)
            {
                return(id.Name);
            }
            else if (ex is IntNumNode intNum)
            {
                return(intNum.Num.ToString());
            }
            else if (ex is BoolValNode bl)
            {
                return(bl.Val.ToString());
            }

            return(null);
        }
Esempio n. 4
0
        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", "", "", "");
        }
Esempio n. 5
0
        internal static (string str, IReadOnlyList <Instruction> instructions) GetTACWithOpt(
            Parser parser, List <int> lstCheck)
        {
            ThreeAddressCodeTmp.ResetTmpLabel();
            ThreeAddressCodeTmp.ResetTmpName();
            var threeAddrCodeVisitor = new ThreeAddrGenVisitor();

            parser.root.Visit(threeAddrCodeVisitor);
            var threeAddressCode = threeAddrCodeVisitor.Instructions;


            if (lstCheck.Count > 0)
            {
                List <Optimization> bBlOpt = new List <Optimization>(),
                                    allCodeOpt = new List <Optimization>(), allAllOpt = new List <Optimization>();
                var numPos = BasicBlockOptimizations.Count;
                var numPosFalse = BasicBlockOptimizations.Count + AllCodeOptimizations.Count;

                foreach (var n in lstCheck.TakeWhile(x => x < numPos))
                {
                    bBlOpt.Add(BasicBlockOptimizations[n]);
                    allAllOpt.Add(BasicBlockOptimizations[n]);
                }

                foreach (var n in lstCheck.SkipWhile(x => x < numPos).TakeWhile(x => x < numPosFalse))
                {
                    allCodeOpt.Add(AllCodeOptimizations[n - numPos]);
                    allAllOpt.Add(AllCodeOptimizations[n - numPos]);
                }

                var UCE = lstCheck[^ 1] == numPosFalse;
        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 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);
        }
Esempio n. 9
0
        internal static (string str, IReadOnlyList <Instruction> instructions) GetTACWithOpt(
            Parser parser, List <int> lstCheck)
        {
            ThreeAddressCodeTmp.ResetTmpLabel();
            ThreeAddressCodeTmp.ResetTmpName();
            var threeAddrCodeVisitor = new ThreeAddrGenVisitor();

            parser.root.Visit(threeAddrCodeVisitor);
            var threeAddressCode = threeAddrCodeVisitor.Instructions;


            if (lstCheck.Count > 0)
            {
                List <Optimization> bBlOpt = new List <Optimization>(),
                                    allCodeOpt = new List <Optimization>(), allAllOpt = new List <Optimization>();
                var numPos = BasicBlockOptimizations.Count;
                var numPosFalse = BasicBlockOptimizations.Count + AllCodeOptimizations.Count;

                foreach (var n in lstCheck.TakeWhile(x => x < numPos))
                {
                    bBlOpt.Add(BasicBlockOptimizations[n]);
                    allAllOpt.Add(BasicBlockOptimizations[n]);
                }

                foreach (var n in lstCheck.SkipWhile(x => x < numPos).TakeWhile(x => x < numPosFalse))
                {
                    allCodeOpt.Add(AllCodeOptimizations[n - numPos]);
                    allAllOpt.Add(AllCodeOptimizations[n - numPos]);
                }

                var UCE = lstCheck[lstCheck.Count - 1] == numPosFalse;

                var result = ThreeAddressCodeOptimizer.Optimize(threeAddressCode,
                                                                bBlOpt, allCodeOpt, UCE).ToList();

                var strR = new StringBuilder();
                foreach (var x in result)
                {
                    strR.AppendLine(x.ToString());
                }
                return(strR.ToString(), threeAddressCode);
            }

            var str = new StringBuilder();

            foreach (var x in threeAddressCode)
            {
                str.AppendLine(x.ToString());
            }

            return(str.ToString(), threeAddressCode);
        }
        public void OptimizationAfterOtherOptimizations()
        {
            GenTAC(@"var a;");  // для корректной работы теста

            var expectedTAC = new List <string>()
            {
                "input a",
                "1: #t1 = a == 0",
                "#t2 = !#t1",
                "if #t2 goto 2",
                "goto 3",
                "2: a = 2",
                "3: a = 3",
            };

            var TAC = new List <Instruction>()
            {
                new Instruction("", "input", "", "", "a"),
                new Instruction("1", "EQUAL", "a", "0", "#t1"),
                new Instruction("", "NOT", "#t1", "", "#t2"),
                new Instruction("", "ifgoto", "#t2", "2", ""),
                new Instruction("", "goto", "3", "", ""),
                new Instruction("2", "assign", "2", "", "a"),
                new Instruction("3", "assign", "3", "", "a"),
            };

            ThreeAddressCodeTmp.GenTmpName();  // #t1
            ThreeAddressCodeTmp.GenTmpName();  // #t2

            //CollectionAssert.AreEqual(TAC.Select(instruction => instruction.ToString()), expectedTAC);

            var expected = new List <string>()
            {
                "input a",
                "1: #t1 = a == 0",
                "#t2 = !#t1",
                "#t3 = !#t2",
                "if #t3 goto 3",
                "2: a = 2",
                "3: a = 3",
            };

            var optimizations = new List <Optimization> {
                ThreeAddressCodeRemoveGotoThroughGoto.RemoveGotoThroughGoto
            };
            var actual = ThreeAddressCodeOptimizer.Optimize(TAC, allCodeOptimizations: optimizations)
                         .Select(instruction => instruction.ToString()).ToList();

            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);
        }
            private void ChangeInstructionsInGraph()
            {
                var tmpVariable = ThreeAddressCodeTmp.GenTmpName();

                foreach (var(block, numberInstruction, instruction) in listOfPointsInBlock)
                {
                    block.RemoveInstructionByIndex(numberInstruction);
                    block.InsertInstruction(numberInstruction,
                                            new Instruction("", "assign", tmpVariable, "", instruction.Result));
                    block.InsertInstruction(numberInstruction,
                                            new Instruction(instruction.Label, instruction.Operation, instruction.Argument1,
                                                            instruction.Argument2, tmpVariable));
                }
                var targetTemp = targetBlock.GetInstructions()[targetInstructionIndex];

                targetBlock.RemoveInstructionByIndex(targetInstructionIndex);
                targetBlock.InsertInstruction(targetInstructionIndex,
                                              new Instruction(targetTemp.Label, "assign", tmpVariable, "", targetTemp.Result));
            }
Esempio n. 14
0
        protected List <Instruction> GenTAC(string sourceCode)
        {
            ThreeAddressCodeTmp.ResetTmpName();
            ThreeAddressCodeTmp.ResetTmpLabel();
            SymbolTable.vars.Clear();   // oh yeah, all variables are stored in a static dict :D
            var scanner = new Scanner();

            scanner.SetSource(sourceCode, 0);
            var parser = new Parser(scanner);

            parser.Parse();
            var fillParents = new FillParentsVisitor();

            parser.root.Visit(fillParents);
            var threeAddrCodeVisitor = new ThreeAddrGenVisitor();

            parser.root.Visit(threeAddrCodeVisitor);
            return(threeAddrCodeVisitor.Instructions);
        }
        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", "", "", "");
        }
Esempio n. 19
0
        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", "", "", "");
        }
Esempio n. 20
0
        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", "", "", "");
        }