Exemplo n.º 1
0
        public override CodeNode Construct(AASTNode aastNode, CodeNode?parent)
        {
            CodeNode literalNode = new CodeNode(aastNode, parent);

            CodeNode fr0Node = GetFreeRegisterNode(aastNode, literalNode);
            byte     fr0     = fr0Node.ByteToReturn;

            literalNode.Children.AddLast(fr0Node);
            literalNode.ByteToReturn = fr0;

            if (aastNode.AASTValue > 31 || aastNode.AASTValue < 0)
            {
                // FR0 := 0;
                // FR0 := FR0 + node.AASTValue;
                // FR0
                literalNode.Children.AddLast(new CodeNode("Load LDA constant", literalNode)
                                             .Add(GenerateLDC(0, fr0))
                                             .Add(GenerateLDA(fr0, fr0, aastNode.AASTValue)));
            }
            else
            {
                // FR0 := node.AASTValue;
                // FR0
                literalNode.Children.AddLast(new CodeNode("Load LDC constant", literalNode)
                                             .Add(GenerateLDC(aastNode.AASTValue, fr0)));
            }

            return(literalNode);
        }
Exemplo n.º 2
0
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            AASTNode gotoNode = new AASTNode(astNode, parent, SemanticAnalyzer.no_type);

            gotoNode.Children.Add(base.Annotate(astNode.Children[1], gotoNode));
            return(gotoNode);
        }
