CLion reformatting pass, finish struct implementation

This commit is contained in:
Curle 2022-03-03 00:05:10 +00:00
parent ac8c0ed9c7
commit 537246daae
43 changed files with 929 additions and 665 deletions

20
CMakeLists.txt Normal file
View File

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.21)
project(Erythro C)
set(CMAKE_C_STANDARD 11)
include_directories(include)
add_executable(Erythro
include/Data.h
include/Defs.h
src/Assembler.c
src/Delegate.c
src/Dump.c
src/Lexer.c
src/Main.c
src/Parser.c
src/Pointers.c
src/Statements.c
src/Symbols.c
src/Types.c)

View File

@ -4,6 +4,7 @@
/*************/ /*************/
#pragma once #pragma once
#include <stdio.h> #include <stdio.h>
#include <Defs.h> #include <Defs.h>
#include <stdbool.h> #include <stdbool.h>
@ -15,14 +16,14 @@
#define TEXTLEN 512 #define TEXTLEN 512
#define SYMBOLS 1024 #define SYMBOLS 1024
extern_ struct SymbolTableEntry* Globals, *GlobalsEnd; extern_ struct SymbolTableEntry* Globals, * GlobalsEnd;
extern_ struct SymbolTableEntry* Locals, *LocalsEnd; extern_ struct SymbolTableEntry* Locals, * LocalsEnd;
extern_ struct SymbolTableEntry* Params, *ParamsEnd; extern_ struct SymbolTableEntry* Params, * ParamsEnd;
extern_ struct SymbolTableEntry* Structs, *StructsEnd; extern_ struct SymbolTableEntry* Structs, * StructsEnd;
extern_ struct SymbolTableEntry* StructMembers, *StructMembersEnd; extern_ struct SymbolTableEntry* StructMembers, * StructMembersEnd;
extern_ struct SymbolTableEntry* Unions, *UnionsEnd; extern_ struct SymbolTableEntry* Unions, * UnionsEnd;
extern_ struct SymbolTableEntry* Enums, *EnumsEnd; extern_ struct SymbolTableEntry* Enums, * EnumsEnd;
extern_ bool OptDumpTree; extern_ bool OptDumpTree;
extern_ bool OptKeepAssembly; extern_ bool OptKeepAssembly;
@ -31,7 +32,7 @@ extern_ bool OptLinkFiles;
extern_ bool OptVerboseOutput; extern_ bool OptVerboseOutput;
extern_ char* OutputFileName; extern_ char* OutputFileName;
extern_ char* CurrentASMFile, *CurrentObjectFile; extern_ char* CurrentASMFile, * CurrentObjectFile;
extern_ int TypeSizes[5]; extern_ int TypeSizes[5];

View File

