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); }
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); }
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"))
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); }
/// <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); }
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
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); }
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); }
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); }
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); }
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); }
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); }
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)); } }
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); }
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); }
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); }
/// <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)
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); }
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); }
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
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); }
/// <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); }
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); }