Exemplo n.º 3
0
        public override CodeNode Construct(AASTNode aastNode, CodeNode?parent)
        {
            Generator g          = Program.currentCompiler.generator;
            CodeNode  asgmntNode = new CodeNode(aastNode, parent);

            Context?ctx = SemanticAnalyzer.FindParentContext(aastNode)
                          ?? throw new CompilationErrorException("No parent context found!!!\r\n  At line " + aastNode.Token.Position.Line);

            // Expression (right-value)
            CodeNode exprNode = base.Construct((AASTNode)aastNode.Children[1], asgmntNode);

            asgmntNode.Children.AddLast(exprNode);
            byte fr0 = exprNode.ByteToReturn;

            // Left-value to be assigned
            CodeNode receiverNode = base.Construct((AASTNode)aastNode.Children[0], asgmntNode);

            asgmntNode.Children.AddLast(receiverNode);
            byte fr1 = receiverNode.ByteToReturn;

            switch (aastNode.Children[0].ASTType)
            {
            case "Primary":     // Array or variable (TODO: dot-notation for structures and modules)
            {
                AASTNode prim = (AASTNode)aastNode.Children[0];
                if (prim.Children[^ 1].ASTType.Equals("IDENTIFIER"))
Exemplo n.º 4
0
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            AASTNode returnNode = new AASTNode(astNode, parent, SemanticAnalyzer.no_type);
            // Check if "return" is in right place - inside the routine body
            ASTNode?parentCopy = returnNode.Parent;

            while (parentCopy != null)
            {
                if (parentCopy.ASTType.Equals("Routine body"))
                {
                    // Perform the rest of checks
                    if (astNode.Children[1].Children[0].Children.Count > 0) // If it has something to return
                    {
                        if (astNode.Children[1].Children[0].Children[0].Children[0].ASTType.Equals("Call"))
                        {
                            returnNode.Children.Add(base.Annotate(astNode.Children[1].Children[0].Children[0], returnNode));
                        }
                        else
                        {
                            returnNode.Children.Add(base.Annotate(astNode.Children[1].Children[0].Children[0].Children[0], returnNode));
                        }
                    }
                    return(returnNode);
                }
                parentCopy = parentCopy.Parent;
            }
            throw new SemanticErrorException(
                      "Return is not in place!!!\r\n" +
                      "  At (Line: " + astNode.Children[0].Token.Position.Line.ToString() + ", " +
                      "Char: " + astNode.Children[0].Token.Position.Char.ToString() + ")."
                      );
        }
 public override CodeNode Construct(AASTNode aastNode, CodeNode?parent)
 {
     return(new CodeNode(aastNode, parent)
     {
         ByteToReturn = Generator.IdentifyRegister(aastNode.Token.Value)
     });
 }
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            AASTNode loop = new AASTNode(astNode, parent, SemanticAnalyzer.no_type);

            loop.Children.Add(base.Annotate(astNode.Children[1], loop));
            return(loop);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Constructs a Code Node that has generated asm commands that deallocates registers (if possible) after given statement has been already constructed.
        /// </summary>
        /// <param name="aastNode">Already constructed statement.</param>
        /// <param name="parent">Parent Code Node</param>
        /// <param name="dependOnStatementNum">Whether we deallocate only those variables that are never appear after given statement
        /// or just to deallocate everything what has been allocated (in current context branch).</param>
        /// <returns>Constructed Code Node with asm commands representing register deallocation.</returns>
        protected CodeNode GetRegisterDeallocationNode(AASTNode aastNode, CodeNode?parent, bool dependOnStatementNum = true)
        {
            Generator g   = Program.currentCompiler.generator;
            Context?  ctx = SemanticAnalyzer.FindParentContext(aastNode);

            if (ctx == null)
            {
                throw new CompilationErrorException("TODO: ");
            }
            CodeNode regDeallocNode = new CodeNode("Register deallocation", parent);

            foreach (string var in g.regAllocVTR.Keys)
            {
                if ((ctx.IsVarDeclared(var) && !dependOnStatementNum || ctx.IsVarDeclaredInThisContext(var) && dependOnStatementNum) &&
                    !ctx.IsVarRoutine(var) && !ctx.IsVarConstant(var) && !ctx.IsVarLabel(var))
                {
                    int liEnd = ctx.GetLIEnd(var);

                    if (liEnd <= aastNode.BlockPosition || !dependOnStatementNum)
                    {
                        byte reg = g.regAllocVTR[var];
                        regDeallocNode.Children.AddLast(GetStoreVariableNode(regDeallocNode, var, reg, ctx));
                        g.regAllocVTR.Remove(var);
                        g.regAllocRTV.Remove(reg);
                        g.FreeReg(reg);
                    }
                }
            }
            return(regDeallocNode);
        }
        public override CodeNode Construct(AASTNode aastNode, CodeNode?parent)
        {
            Context?ctx = aastNode.Context
                          ?? throw new CompilationErrorException("No parent context found!!!\r\n  At line " + aastNode.Token.Position.Line);
            CodeNode bbNode = new CodeNode(aastNode, parent);

            int frameSize = 0; // Frame size (variables, arrays, etc.) in bytes

            foreach (AASTNode variable in ctx.GetDeclaredVars())
            {
                frameSize += variable.AASTType.GetSize();
            }

            // Store where to return FP and move SP further depending on the frame size.
            bbNode.Children.AddLast(new CodeNode("Block body cmds 1", bbNode)
                                    .Add(GenerateST(FP, SP)) // Store where to return
                                    .Add(GenerateMOV(SP, FP))
                                    .Add(GenerateLDA(FP, FP, 4))
                                    .Add(GenerateMOV(FP, SP))
                                    .Add(GenerateLDA(SP, SP, frameSize)));

            foreach (AASTNode statement in aastNode.Children)
            {
                bbNode.Children.AddLast(GetRegisterAllocationNode(statement, bbNode));   // Statement-aware allocation
                bbNode.Children.AddLast(base.Construct(statement, bbNode));              // Statement construction
                bbNode.Children.AddLast(GetRegisterDeallocationNode(statement, bbNode)); // Statement-aware deallocation
            }
            // Final unconditional (statement-unaware) deallocation. Specially for 'for' iterators since they cannot be deallocated in usual way.
            if (aastNode.Children.Count > 0)
            {
                bbNode.Children.AddLast(GetRegisterDeallocationNode((AASTNode)aastNode.Children[^ 1], bbNode, false));
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            // TODO: name of the block body (if we really need it)
            string   bbName = "name";
            AASTNode bb     = new AASTNode(astNode, parent, SemanticAnalyzer.no_type);

            bb.Context = new Context("BlockBody_" + bbName, SemanticAnalyzer.FindParentContext(parent), bb);
            bool   setLIEnd = false;
            string varName  = "";

            if (Program.currentCompiler.semantics.varToAddToCtx != null)
            {
                bb.Context.AddVar(Program.currentCompiler.semantics.varToAddToCtx, Program.currentCompiler.semantics.varToAddToCtx.Token.Value);
                varName  = Program.currentCompiler.semantics.varToAddToCtx.Token.Value;
                setLIEnd = true;
                Program.currentCompiler.semantics.varToAddToCtx = null;
            }
            foreach (ASTNode child in astNode.Children)
            {
                bb.Children.Add(base.Annotate(child, bb));
            }
            if (setLIEnd)
            {
                bb.Context.SetLIEnd(varName, SemanticAnalyzer.GetMaxDepth(bb));
            }
            return(bb);
        }
Exemplo n.º 10
0
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            AASTNode call = new AASTNode(astNode, parent, SemanticAnalyzer.no_type);

            call.Children.Add(base.Annotate(astNode.Children[0], call));
            call.Children.Add(base.Annotate(astNode.Children[1], call));
            return(call);
        }
        public override CodeNode Construct(AASTNode aastNode, CodeNode?parent)
        {
            Generator g        = Program.currentCompiler.generator;
            CodeNode  primNode = new CodeNode(aastNode, parent);
            Context?  ctx      = SemanticAnalyzer.FindParentContext(aastNode)
                                 ?? throw new CompilationErrorException("No parent context found!!!\r\n  At line " + aastNode.Token.Position.Line);

            if (aastNode.Children[^ 1].ASTType.Equals("IDENTIFIER")) // Regular identifier access. TODO: context descend using dot-notation
Exemplo n.º 12
0
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            AASTNode literal = new AASTNode(astNode, parent, SemanticAnalyzer.no_type)
            {
                AASTValue = int.Parse(astNode.Children[1].Token.Value) * (astNode.Children[0].Children.Count > 0 ? -1 : 1)
            };

            return(literal);
        }
Exemplo n.º 13
0
        public override CodeNode Construct(AASTNode aastNode, CodeNode?parent)
        {
            CodeNode gotoNode = new CodeNode(aastNode, parent);

            // We have to deallocate everything since we do not know where are we jumping to
            gotoNode.Children.AddLast(GetRegisterDeallocationNode(aastNode, gotoNode, false));
            // Final(e) CodeNode is added later at the end of the Program constructor
            return(gotoNode);
        }
Exemplo n.º 14
0
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            AASTNode nodeToPass = new AASTNode(astNode, parent, SemanticAnalyzer.no_type);

            foreach (ASTNode child in astNode.Children)
            {
                nodeToPass.Children.Add(base.Annotate(child, nodeToPass));
            }
            return(nodeToPass);
        }
Exemplo n.º 15
0
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            AASTNode body = new AASTNode(astNode, parent, SemanticAnalyzer.no_type);

            foreach (ASTNode child in astNode.Children[1].Children)
            {
                body.Children.Add(base.Annotate(child, body));
            }
            return(body);
        }
        public override CodeNode Construct(AASTNode aastNode, CodeNode?parent)
        {
            // Just create a new CodeNode and construct its children
            CodeNode toReturn = new CodeNode(aastNode, parent);

            foreach (AASTNode child in aastNode.Children)
            {
                toReturn.Children.AddLast(base.Construct(child, toReturn));
            }
            return(toReturn);
        }
