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,9 +32,9 @@ 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];
extern_ char* TokenNames[]; extern_ char* TokenNames[];

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
}; };
@ -220,11 +221,11 @@ enum StorageScope {
SC_STRUCT, // Struct Definitions SC_STRUCT, // Struct Definitions
SC_ENUM, // Enum Definitions SC_ENUM, // Enum Definitions
SC_MEMBER, // The members of Structs or Enums SC_MEMBER, // The members of Structs or Enums
//SC_CLASS, // Class-local definitions //SC_CLASS, // Class-local definitions
//SC_STATIC, // Static storage definitions //SC_STATIC, // Static storage definitions
SC_PARAM, // Function parameters SC_PARAM, // Function parameters
SC_LOCAL // Function-local scope. SC_LOCAL // Function-local scope.
// There is no deeper scope than function. // There is no deeper scope than function.
}; };
@ -258,8 +259,8 @@ enum StructureType {
ST_FUNC, // This is a function ST_FUNC, // This is a function
ST_ARR, // This is an array ST_ARR, // This is an array
ST_RUCT // This is a struct ST_RUCT // This is a struct
// This is an enum // This is an enum
// This is a typedef // This is a typedef
}; };
@ -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,24 +842,30 @@ 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);
fprintf(OutputFile, "\t.data\n" fprintf(OutputFile, "\t.data\n"
"\t.globl\t%s\n", "\t.globl\t%s\n",
Entry->Name); Entry->Name);
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");
case REF_IDENT: return;
if(Node->RVal) case OP_DIVIDE:
fprintf(stdout, "REF_IDENT rval %s\n", Node->Symbol->Name); fprintf(stdout, "OP_DIVIDE\n");
else return;
fprintf(stdout, "REF_IDENT %s\n", Node->Symbol->Name); 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:
if (Node->RVal)
fprintf(stdout, "REF_IDENT rval %s\n", Node->Symbol->Name);
else
fprintf(stdout, "REF_IDENT %s\n", Node->Symbol->Name);
return;
case OP_ASSIGN:
fprintf(stdout, "OP_ASSIGN\n");
return;
case OP_WIDEN:
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; return;
case OP_ASSIGN: fprintf(stdout, "OP_ASSIGN\n"); return;
case OP_WIDEN: 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,12 +458,12 @@ 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 {
ReturnCharToStream(Char); ReturnCharToStream(Char);
Token->type = LI_EQUAL; Token->type = LI_EQUAL;
@ -463,9 +473,9 @@ 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 {
Token->type = BOOL_INVERT; Token->type = BOOL_INVERT;
ReturnCharToStream(Char); ReturnCharToStream(Char);
@ -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,96 +4,99 @@
/*************/ /*************/
#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",
"Equivalency", "Equivalency",
"Boolean Logic OR", "Boolean Logic OR",
"Boolean Logic AND", "Boolean Logic AND",
"Bitwise OR", "Bitwise OR",
"Bitwise XOR", "Bitwise XOR",
"Bitwise AND", "Bitwise AND",
"Equality Check", "Equality Check",
"Inequality Check", "Inequality Check",
"Less Than", "Less Than",
"Greater Than", "Greater Than",
"Less Than or Equal", "Less Than or Equal",
"Greater Than or Equal", "Greater Than or Equal",
"Left Shift", "Left Shift",
"Right Shift", "Right Shift",
"Addition", "Addition",
"Subtraction", "Subtraction",
"Multiplication", "Multiplication",
"Division", "Division",
"Increment", "Increment",
"Decrement", "Decrement",
"Statement Logical Invert", "Statement Logical Invert",
"Bitwise Invert", "Bitwise Invert",
"Integer literal", "Integer literal",
"String literal", "String literal",
"Statement End", "Statement End",
"Compound Block Start", "Compound Block Start",
"Compound Block End", "Compound Block End",
"Array index start", "Array index start",
"Array index end", "Array index end",
"Logical Block Start", "Logical Block Start",
"Logical Block End", "Logical Block End",
"Comma", "Comma",
"Dot", "Dot",
"Arrow", "Arrow",
"Identifier", "Identifier",
"None Type", "None Type",
"Char Type", "Char Type",
"Int Type", "Int Type",
"Long Type", "Long Type",
"Void Type", "Void Type",
"Function keyword", "Function keyword",
"Print Keyword", "Print Keyword",
"If keyword", "If keyword",
"Else keyword", "Else keyword",
"While keyword", "While keyword",
"For keyword", "For keyword",
"Return keyword", "Return keyword",
"Struct keyword" "Struct keyword"
}; };
char* ScopeNames[] = { char* ScopeNames[] = {
"INVALID", "INVALID",
"GLOBAL", "GLOBAL",
"STRUCT", "STRUCT",
"ENUM", "ENUM",
"MEMBER", "MEMBER",
"PARAMETER", "PARAMETER",
"LOCAL" "LOCAL"
}; };
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,24 +107,24 @@ 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
OptAssembleFiles = true; OptAssembleFiles = true;
OptKeepAssembly = false; OptKeepAssembly = false;
@ -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

@ -16,14 +16,14 @@
* This allows for things like the common Order of Operations. * This allows for things like the common Order of Operations.
*/ */
static int Precedence[] = { static int Precedence[] = {
0, 10, // EOF, ASSIGN 0, 10, // EOF, ASSIGN
20, 30, // || && 20, 30, // || &&
40, 50, // | ^ 40, 50, // | ^
60, 70, // & =? 60, 70, // & =?
70, 80, // != < 70, 80, // != <
80, 80, // > <= 80, 80, // > <=
80, 90, // => << 80, 90, // => <<
90, 100, // >> + 90, 100, // >> +
100, 110, // - * 100, 110, // - *
110 // / 110 // /
}; };
@ -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]);
@ -56,7 +56,7 @@ static int OperatorPrecedence(int Token) {
*/ */
static int IsRightExpr(int Token) { static int IsRightExpr(int Token) {
return (Token == LI_EQUAL); return (Token == LI_EQUAL);
} }
/* * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * *
@ -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; RightNode = RightTemp; // ConstructASTBranch(RightType, LeftNode->ExprType, RightNode, 0);
} }
/** LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode,
* Checks over, back to normal parsing. NULL, 0);
*/
if(LeftTemp != NULL)
LeftNode = LeftTemp; //ConstructASTBranch(LeftType, RightNode->ExprType, LeftNode, 0);
if(RightTemp != NULL)
RightNode = RightTemp; // ConstructASTBranch(RightType, LeftNode->ExprType, RightNode, 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);
} }
@ -202,11 +202,11 @@ struct ASTNode* ParseFunction(int Type) {
VerifyToken(LI_RPARE, ")"); VerifyToken(LI_RPARE, ")");
printf("\nIdentified%sfunction %s of return type %s, end label %d\n", printf("\nIdentified%sfunction %s of return type %s, end label %d\n",
(OldFunction == NULL) ? " new " : " overloaded ", (OldFunction == NULL) ? " new " : " overloaded ",
(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,10 +193,11 @@ 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));
Node->Name = strdup(Name); Node->Name = strdup(Name);
Node->Type = Type; Node->Type = Type;
@ -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);
}