Skip to content

Commit

Permalink
DOCS: documentation added
Browse files Browse the repository at this point in the history
Problem
Future generations want to have good documentation of ERA compiler.

Solution
I did as much as I could.

Note
Some fixes are done, obviously.
  • Loading branch information
egorklementev committed Jun 17, 2021
1 parent f77d3e3 commit a123640
Show file tree
Hide file tree
Showing 10 changed files with 11,043 additions and 268 deletions.
95 changes: 95 additions & 0 deletions ERACompiler/ERACompiler/ERACompiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions ERACompiler/ERACompiler/Modules/Compiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ public byte[] Compile(string sourceCode)
return Compile(sourceCode, CompilationMode.GENERATION);
}

/// <summary>
/// Simple DFS to convert the CodeNode tree to the flat linked list of bytes
/// </summary>
/// <param name="cn"></param>
/// <returns></returns>
private LinkedList<byte> CollectBytes(CodeNode cn)
{
if (cn.IsLeaf())
Expand Down
32 changes: 26 additions & 6 deletions ERACompiler/ERACompiler/Modules/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,19 +73,32 @@ public static CodeNode GetProgramCodeNodeRoot(AASTNode root)
Helper functions
*/

/// <summary>
/// Marks given register as "occupied", so that, for example, GetFreeRegisterNode() does not consider this register until it is free.
/// </summary>
/// <param name="regNum">The number of a register to be occupied.</param>
public void OccupateReg(byte regNum)
{
regOccup[regNum] = true;
}

/// <summary>
/// Frees a given register.
/// </summary>
/// <param name="regNum">The number of a register to be freed.</param>
public void FreeReg(byte regNum)
{
// If register is allocated to a variable - do not free it
// It will be swapped if needed when calling GetFreeReg()
if (!regAllocRTV.ContainsKey(regNum))
if (!regAllocRTV.ContainsKey(regNum) && regNum < regOccup.Length)
regOccup[regNum] = false;
}

/// <summary>
/// Returns a byte representing the register number.
/// </summary>
/// <param name="reg">A string formatted in the following way: "r0", "r25", "pc", "sb", etc.</param>
/// <returns>The number of a register represented in a string.</returns>
public static byte IdentifyRegister(string reg)
{
if (reg[0] == 'r')
Expand All @@ -103,15 +116,22 @@ public static byte IdentifyRegister(string reg)
{
return reg switch
{
"pc" => 0xFF,
"sb" => 0xFE,
"sp" => 0xFD,
"fp" => 0xFC,
_ => 0x00,
"pc" => 0x0000001F,
"sb" => 0x0000001E,
"sp" => 0x0000001D,
"fp" => 0x0000001C,
_ => 0x00000000,
};
}
}

/// <summary>
/// Converts given list of bytes to the string (JSON) representation which is ERA assembly language apparently.
/// </summary>
/// <param name="bincode">The list of bytes to be converted.</param>
/// <param name="offset">Command address parameter. Used for marking an asm command with its address within the binary file.</param>
/// <param name="padding">Tabulation parameter. Used for fancy JSON output.</param>
/// <returns>A string formatted in JSON representing asm commands in ERA assembly language.</returns>
public static string ConvertToAssemblyCode(LinkedList<byte> bincode, int offset, int padding = 0)
{
int i = -1;
Expand Down
46 changes: 45 additions & 1 deletion ERACompiler/ERACompiler/Modules/SemanticAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,19 @@

namespace ERACompiler.Modules
{
/// <summary>
/// Performs all semantics checks and prepares AST to be transfered to the Generator.
/// Contains some necessary static methods used in node annotators.
/// </summary>
public class SemanticAnalyzer
{
public static readonly VarType no_type = new VarType(VarType.ERAType.NO_TYPE); // Placeholder
public readonly Dictionary<string, NodeAnnotator> nodeAnnotators;
public readonly Dictionary<string, NodeAnnotator> nodeAnnotators; // All the AST annotators
public AASTNode varToAddToCtx = null; // For "for" loops

/// <summary>
/// Initializes all node annotators
/// </summary>
public SemanticAnalyzer()
{
nodeAnnotators = new Dictionary<string, NodeAnnotator>
Expand Down Expand Up @@ -70,6 +77,12 @@ public SemanticAnalyzer()
};
}

/// <summary>
/// Builds annotated AST which is basically reduced AST with some changes and additional information
/// that is needed for the Generator
/// </summary>
/// <param name="ASTRoot">The root node of the AST from SyntaxAnalyzer</param>
/// <returns>The root node of the annotated AST</returns>
public AASTNode BuildAAST(ASTNode ASTRoot)
{
AASTNode program = nodeAnnotators[ASTRoot.ASTType].Annotate(ASTRoot, null);
Expand All @@ -87,6 +100,12 @@ public AASTNode BuildAAST(ASTNode ASTRoot)
return program;
}

/// <summary>
/// Identifies a variable type given a type AST node.
/// </summary>
/// <param name="node">Type AST node</param>
/// <param name="isConst">Is type constant or not.</param>
/// <returns>A new VarType object identified from a given AST Type node.</returns>
public static VarType IdentifyType(ASTNode node, bool isConst = false)
{
VarType vt;
Expand Down Expand Up @@ -147,6 +166,11 @@ public static VarType IdentifyType(ASTNode node, bool isConst = false)
return vt;
}

/// <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>();
Expand All @@ -159,6 +183,15 @@ public static HashSet<string> GetAllUsedVars(AASTNode node)
return set;
}

/// <summary>
/// Evaluates the maximum depth of a Block Bodies down the AAST tree. Maximum depth in this sense is the maximum number of children that can have
/// some Block Body down the AAST tree starting from a given AAST node. It is used when calculating the Live Interval end for, for example, 'for' loop
/// iterators (know as 'i' usually). Some inner Block Bodies may have more Statements inside them, than the 'for' loop Block Body, so we do not
/// want the Register Allocation algorithm to deallocate our 'i' iterator before we reach the end of the most outer (or 'for') Block Body.
/// Therefore, we use this DFS that tells us the number of children of a Block Body with maximum number of children (Statements basically).
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
public static int GetMaxDepth(AASTNode node)
{
int maxDepth = 1;
Expand Down Expand Up @@ -192,6 +225,11 @@ public static int GetMaxDepth(AASTNode node)
return null;
}

/// <summary>
/// Retrieves all parameter types from a given Parameters AST node.
/// </summary>
/// <param name="node">A Paramters AST node.</param>
/// <returns>A list of VarType objects representing types of the routine parameters.</returns>
public static List<VarType> RetrieveParamTypes(ASTNode node)
{
List<VarType> lst = new List<VarType>
Expand Down Expand Up @@ -755,6 +793,12 @@ public static bool IsExprConstant(ASTNode node, Context ctx)
return true;
}

/// <summary>
/// Checks whether an operand is constant or not.
/// </summary>
/// <param name="node">And operand AST node</param>
/// <param name="ctx">The current context the node belongs to.</param>
/// <returns>True if operand is constant, false otherwise.</returns>
public static bool IsOperandConstant(ASTNode node, Context ctx)
{
string type = node.Children[0].ASTType; // The child of Operand
Expand Down
Loading

0 comments on commit a123640

Please sign in to comment.