Exemplo n.º 17
0
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            AASTNode swap = new AASTNode(astNode, parent, SemanticAnalyzer.no_type);

            // TODO: perform type check
            foreach (ASTNode child in astNode.Children)
            {
                swap.Children.Add(base.Annotate(child, swap));
            }
            return(swap);
        }
Exemplo n.º 18
0
        public override CodeNode Construct(AASTNode aastNode, CodeNode?parent)
        {
            Generator g   = Program.currentCompiler.generator;
            Context?  ctx = SemanticAnalyzer.FindParentContext(aastNode)
                            ?? throw new CompilationErrorException("No parent context found!!!\r\n  At line " + aastNode.Token.Position.Line);
            CodeNode rbNode = new CodeNode(aastNode, parent);

            int frameSize = 0;

            foreach (AASTNode variable in ctx.GetDeclaredVars())
            {
                frameSize += variable.AASTType.GetSize();
            }

            rbNode.Children.AddLast(new CodeNode("Pre routine body", rbNode)
                                    .Add(GenerateST(FP, SP))
                                    .Add(GenerateMOV(SP, FP))
                                    .Add(GenerateLDA(FP, FP, 4))
                                    .Add(GenerateST(27, FP))
                                    .Add(GenerateLDA(FP, FP, 4))
                                    .Add(GenerateMOV(FP, SP))
                                    .Add(GenerateLDA(SP, SP, frameSize)));

            foreach (AASTNode statement in aastNode.Children)
            {
                rbNode.Children.AddLast(GetRegisterAllocationNode(statement, rbNode));
                rbNode.Children.AddLast(base.Construct(statement, rbNode));
                rbNode.Children.AddLast(GetRegisterDeallocationNode(statement, rbNode));
            }

            for (byte i = 0; i < 26; i++)
            {
                g.FreeReg(i);
                if (g.regAllocRTV.ContainsKey(i))
                {
                    string varName = g.regAllocRTV[i];
                    g.regAllocRTV.Remove(i);
                    g.regAllocVTR.Remove(varName);
                }
            }

            // Deallocate dynamic arrays
            rbNode.Children.AddLast(GetDynamicMemoryDeallocationNode(aastNode, rbNode));

            rbNode.Children.AddLast(new CodeNode("Post routine body", rbNode)
                                    .Add(GenerateLDA(FP, FP, -4))
                                    .Add(GenerateLD(FP, 27))
                                    .Add(GenerateLDA(FP, FP, -4))
                                    .Add(GenerateMOV(FP, SP))
                                    .Add(GenerateLD(FP, FP))
                                    .Add(GenerateCBR(27, 27)));

            return(rbNode);
        }