@ -4,6 +4,7 @@
/*************/ /*************/
#pragma once #pragma once
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
@ -117,32 +118,32 @@ enum SyntaxOps {
OP_BOOLOR, // Boolean OR two statements OP_BOOLOR, // Boolean OR two statements
OP_BOOLAND, // Boolean AND two statements OP_BOOLAND, // Boolean AND two statements
OP_BITOR, // Bitwise OR a number OP_BITOR, // Bitwise OR a number
OP_BITXOR, // Bitwise XOR a number OP_BITXOR = 5, // Bitwise XOR a number
OP_BITAND, // Bitwise AND a number OP_BITAND, // Bitwise AND a number
OP_EQUAL, // Compare equality OP_EQUAL, // Compare equality
OP_INEQ, // Compare inequality OP_INEQ, // Compare inequality
OP_LESS, // Less than? OP_LESS, // Less than?
OP_GREAT, // Greater than? OP_GREAT = 10, // Greater than?
OP_LESSE, // Less than or Equal to? OP_LESSE, // Less than or Equal to?
OP_GREATE, // Greater than or Equal to? OP_GREATE, // Greater than or Equal to?
OP_SHIFTL, // Arithmetic Shift Left (Multiply by 2) OP_SHIFTL, // Arithmetic Shift Left (Multiply by 2)
OP_SHIFTR, // Arithmetic Shift Right (Divide by 2) OP_SHIFTR, // Arithmetic Shift Right (Divide by 2)
OP_ADD, // Add two numbers. OP_ADD = 15, // Add two numbers.
OP_SUBTRACT, // Subtract two numbers. OP_SUBTRACT, // Subtract two numbers.
OP_MULTIPLY, // Multiply two numbers. OP_MULTIPLY, // Multiply two numbers.
OP_DIVIDE, // Divide two numbers. OP_DIVIDE, // Divide two numbers.
OP_PREINC, // Increment var before reference. OP_PREINC, // Increment var before reference.
OP_PREDEC, // Decrement var before reference. OP_PREDEC = 20, // Decrement var before reference.
OP_POSTINC, // Increment var after reference. OP_POSTINC, // Increment var after reference.
OP_POSTDEC, // Decrement var after reference. OP_POSTDEC, // Decrement var after reference.
OP_BITNOT, // Invert a number bitwise OP_BITNOT, // Invert a number bitwise
OP_BOOLNOT, // Invert a statement logically OP_BOOLNOT, // Invert a statement logically
OP_NEGATE, // Negate a number (turn a positive number negative) OP_NEGATE = 25, // Negate a number (turn a positive number negative)
OP_BOOLCONV, // Convert an expression to a boolean.s OP_BOOLCONV, // Convert an expression to a boolean.s
@ -150,7 +151,7 @@ enum SyntaxOps {
OP_DEREF, // Get the value of the address in a pointer OP_DEREF, // Get the value of the address in a pointer
TERM_INTLITERAL, // Integer Literal. This is a virtual operation, so it's a terminal. TERM_INTLITERAL, // Integer Literal. This is a virtual operation, so it's a terminal.
TERM_STRLITERAL, // String Literal. Also terminal. TERM_STRLITERAL = 30, // String Literal. Also terminal.
REF_IDENT, // Reference (read) an identifier (variable). REF_IDENT, // Reference (read) an identifier (variable).
@ -158,14 +159,14 @@ enum SyntaxOps {
OP_SCALE, // We have a pointer that needs to be scaled! OP_SCALE, // We have a pointer that needs to be scaled!
OP_CALL, // Call a function OP_CALL, // Call a function
OP_RET, // Return from a function OP_RET = 35, // Return from a function
OP_COMP, // Compound statements need a way to be "glued" together. This is one of those mechanisms OP_COMP, // Compound statements need a way to be "glued" together. This is one of those mechanisms
OP_IF, // If statement OP_IF, // If statement
OP_LOOP, // FOR, WHILE OP_LOOP, // FOR, WHILE
OP_PRINT, // Print statement OP_PRINT, // Print statement
OP_FUNC, // Define a function OP_FUNC = 40, // Define a function
}; };
@ -268,9 +269,13 @@ enum StructureType {
* * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char* Suffixate(char* String, char Suffix); char* Suffixate(char* String, char Suffix);
char* Compile(char* InputFile); char* Compile(char* InputFile);
char* Assemble(char* InputFile); char* Assemble(char* InputFile);
void Link(char* Output, char* Objects[]); void Link(char* Output, char* Objects[]);
void DisplayUsage(char* ProgName); void DisplayUsage(char* ProgName);
@ -282,9 +287,11 @@ void DisplayUsage(char* ProgName);
void Tokenise(); void Tokenise();
void VerifyToken(int Type, char* TokenExpected); void VerifyToken(int Type, char* TokenExpected);
void RejectToken(struct Token* Token); void RejectToken(struct Token* Token);
static int ReadIdentifier(int Char, char* Buffer, int Limit); static int ReadIdentifier(int Char, char* Buffer, int Limit);
static int ReadKeyword(char* Str); static int ReadKeyword(char* Str);
/* * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * *
@ -294,9 +301,11 @@ static int ReadKeyword(char* Str);
struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation); struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation);
int TypeIsInt(int Type); int TypeIsInt(int Type);
int TypeIsPtr(int Type); int TypeIsPtr(int Type);
char* TypeNames(int Type); char* TypeNames(int Type);
int TypeSize(int Type, struct SymbolTableEntry* Composite); int TypeSize(int Type, struct SymbolTableEntry* Composite);
@ -314,7 +323,8 @@ struct ASTNode* ConstructASTNode(int Operation, int Type,
struct ASTNode* ConstructASTLeaf(int Operation, int Type, struct SymbolTableEntry* Symbol, int IntValue); struct ASTNode* ConstructASTLeaf(int Operation, int Type, struct SymbolTableEntry* Symbol, int IntValue);
struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, struct SymbolTableEntry* Symbol, int IntValue); struct ASTNode*
ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, struct SymbolTableEntry* Symbol, int IntValue);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
@ -325,25 +335,35 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence);
struct ASTNode* ParsePrimary(void); struct ASTNode* ParsePrimary(void);
struct ASTNode* ParseStatement(void); struct ASTNode* ParseStatement(void);
struct ASTNode* PrefixStatement(); struct ASTNode* PrefixStatement();
struct ASTNode* PostfixStatement(); struct ASTNode* PostfixStatement();
void ParseGlobals(); void ParseGlobals();
struct ASTNode* ParseFunction(int Type); struct ASTNode* ParseFunction(int Type);
struct ASTNode* ParseCompound(); struct ASTNode* ParseCompound();
struct SymbolTableEntry* BeginStructDeclaration(); struct SymbolTableEntry* BeginStructDeclaration();
struct ASTNode* GetExpressionList(); struct ASTNode* GetExpressionList();
struct ASTNode* CallFunction(); struct ASTNode* CallFunction();
struct ASTNode* ReturnStatement(); struct ASTNode* ReturnStatement();
int ParseOptionalPointer(struct SymbolTableEntry** Composite); int ParseOptionalPointer(struct SymbolTableEntry** Composite);
int ValueAt(int Type); int ValueAt(int Type);
int PointerTo(int Type); int PointerTo(int Type);
struct ASTNode* AccessArray(); struct ASTNode* AccessArray();
struct ASTNode* AccessMember(bool Deref); struct ASTNode* AccessMember(bool Deref);
int ParseTokenToOperation(int Token); int ParseTokenToOperation(int Token);
@ -351,35 +371,45 @@ int ParseTokenToOperation(int Token);
struct ASTNode* PrintStatement(void); struct ASTNode* PrintStatement(void);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * S Y M B O L T A B L E * * * * * * * * * * * * S Y M B O L T A B L E * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void DumpAllLists(); void DumpAllLists();
void DumpList(struct SymbolTableEntry* List); void DumpList(struct SymbolTableEntry* List);
struct SymbolTableEntry* FindSymbol(char* Symbol); struct SymbolTableEntry* FindSymbol(char* Symbol);
struct SymbolTableEntry* FindLocal(char* Symbol); struct SymbolTableEntry* FindLocal(char* Symbol);
struct SymbolTableEntry* FindGlobal(char* Symbol); struct SymbolTableEntry* FindGlobal(char* Symbol);
struct SymbolTableEntry* FindStruct(char* Symbol); struct SymbolTableEntry* FindStruct(char* Symbol);
struct SymbolTableEntry* FindMember(char* Symbol); struct SymbolTableEntry* FindMember(char* Symbol);
void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node); void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node);
void FreeLocals(); void FreeLocals();
void ClearTables(); void ClearTables();
struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Storage, int Length, int SinkOffset, struct SymbolTableEntry* CompositeType); struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Storage, int Length, int SinkOffset,
struct SymbolTableEntry* CompositeType);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * C O N T R O L S T A T U S * * * * * * * * C O N T R O L S T A T U S * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void Die(char* Error); void Die(char* Error);
void DieMessage(char* Error, char* Reason); void DieMessage(char* Error, char* Reason);
void DieDecimal(char* Error, int Number); void DieDecimal(char* Error, int Number);
void DieChar(char* Error, int Char); void DieChar(char* Error, int Char);
void DieBinary(char* Error, int Number); void DieBinary(char* Error, int Number);
@ -396,62 +426,94 @@ int RetrieveRegister();
void DeallocateRegister(int Register); void DeallocateRegister(int Register);
int PrimitiveSize(int Type); int PrimitiveSize(int Type);
int AsAlignMemory(int Type, int Offset, int Direction); int AsAlignMemory(int Type, int Offset, int Direction);
int AsLoad(int Value); int AsLoad(int Value);
int AsAdd(int Left, int Right); int AsAdd(int Left, int Right);
int AsMul(int Left, int Right); int AsMul(int Left, int Right);
int AsSub(int Left, int Right); int AsSub(int Left, int Right);
int AsDiv(int Left, int Right); int AsDiv(int Left, int Right);
int AsLdGlobalVar(struct SymbolTableEntry* Entry, int Operation); int AsLdGlobalVar(struct SymbolTableEntry* Entry, int Operation);
int AsLdLocalVar(struct SymbolTableEntry* Entry, int Operation); int AsLdLocalVar(struct SymbolTableEntry* Entry, int Operation);
int AsStrGlobalVar(struct SymbolTableEntry* Entry, int Register); int AsStrGlobalVar(struct SymbolTableEntry* Entry, int Register);
int AsStrLocalVar(struct SymbolTableEntry* Entry, int Register); int AsStrLocalVar(struct SymbolTableEntry* Entry, int Register);
int AsCalcOffset(int Type); int AsCalcOffset(int Type);
void AsNewStackFrame(); void AsNewStackFrame();
int AsDeref(int Reg, int Type); int AsDeref(int Reg, int Type);
int AsStrDeref(int Register1, int Register2, int Type); int AsStrDeref(int Register1, int Register2, int Type);
int AsAddr(struct SymbolTableEntry* Entry); int AsAddr(struct SymbolTableEntry* Entry);
void AsGlobalSymbol(struct SymbolTableEntry* Entry); void AsGlobalSymbol(struct SymbolTableEntry* Entry);
int AsNewString(char* Value); int AsNewString(char* Value);
int AsLoadString(int ID); int AsLoadString(int ID);
int AsEqual(int Left, int Right); int AsEqual(int Left, int Right);
int AsIneq(int Left, int Right); int AsIneq(int Left, int Right);
int AsLess(int Left, int Right); int AsLess(int Left, int Right);
int AsGreat(int Left, int Right); int AsGreat(int Left, int Right);
int AsLessE(int Left, int Right); int AsLessE(int Left, int Right);
int AsGreatE(int Left, int Right); int AsGreatE(int Left, int Right);
int AsBitwiseAND(int Left, int Right); int AsBitwiseAND(int Left, int Right);
int AsBitwiseOR(int Left, int Right); int AsBitwiseOR(int Left, int Right);
int AsBitwiseXOR(int Left, int Right); int AsBitwiseXOR(int Left, int Right);
int AsNegate(int Register); int AsNegate(int Register);
int AsInvert(int Register); int AsInvert(int Register);
int AsBooleanNOT(int Register); int AsBooleanNOT(int Register);
int AsShiftLeft(int Left, int Right); int AsShiftLeft(int Left, int Right);
int AsShiftRight(int Left, int Right); int AsShiftRight(int Left, int Right);
int AsBooleanConvert(int Register, int Operation, int Label); int AsBooleanConvert(int Register, int Operation, int Label);
int AsCompareJmp(int Operation, int RegisterLeft, int RegisterRight, int Label); int AsCompareJmp(int Operation, int RegisterLeft, int RegisterRight, int Label);
int AsCompare(int Operation, int RegisterLeft, int RegisterRight); int AsCompare(int Operation, int RegisterLeft, int RegisterRight);
int AsIf(struct ASTNode* Node); int AsIf(struct ASTNode* Node);
int NewLabel(void); int NewLabel(void);
void AsJmp(int Label); void AsJmp(int Label);
void AsLabel(int Label); void AsLabel(int Label);
int AsShl(int Register, int Val); int AsShl(int Register, int Val);
int AsReturn(struct SymbolTableEntry* Entry, int Register); int AsReturn(struct SymbolTableEntry* Entry, int Register);
int AsCallWrapper(struct ASTNode* Node); int AsCallWrapper(struct ASTNode* Node);
void AsCopyArgs(int Register, int Position); void AsCopyArgs(int Register, int Position);
int AsCall(struct SymbolTableEntry* Entry, int Args); int AsCall(struct SymbolTableEntry* Entry, int Args);
int AsWhile(struct ASTNode* Node); int AsWhile(struct ASTNode* Node);
@ -459,7 +521,9 @@ int AsWhile(struct ASTNode* Node);
void AssemblerPrint(int Register); void AssemblerPrint(int Register);
void AssemblerPreamble(); void AssemblerPreamble();
void AsFunctionPreamble(struct SymbolTableEntry* Entry); void AsFunctionPreamble(struct SymbolTableEntry* Entry);
void AsFunctionEpilogue(struct SymbolTableEntry* Entry); void AsFunctionEpilogue(struct SymbolTableEntry* Entry);
@ -468,10 +532,13 @@ void AsFunctionEpilogue(struct SymbolTableEntry* Entry);
* * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * */
struct SymbolTableEntry* BeginVariableDeclaration(int Type, struct SymbolTableEntry* Composite, int Scope); struct SymbolTableEntry* BeginVariableDeclaration(int Type, struct SymbolTableEntry* Composite, int Scope);
struct ASTNode* ParseIdentifier(void); struct ASTNode* ParseIdentifier(void);
struct ASTNode* IfStatement(); struct ASTNode* IfStatement();
struct ASTNode* WhileStatement(); struct ASTNode* WhileStatement();
struct ASTNode* ForStatement(); struct ASTNode* ForStatement();

View File

@ -29,17 +29,17 @@ static int UsedRegisters[4];
* *
* The 4 clobber registers are first, and the 4 parameter registers are last. * The 4 clobber registers are first, and the 4 parameter registers are last.
*/ */
static char* Registers[8] = { "%r10", "%r11" , "%r12" , "%r13", "%r9" , "%r8", "%rdx", "%rcx" }; static char* Registers[8] = {"%r10", "%r11", "%r12", "%r13", "%r9", "%r8", "%rdx", "%rcx"};
static char* DoubleRegisters[8] = { "%r10d", "%r11d", "%r12d", "%r13d", "%r9d", "%r8d", "%edx", "%ecx" }; static char* DoubleRegisters[8] = {"%r10d", "%r11d", "%r12d", "%r13d", "%r9d", "%r8d", "%edx", "%ecx"};
static char* ByteRegisters[8] = { "%r10b", "%r11b", "%r12b", "%r13b", "%r9b", "%r8b", "%dl" , "%cl" }; static char* ByteRegisters[8] = {"%r10b", "%r11b", "%r12b", "%r13b", "%r9b", "%r8b", "%dl", "%cl"};
/* /*
* For ease of reading later code, we store the valid x86 comparison instructions, * For ease of reading later code, we store the valid x86 comparison instructions,
* and the inverse jump instructions together, in a synchronized fashion. * and the inverse jump instructions together, in a synchronized fashion.
*/ */
static char* Comparisons[6] = { "sete", "setne", "setl", "setg", "setle", "setge" }; static char* Comparisons[6] = {"sete", "setne", "setl", "setg", "setle", "setge"};
static char* InvComparisons[6] = { "jne", "je", "jge", "jle", "jg", "jl"}; static char* InvComparisons[6] = {"jne", "je", "jge", "jle", "jg", "jl"};
// How far above the base pointer is the last local? // How far above the base pointer is the last local?
static int LocalVarOffset; static int LocalVarOffset;
@ -66,12 +66,12 @@ static int Started = 0;
*/ */
int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) { int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
int LeftVal, RightVal; int LeftVal, RightVal;
if(!Started && OptDumpTree) if (!Started && OptDumpTree)
DumpTree(Node, 0); DumpTree(Node, 0);
Started = 1; Started = 1;
printf("Current operation: %d\r\n", Node->Operation); printf("Current operation: %d\r\n", Node->Operation);
switch(Node->Operation) { switch (Node->Operation) {
case OP_IF: case OP_IF:
return AsIf(Node); return AsIf(Node);
@ -96,13 +96,13 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
} }
if(Node->Left) if (Node->Left)
LeftVal = AssembleTree(Node->Left, -1, Node->Operation); LeftVal = AssembleTree(Node->Left, -1, Node->Operation);
if(Node->Right) if (Node->Right)
RightVal = AssembleTree(Node->Right, LeftVal, Node->Operation); RightVal = AssembleTree(Node->Right, LeftVal, Node->Operation);
switch(Node->Operation) { switch (Node->Operation) {
case OP_ADD: case OP_ADD:
return AsAdd(LeftVal, RightVal); return AsAdd(LeftVal, RightVal);
@ -118,10 +118,13 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
case OP_SCALE: case OP_SCALE:
// We can (ab)use the powers of 2 to do // We can (ab)use the powers of 2 to do
// efficient scaling with bitshifting. // efficient scaling with bitshifting.
switch(Node->Size) { switch (Node->Size) {
case 2: return AsShl(LeftVal, 1); case 2:
case 4: return AsShl(LeftVal, 2); return AsShl(LeftVal, 1);
case 8: return AsShl(LeftVal, 3); case 4:
return AsShl(LeftVal, 2);
case 8:
return AsShl(LeftVal, 3);
default: default:
RightVal = AsLoad(Node->Size); RightVal = AsLoad(Node->Size);
@ -135,19 +138,21 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
case OP_ASSIGN: case OP_ASSIGN:
printf("Preparing for assignment..\r\n"); printf("Preparing for assignment..\r\n");
if(Node->Right == NULL) if (Node->Right == NULL)
Die("Fault in assigning a null rvalue"); Die("Fault in assigning a null rvalue");
printf("\tCalculating assignment for target %s:\r\n", Node->Right->Symbol->Name); printf("\tCalculating assignment for target %s:\r\n", Node->Right->Symbol->Name);
switch(Node->Right->Operation) { switch (Node->Right->Operation) {
case REF_IDENT: case REF_IDENT:
if(Node->Right->Symbol->Storage == SC_LOCAL) if (Node->Right->Symbol->Storage == SC_LOCAL)
return AsStrLocalVar(Node->Right->Symbol, LeftVal); return AsStrLocalVar(Node->Right->Symbol, LeftVal);
else else
return AsStrGlobalVar(Node->Right->Symbol, LeftVal); return AsStrGlobalVar(Node->Right->Symbol, LeftVal);
case OP_DEREF: return AsStrDeref(LeftVal, RightVal, Node->Right->ExprType); case OP_DEREF:
default: DieDecimal("Can't ASSIGN in AssembleTree: ", Node->Operation); return AsStrDeref(LeftVal, RightVal, Node->Right->ExprType);
default:
DieDecimal("Can't ASSIGN in AssembleTree: ", Node->Operation);
} }
case OP_WIDEN: case OP_WIDEN:
@ -165,15 +170,19 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
case OP_GREAT: case OP_GREAT:
case OP_LESSE: case OP_LESSE:
case OP_GREATE: case OP_GREATE:
if(ParentOp == OP_IF || ParentOp == OP_LOOP) if (ParentOp == OP_IF || ParentOp == OP_LOOP)
return AsCompareJmp(Node->Operation, LeftVal, RightVal, Register); return AsCompareJmp(Node->Operation, LeftVal, RightVal, Register);
else else
return AsCompare(Node->Operation, LeftVal, RightVal); return AsCompare(Node->Operation, LeftVal, RightVal);
case REF_IDENT: case REF_IDENT:
if(Node->RVal || ParentOp == OP_DEREF) { if (TypeIsPtr(Node->ExprType)) {
if(Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM) return AsAddr(Node->Symbol);
}
if (Node->RVal || ParentOp == OP_DEREF) {
if (Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM)
return AsLdLocalVar(Node->Symbol, Node->Operation); return AsLdLocalVar(Node->Symbol, Node->Operation);
else else
return AsLdGlobalVar(Node->Symbol, Node->Operation); return AsLdGlobalVar(Node->Symbol, Node->Operation);
@ -250,7 +259,7 @@ void DeallocateAllRegisters() {
*/ */
int RetrieveRegister() { int RetrieveRegister() {
for (size_t i = 0; i < 4; i++) { for (size_t i = 0; i < 4; i++) {
if(UsedRegisters[i] == 0) { if (UsedRegisters[i] == 0) {
UsedRegisters[i] = 1; UsedRegisters[i] = 1;
return i; return i;
} }
@ -265,7 +274,7 @@ int RetrieveRegister() {
* @param Register: The Registers index to deallocate. * @param Register: The Registers index to deallocate.
*/ */
void DeallocateRegister(int Register) { void DeallocateRegister(int Register) {
if(UsedRegisters[Register] != 1) { if (UsedRegisters[Register] != 1) {
fprintf(stderr, "Error trying to free register %d\n", Register); fprintf(stderr, "Error trying to free register %d\n", Register);
exit(1); exit(1);
} }
@ -328,15 +337,18 @@ int NewLabel(void) {
* *
*/ */
int AsAlignMemory(int Type, int Offset, int Direction) { int AsAlignMemory(int Type, int Offset, int Direction) {
switch(Type) { switch (Type) {
case RET_CHAR: return Offset; case RET_CHAR:
case RET_INT: case RET_LONG: break; return Offset;
case RET_INT:
case RET_LONG:
break;
default: default:
DieDecimal("Unable to align type", Type); DieDecimal("Unable to align type", Type);
} }
int Alignment = 4; int Alignment = 4;
Offset = (Offset + Direction * (Alignment-1)) & ~(Alignment-1); Offset = (Offset + Direction * (Alignment - 1)) & ~(Alignment - 1);
return (Offset); return (Offset);
} }
@ -345,7 +357,7 @@ int AsIf(struct ASTNode* Node) {
int FalseLabel, EndLabel; int FalseLabel, EndLabel;
FalseLabel = NewLabel(); FalseLabel = NewLabel();
if(Node->Right) if (Node->Right)
EndLabel = NewLabel(); EndLabel = NewLabel();
@ -358,12 +370,12 @@ int AsIf(struct ASTNode* Node) {
DeallocateAllRegisters(); DeallocateAllRegisters();
// Right is the optional else // Right is the optional else
if(Node->Right) if (Node->Right)
AsJmp(EndLabel); AsJmp(EndLabel);
AsLabel(FalseLabel); AsLabel(FalseLabel);
if(Node->Right) { if (Node->Right) {
AssembleTree(Node->Right, -1, Node->Operation); AssembleTree(Node->Right, -1, Node->Operation);
DeallocateAllRegisters(); DeallocateAllRegisters();
AsLabel(EndLabel); AsLabel(EndLabel);
@ -376,7 +388,7 @@ int AsIf(struct ASTNode* Node) {
int AsCompare(int Operation, int RegisterLeft, int RegisterRight) { int AsCompare(int Operation, int RegisterLeft, int RegisterRight) {
printf("Comparing registers %d & %d\n", RegisterLeft, RegisterRight); printf("Comparing registers %d & %d\n", RegisterLeft, RegisterRight);
if(Operation < OP_EQUAL || Operation > OP_GREATE) if (Operation < OP_EQUAL || Operation > OP_GREATE)
Die("Bad Operation in AsCompare"); Die("Bad Operation in AsCompare");
fprintf(OutputFile, "\tcmpq\t%s, %s\n", Registers[RegisterRight], Registers[RegisterLeft]); fprintf(OutputFile, "\tcmpq\t%s, %s\n", Registers[RegisterRight], Registers[RegisterLeft]);
@ -388,10 +400,11 @@ int AsCompare(int Operation, int RegisterLeft, int RegisterRight) {
// Assemble an inverse comparison (a one-line jump) // Assemble an inverse comparison (a one-line jump)
int AsCompareJmp(int Operation, int RegisterLeft, int RegisterRight, int Label) { int AsCompareJmp(int Operation, int RegisterLeft, int RegisterRight, int Label) {
if(Operation < OP_EQUAL || Operation > OP_GREATE) if (Operation < OP_EQUAL || Operation > OP_GREATE)
Die("Bad Operation in AsCompareJmp"); Die("Bad Operation in AsCompareJmp");
printf("\tBranching on comparison of registers %d & %d, with operation %s\n\n", RegisterLeft, RegisterRight, Comparisons[Operation - OP_EQUAL]); printf("\tBranching on comparison of registers %d & %d, with operation %s\n\n", RegisterLeft, RegisterRight,
Comparisons[Operation - OP_EQUAL]);
fprintf(OutputFile, "\tcmpq\t%s, %s\n", Registers[RegisterRight], Registers[RegisterLeft]); fprintf(OutputFile, "\tcmpq\t%s, %s\n", Registers[RegisterRight], Registers[RegisterLeft]);
fprintf(OutputFile, "\t%s\tL%d\n", InvComparisons[Operation - OP_EQUAL], Label); fprintf(OutputFile, "\t%s\tL%d\n", InvComparisons[Operation - OP_EQUAL], Label);
@ -424,7 +437,7 @@ int AsNewString(char* Value) {
AsLabel(Label); AsLabel(Label);
for(CharPtr = Value; *CharPtr; CharPtr++) for (CharPtr = Value; *CharPtr; CharPtr++)
fprintf(OutputFile, "\t.byte\t%d\r\n", *CharPtr); fprintf(OutputFile, "\t.byte\t%d\r\n", *CharPtr);
fprintf(OutputFile, "\t.byte\t0\r\n"); fprintf(OutputFile, "\t.byte\t0\r\n");
@ -544,59 +557,71 @@ int AsLdGlobalVar(struct SymbolTableEntry* Entry, int Operation) {
printf("\tStoring %s's contents into %s, globally\n", Entry->Name, Registers[Reg]); printf("\tStoring %s's contents into %s, globally\n", Entry->Name, Registers[Reg]);
int TypeSize = PrimitiveSize(Entry->Type); int TypeSize = PrimitiveSize(Entry->Type);
switch(TypeSize) { switch (TypeSize) {
case 1: case 1:
switch(Operation) { switch (Operation) {
case OP_PREINC: case OP_PREINC:
fprintf(OutputFile, "\tincb\t%s(\%%rip)\n", Entry->Name); break; fprintf(OutputFile, "\tincb\t%s(\%%rip)\n", Entry->Name);
break;
case OP_PREDEC: case OP_PREDEC:
fprintf(OutputFile, "\tdecb\t%s(\%%rip)\n", Entry->Name); break; fprintf(OutputFile, "\tdecb\t%s(\%%rip)\n", Entry->Name);
break;
} }
fprintf(OutputFile, "\tmovzbq\t%s(\%%rip), %s\n", Entry->Name, Registers[Reg]); fprintf(OutputFile, "\tmovzbq\t%s(\%%rip), %s\n", Entry->Name, Registers[Reg]);
switch(Operation) { switch (Operation) {
case OP_POSTINC: case OP_POSTINC:
fprintf(OutputFile, "\tincb\t%s(\%%rip)\n", Entry->Name); break; fprintf(OutputFile, "\tincb\t%s(\%%rip)\n", Entry->Name);
break;
case OP_POSTDEC: case OP_POSTDEC:
fprintf(OutputFile, "\tdecb\t%s(\%%rip)\n", Entry->Name); break; fprintf(OutputFile, "\tdecb\t%s(\%%rip)\n", Entry->Name);
break;
} }
break; break;
case 4: case 4:
switch(Operation) { switch (Operation) {
case OP_PREINC: case OP_PREINC:
fprintf(OutputFile, "\tincl\t%s(\%%rip)\n", Entry->Name); break; fprintf(OutputFile, "\tincl\t%s(\%%rip)\n", Entry->Name);
break;
case OP_PREDEC: case OP_PREDEC:
fprintf(OutputFile, "\tdecl\t%s(\%%rip)\n", Entry->Name); break; fprintf(OutputFile, "\tdecl\t%s(\%%rip)\n", Entry->Name);
break;
} }
fprintf(OutputFile, "\tmovslq\t%s(\%%rip), %s\n", Entry->Name, Registers[Reg]); fprintf(OutputFile, "\tmovslq\t%s(\%%rip), %s\n", Entry->Name, Registers[Reg]);
switch(Operation) { switch (Operation) {
case OP_POSTINC: case OP_POSTINC:
fprintf(OutputFile, "\tincl\t%s(\%%rip)\n", Entry->Name); break; fprintf(OutputFile, "\tincl\t%s(\%%rip)\n", Entry->Name);
break;
case OP_POSTDEC: case OP_POSTDEC:
fprintf(OutputFile, "\tdecl\t%s(\%%rip)\n", Entry->Name); break; fprintf(OutputFile, "\tdecl\t%s(\%%rip)\n", Entry->Name);
break;
} }
break; break;
case 8: case 8:
switch(Operation) { switch (Operation) {
case OP_PREINC: case OP_PREINC:
fprintf(OutputFile, "\tincq\t%s(\%%rip)\n", Entry->Name); break; fprintf(OutputFile, "\tincq\t%s(\%%rip)\n", Entry->Name);
break;
case OP_PREDEC: case OP_PREDEC:
fprintf(OutputFile, "\tdecq\t%s(\%%rip)\n", Entry->Name); break; fprintf(OutputFile, "\tdecq\t%s(\%%rip)\n", Entry->Name);
break;
} }
fprintf(OutputFile, "\tmovq\t%s(\%%rip), %s\n", Entry->Name, Registers[Reg]); fprintf(OutputFile, "\tmovq\t%s(\%%rip), %s\n", Entry->Name, Registers[Reg]);
switch(Operation) { switch (Operation) {
case OP_POSTINC: case OP_POSTINC:
fprintf(OutputFile, "\tincq\t%s(\%%rip)\n", Entry->Name); break; fprintf(OutputFile, "\tincq\t%s(\%%rip)\n", Entry->Name);
break;
case OP_POSTDEC: case OP_POSTDEC:
fprintf(OutputFile, "\tdecq\t%s(\%%rip)\n", Entry->Name); break; fprintf(OutputFile, "\tdecq\t%s(\%%rip)\n", Entry->Name);
break;
} }
break; break;
@ -617,7 +642,7 @@ int AsStrGlobalVar(struct SymbolTableEntry* Entry, int Register) {
printf("\tStoring contents of %s into %s, type %d, globally:\n", Registers[Register], Entry->Name, Entry->Type); printf("\tStoring contents of %s into %s, type %d, globally:\n", Registers[Register], Entry->Name, Entry->Type);
int TypeSize = PrimitiveSize(Entry->Type); int TypeSize = PrimitiveSize(Entry->Type);
switch(TypeSize) { switch (TypeSize) {
case 1: case 1:
// movzbq zeroes, then moves a byte into the quad register // movzbq zeroes, then moves a byte into the quad register
fprintf(OutputFile, "\tmovb\t%s, %s(\%%rip)\n", ByteRegisters[Register], Entry->Name); fprintf(OutputFile, "\tmovb\t%s, %s(\%%rip)\n", ByteRegisters[Register], Entry->Name);
@ -650,59 +675,71 @@ int AsLdLocalVar(struct SymbolTableEntry* Entry, int Operation) {
printf("\tStoring the var at %d's contents into %s, locally\n", Entry->SinkOffset, Registers[Reg]); printf("\tStoring the var at %d's contents into %s, locally\n", Entry->SinkOffset, Registers[Reg]);
int TypeSize = PrimitiveSize(Entry->Type); int TypeSize = PrimitiveSize(Entry->Type);
switch(TypeSize) { switch (TypeSize) {
case 1: case 1:
switch(Operation) { switch (Operation) {
case OP_PREINC: case OP_PREINC:
fprintf(OutputFile, "\tincb\t%d(\%%rbp)\n", Entry->SinkOffset); break; fprintf(OutputFile, "\tincb\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
case OP_PREDEC: case OP_PREDEC:
fprintf(OutputFile, "\tdecb\t%d(\%%rbp)\n", Entry->SinkOffset); break; fprintf(OutputFile, "\tdecb\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
} }
fprintf(OutputFile, "\tmovzbq\t%d(\%%rbp), %s\n", Entry->SinkOffset, Registers[Reg]); fprintf(OutputFile, "\tmovzbq\t%d(\%%rbp), %s\n", Entry->SinkOffset, Registers[Reg]);
switch(Operation) { switch (Operation) {
case OP_POSTINC: case OP_POSTINC:
fprintf(OutputFile, "\tincb\t%d(\%%rbp)\n", Entry->SinkOffset); break; fprintf(OutputFile, "\tincb\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
case OP_POSTDEC: case OP_POSTDEC:
fprintf(OutputFile, "\tdecb\t%d(\%%rbp)\n", Entry->SinkOffset); break; fprintf(OutputFile, "\tdecb\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
} }
break; break;
case 4: case 4:
switch(Operation) { switch (Operation) {
case OP_PREINC: case OP_PREINC:
fprintf(OutputFile, "\tincl\t%d(\%%rbp)\n", Entry->SinkOffset); break; fprintf(OutputFile, "\tincl\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
case OP_PREDEC: case OP_PREDEC:
fprintf(OutputFile, "\tdecl\t%d(\%%rbp)\n", Entry->SinkOffset); break; fprintf(OutputFile, "\tdecl\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
} }
fprintf(OutputFile, "\tmovslq\t%d(\%%rbp), %s\n", Entry->SinkOffset, Registers[Reg]); fprintf(OutputFile, "\tmovslq\t%d(\%%rbp), %s\n", Entry->SinkOffset, Registers[Reg]);
switch(Operation) { switch (Operation) {
case OP_POSTINC: case OP_POSTINC:
fprintf(OutputFile, "\tincl\t%d(\%%rbp)\n", Entry->SinkOffset); break; fprintf(OutputFile, "\tincl\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
case OP_POSTDEC: case OP_POSTDEC:
fprintf(OutputFile, "\tdecl\t%d(\%%rbp)\n", Entry->SinkOffset); break; fprintf(OutputFile, "\tdecl\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
} }
break; break;
case 8: case 8:
switch(Operation) { switch (Operation) {
case OP_PREINC: case OP_PREINC:
fprintf(OutputFile, "\tincq\t%d(\%%rbp)\n", Entry->SinkOffset); break; fprintf(OutputFile, "\tincq\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
case OP_PREDEC: case OP_PREDEC:
fprintf(OutputFile, "\tdecq\t%d(\%%rbp)\n", Entry->SinkOffset); break; fprintf(OutputFile, "\tdecq\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
} }
fprintf(OutputFile, "\tmovq\t%d(\%%rbp), %s\n", Entry->SinkOffset, Registers[Reg]); fprintf(OutputFile, "\tmovq\t%d(\%%rbp), %s\n", Entry->SinkOffset, Registers[Reg]);
switch(Operation) { switch (Operation) {
case OP_POSTINC: case OP_POSTINC:
fprintf(OutputFile, "\tincq\t%d(\%%rbp)\n", Entry->SinkOffset); break; fprintf(OutputFile, "\tincq\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
case OP_POSTDEC: case OP_POSTDEC:
fprintf(OutputFile, "\tdecq\t%d(\%%rbp)\n", Entry->SinkOffset); break; fprintf(OutputFile, "\tdecq\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
} }
break; break;
@ -724,7 +761,7 @@ int AsStrLocalVar(struct SymbolTableEntry* Entry, int Register) {
printf("\tStoring contents of %s into %s, type %d, locally\n", Registers[Register], Entry->Name, Entry->Type); printf("\tStoring contents of %s into %s, type %d, locally\n", Registers[Register], Entry->Name, Entry->Type);
int TypeSize = PrimitiveSize(Entry->Type); int TypeSize = PrimitiveSize(Entry->Type);
switch(TypeSize) { switch (TypeSize) {
case 1: case 1:
// movzbq zeroes, then moves a byte into the quad register // movzbq zeroes, then moves a byte into the quad register
fprintf(OutputFile, "\tmovb\t%s, %d(\%%rbp)\n", ByteRegisters[Register], Entry->SinkOffset); fprintf(OutputFile, "\tmovb\t%s, %d(\%%rbp)\n", ByteRegisters[Register], Entry->SinkOffset);
@ -760,13 +797,16 @@ int AsDeref(int Reg, int Type) {
int DestSize = PrimitiveSize(ValueAt(Type)); int DestSize = PrimitiveSize(ValueAt(Type));
printf("\tDereferencing %s\n", Registers[Reg]); printf("\tDereferencing %s\n", Registers[Reg]);
switch(DestSize) { switch (DestSize) {
case 1: case 1:
fprintf(OutputFile, "\tmovzbq\t(%s), %s\n", Registers[Reg], Registers[Reg]); fprintf(OutputFile, "\tmovzbq\t(%s), %s\n", Registers[Reg], ByteRegisters[Reg]);
break; break;
case 2: case 2:
fprintf(OutputFile, "\tmovslq\t(%s), %s\n", Registers[Reg], Registers[Reg]); fprintf(OutputFile, "\tmovslq\t(%s), %s\n", Registers[Reg], DoubleRegisters[Reg]);
break;
case 4: case 4:
fprintf(OutputFile, "\tmovl\t(%s), %s\n", Registers[Reg], DoubleRegisters[Reg]);
break;
case 8: case 8:
fprintf(OutputFile, "\tmovq\t(%s), %s\n", Registers[Reg], Registers[Reg]); fprintf(OutputFile, "\tmovq\t(%s), %s\n", Registers[Reg], Registers[Reg]);
break; break;
@ -779,13 +819,16 @@ int AsDeref(int Reg, int Type) {
// Assemble a store-through-dereference // Assemble a store-through-dereference
int AsStrDeref(int Register1, int Register2, int Type) { int AsStrDeref(int Register1, int Register2, int Type) {
printf("\tStoring contents of %s into %s through a dereference, type %d\n", Registers[Register1], Registers[Register2], Type); printf("\tStoring contents of %s into %s through a dereference, type %d\n", Registers[Register1],
Registers[Register2], Type);
switch(Type) { switch (Type) {
case RET_CHAR: case RET_CHAR:
fprintf(OutputFile, "\tmovb\t%s, (%s)\n", ByteRegisters[Register1], Registers[Register2]); fprintf(OutputFile, "\tmovb\t%s, (%s)\n", ByteRegisters[Register1], Registers[Register2]);
break; break;
case RET_INT: case RET_INT:
fprintf(OutputFile, "\tmovl\t%s, (%s)\n", DoubleRegisters[Register1], Registers[Register2]);
break;
case RET_LONG: case RET_LONG:
fprintf(OutputFile, "\tmovq\t%s, (%s)\n", Registers[Register1], Registers[Register2]); fprintf(OutputFile, "\tmovq\t%s, (%s)\n", Registers[Register1], Registers[Register2]);
break; break;
@ -799,8 +842,8 @@ int AsStrDeref(int Register1, int Register2, int Type) {
// Assemble a global symbol (variable, struct, enum, function, string) // Assemble a global symbol (variable, struct, enum, function, string)
void AsGlobalSymbol(struct SymbolTableEntry* Entry) { void AsGlobalSymbol(struct SymbolTableEntry* Entry) {
if(Entry == NULL) return; if (Entry == NULL) return;
if(Entry->Structure == ST_FUNC) return; if (Entry->Structure == ST_FUNC) return;
int Size = TypeSize(Entry->Type, Entry->CompositeType); int Size = TypeSize(Entry->Type, Entry->CompositeType);
@ -811,12 +854,18 @@ void AsGlobalSymbol(struct SymbolTableEntry* Entry) {
fprintf(OutputFile, "%s:\n", Entry->Name); fprintf(OutputFile, "%s:\n", Entry->Name);
switch(Size) { switch (Size) {
case 1: fprintf(OutputFile, "\t.byte\t0\r\n", Entry->Name); break; case 1:
case 4: fprintf(OutputFile, "\t.long\t0\r\n", Entry->Name); break; fprintf(OutputFile, "\t.byte\t0\r\n", Entry->Name);
case 8: fprintf(OutputFile, "\t.quad\t0\r\n", Entry->Name); break; break;
case 4:
fprintf(OutputFile, "\t.long\t0\r\n", Entry->Name);
break;
case 8:
fprintf(OutputFile, "\t.quad\t0\r\n", Entry->Name);
break;
default: default:
for(int i = 0; i < Size; i++) for (int i = 0; i < Size; i++)
fprintf(OutputFile, "\t.byte\t0\n"); fprintf(OutputFile, "\t.byte\t0\n");
} }
@ -827,10 +876,10 @@ int AsCallWrapper(struct ASTNode* Node) {
struct ASTNode* CompositeTree = Node->Left; struct ASTNode* CompositeTree = Node->Left;
int Register, Args = 0; int Register, Args = 0;
while(CompositeTree) { while (CompositeTree) {
Register = AssembleTree(CompositeTree->Right, -1, CompositeTree->Operation); Register = AssembleTree(CompositeTree->Right, -1, CompositeTree->Operation);
AsCopyArgs(Register, CompositeTree->Size); AsCopyArgs(Register, CompositeTree->Size);
if(Args == 0) Args = CompositeTree->Size; if (Args == 0) Args = CompositeTree->Size;
DeallocateAllRegisters(); DeallocateAllRegisters();
CompositeTree = CompositeTree->Left; CompositeTree = CompositeTree->Left;
} }
@ -840,10 +889,10 @@ int AsCallWrapper(struct ASTNode* Node) {
// Copy a function argument from Register to argument Position // Copy a function argument from Register to argument Position
void AsCopyArgs(int Register, int Position) { void AsCopyArgs(int Register, int Position) {
if(Position > 4) { // Args above 4 go on the stack if (Position > 4) { // Args above 4 go on the stack
fprintf(OutputFile, "\tpushq\t%s\n", Registers[Register]); fprintf(OutputFile, "\tpushq\t%s\n", Registers[Register]);
} else { } else {
fprintf(OutputFile, "\tmovq\t%s, %s\n", Registers[Register], Registers[10 - Position]); fprintf(OutputFile, "\tmovq\t%s, %s\n", Registers[Register], Registers[8 - Position]);
} }
} }
@ -857,7 +906,7 @@ int AsCall(struct SymbolTableEntry* Entry, int Args) {
printf("\t\t\tFunction returns into %s\n", Registers[OutRegister]); printf("\t\t\tFunction returns into %s\n", Registers[OutRegister]);
fprintf(OutputFile, "\tcall\t%s\n", Entry->Name); fprintf(OutputFile, "\tcall\t%s\n", Entry->Name);
if(Args > 4) if (Args > 4)
fprintf(OutputFile, "\taddq\t$%d, %%rsp\n", 8 * (Args - 4)); fprintf(OutputFile, "\taddq\t$%d, %%rsp\n", 8 * (Args - 4));
fprintf(OutputFile, "\tmovq\t%%rax, %s\n", Registers[OutRegister]); fprintf(OutputFile, "\tmovq\t%%rax, %s\n", Registers[OutRegister]);
@ -870,7 +919,7 @@ int AsReturn(struct SymbolTableEntry* Entry, int Register) {
printf("\t\tCreating return for function %s\n", Entry->Name); printf("\t\tCreating return for function %s\n", Entry->Name);
switch(Entry->Type) { switch (Entry->Type) {
case RET_CHAR: case RET_CHAR:
fprintf(OutputFile, "\tmovzbl\t%s, %%eax\n", ByteRegisters[Register]); fprintf(OutputFile, "\tmovzbl\t%s, %%eax\n", ByteRegisters[Register]);
break; break;
@ -1001,7 +1050,7 @@ int AsShiftRight(int Left, int Right) {
int AsBooleanConvert(int Register, int Operation, int Label) { int AsBooleanConvert(int Register, int Operation, int Label) {
fprintf(OutputFile, "\ttest\t%s, %s\n", Registers[Register], Registers[Register]); fprintf(OutputFile, "\ttest\t%s, %s\n", Registers[Register], Registers[Register]);
switch(Operation) { switch (Operation) {
case OP_IF: case OP_IF:
case OP_LOOP: case OP_LOOP:
fprintf(OutputFile, "\tje\tL%d\n", Label); fprintf(OutputFile, "\tje\tL%d\n", Label);
@ -1036,7 +1085,7 @@ void AssemblerPreamble() {
*/ */
void AsFunctionPreamble(struct SymbolTableEntry* Entry) { void AsFunctionPreamble(struct SymbolTableEntry* Entry) {
char* Name = Entry->Name; char* Name = Entry->Name;
struct SymbolTableEntry* Param, *Local; struct SymbolTableEntry* Param, * Local;
int ParamOffset = 0, ParamReg = 9, ParamCount = 0; int ParamOffset = 0, ParamReg = 9, ParamCount = 0;
LocalVarOffset = 4; // Prepare parameters LocalVarOffset = 4; // Prepare parameters
@ -1051,15 +1100,15 @@ void AsFunctionPreamble(struct SymbolTableEntry* Entry) {
Name, Name, Name); Name, Name, Name);
//PECOFF requires we call the global initialisers //PECOFF requires we call the global initialisers
if(!strcmp(Name, "main")) if (!strcmp(Name, "main"))
fprintf(OutputFile, "\tcall\t__main\n"); fprintf(OutputFile, "\tcall\t__main\n");
// Need to share this between two loops. Fun. // Need to share this between two loops. Fun.
int LoopIndex; int LoopIndex;
// If we have parameters, move them to the last 4 registers // If we have parameters, move them to the last 4 registers
for(Param = Entry->Start, ParamCount = 1; Param != NULL; Param = Param->NextSymbol, ParamCount++) { for (Param = Entry->Start, ParamCount = 1; Param != NULL; Param = Param->NextSymbol, ParamCount++) {
if(ParamCount > 4) { // We only have 4 argument registers if (ParamCount > 4) { // We only have 4 argument registers
Param->SinkOffset = ParamOffset; Param->SinkOffset = ParamOffset;
ParamOffset += 8; ParamOffset += 8;
} }
@ -1069,7 +1118,7 @@ void AsFunctionPreamble(struct SymbolTableEntry* Entry) {
} }
// If we have more parameters, move them to the stack // If we have more parameters, move them to the stack
for(Local = Locals; Local != NULL; Local = Local->NextSymbol) { for (Local = Locals; Local != NULL; Local = Local->NextSymbol) {
Local->SinkOffset = AsCalcOffset(Local->Type); Local->SinkOffset = AsCalcOffset(Local->Type);
} }

View File

@ -31,17 +31,17 @@
*/ */
char* Suffixate(char* String, char Suffix) { char* Suffixate(char* String, char Suffix) {
char* Pos, *NewStr; char* Pos, * NewStr;
if((NewStr = strdup(String)) == NULL) if ((NewStr = strdup(String)) == NULL)
return NULL; return NULL;
if((Pos = strrchr(NewStr, '.')) == NULL) if ((Pos = strrchr(NewStr, '.')) == NULL)
return NULL; return NULL;
Pos++; Pos++;
if(*Pos == '\0') if (*Pos == '\0')
return NULL; return NULL;
*Pos++ = Suffix; *Pos++ = Suffix;
@ -68,17 +68,17 @@ char* Suffixate(char* String, char Suffix) {
char* Compile(char* InputFile) { char* Compile(char* InputFile) {
char* OutputName; char* OutputName;
OutputName = Suffixate(InputFile, 's'); OutputName = Suffixate(InputFile, 's');
if(OutputName == NULL) { if (OutputName == NULL) {
fprintf(stderr, "%s must have a suffix.\r\n", InputFile); fprintf(stderr, "%s must have a suffix.\r\n", InputFile);
exit(1); exit(1);
} }
if((SourceFile = fopen(InputFile, "r")) == NULL) { if ((SourceFile = fopen(InputFile, "r")) == NULL) {
fprintf(stderr, "Unable to open %s: %s\n", InputFile, strerror(errno)); fprintf(stderr, "Unable to open %s: %s\n", InputFile, strerror(errno));
exit(1); exit(1);
} }
if((OutputFile = fopen(OutputName, "w")) == NULL) { if ((OutputFile = fopen(OutputName, "w")) == NULL) {
fprintf(stderr, "Unable to open %s: %s\n", OutputName, strerror(errno)); fprintf(stderr, "Unable to open %s: %s\n", OutputName, strerror(errno));
exit(1); exit(1);
} }
@ -88,7 +88,7 @@ char* Compile(char* InputFile) {
CurrentGlobal = 0; CurrentGlobal = 0;
CurrentLocal = SYMBOLS - 1; CurrentLocal = SYMBOLS - 1;
if(OptVerboseOutput) if (OptVerboseOutput)
printf("Compiling %s\r\n", InputFile); printf("Compiling %s\r\n", InputFile);
Tokenise(); Tokenise();
@ -120,18 +120,18 @@ char* Assemble(char* InputFile) {
int Error; int Error;
char* OutputName; char* OutputName;
OutputName = Suffixate(InputFile, 'o'); OutputName = Suffixate(InputFile, 'o');
if(OutputName == NULL) { if (OutputName == NULL) {
fprintf(stderr, "%s must have a suffix.\r\n", InputFile); fprintf(stderr, "%s must have a suffix.\r\n", InputFile);
exit(1); exit(1);
} }
snprintf(Command, TEXTLEN, "%s %s %s", "as -o ", OutputName, InputFile); snprintf(Command, TEXTLEN, "%s %s %s", "as -o ", OutputName, InputFile);
if(OptVerboseOutput) if (OptVerboseOutput)
printf("%s\n", Command); printf("%s\n", Command);
Error = system(Command); Error = system(Command);
if(Error != 0) { if (Error != 0) {
fprintf(stderr, "Assembling of %s failed with code %d\n", InputFile, Error); fprintf(stderr, "Assembling of %s failed with code %d\n", InputFile, Error);
exit(1); exit(1);
} }
@ -152,26 +152,26 @@ char* Assemble(char* InputFile) {
void Link(char* Output, char* Objects[]) { void Link(char* Output, char* Objects[]) {
int Count, Size = TEXTLEN, Error; int Count, Size = TEXTLEN, Error;
char Command[TEXTLEN], *CommandPtr; char Command[TEXTLEN], * CommandPtr;
CommandPtr = Command; CommandPtr = Command;
Count = snprintf(CommandPtr, Size, "%s %s ", "gcc -o ", OutputFileName); Count = snprintf(CommandPtr, Size, "%s %s ", "gcc -o ", OutputFileName);
CommandPtr += Count; CommandPtr += Count;
Size -= Count; Size -= Count;
while(*Objects != NULL) { while (*Objects != NULL) {
Count = snprintf(CommandPtr, Size, "%s ", *Objects); Count = snprintf(CommandPtr, Size, "%s ", *Objects);
CommandPtr += Count; CommandPtr += Count;
Size -= Count; Size -= Count;
Objects++; Objects++;
} }
if(OptVerboseOutput) if (OptVerboseOutput)
printf("%s\n", Command); printf("%s\n", Command);
Error = system(Command); Error = system(Command);
if(Error != 0) { if (Error != 0) {
fprintf(stderr, "Link failure\n"); fprintf(stderr, "Link failure\n");
exit(1); exit(1);
} }

View File

@ -19,13 +19,13 @@ void DumpTree(struct ASTNode* Node, int level) {
int Lfalse, Lstart, Lend; int Lfalse, Lstart, Lend;
// Handle weirdo loops and conditions first. // Handle weirdo loops and conditions first.
switch(Node->Operation) { switch (Node->Operation) {
case OP_IF: case OP_IF:
Lfalse = GenerateSrg(); Lfalse = GenerateSrg();
for(int i = 0; i < level; i++) for (int i = 0; i < level; i++)
fprintf(stdout, " "); fprintf(stdout, " ");
fprintf(stdout, "IF"); fprintf(stdout, "IF");
if(Node->Right) { if (Node->Right) {
Lend = GenerateSrg(); Lend = GenerateSrg();
fprintf(stdout, ", end label %d", Lend); fprintf(stdout, ", end label %d", Lend);
} }
@ -34,13 +34,13 @@ void DumpTree(struct ASTNode* Node, int level) {
DumpTree(Node->Left, level + 2); DumpTree(Node->Left, level + 2);
DumpTree(Node->Middle, level + 2); DumpTree(Node->Middle, level + 2);
if(Node->Right) if (Node->Right)
DumpTree(Node->Right, level + 2); DumpTree(Node->Right, level + 2);
return; return;
case OP_LOOP: case OP_LOOP:
Lstart = GenerateSrg(); Lstart = GenerateSrg();
for(int i = 0; i < level; i++) for (int i = 0; i < level; i++)
fprintf(stdout, " "); fprintf(stdout, " ");
fprintf(stdout, "LOOP starts at %d\n", Lstart); fprintf(stdout, "LOOP starts at %d\n", Lstart);
Lend = GenerateSrg(); Lend = GenerateSrg();
@ -50,68 +50,139 @@ void DumpTree(struct ASTNode* Node, int level) {
} }
// If current node is a compound, we treat it as if we didn't just enter a loop. // If current node is a compound, we treat it as if we didn't just enter a loop.
if(Node->Operation == OP_COMP) if (Node->Operation == OP_COMP)
level = -2; level = -2;
if(Node->Left) if (Node->Left)
DumpTree(Node->Left, level + 2); DumpTree(Node->Left, level + 2);
if(Node->Right) if (Node->Right)
DumpTree(Node->Right, level + 2); DumpTree(Node->Right, level + 2);
// The meat of this operation! // The meat of this operation!
for(int i = 0; i < level; i++) for (int i = 0; i < level; i++)
fprintf(stdout, " "); fprintf(stdout, " ");
switch (Node->Operation){ switch (Node->Operation) {
case OP_COMP: fprintf(stdout, "\n\n"); return; case OP_COMP:
case OP_FUNC: fprintf(stdout, "OP_FUNC %s\n", Node->Symbol->Name); return; fprintf(stdout, "\n\n");
case OP_ADD: fprintf(stdout, "OP_ADD\n"); return; return;
case OP_SUBTRACT: fprintf(stdout, "OP_SUBTRACT\n"); return; case OP_FUNC:
case OP_MULTIPLY: fprintf(stdout, "OP_MULTIPLY\n"); return; fprintf(stdout, "OP_FUNC %s\n", Node->Symbol->Name);
case OP_DIVIDE: fprintf(stdout, "OP_DIVIDE\n"); return; return;
case OP_EQUAL: fprintf(stdout, "OP_EQUAL\n"); return; case OP_ADD:
case OP_INEQ: fprintf(stdout, "OP_INEQ\n"); return; fprintf(stdout, "OP_ADD\n");
case OP_LESS: fprintf(stdout, "OP_LESS\n"); return; return;
case OP_GREAT: fprintf(stdout, "OP_GREAT\n"); return; case OP_SUBTRACT:
case OP_LESSE: fprintf(stdout, "OP_LESSE\n"); return; fprintf(stdout, "OP_SUBTRACT\n");
case OP_GREATE: fprintf(stdout, "OP_GREATE\n"); return; return;
case TERM_INTLITERAL: fprintf(stdout, "TERM_INTLITERAL %d\n", Node->IntValue); return; case OP_MULTIPLY:
case TERM_STRLITERAL: fprintf(stdout, "TERM_STRLITERAL rval L%d\n", Node->IntValue); return; fprintf(stdout, "OP_MULTIPLY\n");
return;
case OP_DIVIDE:
fprintf(stdout, "OP_DIVIDE\n");
return;
case OP_EQUAL:
fprintf(stdout, "OP_EQUAL\n");
return;
case OP_INEQ:
fprintf(stdout, "OP_INEQ\n");
return;
case OP_LESS:
fprintf(stdout, "OP_LESS\n");
return;
case OP_GREAT:
fprintf(stdout, "OP_GREAT\n");
return;
case OP_LESSE:
fprintf(stdout, "OP_LESSE\n");
return;
case OP_GREATE:
fprintf(stdout, "OP_GREATE\n");
return;
case TERM_INTLITERAL:
fprintf(stdout, "TERM_INTLITERAL %d\n", Node->IntValue);
return;
case TERM_STRLITERAL:
fprintf(stdout, "TERM_STRLITERAL rval L%d\n", Node->IntValue);
return;
case REF_IDENT: case REF_IDENT:
if(Node->RVal) if (Node->RVal)
fprintf(stdout, "REF_IDENT rval %s\n", Node->Symbol->Name); fprintf(stdout, "REF_IDENT rval %s\n", Node->Symbol->Name);
else else
fprintf(stdout, "REF_IDENT %s\n", Node->Symbol->Name); fprintf(stdout, "REF_IDENT %s\n", Node->Symbol->Name);
return; return;
case OP_ASSIGN: fprintf(stdout, "OP_ASSIGN\n"); return; case OP_ASSIGN:
case OP_WIDEN: fprintf(stdout, "OP_WIDEN\n"); return; fprintf(stdout, "OP_ASSIGN\n");
case OP_RET: fprintf(stdout, "OP_RET\n"); return; return;
case OP_CALL: fprintf(stdout, "OP_CALL %s\n", Node->Symbol->Name); return; case OP_WIDEN:
case OP_ADDRESS: fprintf(stdout, "OP_ADDRESS %s\n", Node->Symbol->Name); return; fprintf(stdout, "OP_WIDEN\n");
return;
case OP_RET:
fprintf(stdout, "OP_RET\n");
return;
case OP_CALL:
fprintf(stdout, "OP_CALL %s\n", Node->Symbol->Name);
return;
case OP_ADDRESS:
fprintf(stdout, "OP_ADDRESS %s\n", Node->Symbol->Name);
return;
case OP_DEREF: case OP_DEREF:
fprintf(stdout, "OP_DEREF %s\n", Node->RVal ? "rval" : ""); return; fprintf(stdout, "OP_DEREF %s\n", Node->RVal ? "rval" : "");
case OP_SCALE: fprintf(stdout, "OP_SCALE %s\n", TypeNames(Node->Size)); return; return;
case OP_SCALE:
fprintf(stdout, "OP_SCALE %s\n", TypeNames(Node->Size));
return;
case OP_BOOLOR: fprintf(stdout, "OP_BOOLOR\n"); return; case OP_BOOLOR:
case OP_BOOLAND: fprintf(stdout, "OP_BOOLAND\n"); return; fprintf(stdout, "OP_BOOLOR\n");
case OP_BITOR: fprintf(stdout, "OP_BITOR\n"); return; return;
case OP_BITXOR: fprintf(stdout, "OP_BITXOR\n"); return; case OP_BOOLAND:
case OP_BITAND: fprintf(stdout, "OP_BITAND\n"); return; fprintf(stdout, "OP_BOOLAND\n");
return;
case OP_BITOR:
fprintf(stdout, "OP_BITOR\n");
return;
case OP_BITXOR:
fprintf(stdout, "OP_BITXOR\n");
return;
case OP_BITAND:
fprintf(stdout, "OP_BITAND\n");
return;
case OP_SHIFTL: fprintf(stdout, "OP_SHIFTL\n"); return; case OP_SHIFTL:
case OP_SHIFTR: fprintf(stdout, "OP_SHIFTR\n"); return; fprintf(stdout, "OP_SHIFTL\n");
return;
case OP_SHIFTR:
fprintf(stdout, "OP_SHIFTR\n");
return;
case OP_PREINC: fprintf(stdout, "OP_PREINC\n"); return; case OP_PREINC:
case OP_PREDEC: fprintf(stdout, "OP_PREDEC\n"); return; fprintf(stdout, "OP_PREINC\n");
case OP_POSTINC: fprintf(stdout, "OP_POSTINC\n"); return; return;
case OP_POSTDEC: fprintf(stdout, "OP_POSTDEC\n"); return; case OP_PREDEC:
fprintf(stdout, "OP_PREDEC\n");
return;
case OP_POSTINC:
fprintf(stdout, "OP_POSTINC\n");
return;
case OP_POSTDEC:
fprintf(stdout, "OP_POSTDEC\n");
return;
case OP_BITNOT: fprintf(stdout, "OP_BITNOT\n"); return; case OP_BITNOT:
case OP_BOOLNOT: fprintf(stdout, "OP_BOOLNOT\n"); return; fprintf(stdout, "OP_BITNOT\n");
case OP_NEGATE: fprintf(stdout, "OP_NEGATE\n"); return; return;
case OP_BOOLNOT:
fprintf(stdout, "OP_BOOLNOT\n");
return;
case OP_NEGATE:
fprintf(stdout, "OP_NEGATE\n");
return;
case OP_BOOLCONV: fprintf(stdout, "OP_BOOLCONV\n"); return; case OP_BOOLCONV:
fprintf(stdout, "OP_BOOLCONV\n");
return;
default: default:
DieDecimal("Unknown Dump Operator", Node->Operation); DieDecimal("Unknown Dump Operator", Node->Operation);

View File

@ -37,7 +37,7 @@ static void ReturnCharToStream(int Char) {
static int NextChar(void) { static int NextChar(void) {
int Char; int Char;
if(Overread) { if (Overread) {
Char = Overread; Char = Overread;
Overread = 0; Overread = 0;
return Char; return Char;
@ -45,7 +45,7 @@ static int NextChar(void) {
Char = fgetc(SourceFile); Char = fgetc(SourceFile);
if(Char == '\n') if (Char == '\n')
Line++; Line++;
return Char; return Char;
@ -61,7 +61,7 @@ static int FindChar() {
Char = NextChar(); Char = NextChar();
while(Char == ' ' || Char == '\t' || Char == '\n' || Char == '\r') { while (Char == ' ' || Char == '\t' || Char == '\n' || Char == '\r') {
Char = NextChar(); Char = NextChar();
} }
@ -77,7 +77,7 @@ static int FindChar() {
static int FindDigitFromPos(char* String, char Char) { static int FindDigitFromPos(char* String, char Char) {
char* Result = strchr(String, Char); char* Result = strchr(String, Char);
return(Result ? Result - String : -1); return (Result ? Result - String : -1);
} }
/* /*
@ -91,7 +91,7 @@ static int FindDigitFromPos(char* String, char Char) {
*/ */
void VerifyToken(int Type, char* TokenExpected) { void VerifyToken(int Type, char* TokenExpected) {
if(CurrentToken.type == Type) if (CurrentToken.type == Type)
Tokenise(); Tokenise();
else { else {
printf("Expected %s on line %d\n", TokenExpected, Line); printf("Expected %s on line %d\n", TokenExpected, Line);
@ -108,7 +108,7 @@ static struct Token* RejectedToken = NULL;
*/ */
void RejectToken(struct Token* Token) { void RejectToken(struct Token* Token) {
if(RejectedToken != NULL) if (RejectedToken != NULL)
Die("Cannot reject two tokens in a row!"); Die("Cannot reject two tokens in a row!");
RejectedToken = Token; RejectedToken = Token;
@ -137,7 +137,7 @@ static int ReadInteger(int Char) {
int CurrentChar = 0; int CurrentChar = 0;
int IntegerValue = 0; int IntegerValue = 0;
while((CurrentChar = FindDigitFromPos("0123456789", Char)) >= 0) { while ((CurrentChar = FindDigitFromPos("0123456789", Char)) >= 0) {
IntegerValue = IntegerValue * 10 + CurrentChar; IntegerValue = IntegerValue * 10 + CurrentChar;
Char = NextChar(); Char = NextChar();
} }
@ -168,7 +168,7 @@ static int ReadIdentifier(int Char, char* Buffer, int Limit) {
int ind = 0; int ind = 0;
// This defines the valid chars in a keyword/variable/function. // This defines the valid chars in a keyword/variable/function.
while(isalpha(Char) || isdigit(Char) || Char == '_') { while (isalpha(Char) || isdigit(Char) || Char == '_') {
if (ind >= Limit - 1) { if (ind >= Limit - 1) {
printf("Identifier too long: %d\n", Line); printf("Identifier too long: %d\n", Line);
exit(1); exit(1);
@ -199,18 +199,28 @@ static int ReadIdentifier(int Char, char* Buffer, int Limit) {
static int ReadCharLiteral() { static int ReadCharLiteral() {
int Char; int Char;
Char = NextChar(); Char = NextChar();
if(Char == '\\') { if (Char == '\\') {
switch(Char = NextChar()) { switch (Char = NextChar()) {
case 'a': return '\a'; case 'a':
case 'b': return '\b'; return '\a';
case 'f': return '\f'; case 'b':
case 'n': return '\n'; return '\b';
case 'r': return '\r'; case 'f':
case 't': return '\t'; return '\f';
case 'v': return '\v'; case 'n':
case '\\': return '\\'; return '\n';
case '"': return '"'; case 'r':
case '\'': return '\''; return '\r';
case 't':
return '\t';
case 'v':
return '\v';
case '\\':
return '\\';
case '"':
return '"';
case '\'':
return '\'';
default: default:
DieChar("Unknown Escape: ", Char); DieChar("Unknown Escape: ", Char);
} }
@ -236,9 +246,10 @@ static int ReadCharLiteral() {
static int ReadStringLiteral(char* Buffer) { static int ReadStringLiteral(char* Buffer) {
int Char; int Char;
for(int i = 0; i < TEXTLEN - 1; i++) { for (int i = 0; i < TEXTLEN - 1; i++) {
if((Char = ReadCharLiteral()) == '"') { if ((Char = ReadCharLiteral()) == '"') {
Buffer[i] = 0; return i; Buffer[i] = 0;
return i;
} }
Buffer[i] = Char; Buffer[i] = Char;
@ -265,80 +276,79 @@ static int ReadStringLiteral(char* Buffer) {
*/ */
static int ReadKeyword(char* Str) { static int ReadKeyword(char* Str) {
// First, scan with reference intact. // First, scan with reference intact.
switch(*Str) { switch (*Str) {
// This lets us case against the first char: // This lets us case against the first char:
case ':': case ':':
if(!strcmp(Str, "::")) if (!strcmp(Str, "::"))
return KW_FUNC; return KW_FUNC;
break; break;
case 'c': case 'c':
if(!strcmp(Str, "char")) if (!strcmp(Str, "char"))
return TY_CHAR; return TY_CHAR;
break; break;
case 'e': case 'e':
if(!strcmp(Str, "else")) if (!strcmp(Str, "else"))
return KW_ELSE; return KW_ELSE;
break; break;
case 'f': case 'f':
if(!strcmp(Str, "for")) if (!strcmp(Str, "for"))
return KW_FOR; return KW_FOR;
break; break;
case 'i': case 'i':
// alias char, int and long types // alias char, int and long types
if(!strcmp(Str, "i8")) if (!strcmp(Str, "i8"))
return TY_CHAR; return TY_CHAR;
if(!strcmp(Str, "i32")) if (!strcmp(Str, "i32"))
return TY_INT; return TY_INT;
if(!strcmp(Str, "i64")) if (!strcmp(Str, "i64"))
return TY_LONG; return TY_LONG;
if(!strcmp(Str, "int")) if (!strcmp(Str, "int"))
return TY_INT; return TY_INT;
if(!strcmp(Str, "if")) if (!strcmp(Str, "if"))
return KW_IF; return KW_IF;
break; break;
case 'l': case 'l':
if(!strcmp(Str, "long")) if (!strcmp(Str, "long"))
return TY_LONG; return TY_LONG;
break; break;
case 'p': case 'p':
if(!strcmp(Str, "print")) if (!strcmp(Str, "print"))
return KW_PRINT; return KW_PRINT;
break; break;
case 'r': case 'r':
if(!strcmp(Str, "return")) if (!strcmp(Str, "return"))
return KW_RETURN; return KW_RETURN;
break; break;
case 's': case 's':
if(!strcmp(Str, "struct")) if (!strcmp(Str, "struct"))
return KW_STRUCT; return KW_STRUCT;
break; break;
case 'v': case 'v':
if(!strcmp(Str, "void")) if (!strcmp(Str, "void"))
return TY_VOID; return TY_VOID;
break; break;
case 'w': case 'w':
if(!strcmp(Str, "while")) if (!strcmp(Str, "while"))
return KW_WHILE; return KW_WHILE;
break; break;
} }
return 0; return 0;
@ -364,7 +374,7 @@ void Tokenise() {
int Char, TokenType; int Char, TokenType;
struct Token* Token = &CurrentToken; struct Token* Token = &CurrentToken;
if(RejectedToken != NULL) { if (RejectedToken != NULL) {
Token = RejectedToken; Token = RejectedToken;
RejectedToken = NULL; RejectedToken = NULL;
return; return;
@ -372,7 +382,7 @@ void Tokenise() {
Char = FindChar(); Char = FindChar();
switch(Char) { switch (Char) {
case EOF: case EOF:
Token->type = LI_EOF; Token->type = LI_EOF;
return; return;
@ -384,7 +394,7 @@ void Tokenise() {
case '+': case '+':
// + can be either "+" or "++". // + can be either "+" or "++".
Char = NextChar(); Char = NextChar();
if(Char == '+') { if (Char == '+') {
Token->type = PPMM_PLUS; Token->type = PPMM_PLUS;
} else { } else {
Token->type = AR_PLUS; Token->type = AR_PLUS;
@ -395,9 +405,9 @@ void Tokenise() {
case '-': case '-':
// - can be either "-" or "--" or "->" // - can be either "-" or "--" or "->"
Char = NextChar(); Char = NextChar();
if(Char == '-') { if (Char == '-') {
Token->type = PPMM_MINUS; Token->type = PPMM_MINUS;
} else if(Char == '>') { } else if (Char == '>') {
Token->type = LI_ARROW; Token->type = LI_ARROW;
} else { } else {
Token->type = AR_MINUS; Token->type = AR_MINUS;
@ -415,7 +425,7 @@ void Tokenise() {
case '&': case '&':
Char = NextChar(); Char = NextChar();
if(Char == '&') { if (Char == '&') {
Token->type = BOOL_AND; Token->type = BOOL_AND;
} else { } else {
Token->type = BIT_AND; Token->type = BIT_AND;
@ -425,7 +435,7 @@ void Tokenise() {
case '|': case '|':
Char = NextChar(); Char = NextChar();
if(Char == '|') { if (Char == '|') {
Token->type = BOOL_OR; Token->type = BOOL_OR;
} else { } else {
Token->type = BIT_OR; Token->type = BIT_OR;
@ -448,10 +458,10 @@ void Tokenise() {
case '=': case '=':
Char = NextChar(); Char = NextChar();
// If the next char is =, we have ==, the compare equality token. // If the next char is =, we have ==, the compare equality token.
if(Char == '?') { if (Char == '?') {
Token->type = CMP_EQUAL; Token->type = CMP_EQUAL;
// if the next char is >, we have =>, the greater than or equal token. // if the next char is >, we have =>, the greater than or equal token.
} else if(Char == '>') { } else if (Char == '>') {
Token->type = CMP_GTE; Token->type = CMP_GTE;
// If none of the above match, we have = and an extra char. Return the char and set the token // If none of the above match, we have = and an extra char. Return the char and set the token
} else { } else {
@ -463,7 +473,7 @@ void Tokenise() {
case '!': case '!':
Char = NextChar(); Char = NextChar();
// If the next char is =, we have !=, the compare inequality operator. // If the next char is =, we have !=, the compare inequality operator.
if(Char == '=') { if (Char == '=') {
Token->type = CMP_INEQ; Token->type = CMP_INEQ;
// Otherwise, we have a spare char // Otherwise, we have a spare char
} else { } else {
@ -475,9 +485,9 @@ void Tokenise() {
case '<': case '<':
Char = NextChar(); Char = NextChar();
// If the next char is =, we have <=, the less than or equal comparator. // If the next char is =, we have <=, the less than or equal comparator.
if(Char == '=') { if (Char == '=') {
Token->type = CMP_LTE; Token->type = CMP_LTE;
} else if(Char == '<') { // But if the next char is <, we have << - the Shift Left operator. } else if (Char == '<') { // But if the next char is <, we have << - the Shift Left operator.
Token->type = SH_LEFT; Token->type = SH_LEFT;
} else { } else {
ReturnCharToStream(Char); ReturnCharToStream(Char);
@ -488,7 +498,7 @@ void Tokenise() {
case '>': case '>':
// For >, Less than or equal is => so we can ignore it, but the Shift Right operator is >>. // For >, Less than or equal is => so we can ignore it, but the Shift Right operator is >>.
Char = NextChar(); Char = NextChar();
if(Char == '>') { if (Char == '>') {
Token->type = SH_RIGHT; Token->type = SH_RIGHT;
} else { } else {
Token->type = CMP_GT; Token->type = CMP_GT;
@ -527,7 +537,7 @@ void Tokenise() {
case ':': case ':':
Char = NextChar(); Char = NextChar();
if(Char == ':') { if (Char == ':') {
Token->type = KW_FUNC; Token->type = KW_FUNC;
} else { } else {
ReturnCharToStream(Char); ReturnCharToStream(Char);
@ -538,7 +548,7 @@ void Tokenise() {
Token->value = ReadCharLiteral(); Token->value = ReadCharLiteral();
Token->type = LI_INT; Token->type = LI_INT;
if(NextChar() != '\'') if (NextChar() != '\'')
Die("Expected '\\'' at the end of a character."); Die("Expected '\\'' at the end of a character.");
break; break;
@ -548,23 +558,24 @@ void Tokenise() {
break; break;
default: default:
if(isdigit(Char)) { if (isdigit(Char)) {
Token->value = ReadInteger(Char); Token->value = ReadInteger(Char);
Token->type = LI_INT; Token->type = LI_INT;
break; break;
} else if(isalpha(Char) || Char == '_') { // This is what defines what a variable/function/keyword can START with. } else if (isalpha(Char) ||
Char == '_') { // This is what defines what a variable/function/keyword can START with.
ReadIdentifier(Char, CurrentIdentifier, TEXTLEN); ReadIdentifier(Char, CurrentIdentifier, TEXTLEN);
if(TokenType = ReadKeyword(CurrentIdentifier)) { if (TokenType = ReadKeyword(CurrentIdentifier)) {
Token->type = TokenType; Token->type = TokenType;
break; break;
} }
Token->type = TY_IDENTIFIER; Token->type = TY_IDENTIFIER;
break; break;
//printf("Line %d: Unrecognized symbol %s\n", CurrentIdentifier, Line); //printf.er("Line %d: Unrecognized symbol %s\n", CurrentIdentifier, Line);
//exit(1); //exit(1);
} }

View File

@ -4,13 +4,16 @@
/*************/ /*************/
#include <Defs.h> #include <Defs.h>
#define extern_ #define extern_
#include <Data.h> #include <Data.h>
#undef extern_ #undef extern_
#include <errno.h>
int TypeSizes[5] = { 0, 1, 4, 8, 0}; // in BYTES
int TypeSizes[5] = {0, 1, 4, 8, 0}; // in BYTES
char* TokenNames[] = { char* TokenNames[] = {
"End of file", "End of file",
@ -93,7 +96,7 @@ char* ScopeNames[] = {
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
// Option initialisers // Option initialisers
OptDumpTree = false; OptDumpTree = false;
OptKeepAssembly = false; OptKeepAssembly = true;
OptAssembleFiles = false; OptAssembleFiles = false;
OptLinkFiles = true; OptLinkFiles = true;
OptVerboseOutput = false; OptVerboseOutput = false;
@ -104,22 +107,22 @@ int main(int argc, char* argv[]) {
// Parse command line arguments. // Parse command line arguments.
int i; int i;
for(i = 1/*skip 0*/; i < argc; i++) { for (i = 1/*skip 0*/; i < argc; i++) {
// If we're not a flag, we can skip. // If we're not a flag, we can skip.
// We only care about flags in rows. // We only care about flags in rows.
// ie. erc >> -v -T -o << test.exe src/main.er // ie. erc >> -v -T -o << test.exe src/main.er
if(*argv[i] != '-') if (*argv[i] != '-')
break; break;
// Once we identify a flag, we need to make sure it's not just a minus in-place. // Once we identify a flag, we need to make sure it's not just a minus in-place.
for(int j = 1; (*argv[i] == '-') && argv[i][j]; j++) { for (int j = 1; (*argv[i] == '-') && argv[i][j]; j++) {
// Finally, identify what option is being invoked. // Finally, identify what option is being invoked.
switch(argv[i][j]) { switch (argv[i][j]) {
case 'o': // output case 'o': // output
OutputFileName = argv[++i]; OutputFileName = argv[++i];
break; break;
case 'T': // Debug case 'T': // print Tree (debug)
OptDumpTree = true; OptDumpTree = true;
break; break;
case 'c': // Compile only case 'c': // Compile only
@ -142,19 +145,19 @@ int main(int argc, char* argv[]) {
} }
// If we didn't provide anything other than flags, we need to show how to use the program. // If we didn't provide anything other than flags, we need to show how to use the program.
if(i >= argc) if (i >= argc)
DisplayUsage(argv[0]); DisplayUsage(argv[0]);
// For the rest of the files specified, we can iterate them right to left. // For the rest of the files specified, we can iterate them right to left.
while(i < argc) { while (i < argc) {
// Compile the file by invoking the Delegate // Compile the file by invoking the Delegate
CurrentASMFile = Compile(argv[i]); CurrentASMFile = Compile(argv[i]);
if(OptLinkFiles || OptAssembleFiles) { if (OptLinkFiles || OptAssembleFiles) {
// If we need to assemble (or link, which requires assembly) // If we need to assemble (or link, which requires assembly)
// then we invoke the Delegate again // then we invoke the Delegate again
CurrentObjectFile = Assemble(CurrentASMFile); CurrentObjectFile = Assemble(CurrentASMFile);
// We can only keep track of 99 objects, so we should crash at 98 to ensure we have enough room for the output file too. // We can only keep track of 99 objects, so we should crash at 98 to ensure we have enough room for the output file too.
if(ObjectCount == 98) { if (ObjectCount == 98) {
fprintf(stderr, "Too many inputs"); fprintf(stderr, "Too many inputs");
return 1; // We use return because we're in main, rather than invoking Die. return 1; // We use return because we're in main, rather than invoking Die.
} }
@ -165,19 +168,19 @@ int main(int argc, char* argv[]) {
ObjectFiles[ObjectCount] = NULL; ObjectFiles[ObjectCount] = NULL;
} }
if(!OptKeepAssembly) if (!OptKeepAssembly)
// unlink = delete // unlink = delete
unlink(CurrentASMFile); unlink(CurrentASMFile);
i++; i++;
} }
if(OptLinkFiles) { if (OptLinkFiles) {
// If needed, invoke the Delegate one last time. // If needed, invoke the Delegate one last time.
Link(OutputFileName, ObjectFiles); Link(OutputFileName, ObjectFiles);
if(!OptAssembleFiles) { if (!OptAssembleFiles) {
// Even though we need to assemble to link, we can respect the user's options and delete the intermediary files. // Even though we need to assemble to link, we can respect the user's options and delete the intermediary files.
for(i = 0; ObjectFiles[i] != NULL; i++) for (i = 0; ObjectFiles[i] != NULL; i++)
unlink(ObjectFiles[i]); unlink(ObjectFiles[i]);
} }
} }

View File

@ -38,8 +38,8 @@ static int Precedence[] = {
static int OperatorPrecedence(int Token) { static int OperatorPrecedence(int Token) {
int Prec = Precedence[Token]; int Prec = Precedence[Token];
if(Prec == 0 || Token >= PPMM_PLUS) { if (Prec == 0 || Token >= PPMM_PLUS) {
if(Token == TY_IDENTIFIER) if (Token == TY_IDENTIFIER)
DieMessage("Attempting to determine operator precedence of identifier", CurrentIdentifier); DieMessage("Attempting to determine operator precedence of identifier", CurrentIdentifier);
DieMessage("Attempting to determine operator precedence of an EOF or INT literal", TokenNames[Token]); DieMessage("Attempting to determine operator precedence of an EOF or INT literal", TokenNames[Token]);
@ -97,7 +97,7 @@ struct ASTNode* ConstructASTNode(int Operation, int Type,
Node = (struct ASTNode*) malloc(sizeof(struct ASTNode)); Node = (struct ASTNode*) malloc(sizeof(struct ASTNode));
if(!Node) if (!Node)
Die("Unable to allocate node!"); Die("Unable to allocate node!");
@ -135,7 +135,8 @@ struct ASTNode* ConstructASTLeaf(int Operation, int Type, struct SymbolTableEntr
* @param IntValue: The integer value encoded by this Node, if applicable. * @param IntValue: The integer value encoded by this Node, if applicable.
* @return a newly constructed AST Node * @return a newly constructed AST Node
*/ */
struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, struct SymbolTableEntry* Symbol, int IntValue) { struct ASTNode*
ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, struct SymbolTableEntry* Symbol, int IntValue) {
return ConstructASTNode(Operation, Type, Left, NULL, NULL, Symbol, IntValue); return ConstructASTNode(Operation, Type, Left, NULL, NULL, Symbol, IntValue);
} }
@ -152,7 +153,7 @@ struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left
*/ */
int ParseTokenToOperation(int Token) { int ParseTokenToOperation(int Token) {
if(Token > LI_EOF && Token < LI_INT) if (Token > LI_EOF && Token < LI_INT)
return Token; return Token;
DieDecimal("ParseToken: Unknown token", Token); DieDecimal("ParseToken: Unknown token", Token);
@ -172,10 +173,10 @@ struct ASTNode* ParsePrimary(void) {
struct ASTNode* Node; struct ASTNode* Node;
int ID; int ID;
switch(CurrentToken.type) { switch (CurrentToken.type) {
case LI_INT: case LI_INT:
if((CurrentToken.value >= 0) && (CurrentToken.value < 256)) if ((CurrentToken.value >= 0) && (CurrentToken.value < 256))
Node = ConstructASTLeaf(TERM_INTLITERAL, RET_CHAR, NULL, CurrentToken.value); Node = ConstructASTLeaf(TERM_INTLITERAL, RET_CHAR, NULL, CurrentToken.value);
else else
Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, CurrentToken.value); Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, CurrentToken.value);
@ -223,8 +224,8 @@ struct ASTNode* ParsePrimary(void) {
* *
*/ */
struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) { struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
struct ASTNode* LeftNode, *RightNode; struct ASTNode* LeftNode, * RightNode;
struct ASTNode* LeftTemp, *RightTemp; struct ASTNode* LeftTemp, * RightTemp;
// int LeftType, RightType; // int LeftType, RightType;
int NodeType, OpType; int NodeType, OpType;
@ -232,13 +233,15 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
NodeType = CurrentToken.type; NodeType = CurrentToken.type;
if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS || NodeType == LI_COM) { if (NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS || NodeType == LI_COM) {
LeftNode->RVal = 1; return LeftNode; LeftNode->RVal = 1;
return LeftNode;
} }
while((OperatorPrecedence(NodeType) > PreviousTokenPrecedence) || (IsRightExpr(OpType) && OperatorPrecedence(OpType) == PreviousTokenPrecedence)) { while ((OperatorPrecedence(NodeType) > PreviousTokenPrecedence) ||
(IsRightExpr(OpType) && OperatorPrecedence(OpType) == PreviousTokenPrecedence)) {
Tokenise(); Tokenise();
if(CurrentToken.type == LI_RPARE) if (CurrentToken.type == LI_RPARE)
break; break;
RightNode = ParsePrecedenceASTNode(Precedence[NodeType]); RightNode = ParsePrecedenceASTNode(Precedence[NodeType]);
@ -251,13 +254,13 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
OpType = ParseTokenToOperation(NodeType); OpType = ParseTokenToOperation(NodeType);
if(OpType == OP_ASSIGN) { if (OpType == OP_ASSIGN) {
printf("\tParsePrecedenceASTNode: Assignment statement\r\n"); printf("\tParsePrecedenceASTNode: Assignment statement\r\n");
RightNode->RVal = 1; RightNode->RVal = 1;
LeftNode->RVal = 0; LeftNode->RVal = 0;
RightNode = MutateType(RightNode, LeftNode->ExprType, 0); RightNode = MutateType(RightNode, LeftNode->ExprType, 0);
if(LeftNode == NULL) if (RightNode == NULL)
Die("Incompatible Expression encountered in assignment"); Die("Incompatible Expression encountered in assignment");
// LeftNode holds the target, the target variable in this case // LeftNode holds the target, the target variable in this case
@ -282,7 +285,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
* If both are null, the types are incompatible. * If both are null, the types are incompatible.
*/ */
if(LeftTemp == NULL && RightTemp == NULL) if (LeftTemp == NULL && RightTemp == NULL)
Die("Incompatible types in parsing nodes"); Die("Incompatible types in parsing nodes");
/** /**
@ -293,8 +296,9 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
* equivalent to LeftNode = LeftNode * equivalent to LeftNode = LeftNode
*/ */
if(LeftTemp)
LeftNode = LeftTemp; if (LeftTemp != NULL)
LeftNode = LeftTemp; //ConstructASTBranch(LeftType, RightNode->ExprType, LeftNode, 0);
/** /**
* Same here, but there is a higher chance * Same here, but there is a higher chance
@ -302,22 +306,15 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
* to the nature of widening types. * to the nature of widening types.
*/ */
if(RightTemp) if (RightTemp != NULL)
RightNode = RightTemp;
}
/**
* Checks over, back to normal parsing.
*/
if(LeftTemp != NULL)
LeftNode = LeftTemp; //ConstructASTBranch(LeftType, RightNode->ExprType, LeftNode, 0);
if(RightTemp != NULL)
RightNode = RightTemp; // ConstructASTBranch(RightType, LeftNode->ExprType, RightNode, 0); RightNode = RightTemp; // ConstructASTBranch(RightType, LeftNode->ExprType, RightNode, 0);
LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode, NULL, 0); }
LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode,
NULL, 0);
NodeType = CurrentToken.type; NodeType = CurrentToken.type;
if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) { if (NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) {
LeftNode->RVal = 1; LeftNode->RVal = 1;
return LeftNode; return LeftNode;
} }
@ -348,7 +345,7 @@ struct ASTNode* CallFunction() {
struct SymbolTableEntry* Function; struct SymbolTableEntry* Function;
//TODO: Test structural type! //TODO: Test structural type!
if((Function = FindSymbol(CurrentIdentifier)) == NULL || (Function->Structure != ST_FUNC)) if ((Function = FindSymbol(CurrentIdentifier)) == NULL || (Function->Structure != ST_FUNC))
DieMessage("Undeclared function", CurrentIdentifier); DieMessage("Undeclared function", CurrentIdentifier);
VerifyToken(LI_LPARE, "("); VerifyToken(LI_LPARE, "(");
@ -378,16 +375,16 @@ struct ASTNode* CallFunction() {
* *
*/ */
struct ASTNode* GetExpressionList() { struct ASTNode* GetExpressionList() {
struct ASTNode* Tree = NULL, *Child = NULL; struct ASTNode* Tree = NULL, * Child = NULL;
int Count; int Count;
while(CurrentToken.type != LI_RPARE) { while (CurrentToken.type != LI_RPARE) {
Child = ParsePrecedenceASTNode(0); Child = ParsePrecedenceASTNode(0);
Count++; Count++;
Tree = ConstructASTNode(OP_COMP, PointerTo(RET_VOID), Tree, NULL, Child, NULL, Count); Tree = ConstructASTNode(OP_COMP, PointerTo(RET_VOID), Tree, NULL, Child, NULL, Count);
switch(CurrentToken.type) { switch (CurrentToken.type) {
case LI_COM: case LI_COM:
Tokenise(); Tokenise();
break; break;
@ -422,7 +419,7 @@ struct ASTNode* ParseStatement(void) {
int Type; int Type;
printf("\t\tBranch leads to here, type %s/%d\r\n", TokenNames[CurrentToken.type], CurrentToken.type); printf("\t\tBranch leads to here, type %s/%d\r\n", TokenNames[CurrentToken.type], CurrentToken.type);
switch(CurrentToken.type) { switch (CurrentToken.type) {
case TY_CHAR: case TY_CHAR:
case TY_LONG: case TY_LONG:
case TY_INT: case TY_INT:
@ -468,29 +465,29 @@ struct ASTNode* ParseStatement(void) {
* *
*/ */
struct ASTNode* ParseCompound() { struct ASTNode* ParseCompound() {
struct ASTNode* Left = NULL, *Tree; struct ASTNode* Left = NULL, * Tree;
// Compound statements are defined by comprising // Compound statements are defined by comprising
// multiple statements inside { a bracket block } // multiple statements inside { a bracket block }
VerifyToken(LI_LBRAC, "{"); VerifyToken(LI_LBRAC, "{");
while(1) { while (1) {
printf("\tNew branch in compound\n"); printf("\tNew branch in compound\n");
Tree = ParseStatement(); Tree = ParseStatement();
if(Tree && (Tree->Operation == OP_PRINT || Tree->Operation == OP_ASSIGN if (Tree && (Tree->Operation == OP_PRINT || Tree->Operation == OP_ASSIGN
|| Tree->Operation == OP_RET || Tree->Operation == OP_CALL)) || Tree->Operation == OP_RET || Tree->Operation == OP_CALL))
VerifyToken(LI_SEMIC, ";"); VerifyToken(LI_SEMIC, ";");
if(Tree) { if (Tree) {
if(Left == NULL) if (Left == NULL)
Left = Tree; Left = Tree;
else else
Left = ConstructASTNode(OP_COMP, RET_NONE, Left, NULL, Tree, NULL, 0); Left = ConstructASTNode(OP_COMP, RET_NONE, Left, NULL, Tree, NULL, 0);
} }
if(CurrentToken.type == LI_RBRAC) { if (CurrentToken.type == LI_RBRAC) {
VerifyToken(LI_RBRAC, "}"); VerifyToken(LI_RBRAC, "}");
return Left; return Left;
} }
@ -519,35 +516,35 @@ void ParseGlobals() {
printf("Parsing global definitions\r\n"); printf("Parsing global definitions\r\n");
while(1) { while (1) {
// We loop early if there's a struct, and since a struct may be the last // We loop early if there's a struct, and since a struct may be the last
// thing in a file, we need to check for eof before anything else // thing in a file, we need to check for eof before anything else
if(CurrentToken.type == LI_EOF) if (CurrentToken.type == LI_EOF)
break; break;
printf("New definition incoming..\r\n\n"); printf("New definition incoming..\r\n\n");
Type = ParseOptionalPointer(&Composite); Type = ParseOptionalPointer(&Composite);
//TODO: converge pathways on this block? //TODO: converge pathways on this block?
if(CurrentToken.type == KW_FUNC) { if (CurrentToken.type == KW_FUNC) {
VerifyToken(KW_FUNC, "::"); VerifyToken(KW_FUNC, "::");
FunctionComing = 1; FunctionComing = 1;
} }
// Structs are parsed fully in ParseOptionalPointer // Structs are parsed fully in ParseOptionalPointer
// TODO: FIX THAT!! // TODO: FIX THAT!!
if(Type == DAT_STRUCT && CurrentToken.type == LI_SEMIC) { if (Type == DAT_STRUCT && CurrentToken.type == LI_SEMIC) {
Tokenise(); Tokenise();
continue; continue;
} }
VerifyToken(TY_IDENTIFIER, "ident"); VerifyToken(TY_IDENTIFIER, "ident");
if(FunctionComing && CurrentToken.type == LI_LPARE) { if (FunctionComing && CurrentToken.type == LI_LPARE) {
printf("\tParsing function\n"); printf("\tParsing function\n");
Tree = ParseFunction(Type); Tree = ParseFunction(Type);
if(Tree) { if (Tree) {
printf("\nBeginning assembler creation of new function %s\n", Tree->Symbol->Name); printf("\nBeginning assembler creation of new function %s\n", Tree->Symbol->Name);
AssembleTree(Tree, -1, 0); AssembleTree(Tree, -1, 0);
FreeLocals(); FreeLocals();

View File

@ -36,7 +36,7 @@
*/ */
int PointerTo(int Type) { int PointerTo(int Type) {
if((Type & 0xf) == 0xf) if ((Type & 0xf) == 0xf)
DieDecimal("Unrecognized type in pointerisation", Type); DieDecimal("Unrecognized type in pointerisation", Type);
printf("\t\tPointerising a %s\n", TypeNames(Type)); printf("\t\tPointerising a %s\n", TypeNames(Type));
return (Type + 1); return (Type + 1);
@ -52,7 +52,7 @@ int PointerTo(int Type) {
int ValueAt(int Type) { int ValueAt(int Type) {
printf("\t\tDereferencing a %s\n", TypeNames(Type)); printf("\t\tDereferencing a %s\n", TypeNames(Type));
if((Type & 0xf) == 0x0) if ((Type & 0xf) == 0x0)
DieDecimal("Unrecognized type in defererencing", Type); DieDecimal("Unrecognized type in defererencing", Type);
return (Type - 1); return (Type - 1);
} }
@ -75,7 +75,7 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
int Type; int Type;
switch(CurrentToken.type) { switch (CurrentToken.type) {
case TY_VOID: case TY_VOID:
Type = RET_VOID; Type = RET_VOID;
Tokenise(); Tokenise();
@ -103,9 +103,9 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
// This makes things like: // This makes things like:
// x = **y; // x = **y;
// possible. // possible.
while(1) { while (1) {
printf("\t\t\tType on parsing is %d\n", CurrentToken.type); printf("\t\t\tType on parsing is %d\n", CurrentToken.type);
if(CurrentToken.type != AR_STAR) if (CurrentToken.type != AR_STAR)
break; break;
Type = PointerTo(Type); Type = PointerTo(Type);
@ -129,7 +129,7 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
*/ */
struct ASTNode* AccessArray() { struct ASTNode* AccessArray() {
struct ASTNode* LeftNode, *RightNode; struct ASTNode* LeftNode, * RightNode;
struct SymbolTableEntry* Entry; struct SymbolTableEntry* Entry;
printf("\tAccessing array %s as requested\r\n", CurrentIdentifier); printf("\tAccessing array %s as requested\r\n", CurrentIdentifier);
@ -143,10 +143,11 @@ struct ASTNode* AccessArray() {
VerifyToken(LI_RBRAS, "]"); VerifyToken(LI_RBRAS, "]");
if(!TypeIsInt(RightNode->ExprType)) if (!TypeIsInt(RightNode->ExprType))
Die("Array index is not integer"); Die("Array index is not integer");
printf("\t\tPreparing types - RightNode of type %s must be mutated to LeftNode type %s\r\n", (RightNode->ExprType), TypeNames(LeftNode->ExprType)); printf("\t\tPreparing types - RightNode of type %s must be mutated to LeftNode type %s\r\n", (RightNode->ExprType),
TypeNames(LeftNode->ExprType));
RightNode = MutateType(RightNode, LeftNode->ExprType, OP_ADD); RightNode = MutateType(RightNode, LeftNode->ExprType, OP_ADD);
LeftNode = ConstructASTNode(OP_ADD, Entry->Type, LeftNode, NULL, RightNode, NULL, 0); LeftNode = ConstructASTNode(OP_ADD, Entry->Type, LeftNode, NULL, RightNode, NULL, 0);
@ -168,18 +169,18 @@ struct ASTNode* AccessArray() {
* @return the AST Node representing this statement. * @return the AST Node representing this statement.
*/ */
struct ASTNode* AccessMember(bool Deref) { struct ASTNode* AccessMember(bool Deref) {
struct ASTNode* LeftNode, *RightNode; struct ASTNode* LeftNode, * RightNode;
struct SymbolTableEntry* CompositeVar, *TypePtr, *Member; struct SymbolTableEntry* CompositeVar, * TypePtr, * Member;
if((CompositeVar = FindSymbol(CurrentIdentifier)) == NULL) if ((CompositeVar = FindSymbol(CurrentIdentifier)) == NULL)
DieMessage("Undecalred variable", CurrentIdentifier); DieMessage("Undeclared variable", CurrentIdentifier);
if(Deref && CompositeVar->Type != PointerTo(DAT_STRUCT)) if (Deref && CompositeVar->Type != PointerTo(DAT_STRUCT))
DieMessage("Undeclared struct", CurrentIdentifier); DieMessage("Undeclared struct", CurrentIdentifier);
if(!Deref && CompositeVar->Type != DAT_STRUCT) if (!Deref && CompositeVar->Type != DAT_STRUCT)
DieMessage("Undeclared struct", CurrentIdentifier); DieMessage("Undeclared struct", CurrentIdentifier);
if(Deref) if (Deref)
LeftNode = ConstructASTLeaf(REF_IDENT, PointerTo(DAT_STRUCT), CompositeVar, 0); LeftNode = ConstructASTLeaf(REF_IDENT, PointerTo(DAT_STRUCT), CompositeVar, 0);
else else
LeftNode = ConstructASTLeaf(OP_ADDRESS, CompositeVar->Type, CompositeVar, 0); LeftNode = ConstructASTLeaf(OP_ADDRESS, CompositeVar->Type, CompositeVar, 0);
@ -191,13 +192,14 @@ struct ASTNode* AccessMember(bool Deref) {
Tokenise(); Tokenise();
VerifyToken(TY_IDENTIFIER, "identifier"); VerifyToken(TY_IDENTIFIER, "identifier");
for(Member = TypePtr->Start; Member != NULL, Member = Member->NextSymbol;) { for (Member = TypePtr->Start; Member != NULL; Member = Member->NextSymbol) {
printf("\tComparing struct entry %s with the wanted %s. Index %d.\r\n", Member->Name, CurrentIdentifier, Member->SinkOffset); printf("\tComparing struct entry %s with the wanted %s. Index %d.\r\n", Member->Name, CurrentIdentifier,
if(!strcmp(Member->Name, CurrentIdentifier)) Member->SinkOffset);
if (!strcmp(Member->Name, CurrentIdentifier))
break; break;
} }
if(Member == NULL) if (Member == NULL)
DieMessage("Invalid struct member", CurrentIdentifier); DieMessage("Invalid struct member", CurrentIdentifier);
RightNode = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, Member->SinkOffset); RightNode = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, Member->SinkOffset);

View File

@ -28,34 +28,34 @@
static int ReadDeclarationList(struct SymbolTableEntry* FunctionSymbol, int Storage, int End) { static int ReadDeclarationList(struct SymbolTableEntry* FunctionSymbol, int Storage, int End) {
int TokenType, ParamCount = 0; int TokenType, ParamCount = 0;
struct SymbolTableEntry* PrototypePointer = NULL, *Composite; struct SymbolTableEntry* PrototypePointer = NULL, * Composite;
if(FunctionSymbol != NULL) if (FunctionSymbol != NULL)
PrototypePointer = FunctionSymbol->Start; PrototypePointer = FunctionSymbol->Start;
while(CurrentToken.type != End) { while (CurrentToken.type != End) {
TokenType = ParseOptionalPointer(&Composite); TokenType = ParseOptionalPointer(&Composite);
VerifyToken(TY_IDENTIFIER, "identifier"); VerifyToken(TY_IDENTIFIER, "identifier");
printf("\tReading a new element: %s of type %d, scope %s\n", CurrentIdentifier, TokenType, ScopeNames[Storage]); printf("\tReading a new element: %s of type %d, scope %s\n", CurrentIdentifier, TokenType, ScopeNames[Storage]);
if(PrototypePointer != NULL) { if (PrototypePointer != NULL) {
if(TokenType != PrototypePointer->Type) if (TokenType != PrototypePointer->Type)
DieDecimal("Function parameter of invalid type at index", ParamCount + 1); DieDecimal("Function parameter of invalid type at index", ParamCount + 1);
PrototypePointer=PrototypePointer->NextSymbol; PrototypePointer = PrototypePointer->NextSymbol;
} else { } else {
BeginVariableDeclaration(TokenType, Composite, Storage); BeginVariableDeclaration(TokenType, Composite, Storage);
} }
ParamCount++; ParamCount++;
if((CurrentToken.type != LI_COM) && (CurrentToken.type != End)) if ((CurrentToken.type != LI_COM) && (CurrentToken.type != End))
DieDecimal("Unexpected token in parameter", CurrentToken.type); DieDecimal("Unexpected token in parameter", CurrentToken.type);
if(CurrentToken.type == LI_COM) if (CurrentToken.type == LI_COM)
Tokenise(); Tokenise();
} }
if((FunctionSymbol != NULL) && (ParamCount != FunctionSymbol->Length)) if ((FunctionSymbol != NULL) && (ParamCount != FunctionSymbol->Length))
DieMessage("Invalid number of parameters in prototyped function", FunctionSymbol->Name); DieMessage("Invalid number of parameters in prototyped function", FunctionSymbol->Name);
return ParamCount; return ParamCount;
@ -74,23 +74,23 @@ static int ReadDeclarationList(struct SymbolTableEntry* FunctionSymbol, int Stor
*/ */
struct SymbolTableEntry* BeginStructDeclaration() { struct SymbolTableEntry* BeginStructDeclaration() {
struct SymbolTableEntry* Composite = NULL, *Member; struct SymbolTableEntry* Composite = NULL, * Member;
int Offset; int Offset;
Tokenise(); Tokenise();
if(CurrentToken.type == TY_IDENTIFIER) { if (CurrentToken.type == TY_IDENTIFIER) {
Composite = FindStruct(CurrentIdentifier); Composite = FindStruct(CurrentIdentifier);
Tokenise(); Tokenise();
} }
if(CurrentToken.type != LI_LBRAC) { if (CurrentToken.type != LI_LBRAC) {
if(Composite == NULL) if (Composite == NULL)
DieMessage("Unknown Struct", CurrentIdentifier); DieMessage("Unknown Struct", CurrentIdentifier);
return Composite; return Composite;
} }
if(Composite) if (Composite)
DieMessage("Redefinition of struct", CurrentIdentifier); DieMessage("Redefinition of struct", CurrentIdentifier);
Composite = AddSymbol(CurrentIdentifier, DAT_STRUCT, 0, SC_STRUCT, 0, 0, NULL); Composite = AddSymbol(CurrentIdentifier, DAT_STRUCT, 0, SC_STRUCT, 0, 0, NULL);
@ -107,7 +107,7 @@ struct SymbolTableEntry* BeginStructDeclaration() {
Member->SinkOffset = 0; Member->SinkOffset = 0;
Offset = TypeSize(Member->Type, Member->CompositeType); Offset = TypeSize(Member->Type, Member->CompositeType);
for(Member = Member->NextSymbol; Member != NULL; Member = Member->NextSymbol) { for (Member = Member->NextSymbol; Member != NULL; Member = Member->NextSymbol) {
Member->SinkOffset = AsAlignMemory(Member->Type, Offset, 1); Member->SinkOffset = AsAlignMemory(Member->Type, Offset, 1);
Offset += TypeSize(Member->Type, Member->CompositeType); Offset += TypeSize(Member->Type, Member->CompositeType);
@ -132,24 +132,24 @@ struct SymbolTableEntry* BeginStructDeclaration() {
struct SymbolTableEntry* BeginVariableDeclaration(int Type, struct SymbolTableEntry* Composite, int Scope) { struct SymbolTableEntry* BeginVariableDeclaration(int Type, struct SymbolTableEntry* Composite, int Scope) {
struct SymbolTableEntry* Symbol = NULL; struct SymbolTableEntry* Symbol = NULL;
switch(Scope) { switch (Scope) {
case SC_GLOBAL: case SC_GLOBAL:
if(FindGlobal(CurrentIdentifier) != NULL) if (FindGlobal(CurrentIdentifier) != NULL)
DieMessage("Invalid redeclaration of global variable", CurrentIdentifier); DieMessage("Invalid redeclaration of global variable", CurrentIdentifier);
case SC_LOCAL: case SC_LOCAL:
case SC_PARAM: case SC_PARAM:
if(FindLocal(CurrentIdentifier) != NULL) if (FindLocal(CurrentIdentifier) != NULL)
DieMessage("Invalid redeclaration of local variable", CurrentIdentifier); DieMessage("Invalid redeclaration of local variable", CurrentIdentifier);
case SC_MEMBER: case SC_MEMBER:
if(FindMember(CurrentIdentifier) != NULL) if (FindMember(CurrentIdentifier) != NULL)
DieMessage("Invalid redeclaration of Enum/Struct member", CurrentIdentifier); DieMessage("Invalid redeclaration of Enum/Struct member", CurrentIdentifier);
} }
if(CurrentToken.type == LI_LBRAS) { if (CurrentToken.type == LI_LBRAS) {
Tokenise(); Tokenise();
if(CurrentToken.type == LI_INT) { if (CurrentToken.type == LI_INT) {
switch(Scope) { switch (Scope) {
case SC_GLOBAL: case SC_GLOBAL:
Symbol = AddSymbol(CurrentIdentifier, PointerTo(Type), ST_ARR, Scope, 1, 0, NULL); Symbol = AddSymbol(CurrentIdentifier, PointerTo(Type), ST_ARR, Scope, 1, 0, NULL);
break; break;
@ -186,13 +186,13 @@ struct SymbolTableEntry* BeginVariableDeclaration(int Type, struct SymbolTableEn
struct ASTNode* ParseFunction(int Type) { struct ASTNode* ParseFunction(int Type) {
struct ASTNode* Tree; struct ASTNode* Tree;
struct ASTNode* FinalStatement; struct ASTNode* FinalStatement;
struct SymbolTableEntry* OldFunction, *NewFunction = NULL; struct SymbolTableEntry* OldFunction, * NewFunction = NULL;
int SymbolSlot, BreakLabel, ParamCount, ID; int SymbolSlot, BreakLabel, ParamCount, ID;
if((OldFunction = FindSymbol(CurrentIdentifier)) != NULL) if ((OldFunction = FindSymbol(CurrentIdentifier)) != NULL)
if(OldFunction->Storage != ST_FUNC) if (OldFunction->Storage != ST_FUNC)
OldFunction = NULL; OldFunction = NULL;
if(OldFunction == NULL) { if (OldFunction == NULL) {
BreakLabel = NewLabel(); BreakLabel = NewLabel();
NewFunction = AddSymbol(CurrentIdentifier, Type, ST_FUNC, SC_GLOBAL, BreakLabel, 0, NULL); NewFunction = AddSymbol(CurrentIdentifier, Type, ST_FUNC, SC_GLOBAL, BreakLabel, 0, NULL);
} }
@ -206,7 +206,7 @@ struct ASTNode* ParseFunction(int Type) {
(OldFunction == NULL) ? NewFunction->Name : OldFunction->Name, (OldFunction == NULL) ? NewFunction->Name : OldFunction->Name,
TypeNames(Type), BreakLabel); TypeNames(Type), BreakLabel);
if(NewFunction) { if (NewFunction) {
NewFunction->Elements = ParamCount; NewFunction->Elements = ParamCount;
NewFunction->Start = Params; NewFunction->Start = Params;
NewFunction->Type = RET_LONG; NewFunction->Type = RET_LONG;
@ -215,7 +215,7 @@ struct ASTNode* ParseFunction(int Type) {
Params = ParamsEnd = NULL; Params = ParamsEnd = NULL;
if(CurrentToken.type == LI_SEMIC) { if (CurrentToken.type == LI_SEMIC) {
Tokenise(); Tokenise();
return NULL; return NULL;
} }
@ -224,11 +224,11 @@ struct ASTNode* ParseFunction(int Type) {
Tree = ParseCompound(); Tree = ParseCompound();
if(Type != RET_VOID) { if (Type != RET_VOID) {
// Functions with one statement have no composite node, so we have to check // Functions with one statement have no composite node, so we have to check
FinalStatement = (Tree->Operation == OP_COMP) ? Tree->Right : Tree; FinalStatement = (Tree->Operation == OP_COMP) ? Tree->Right : Tree;
if(FinalStatement == NULL || FinalStatement->Operation != OP_RET) { if (FinalStatement == NULL || FinalStatement->Operation != OP_RET) {
Die("Function with non-void type does not return"); Die("Function with non-void type does not return");
} }
@ -249,7 +249,7 @@ struct ASTNode* ReturnStatement() {
int ReturnType; int ReturnType;
if(FunctionEntry->Type == RET_VOID) if (FunctionEntry->Type == RET_VOID)
Die("Attempt to return from void function"); Die("Attempt to return from void function");
VerifyToken(KW_RETURN, "return"); VerifyToken(KW_RETURN, "return");
@ -259,7 +259,7 @@ struct ASTNode* ReturnStatement() {
Tree = ParsePrecedenceASTNode(0); Tree = ParsePrecedenceASTNode(0);
Tree = MutateType(Tree, FunctionEntry->Type, 0); Tree = MutateType(Tree, FunctionEntry->Type, 0);
if(Tree == NULL) if (Tree == NULL)
Die("Returning a value of incorrect type for function"); Die("Returning a value of incorrect type for function");
@ -273,7 +273,6 @@ struct ASTNode* ReturnStatement() {
} }
/* /*
* Handles the surrounding logic for If statements. * Handles the surrounding logic for If statements.
* *
@ -300,7 +299,7 @@ struct ASTNode* ReturnStatement() {
* *
*/ */
struct ASTNode* IfStatement() { struct ASTNode* IfStatement() {
struct ASTNode* Condition, *True, *False = NULL; struct ASTNode* Condition, * True, * False = NULL;
VerifyToken(KW_IF, "if"); VerifyToken(KW_IF, "if");
VerifyToken(LI_LPARE, "("); VerifyToken(LI_LPARE, "(");
@ -310,14 +309,14 @@ struct ASTNode* IfStatement() {
// Limit if(x) to =? != < > <= => // Limit if(x) to =? != < > <= =>
// No null checking, no arithmetic, no functions. // No null checking, no arithmetic, no functions.
// TODO: this // TODO: this
if(Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE) if (Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE)
Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, NULL, 0); Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, NULL, 0);
VerifyToken(LI_RPARE, ")"); VerifyToken(LI_RPARE, ")");
True = ParseCompound(); True = ParseCompound();
if(CurrentToken.type == KW_ELSE) { if (CurrentToken.type == KW_ELSE) {
Tokenise(); Tokenise();
False = ParseCompound(); False = ParseCompound();
} }
@ -352,7 +351,7 @@ struct ASTNode* IfStatement() {
* *
*/ */
struct ASTNode* WhileStatement() { struct ASTNode* WhileStatement() {
struct ASTNode* Condition, *Body; struct ASTNode* Condition, * Body;
VerifyToken(KW_WHILE, "while"); VerifyToken(KW_WHILE, "while");
VerifyToken(LI_LPARE, "("); VerifyToken(LI_LPARE, "(");
@ -360,7 +359,7 @@ struct ASTNode* WhileStatement() {
Condition = ParsePrecedenceASTNode(0); Condition = ParsePrecedenceASTNode(0);
if(Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE) if (Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE)
Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, NULL, 0); Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, NULL, 0);
VerifyToken(LI_RPARE, ")"); VerifyToken(LI_RPARE, ")");
@ -400,8 +399,8 @@ struct ASTNode* WhileStatement() {
* @return the AST of this statement * @return the AST of this statement
*/ */
struct ASTNode* ForStatement() { struct ASTNode* ForStatement() {
struct ASTNode* Condition, *Body; struct ASTNode* Condition, * Body;
struct ASTNode* Preop, *Postop; struct ASTNode* Preop, * Postop;
struct ASTNode* Tree; struct ASTNode* Tree;
@ -413,7 +412,7 @@ struct ASTNode* ForStatement() {
Condition = ParsePrecedenceASTNode(0); Condition = ParsePrecedenceASTNode(0);
if(Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE) if (Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE)
Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, NULL, 0); Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, NULL, 0);
VerifyToken(LI_SEMIC, ";"); VerifyToken(LI_SEMIC, ";");
@ -438,7 +437,7 @@ struct ASTNode* ForStatement() {
* Handles the surrounding logic for the Print statement. * Handles the surrounding logic for the Print statement.
* *
* This is a legacy hold-over from the early testing, and it * This is a legacy hold-over from the early testing, and it
* serves merely as a wrapper around the cstdlib printf function. * serves merely as a wrapper around the cstdlib printf.er function.
* *
* It does, however (//TODO), attempt to guess the type that you * It does, however (//TODO), attempt to guess the type that you
* want to print, which takes a lot of the guesswork out of printing. * want to print, which takes a lot of the guesswork out of printing.
@ -457,10 +456,10 @@ struct ASTNode* PrintStatement(void) {
RightType = Tree->ExprType; RightType = Tree->ExprType;
Tree = MutateType(Tree, RightType, 0); Tree = MutateType(Tree, RightType, 0);
if(!Tree) if (!Tree)
DieDecimal("Attempting to print an invalid type:", RightType); DieDecimal("Attempting to print an invalid type:", RightType);
if(RightType) if (RightType)
Tree = ConstructASTBranch(Tree->Right->Operation, RET_INT, Tree, NULL, 0); Tree = ConstructASTBranch(Tree->Right->Operation, RET_INT, Tree, NULL, 0);
Tree = ConstructASTBranch(OP_PRINT, RET_NONE, Tree, NULL, 0); Tree = ConstructASTBranch(OP_PRINT, RET_NONE, Tree, NULL, 0);
@ -499,24 +498,25 @@ struct ASTNode* PostfixStatement() {
Tokenise(); Tokenise();
if(CurrentToken.type == LI_LPARE) if (CurrentToken.type == LI_LPARE)
return CallFunction(); return CallFunction();
if(CurrentToken.type == LI_LBRAS) if (CurrentToken.type == LI_LBRAS)
return AccessArray(); return AccessArray();
// If we get here, we must be a variable. // If we get here, we must be a variable.
// (as functions have been called and arrays have been indexed) // (as functions have been called and arrays have been indexed)
// Check that the variable is recognized.. // Check that the variable is recognized..
if((Entry = FindSymbol(CurrentIdentifier)) == NULL || (Entry->Structure != ST_VAR && Entry->Structure != ST_FUNC)) { if ((Entry = FindSymbol(CurrentIdentifier)) == NULL ||
(Entry->Structure != ST_VAR && Entry->Structure != ST_FUNC)) {
DumpAllLists(); DumpAllLists();
DieMessage("Unknown Variable", CurrentIdentifier); DieMessage("Unknown Variable", CurrentIdentifier);
} }
// Here we check for postincrement and postdecrement. // Here we check for postincrement and postdecrement.
switch(CurrentToken.type) { switch (CurrentToken.type) {
case LI_DOT: case LI_DOT:
return AccessMember(false); return AccessMember(false);
case LI_ARROW: case LI_ARROW:
@ -591,7 +591,7 @@ struct ASTNode* PrefixStatement() {
Tokenise(); Tokenise();
Tree = PrefixStatement(); Tree = PrefixStatement();
if(Tree->Operation != REF_IDENT) if (Tree->Operation != REF_IDENT)
Die("++ not followed by identifier"); Die("++ not followed by identifier");
Tree = ConstructASTBranch(OP_PREINC, Tree->ExprType, Tree, NULL, 0); Tree = ConstructASTBranch(OP_PREINC, Tree->ExprType, Tree, NULL, 0);
break; break;
@ -600,7 +600,7 @@ struct ASTNode* PrefixStatement() {
Tokenise(); Tokenise();
Tree = PrefixStatement(); Tree = PrefixStatement();
if(Tree->Operation != REF_IDENT) if (Tree->Operation != REF_IDENT)
Die("-- not followed by identifier"); Die("-- not followed by identifier");
Tree = ConstructASTBranch(OP_PREDEC, Tree->ExprType, Tree, NULL, 0); Tree = ConstructASTBranch(OP_PREDEC, Tree->ExprType, Tree, NULL, 0);
@ -614,7 +614,7 @@ struct ASTNode* PrefixStatement() {
// We need to recursively parse prefixes; // We need to recursively parse prefixes;
Tree = PrefixStatement(); Tree = PrefixStatement();
if(Tree->Operation != REF_IDENT) if (Tree->Operation != REF_IDENT)
Die("& must be followed by another & or an identifier."); Die("& must be followed by another & or an identifier.");
Tree->Operation = OP_ADDRESS; Tree->Operation = OP_ADDRESS;
@ -625,7 +625,7 @@ struct ASTNode* PrefixStatement() {
Tree = PrefixStatement(); Tree = PrefixStatement();
if(Tree->Operation != REF_IDENT && Tree->Operation != OP_DEREF) if (Tree->Operation != REF_IDENT && Tree->Operation != OP_DEREF)
Die("* must be followed by another * or an identifier."); Die("* must be followed by another * or an identifier.");
Tree = ConstructASTBranch(OP_DEREF, ValueAt(Tree->ExprType), Tree, NULL, 0); Tree = ConstructASTBranch(OP_DEREF, ValueAt(Tree->ExprType), Tree, NULL, 0);

View File

@ -17,7 +17,7 @@ void DumpAllLists() {
printf("\nLocal symbols:\n"); printf("\nLocal symbols:\n");
DumpList(Locals); DumpList(Locals);
printf("\nParameters:\n"); printf("\nParameters:\n");
if(FunctionEntry != NULL && FunctionEntry->Start != NULL) if (FunctionEntry != NULL && FunctionEntry->Start != NULL)
DumpList(FunctionEntry->Start); DumpList(FunctionEntry->Start);
DumpList(Params); DumpList(Params);
printf("\nStructs:\n"); printf("\nStructs:\n");
@ -32,8 +32,8 @@ void DumpAllLists() {
* @param List the list to dump * @param List the list to dump
*/ */
void DumpList(struct SymbolTableEntry* List) { void DumpList(struct SymbolTableEntry* List) {
for(; List != NULL; List = List->NextSymbol) for (; List != NULL; List = List->NextSymbol)
if((List->Name != NULL)) if ((List->Name != NULL))
printf("%s\t", List->Name); printf("%s\t", List->Name);
} }
@ -47,8 +47,8 @@ void DumpList(struct SymbolTableEntry* List) {
*/ */
static struct SymbolTableEntry* SearchList(char* Name, struct SymbolTableEntry* List) { static struct SymbolTableEntry* SearchList(char* Name, struct SymbolTableEntry* List) {
for(; List != NULL; List = List->NextSymbol) for (; List != NULL; List = List->NextSymbol)
if((List->Name != NULL) && !strcmp(Name, List->Name)) if ((List->Name != NULL) && !strcmp(Name, List->Name))
return (List); return (List);
return NULL; return NULL;
} }
@ -67,14 +67,14 @@ static struct SymbolTableEntry* SearchList(char* Name, struct SymbolTableEntry*
struct SymbolTableEntry* FindSymbol(char* Symbol) { struct SymbolTableEntry* FindSymbol(char* Symbol) {
struct SymbolTableEntry* Node; struct SymbolTableEntry* Node;
if(FunctionEntry) { if (FunctionEntry) {
Node = SearchList(Symbol, FunctionEntry->Start); Node = SearchList(Symbol, FunctionEntry->Start);
if(Node) if (Node)
return Node; return Node;
} }
Node = SearchList(Symbol, Locals); Node = SearchList(Symbol, Locals);
if(Node) if (Node)
return Node; return Node;
@ -90,9 +90,9 @@ struct SymbolTableEntry* FindSymbol(char* Symbol) {
struct SymbolTableEntry* FindLocal(char* Symbol) { struct SymbolTableEntry* FindLocal(char* Symbol) {
struct SymbolTableEntry* Node; struct SymbolTableEntry* Node;
if(FunctionEntry) { if (FunctionEntry) {
Node = SearchList(Symbol, FunctionEntry->Start); Node = SearchList(Symbol, FunctionEntry->Start);
if(Node) if (Node)
return Node; return Node;
} }
@ -145,10 +145,10 @@ struct SymbolTableEntry* FindMember(char* Symbol) {
* *
*/ */
void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node) { void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node) {
if(Head == NULL || Tail == NULL || Node == NULL) if (Head == NULL || Tail == NULL || Node == NULL)
Die("Not enough data to append a symbol to the tables"); Die("Not enough data to append a symbol to the tables");
if(*Tail) { if (*Tail) {
(*Tail)->NextSymbol = Node; (*Tail)->NextSymbol = Node;
*Tail = Node; *Tail = Node;
} else { } else {
@ -193,7 +193,8 @@ void ClearTables() {
* *
* @return The SymbolTableEntry* pointer that corresponds to this newly constructed node. * @return The SymbolTableEntry* pointer that corresponds to this newly constructed node.
*/ */
struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Storage, int Length, int SinkOffset, struct SymbolTableEntry* CompositeType) { struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Storage, int Length, int SinkOffset,
struct SymbolTableEntry* CompositeType) {
struct SymbolTableEntry* Node = struct SymbolTableEntry* Node =
(struct SymbolTableEntry*) malloc(sizeof(struct SymbolTableEntry)); (struct SymbolTableEntry*) malloc(sizeof(struct SymbolTableEntry));
@ -206,12 +207,13 @@ struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Stor
Node->SinkOffset = SinkOffset; Node->SinkOffset = SinkOffset;
Node->CompositeType = CompositeType; Node->CompositeType = CompositeType;
printf("Adding a %s symbol of name %s, type %s to the tables.\n", ScopeNames[Node->Storage], Node->Name, TypeNames(Node->Type)); printf("Adding a %s symbol of name %s, type %s to the tables.\n", ScopeNames[Node->Storage], Node->Name,
switch(Storage) { TypeNames(Node->Type));
switch (Storage) {
case SC_GLOBAL: case SC_GLOBAL:
AppendSymbol(&Globals, &GlobalsEnd, Node); AppendSymbol(&Globals, &GlobalsEnd, Node);
// We don't want to generate a static block for functions. // We don't want to generate a static block for functions.
if(Structure != ST_FUNC) AsGlobalSymbol(Node); if (Structure != ST_FUNC) AsGlobalSymbol(Node);
break; break;
case SC_STRUCT: case SC_STRUCT:
AppendSymbol(&Structs, &StructsEnd, Node); AppendSymbol(&Structs, &StructsEnd, Node);

View File

@ -42,11 +42,14 @@ int TypeIsPtr(int Type) {
int PrimitiveSize(int Type) { int PrimitiveSize(int Type) {
if(TypeIsPtr(Type)) return 8; if (TypeIsPtr(Type)) return 8;
switch(Type) { switch (Type) {
case RET_CHAR: return 1; case RET_CHAR:
case RET_INT: return 4; return 1;
case RET_LONG: return 8; case RET_INT:
return 4;
case RET_LONG:
return 8;
default: default:
DieBinary("Bad type in PrimitiveSize", Type); DieBinary("Bad type in PrimitiveSize", Type);
} }
@ -61,7 +64,7 @@ int PrimitiveSize(int Type) {
*/ */
int TypeSize(int Type, struct SymbolTableEntry* Composite) { int TypeSize(int Type, struct SymbolTableEntry* Composite) {
if(Type == DAT_STRUCT) return Composite->Length; if (Type == DAT_STRUCT) return Composite->Length;
return PrimitiveSize(Type); return PrimitiveSize(Type);
} }
@ -76,15 +79,24 @@ static char TypeBuffer[7];
* Get the name of the input Type as a string. * Get the name of the input Type as a string.
*/ */
char* TypeNames(int Type) { char* TypeNames(int Type) {
switch(Type) { switch (Type) {
case RET_CHAR: memcpy(TypeBuffer, "Char", 4); break; case RET_CHAR:
case RET_INT: memcpy(TypeBuffer, "Int ", 4); break; memcpy(TypeBuffer, "Char", 4);
case RET_LONG: memcpy(TypeBuffer, "Long", 4); break; break;
case RET_VOID: memcpy(TypeBuffer, "Void", 4); break; case RET_INT:
default: break; memcpy(TypeBuffer, "Int ", 4);
break;
case RET_LONG:
memcpy(TypeBuffer, "Long", 4);
break;
case RET_VOID:
memcpy(TypeBuffer, "Void", 4);
break;
default:
break;
}; };
if(TypeIsPtr(Type)) memcpy((void*)((size_t) TypeBuffer + 4), "Ptr", 3); if (TypeIsPtr(Type)) memcpy((void*) ((size_t) TypeBuffer + 4), "Ptr", 3);
else memcpy((void*)((size_t) TypeBuffer + 4), " ", 3); else memcpy((void*) ((size_t) TypeBuffer + 4), " ", 3);
return TypeBuffer; return TypeBuffer;
} }
@ -104,7 +116,7 @@ int TypesCompatible(int* Left, int* Right, int STRICT) {
int LeftSize, RightSize; int LeftSize, RightSize;
// Same types are compatible. No shrinking required // Same types are compatible. No shrinking required
if(*Left == *Right) { if (*Left == *Right) {
*Left = *Right = 0; *Left = *Right = 0;
return 1; return 1;
} }
@ -114,7 +126,7 @@ int TypesCompatible(int* Left, int* Right, int STRICT) {
// Types of size 0 are incompatible // Types of size 0 are incompatible
if((LeftSize == 0) || (RightSize == 0)) if ((LeftSize == 0) || (RightSize == 0))
return 0; return 0;
@ -126,7 +138,7 @@ int TypesCompatible(int* Left, int* Right, int STRICT) {
* x needs to be widened, y copied in, then x shrunk back down * x needs to be widened, y copied in, then x shrunk back down
* AKA, the left must be widened. * AKA, the left must be widened.
*/ */
if(LeftSize < RightSize) { if (LeftSize < RightSize) {
*Left = OP_WIDEN; *Left = OP_WIDEN;
*Right = 0; *Right = 0;
return 1; return 1;
@ -145,8 +157,8 @@ int TypesCompatible(int* Left, int* Right, int STRICT) {
* *
*/ */
if(LeftSize > RightSize) { if (LeftSize > RightSize) {
if(STRICT) if (STRICT)
return 0; // Not compatible if STRICT return 0; // Not compatible if STRICT
*Left = 0; *Left = 0;
@ -191,10 +203,10 @@ struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation) {
printf("\tCalculating compatibility between ltype %d and rtype %d\r\n", LeftType, RightType); printf("\tCalculating compatibility between ltype %d and rtype %d\r\n", LeftType, RightType);
if(TypeIsInt(LeftType) && TypeIsInt(RightType)) { if (TypeIsInt(LeftType) && TypeIsInt(RightType)) {
// Short-circuit for valid types // Short-circuit for valid types
if(LeftType == RightType) { if (LeftType == RightType) {
return Tree; return Tree;
} }
@ -208,7 +220,7 @@ struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation) {
* (The left branch of the tree contains the current AST) * (The left branch of the tree contains the current AST)
* *
*/ */
if(LeftSize > RightSize) if (LeftSize > RightSize)
return NULL; return NULL;
/** /**
@ -220,19 +232,19 @@ struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation) {
* BUT it is possible! * BUT it is possible!
*/ */
if(RightSize > LeftSize) if (RightSize > LeftSize)
return ConstructASTBranch(OP_WIDEN, RightType, Tree, NULL, 0); return ConstructASTBranch(OP_WIDEN, RightType, Tree, NULL, 0);
} }
// Left branch pointers are compatible if we're not doing operations // Left branch pointers are compatible if we're not doing operations
if(TypeIsPtr(LeftType)) { if (TypeIsPtr(LeftType)) {
if(Operation == 0 && LeftType == RightType) if (Operation == 0 && LeftType == RightType)
return Tree; return Tree;
} }
// Otherwise, we can perform some scaling for pointer addition & subtraction // Otherwise, we can perform some scaling for pointer addition & subtraction
if(Operation == OP_ADD || Operation == OP_SUBTRACT) { if (Operation == OP_ADD || Operation == OP_SUBTRACT) {
/** /**
* Left int, right pointer: * Left int, right pointer:
@ -242,11 +254,11 @@ struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation) {
* x = *(y + 1); * x = *(y + 1);
*/ */
if(TypeIsInt(LeftType) && TypeIsPtr(RightType)) { if (TypeIsInt(LeftType) && TypeIsPtr(RightType)) {
printf("\t\t\tMutateType: Right node needs adjustment\r\n"); printf("\t\t\tMutateType: Right node needs adjustment\r\n");
RightSize = PrimitiveSize(ValueAt(RightType)); RightSize = PrimitiveSize(ValueAt(RightType));
if(RightSize > 1) if (RightSize > 1)
return ConstructASTBranch(OP_SCALE, RightType, Tree, NULL, RightSize); return ConstructASTBranch(OP_SCALE, RightType, Tree, NULL, RightSize);
} }
} }

6
tests/calls.c Normal file
View File

@ -0,0 +1,6 @@
#include <stdio.h>
int main() {
printf("%d\n", 55);
puts("more sup\n");
}

View File

@ -6,8 +6,8 @@ int :: close(int fd);
char* textbuffer; char* textbuffer;
int :: main() { int :: main() {
int sourcefile; long sourcefile;
int count; long count;
textbuffer = " "; textbuffer = " ";

View File

@ -3,11 +3,11 @@ struct a {
int y int y
}; };
int printf(char* fmt); int :: printf(char* fmt);
struct a str; struct a str;
int main() { int :: main() {
str.y = 55; str.y = 55;
printf("%d\n", str.y); printf("%d\n", str.y);
return (0); return (0);

23
tests/structbrutal.er Normal file
View File

@ -0,0 +1,23 @@
int :: printf(char* fmt);
struct banana {
int x,
int y
};
struct banana bread;
struct banana* loaf;
int :: main() {
bread.y = 5;
loaf->y = 10;
printf("%d\n", bread.y);
printf("%d\n", loaf->y);
bread.x = 7;
printf("%d\n", bread.y + bread.x);
return (0);
}