Exemplo n.º 19
0
        protected readonly int FP = 28, SP = 29, SB = 30, PC = 31; // Special registers

        /// <summary>
        /// The main method that is usually overwritten in child classes (Code Constructors).
        /// Given an AAST node and (possible) CodeNode parent constructs (recursively) Code Node
        /// that contains either other child Code Nodes or generated binary code inside.
        /// </summary>
        /// <param name="aastNode">An AAST node based on which CodeNode is constructed.</param>
        /// <param name="parent">Possible CodeNode parent (is needed to build CodeNode tree).</param>
        /// <returns>New constructed CodeNode.</returns>
        public virtual CodeNode Construct(AASTNode aastNode, CodeNode?parent)
        {
            if (Program.currentCompiler.generator.codeConstructors.ContainsKey(aastNode.ASTType))
            {
                return(Program.currentCompiler.generator.codeConstructors[aastNode.ASTType].Construct(aastNode, parent));
            }
            else
            {
                return(Program.currentCompiler.generator.codeConstructors["AllChildren"].Construct(aastNode, parent));
            }
        }
Exemplo n.º 20
0
        public override CodeNode Construct(AASTNode aastNode, CodeNode?parent)
        {
            Generator g         = Program.currentCompiler.generator;
            CodeNode  printNode = new CodeNode(aastNode, parent);
            CodeNode  exprNode  = base.Construct((AASTNode)aastNode.Children[1], printNode);
            byte      fr0       = exprNode.ByteToReturn;

            printNode.Children.AddLast(exprNode);
            printNode.Children.AddLast(new CodeNode("Print", printNode).Add(GeneratePRINT(fr0)));
            g.FreeReg(fr0);
            return(printNode);
        }
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            VarType type = SemanticAnalyzer.IdentifyType(astNode.Children[0], astNode.Children[1].Children[0].ASTType.Equals("Constant"));

            if (astNode.Children[1].Children[0].ASTType.Equals("Array"))
            {
                type = new ArrayType(type);
            }
            AASTNode varDecl = new AASTNode(astNode, parent, SemanticAnalyzer.no_type);

            varDecl.Children.AddRange(IdentifyVarDecl(astNode.Children[1].Children[0], varDecl, type));
            return(varDecl);
        }
Exemplo n.º 22
0
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            AASTNode ifNode = new AASTNode(astNode, parent, SemanticAnalyzer.no_type);

            ifNode.Children.Add(base.Annotate(astNode.Children[1], ifNode));
            ifNode.Children.Add(base.Annotate(astNode.Children[3], ifNode)); // If true
            // Annotate else block if any
            if (astNode.Children[4].Children[0].Children.Count > 0)
            {
                ifNode.Children.Add(base.Annotate(astNode.Children[4].Children[0].Children[1], ifNode));
            }
            return(ifNode);
        }
Exemplo n.º 23
0
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            AASTNode program = new AASTNode(astNode, parent, SemanticAnalyzer.no_type);

            program.Context = new Context("Program", null, program);

            foreach (ASTNode child in astNode.Children)
            {
                program.Children.Add(base.Annotate(child, program));
            }

            return(program);
        }
Exemplo n.º 24
0
        /// <summary>
        /// Recursively calculates the size of an address represented by a given expression.
        /// For example, if expression has some int pointers, then expression clearly points to some integer (or 4 bytes).
        /// If expression has only byte pointers, the expression clearly points to some byte address (1 byte).
        /// </summary>
        /// <param name="aastNode">Expression AASTNode</param>
        /// <returns>The size of a variable that given expression points to.</returns>
        protected int GetSizeOfExpressionAddressedVariable(AASTNode aastNode)
        {
            Context?ctx  = SemanticAnalyzer.FindParentContext(aastNode);
            int     size = 0;

            if (aastNode.ASTType.Equals("Dereference"))
            {
                // Careful here
                if (aastNode.Children[2].Children.Count == 1 &&
                    aastNode.Children[2].Children[0].ASTType.Equals("Primary") &&
                    aastNode.Children[2].Children[0].Children[^ 1].ASTType.Equals("IDENTIFIER"))
                {
                    switch (ctx.GetVarType(aastNode.Children[2].Children[0].Children[^ 1].Token).Type)
Exemplo n.º 25
0
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            Context? ctx    = SemanticAnalyzer.FindParentContext(parent);
            AASTNode module = new AASTNode(astNode, parent, new VarType(VarType.ERAType.MODULE));

            module.Context = new Context(astNode.Children[1].Token.Value, ctx, module);
            foreach (ASTNode child in astNode.Children[2].Children)
            {
                module.Children.Add(base.Annotate(child, module));
            }
            ctx?.AddVar(module, astNode.Children[1].Token.Value);
            return(module);
        }
Exemplo n.º 26
0
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            AASTNode anns = new AASTNode(astNode, parent, SemanticAnalyzer.no_type);

            // Annotate the first child
            anns.Children.Add(base.Annotate(astNode.Children[1], anns));
            // Repeat for the rest
            foreach (ASTNode child in astNode.Children[2].Children)
            {
                anns.Children.Add(base.Annotate(child, anns));
            }
            return(anns);
        }
Exemplo n.º 27
0
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            AASTNode forNode = new AASTNode(astNode, parent, SemanticAnalyzer.no_type);

            forNode.Children.Add(base.Annotate(astNode.Children[1], forNode));
            ((AASTNode)forNode.Children[0]).AASTType        = new VarType(VarType.ERAType.INT);
            ((AASTNode)forNode.Children[0]).LIStart         = 1;
            Program.currentCompiler.semantics.varToAddToCtx = (AASTNode)forNode.Children[0];
            // If 'from' expression exists
            if (astNode.Children[2].Children.Count > 0)
            {
                forNode.Children.Add(base.Annotate(astNode.Children[2].Children[1], forNode));
                ((AASTNode)forNode.Children[^ 1]).AASTValue = 1; // For generator
Exemplo n.º 28
0
        public override CodeNode Construct(AASTNode aastNode, CodeNode?parent)
        {
            Generator g             = Program.currentCompiler.generator;
            CodeNode  loopWhileNode = new CodeNode(aastNode, parent);

            // *see ForConstructor
            loopWhileNode.Children.AddLast(GetRegisterDeallocationNode(aastNode, loopWhileNode, false));

            CodeNode fr1Node = GetFreeRegisterNode(aastNode, loopWhileNode);
            byte     fr1     = fr1Node.ByteToReturn;

            loopWhileNode.Children.AddLast(fr1Node);

            CodeNode loopStartLabelDeclNode = new CodeNode("Label declaration", loopWhileNode).Add(new byte[8]);

            loopStartLabelDeclNode.ByteToReturn = fr1;
            CodeNode loopStartLabelNode = new CodeNode("Label", loopWhileNode);

            loopStartLabelNode.LabelDecl = loopStartLabelDeclNode;

            loopWhileNode.Children.AddLast(loopStartLabelDeclNode);
            loopWhileNode.Children.AddLast(loopStartLabelNode);

            loopWhileNode.Children.AddLast(GetHeapTopChangeNode(loopWhileNode, -4));

            loopWhileNode.Children.AddLast(GetStoreToHeapNode(loopWhileNode, fr1, 0));
            g.FreeReg(fr1);

            loopWhileNode.Children.AddLast(base.Construct((AASTNode)aastNode.Children[0], loopWhileNode));

            CodeNode exprNode = base.Construct((AASTNode)aastNode.Children[1], loopWhileNode);
            byte     fr0      = exprNode.ByteToReturn;

            loopWhileNode.Children.AddLast(exprNode);

            CodeNode fr2Node = GetFreeRegisterNode(aastNode, loopWhileNode);
            byte     fr2     = fr2Node.ByteToReturn;

            loopWhileNode.Children.AddLast(fr2Node);

            loopWhileNode.Children.AddLast(new CodeNode("fr0 fr2 mov", loopWhileNode).Add(GenerateMOV(fr0, fr2)));
            loopWhileNode.Children.AddLast(GetLoadFromHeapNode(loopWhileNode, fr1, 0));
            loopWhileNode.Children.AddLast(GetHeapTopChangeNode(loopWhileNode, 4));
            loopWhileNode.Children.AddLast(new CodeNode("if fr2 cbr", loopWhileNode).Add(GenerateCBR(fr2, fr1)));

            g.FreeReg(fr0);
            g.FreeReg(fr1);
            g.FreeReg(fr2);

            return(loopWhileNode);
        }
Exemplo n.º 29
0
        /// <summary>
        /// DFS that identifies all used variables (in fact, identifiers) starting from a given AAST node.
        /// </summary>
        /// <param name="node">An AAST root node from where DFS starts.</param>
        /// <returns>A set of unique variables (identifiers) that are appearing down the AAST tree.</returns>
        public static HashSet <string> GetAllUsedVars(AASTNode node)
        {
            HashSet <string> set = new HashSet <string>();

            foreach (AASTNode child in node.Children)
            {
                if (child.ASTType.Equals("IDENTIFIER"))
                {
                    set.Add(child.Token.Value);
                }
                set.UnionWith(GetAllUsedVars(child));
            }
            return(set);
        }
Exemplo n.º 30
0
        public override AASTNode Annotate(ASTNode astNode, AASTNode?parent)
        {
            AASTNode label = new AASTNode(astNode, parent, new VarType(VarType.ERAType.LABEL));

            // Add label to the context
            Context?ctx = SemanticAnalyzer.FindParentContext(parent);

            ctx?.AddVar(label, astNode.Children[1].Token.Value);
            label.Token.Value = astNode.Children[1].Token.Value;

            // Put identifier
            label.Children.Add(base.Annotate(astNode.Children[1], label));

            return(label);
        }