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

View File

@ -4,6 +4,7 @@
/*************/
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
@ -88,7 +89,7 @@ enum TokenTypes {
TY_VOID, // "void" type keyword
KW_FUNC, // :: function name incoming
KW_PRINT,
KW_IF,
KW_ELSE,
@ -117,40 +118,40 @@ enum SyntaxOps {
OP_BOOLOR, // Boolean OR two statements
OP_BOOLAND, // Boolean AND two statements
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_EQUAL, // Compare equality
OP_INEQ, // Compare inequality
OP_LESS, // Less than?
OP_GREAT, // Greater than?
OP_GREAT = 10, // Greater than?
OP_LESSE, // Less than or Equal to?
OP_GREATE, // Greater than or Equal to?
OP_SHIFTL, // Arithmetic Shift Left (Multiply 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_MULTIPLY, // Multiply two numbers.
OP_DIVIDE, // Divide two numbers.
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_POSTDEC, // Decrement var after reference.
OP_BITNOT, // Invert a number bitwise
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_ADDRESS, // Fetch the address of a var
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_STRLITERAL, // String Literal. Also terminal.
TERM_STRLITERAL = 30, // String Literal. Also terminal.
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_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_IF, // If statement
OP_LOOP, // FOR, WHILE
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_ENUM, // Enum Definitions
SC_MEMBER, // The members of Structs or Enums
//SC_CLASS, // Class-local definitions
//SC_STATIC, // Static storage definitions
//SC_CLASS, // Class-local definitions
//SC_STATIC, // Static storage definitions
SC_PARAM, // Function parameters
SC_LOCAL // Function-local scope.
// There is no deeper scope than function.
// There is no deeper scope than function.
};
@ -243,7 +244,7 @@ enum DataTypes {
RET_INT = 32, // "int" type keyword
RET_LONG = 48, // "long" type keyword
RET_VOID = 64, // "void" type keyword
DAT_STRUCT = 80, // Struct Data
DAT_UNION, // Union Data
};
@ -258,8 +259,8 @@ enum StructureType {
ST_FUNC, // This is a function
ST_ARR, // This is an array
ST_RUCT // This is a struct
// This is an enum
// This is a typedef
// This is an enum
// This is a typedef
};
@ -268,9 +269,13 @@ enum StructureType {
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
char* Suffixate(char* String, char Suffix);
char* Compile(char* InputFile);
char* Assemble(char* InputFile);
void Link(char* Output, char* Objects[]);
void DisplayUsage(char* ProgName);
@ -282,9 +287,11 @@ void DisplayUsage(char* ProgName);
void Tokenise();
void VerifyToken(int Type, char* TokenExpected);
void RejectToken(struct Token* Token);
static int ReadIdentifier(int Char, char* Buffer, int Limit);
static int ReadKeyword(char* Str);
/* * * * * * * * * * * * * * * * * * * *
@ -294,9 +301,11 @@ static int ReadKeyword(char* Str);
struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation);
int TypeIsInt(int Type);
int TypeIsPtr(int Type);
char* TypeNames(int Type);
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* 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* ParseStatement(void);
struct ASTNode* PrefixStatement();
struct ASTNode* PostfixStatement();
void ParseGlobals();
struct ASTNode* ParseFunction(int Type);
struct ASTNode* ParseCompound();
struct SymbolTableEntry* BeginStructDeclaration();
struct ASTNode* GetExpressionList();
struct ASTNode* CallFunction();
struct ASTNode* ReturnStatement();
int ParseOptionalPointer(struct SymbolTableEntry** Composite);
int ValueAt(int Type);
int PointerTo(int Type);
struct ASTNode* AccessArray();
struct ASTNode* AccessMember(bool Deref);
int ParseTokenToOperation(int Token);
@ -351,35 +371,45 @@ int ParseTokenToOperation(int Token);
struct ASTNode* PrintStatement(void);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * S Y M B O L T A B L E * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
void DumpAllLists();
void DumpList(struct SymbolTableEntry* List);
struct SymbolTableEntry* FindSymbol(char* Symbol);
struct SymbolTableEntry* FindLocal(char* Symbol);
struct SymbolTableEntry* FindGlobal(char* Symbol);
struct SymbolTableEntry* FindStruct(char* Symbol);
struct SymbolTableEntry* FindMember(char* Symbol);
void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node);
void FreeLocals();
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 * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
void Die(char* Error);
void DieMessage(char* Error, char* Reason);
void DieDecimal(char* Error, int Number);
void DieChar(char* Error, int Char);
void DieBinary(char* Error, int Number);
@ -396,62 +426,94 @@ int RetrieveRegister();
void DeallocateRegister(int Register);
int PrimitiveSize(int Type);
int AsAlignMemory(int Type, int Offset, int Direction);
int AsLoad(int Value);
int AsAdd(int Left, int Right);
int AsMul(int Left, int Right);
int AsSub(int Left, int Right);
int AsDiv(int Left, int Right);
int AsLdGlobalVar(struct SymbolTableEntry* Entry, int Operation);
int AsLdLocalVar(struct SymbolTableEntry* Entry, int Operation);
int AsStrGlobalVar(struct SymbolTableEntry* Entry, int Register);
int AsStrLocalVar(struct SymbolTableEntry* Entry, int Register);
int AsCalcOffset(int Type);
void AsNewStackFrame();
int AsDeref(int Reg, int Type);
int AsStrDeref(int Register1, int Register2, int Type);
int AsAddr(struct SymbolTableEntry* Entry);
void AsGlobalSymbol(struct SymbolTableEntry* Entry);
int AsNewString(char* Value);
int AsNewString(char* Value);
int AsLoadString(int ID);
int AsEqual(int Left, int Right);
int AsIneq(int Left, int Right);
int AsLess(int Left, int Right);
int AsGreat(int Left, int Right);
int AsLessE(int Left, int Right);
int AsGreatE(int Left, int Right);
int AsBitwiseAND(int Left, int Right);
int AsBitwiseOR(int Left, int Right);
int AsBitwiseXOR(int Left, int Right);
int AsNegate(int Register);
int AsInvert(int Register);
int AsBooleanNOT(int Register);
int AsShiftLeft(int Left, int Right);
int AsShiftRight(int Left, int Right);
int AsBooleanConvert(int Register, int Operation, int Label);
int AsCompareJmp(int Operation, int RegisterLeft, int RegisterRight, int Label);
int AsCompare(int Operation, int RegisterLeft, int RegisterRight);
int AsIf(struct ASTNode* Node);
int NewLabel(void);
void AsJmp(int Label);
void AsLabel(int Label);
int AsShl(int Register, int Val);
int AsReturn(struct SymbolTableEntry* Entry, int Register);
int AsCallWrapper(struct ASTNode* Node);
void AsCopyArgs(int Register, int Position);
int AsCall(struct SymbolTableEntry* Entry, int Args);
int AsWhile(struct ASTNode* Node);
@ -459,7 +521,9 @@ int AsWhile(struct ASTNode* Node);
void AssemblerPrint(int Register);
void AssemblerPreamble();
void AsFunctionPreamble(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 ASTNode* ParseIdentifier(void);
struct ASTNode* IfStatement();
struct ASTNode* WhileStatement();
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.
*/
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* ByteRegisters[8] = { "%r10b", "%r11b", "%r12b", "%r13b", "%r9b", "%r8b", "%dl" , "%cl" };
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* ByteRegisters[8] = {"%r10b", "%r11b", "%r12b", "%r13b", "%r9b", "%r8b", "%dl", "%cl"};
/*
* For ease of reading later code, we store the valid x86 comparison instructions,
* and the inverse jump instructions together, in a synchronized fashion.
*/
static char* Comparisons[6] = { "sete", "setne", "setl", "setg", "setle", "setge" };
static char* InvComparisons[6] = { "jne", "je", "jge", "jle", "jg", "jl"};
static char* Comparisons[6] = {"sete", "setne", "setl", "setg", "setle", "setge"};
static char* InvComparisons[6] = {"jne", "je", "jge", "jle", "jg", "jl"};
// How far above the base pointer is the last local?
static int LocalVarOffset;
@ -66,15 +66,15 @@ static int Started = 0;
*/
int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
int LeftVal, RightVal;
if(!Started && OptDumpTree)
if (!Started && OptDumpTree)
DumpTree(Node, 0);
Started = 1;
printf("Current operation: %d\r\n", Node->Operation);
switch(Node->Operation) {
switch (Node->Operation) {
case OP_IF:
return AsIf(Node);
case OP_LOOP:
return AsWhile(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);
if(Node->Right)
if (Node->Right)
RightVal = AssembleTree(Node->Right, LeftVal, Node->Operation);
switch(Node->Operation) {
switch (Node->Operation) {
case OP_ADD:
return AsAdd(LeftVal, RightVal);
@ -111,18 +111,21 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
case OP_MULTIPLY:
return AsMul(LeftVal, RightVal);
case OP_DIVIDE:
return AsDiv(LeftVal, RightVal);
case OP_SCALE:
// We can (ab)use the powers of 2 to do
// efficient scaling with bitshifting.
switch(Node->Size) {
case 2: return AsShl(LeftVal, 1);
case 4: return AsShl(LeftVal, 2);
case 8: return AsShl(LeftVal, 3);
switch (Node->Size) {
case 2:
return AsShl(LeftVal, 1);
case 4:
return AsShl(LeftVal, 2);
case 8:
return AsShl(LeftVal, 3);
default:
RightVal = AsLoad(Node->Size);
return AsMul(LeftVal, RightVal);
@ -135,25 +138,27 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
case OP_ASSIGN:
printf("Preparing for assignment..\r\n");
if(Node->Right == NULL)
if (Node->Right == NULL)
Die("Fault in assigning a null rvalue");
printf("\tCalculating assignment for target %s:\r\n", Node->Right->Symbol->Name);
switch(Node->Right->Operation) {
case REF_IDENT:
if(Node->Right->Symbol->Storage == SC_LOCAL)
switch (Node->Right->Operation) {
case REF_IDENT:
if (Node->Right->Symbol->Storage == SC_LOCAL)
return AsStrLocalVar(Node->Right->Symbol, LeftVal);
else
else
return AsStrGlobalVar(Node->Right->Symbol, LeftVal);
case OP_DEREF: return AsStrDeref(LeftVal, RightVal, Node->Right->ExprType);
default: DieDecimal("Can't ASSIGN in AssembleTree: ", Node->Operation);
case OP_DEREF:
return AsStrDeref(LeftVal, RightVal, Node->Right->ExprType);
default:
DieDecimal("Can't ASSIGN in AssembleTree: ", Node->Operation);
}
case OP_WIDEN:
printf("\tWidening types..\r\n");
return LeftVal;
case OP_RET:
printf("\tReturning from %s\n", Node->Symbol->Name);
AsReturn(FunctionEntry, LeftVal);
@ -165,24 +170,28 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
case OP_GREAT:
case OP_LESSE:
case OP_GREATE:
if(ParentOp == OP_IF || ParentOp == OP_LOOP)
if (ParentOp == OP_IF || ParentOp == OP_LOOP)
return AsCompareJmp(Node->Operation, LeftVal, RightVal, Register);
else
return AsCompare(Node->Operation, LeftVal, RightVal);
case REF_IDENT:
if(Node->RVal || ParentOp == OP_DEREF) {
if(Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM)
if (TypeIsPtr(Node->ExprType)) {
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);
else
else
return AsLdGlobalVar(Node->Symbol, Node->Operation);
} else
} else
return -1;
case TERM_INTLITERAL:
return AsLoad(Node->IntValue);
case TERM_STRLITERAL:
return AsLoadString(Node->IntValue);
@ -193,40 +202,40 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
case OP_BITAND:
return AsBitwiseAND(LeftVal, RightVal);
case OP_BITOR:
return AsBitwiseOR(LeftVal, RightVal);
case OP_BITXOR:
return AsBitwiseXOR(LeftVal, RightVal);
case OP_SHIFTL:
return AsShiftLeft(LeftVal, RightVal);
case OP_SHIFTR:
return AsShiftRight(LeftVal, RightVal);
case OP_POSTINC:
return AsLdGlobalVar(Node->Symbol, Node->Operation);
case OP_POSTDEC:
return AsLdGlobalVar(Node->Symbol, Node->Operation);
case OP_PREINC:
return AsLdGlobalVar(Node->Symbol, Node->Operation);
case OP_PREDEC:
return AsLdGlobalVar(Node->Symbol, Node->Operation);
case OP_BOOLNOT:
return AsBooleanNOT(LeftVal);
case OP_BITNOT:
return AsInvert(LeftVal);
case OP_NEGATE:
return AsNegate(LeftVal);
case OP_BOOLCONV:
return AsBooleanConvert(LeftVal, ParentOp, Register);
@ -250,7 +259,7 @@ void DeallocateAllRegisters() {
*/
int RetrieveRegister() {
for (size_t i = 0; i < 4; i++) {
if(UsedRegisters[i] == 0) {
if (UsedRegisters[i] == 0) {
UsedRegisters[i] = 1;
return i;
}
@ -265,7 +274,7 @@ int RetrieveRegister() {
* @param Register: The Registers index to deallocate.
*/
void DeallocateRegister(int Register) {
if(UsedRegisters[Register] != 1) {
if (UsedRegisters[Register] != 1) {
fprintf(stderr, "Error trying to free register %d\n", Register);
exit(1);
}
@ -328,27 +337,30 @@ int NewLabel(void) {
*
*/
int AsAlignMemory(int Type, int Offset, int Direction) {
switch(Type) {
case RET_CHAR: return Offset;
case RET_INT: case RET_LONG: break;
default:
DieDecimal("Unable to align type", Type);
switch (Type) {
case RET_CHAR:
return Offset;
case RET_INT:
case RET_LONG:
break;
default:
DieDecimal("Unable to align type", Type);
}
int Alignment = 4;
Offset = (Offset + Direction * (Alignment-1)) & ~(Alignment-1);
Offset = (Offset + Direction * (Alignment - 1)) & ~(Alignment - 1);
return (Offset);
}
// Assemble an If statement
int AsIf(struct ASTNode* Node) {
int FalseLabel, EndLabel;
FalseLabel = NewLabel();
if(Node->Right)
if (Node->Right)
EndLabel = NewLabel();
// Left is the condition
AssembleTree(Node->Left, FalseLabel, Node->Operation);
DeallocateAllRegisters();
@ -358,12 +370,12 @@ int AsIf(struct ASTNode* Node) {
DeallocateAllRegisters();
// Right is the optional else
if(Node->Right)
if (Node->Right)
AsJmp(EndLabel);
AsLabel(FalseLabel);
if(Node->Right) {
if (Node->Right) {
AssembleTree(Node->Right, -1, Node->Operation);
DeallocateAllRegisters();
AsLabel(EndLabel);
@ -376,9 +388,9 @@ int AsIf(struct ASTNode* Node) {
int AsCompare(int Operation, int RegisterLeft, int 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");
fprintf(OutputFile, "\tcmpq\t%s, %s\n", Registers[RegisterRight], Registers[RegisterLeft]);
fprintf(OutputFile, "\t%s\t\t%s\n", Comparisons[Operation - OP_EQUAL], ByteRegisters[RegisterRight]);
fprintf(OutputFile, "\tmovzbq\t%s, %s\n", ByteRegisters[RegisterRight], Registers[RegisterLeft]);
@ -388,11 +400,12 @@ int AsCompare(int Operation, int RegisterLeft, int RegisterRight) {
// Assemble an inverse comparison (a one-line jump)
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");
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, "\t%s\tL%d\n", InvComparisons[Operation - OP_EQUAL], Label);
DeallocateAllRegisters();
@ -424,17 +437,17 @@ int AsNewString(char* Value) {
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\t0\r\n");
return Label;
}
/*
* Load a string into a Register.
* @param ID: the Label number of the string
*/
*/
int AsLoadString(int ID) {
int Register = RetrieveRegister();
fprintf(OutputFile, "\tleaq\tL%d(\%%rip), %s\r\n", ID, Registers[Register]);
@ -444,7 +457,7 @@ int AsLoadString(int ID) {
// Assemble a While loop
int AsWhile(struct ASTNode* Node) {
int BodyLabel, BreakLabel;
BodyLabel = NewLabel();
BreakLabel = NewLabel();
@ -499,7 +512,7 @@ int AsMul(int Left, int Right) {
fprintf(OutputFile, "\timulq\t%s, %s\n", Registers[Left], Registers[Right]);
DeallocateRegister(Left);
return Right;
}
@ -537,66 +550,78 @@ int AsShl(int Register, int Val) {
* Load a global variable into a register, with optional pre/post-inc/dec
* @param Entry: The variable to load.
* @param Operation: An optional SyntaxOps element
*/
*/
int AsLdGlobalVar(struct SymbolTableEntry* Entry, int Operation) {
int Reg = RetrieveRegister();
printf("\tStoring %s's contents into %s, globally\n", Entry->Name, Registers[Reg]);
int TypeSize = PrimitiveSize(Entry->Type);
switch(TypeSize) {
switch (TypeSize) {
case 1:
switch(Operation) {
switch (Operation) {
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:
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]);
switch(Operation) {
switch (Operation) {
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:
fprintf(OutputFile, "\tdecb\t%s(\%%rip)\n", Entry->Name); break;
fprintf(OutputFile, "\tdecb\t%s(\%%rip)\n", Entry->Name);
break;
}
break;
case 4:
switch(Operation) {
switch (Operation) {
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:
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]);
switch(Operation) {
switch (Operation) {
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:
fprintf(OutputFile, "\tdecl\t%s(\%%rip)\n", Entry->Name); break;
fprintf(OutputFile, "\tdecl\t%s(\%%rip)\n", Entry->Name);
break;
}
break;
break;
case 8:
switch(Operation) {
switch (Operation) {
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:
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]);
switch(Operation) {
switch (Operation) {
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:
fprintf(OutputFile, "\tdecq\t%s(\%%rip)\n", Entry->Name); break;
fprintf(OutputFile, "\tdecq\t%s(\%%rip)\n", Entry->Name);
break;
}
break;
@ -617,16 +642,16 @@ int AsStrGlobalVar(struct SymbolTableEntry* Entry, int Register) {
printf("\tStoring contents of %s into %s, type %d, globally:\n", Registers[Register], Entry->Name, Entry->Type);
int TypeSize = PrimitiveSize(Entry->Type);
switch(TypeSize) {
switch (TypeSize) {
case 1:
// movzbq zeroes, then moves a byte into the quad register
fprintf(OutputFile, "\tmovb\t%s, %s(\%%rip)\n", ByteRegisters[Register], Entry->Name);
break;
case 4:
fprintf(OutputFile, "\tmovl\t%s, %s(\%%rip)\n", DoubleRegisters[Register], Entry->Name);
break;
case 8:
fprintf(OutputFile, "\tmovq\t%s, %s(%%rip)\n", Registers[Register], Entry->Name);
break;
@ -634,7 +659,7 @@ int AsStrGlobalVar(struct SymbolTableEntry* Entry, int Register) {
default:
DieMessage("Bad type for saving", TypeNames(Entry->Type));
}
return Register;
}
@ -648,61 +673,73 @@ int AsLdLocalVar(struct SymbolTableEntry* Entry, int Operation) {
int Reg = RetrieveRegister();
printf("\tStoring the var at %d's contents into %s, locally\n", Entry->SinkOffset, Registers[Reg]);
int TypeSize = PrimitiveSize(Entry->Type);
switch(TypeSize) {
switch (TypeSize) {
case 1:
switch(Operation) {
switch (Operation) {
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:
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]);
switch(Operation) {
switch (Operation) {
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:
fprintf(OutputFile, "\tdecb\t%d(\%%rbp)\n", Entry->SinkOffset); break;
fprintf(OutputFile, "\tdecb\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
}
break;
case 4:
switch(Operation) {
switch (Operation) {
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:
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]);
switch(Operation) {
switch (Operation) {
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:
fprintf(OutputFile, "\tdecl\t%d(\%%rbp)\n", Entry->SinkOffset); break;
fprintf(OutputFile, "\tdecl\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
}
break;
break;
case 8:
switch(Operation) {
switch (Operation) {
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:
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]);
switch(Operation) {
switch (Operation) {
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:
fprintf(OutputFile, "\tdecq\t%d(\%%rbp)\n", Entry->SinkOffset); break;
fprintf(OutputFile, "\tdecq\t%d(\%%rbp)\n", Entry->SinkOffset);
break;
}
break;
@ -713,7 +750,7 @@ int AsLdLocalVar(struct SymbolTableEntry* Entry, int Operation) {
return Reg;
}
/*
* Store a value from a register into a local variable.
* @param Entry: The local variable to write to.
@ -724,16 +761,16 @@ int AsStrLocalVar(struct SymbolTableEntry* Entry, int Register) {
printf("\tStoring contents of %s into %s, type %d, locally\n", Registers[Register], Entry->Name, Entry->Type);
int TypeSize = PrimitiveSize(Entry->Type);
switch(TypeSize) {
switch (TypeSize) {
case 1:
// movzbq zeroes, then moves a byte into the quad register
fprintf(OutputFile, "\tmovb\t%s, %d(\%%rbp)\n", ByteRegisters[Register], Entry->SinkOffset);
break;
case 4:
fprintf(OutputFile, "\tmovl\t%s, %d(\%%rbp)\n", DoubleRegisters[Register], Entry->SinkOffset);
break;
case 8:
fprintf(OutputFile, "\tmovq\t%s, %d(%%rbp)\n", Registers[Register], Entry->SinkOffset);
break;
@ -741,7 +778,7 @@ int AsStrLocalVar(struct SymbolTableEntry* Entry, int Register) {
default:
DieMessage("Bad type for saving", TypeNames(Entry->Type));
}
return Register;
}
@ -760,17 +797,20 @@ int AsDeref(int Reg, int Type) {
int DestSize = PrimitiveSize(ValueAt(Type));
printf("\tDereferencing %s\n", Registers[Reg]);
switch(DestSize) {
switch (DestSize) {
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;
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:
fprintf(OutputFile, "\tmovl\t(%s), %s\n", Registers[Reg], DoubleRegisters[Reg]);
break;
case 8:
fprintf(OutputFile, "\tmovq\t(%s), %s\n", Registers[Reg], Registers[Reg]);
break;
default:
default:
DieDecimal("Can't generate dereference for type", Type);
}
@ -779,13 +819,16 @@ int AsDeref(int Reg, int Type) {
// Assemble a store-through-dereference
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:
fprintf(OutputFile, "\tmovb\t%s, (%s)\n", ByteRegisters[Register1], Registers[Register2]);
break;
case RET_INT:
fprintf(OutputFile, "\tmovl\t%s, (%s)\n", DoubleRegisters[Register1], Registers[Register2]);
break;
case RET_LONG:
fprintf(OutputFile, "\tmovq\t%s, (%s)\n", Registers[Register1], Registers[Register2]);
break;
@ -799,27 +842,33 @@ int AsStrDeref(int Register1, int Register2, int Type) {
// Assemble a global symbol (variable, struct, enum, function, string)
void AsGlobalSymbol(struct SymbolTableEntry* Entry) {
if(Entry == NULL) return;
if(Entry->Structure == ST_FUNC) return;
if (Entry == NULL) return;
if (Entry->Structure == ST_FUNC) return;
int Size = TypeSize(Entry->Type, Entry->CompositeType);
fprintf(OutputFile, "\t.data\n"
"\t.globl\t%s\n",
Entry->Name);
Entry->Name);
fprintf(OutputFile, "%s:\n", Entry->Name);
switch(Size) {
case 1: fprintf(OutputFile, "\t.byte\t0\r\n", Entry->Name); 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;
switch (Size) {
case 1:
fprintf(OutputFile, "\t.byte\t0\r\n", Entry->Name);
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:
for(int i = 0; i < Size; i++)
for (int i = 0; i < Size; i++)
fprintf(OutputFile, "\t.byte\t0\n");
}
}
// Assemble a function call, with all associated parameter bumping and stack movement.
@ -827,10 +876,10 @@ int AsCallWrapper(struct ASTNode* Node) {
struct ASTNode* CompositeTree = Node->Left;
int Register, Args = 0;
while(CompositeTree) {
while (CompositeTree) {
Register = AssembleTree(CompositeTree->Right, -1, CompositeTree->Operation);
AsCopyArgs(Register, CompositeTree->Size);
if(Args == 0) Args = CompositeTree->Size;
if (Args == 0) Args = CompositeTree->Size;
DeallocateAllRegisters();
CompositeTree = CompositeTree->Left;
}
@ -840,10 +889,10 @@ int AsCallWrapper(struct ASTNode* Node) {
// Copy a function argument from Register to argument 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]);
} 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,11 +906,11 @@ int AsCall(struct SymbolTableEntry* Entry, int Args) {
printf("\t\t\tFunction returns into %s\n", Registers[OutRegister]);
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, "\tmovq\t%%rax, %s\n", Registers[OutRegister]);
return OutRegister;
}
@ -870,19 +919,19 @@ int AsReturn(struct SymbolTableEntry* Entry, int Register) {
printf("\t\tCreating return for function %s\n", Entry->Name);
switch(Entry->Type) {
switch (Entry->Type) {
case RET_CHAR:
fprintf(OutputFile, "\tmovzbl\t%s, %%eax\n", ByteRegisters[Register]);
break;
case RET_INT:
fprintf(OutputFile, "\tmovl\t%s, %%eax\n", DoubleRegisters[Register]);
break;
case RET_LONG:
fprintf(OutputFile, "\tmovq\t%s, %%rax\n", Registers[Register]);
break;
default:
DieMessage("Bad function type in generating return", TypeNames(Entry->Type));
@ -1001,7 +1050,7 @@ int AsShiftRight(int Left, int Right) {
int AsBooleanConvert(int Register, int Operation, int Label) {
fprintf(OutputFile, "\ttest\t%s, %s\n", Registers[Register], Registers[Register]);
switch(Operation) {
switch (Operation) {
case OP_IF:
case OP_LOOP:
fprintf(OutputFile, "\tje\tL%d\n", Label);
@ -1036,7 +1085,7 @@ void AssemblerPreamble() {
*/
void AsFunctionPreamble(struct SymbolTableEntry* Entry) {
char* Name = Entry->Name;
struct SymbolTableEntry* Param, *Local;
struct SymbolTableEntry* Param, * Local;
int ParamOffset = 0, ParamReg = 9, ParamCount = 0;
LocalVarOffset = 4; // Prepare parameters
@ -1049,17 +1098,17 @@ void AsFunctionPreamble(struct SymbolTableEntry* Entry) {
"\tpushq\t%%rbp\n"
"\tmovq\t%%rsp, %%rbp\r\n",
Name, Name, Name);
//PECOFF requires we call the global initialisers
if(!strcmp(Name, "main"))
if (!strcmp(Name, "main"))
fprintf(OutputFile, "\tcall\t__main\n");
// Need to share this between two loops. Fun.
int LoopIndex;
// If we have parameters, move them to the last 4 registers
for(Param = Entry->Start, ParamCount = 1; Param != NULL; Param = Param->NextSymbol, ParamCount++) {
if(ParamCount > 4) { // We only have 4 argument registers
for (Param = Entry->Start, ParamCount = 1; Param != NULL; Param = Param->NextSymbol, ParamCount++) {
if (ParamCount > 4) { // We only have 4 argument registers
Param->SinkOffset = ParamOffset;
ParamOffset += 8;
}
@ -1069,13 +1118,13 @@ void AsFunctionPreamble(struct SymbolTableEntry* Entry) {
}
// 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);
}
// With all the parameters on the stack, we can allocate the shadow space
StackFrameOffset = ((LocalVarOffset + 31) & ~31);
fprintf(OutputFile,
fprintf(OutputFile,
"\taddq\t$%d, %%rsp\n", -StackFrameOffset);
}

View File

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

View File

@ -19,13 +19,13 @@ void DumpTree(struct ASTNode* Node, int level) {
int Lfalse, Lstart, Lend;
// Handle weirdo loops and conditions first.
switch(Node->Operation) {
switch (Node->Operation) {
case OP_IF:
Lfalse = GenerateSrg();
for(int i = 0; i < level; i++)
for (int i = 0; i < level; i++)
fprintf(stdout, " ");
fprintf(stdout, "IF");
if(Node->Right) {
if (Node->Right) {
Lend = GenerateSrg();
fprintf(stdout, ", end label %d", Lend);
}
@ -33,14 +33,14 @@ void DumpTree(struct ASTNode* Node, int level) {
fprintf(stdout, "\n");
DumpTree(Node->Left, level + 2);
DumpTree(Node->Middle, level + 2);
if(Node->Right)
if (Node->Right)
DumpTree(Node->Right, level + 2);
return;
case OP_LOOP:
Lstart = GenerateSrg();
for(int i = 0; i < level; i++)
for (int i = 0; i < level; i++)
fprintf(stdout, " ");
fprintf(stdout, "LOOP starts at %d\n", Lstart);
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(Node->Operation == OP_COMP)
if (Node->Operation == OP_COMP)
level = -2;
if(Node->Left)
if (Node->Left)
DumpTree(Node->Left, level + 2);
if(Node->Right)
if (Node->Right)
DumpTree(Node->Right, level + 2);
// The meat of this operation!
for(int i = 0; i < level; i++)
for (int i = 0; i < level; i++)
fprintf(stdout, " ");
switch (Node->Operation){
case OP_COMP: fprintf(stdout, "\n\n"); return;
case OP_FUNC: fprintf(stdout, "OP_FUNC %s\n", Node->Symbol->Name); return;
case OP_ADD: fprintf(stdout, "OP_ADD\n"); return;
case OP_SUBTRACT: fprintf(stdout, "OP_SUBTRACT\n"); return;
case OP_MULTIPLY: fprintf(stdout, "OP_MULTIPLY\n"); return;
case OP_DIVIDE: fprintf(stdout, "OP_DIVIDE\n"); return;
case OP_EQUAL: fprintf(stdout, "OP_EQUAL\n"); return;
case OP_INEQ: fprintf(stdout, "OP_INEQ\n"); return;
case OP_LESS: fprintf(stdout, "OP_LESS\n"); return;
case OP_GREAT: fprintf(stdout, "OP_GREAT\n"); return;
case OP_LESSE: fprintf(stdout, "OP_LESSE\n"); return;
case OP_GREATE: fprintf(stdout, "OP_GREATE\n"); return;
case TERM_INTLITERAL: fprintf(stdout, "TERM_INTLITERAL %d\n", Node->IntValue); return;
case TERM_STRLITERAL: fprintf(stdout, "TERM_STRLITERAL rval L%d\n", Node->IntValue); return;
case REF_IDENT:
if(Node->RVal)
fprintf(stdout, "REF_IDENT rval %s\n", Node->Symbol->Name);
else
fprintf(stdout, "REF_IDENT %s\n", Node->Symbol->Name);
switch (Node->Operation) {
case OP_COMP:
fprintf(stdout, "\n\n");
return;
case OP_FUNC:
fprintf(stdout, "OP_FUNC %s\n", Node->Symbol->Name);
return;
case OP_ADD:
fprintf(stdout, "OP_ADD\n");
return;
case OP_SUBTRACT:
fprintf(stdout, "OP_SUBTRACT\n");
return;
case OP_MULTIPLY:
fprintf(stdout, "OP_MULTIPLY\n");
return;
case OP_DIVIDE:
fprintf(stdout, "OP_DIVIDE\n");
return;
case OP_EQUAL:
fprintf(stdout, "OP_EQUAL\n");
return;
case OP_INEQ:
fprintf(stdout, "OP_INEQ\n");
return;
case OP_LESS:
fprintf(stdout, "OP_LESS\n");
return;
case OP_GREAT:
fprintf(stdout, "OP_GREAT\n");
return;
case OP_LESSE:
fprintf(stdout, "OP_LESSE\n");
return;
case OP_GREATE:
fprintf(stdout, "OP_GREATE\n");
return;
case TERM_INTLITERAL:
fprintf(stdout, "TERM_INTLITERAL %d\n", Node->IntValue);
return;
case TERM_STRLITERAL:
fprintf(stdout, "TERM_STRLITERAL rval L%d\n", Node->IntValue);
return;
case REF_IDENT:
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;
case OP_DEREF:
fprintf(stdout, "OP_DEREF %s\n", Node->RVal ? "rval" : "");
return;
case OP_SCALE:
fprintf(stdout, "OP_SCALE %s\n", TypeNames(Node->Size));
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:
fprintf(stdout, "OP_DEREF %s\n", Node->RVal ? "rval" : ""); 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_BOOLAND: 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_BOOLOR:
fprintf(stdout, "OP_BOOLOR\n");
return;
case OP_BOOLAND:
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_SHIFTR: fprintf(stdout, "OP_SHIFTR\n"); return;
case OP_SHIFTL:
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_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_PREINC:
fprintf(stdout, "OP_PREINC\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_BOOLNOT: fprintf(stdout, "OP_BOOLNOT\n"); return;
case OP_NEGATE: fprintf(stdout, "OP_NEGATE\n"); return;
case OP_BITNOT:
fprintf(stdout, "OP_BITNOT\n");
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:
DieDecimal("Unknown Dump Operator", Node->Operation);

View File

@ -37,7 +37,7 @@ static void ReturnCharToStream(int Char) {
static int NextChar(void) {
int Char;
if(Overread) {
if (Overread) {
Char = Overread;
Overread = 0;
return Char;
@ -45,9 +45,9 @@ static int NextChar(void) {
Char = fgetc(SourceFile);
if(Char == '\n')
if (Char == '\n')
Line++;
return Char;
}
@ -61,7 +61,7 @@ static int FindChar() {
Char = NextChar();
while(Char == ' ' || Char == '\t' || Char == '\n' || Char == '\r') {
while (Char == ' ' || Char == '\t' || Char == '\n' || Char == '\r') {
Char = NextChar();
}
@ -77,7 +77,7 @@ static int FindChar() {
static int FindDigitFromPos(char* String, char 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) {
if(CurrentToken.type == Type)
if (CurrentToken.type == Type)
Tokenise();
else {
printf("Expected %s on line %d\n", TokenExpected, Line);
@ -108,9 +108,9 @@ static struct Token* RejectedToken = NULL;
*/
void RejectToken(struct Token* Token) {
if(RejectedToken != NULL)
if (RejectedToken != NULL)
Die("Cannot reject two tokens in a row!");
RejectedToken = Token;
}
@ -137,7 +137,7 @@ static int ReadInteger(int Char) {
int CurrentChar = 0;
int IntegerValue = 0;
while((CurrentChar = FindDigitFromPos("0123456789", Char)) >= 0) {
while ((CurrentChar = FindDigitFromPos("0123456789", Char)) >= 0) {
IntegerValue = IntegerValue * 10 + CurrentChar;
Char = NextChar();
}
@ -165,10 +165,10 @@ static int ReadInteger(int Char) {
*
*/
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.
while(isalpha(Char) || isdigit(Char) || Char == '_') {
while (isalpha(Char) || isdigit(Char) || Char == '_') {
if (ind >= Limit - 1) {
printf("Identifier too long: %d\n", Line);
exit(1);
@ -199,18 +199,28 @@ static int ReadIdentifier(int Char, char* Buffer, int Limit) {
static int ReadCharLiteral() {
int Char;
Char = NextChar();
if(Char == '\\') {
switch(Char = NextChar()) {
case 'a': return '\a';
case 'b': return '\b';
case 'f': return '\f';
case 'n': return '\n';
case 'r': return '\r';
case 't': return '\t';
case 'v': return '\v';
case '\\': return '\\';
case '"': return '"';
case '\'': return '\'';
if (Char == '\\') {
switch (Char = NextChar()) {
case 'a':
return '\a';
case 'b':
return '\b';
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'v':
return '\v';
case '\\':
return '\\';
case '"':
return '"';
case '\'':
return '\'';
default:
DieChar("Unknown Escape: ", Char);
}
@ -236,11 +246,12 @@ static int ReadCharLiteral() {
static int ReadStringLiteral(char* Buffer) {
int Char;
for(int i = 0; i < TEXTLEN - 1; i++) {
if((Char = ReadCharLiteral()) == '"') {
Buffer[i] = 0; return i;
for (int i = 0; i < TEXTLEN - 1; i++) {
if ((Char = ReadCharLiteral()) == '"') {
Buffer[i] = 0;
return i;
}
Buffer[i] = Char;
}
@ -265,80 +276,79 @@ static int ReadStringLiteral(char* Buffer) {
*/
static int ReadKeyword(char* Str) {
// First, scan with reference intact.
switch(*Str) {
switch (*Str) {
// This lets us case against the first char:
case ':':
if(!strcmp(Str, "::"))
if (!strcmp(Str, "::"))
return KW_FUNC;
break;
case 'c':
if(!strcmp(Str, "char"))
if (!strcmp(Str, "char"))
return TY_CHAR;
break;
case 'e':
if(!strcmp(Str, "else"))
if (!strcmp(Str, "else"))
return KW_ELSE;
break;
case 'f':
if(!strcmp(Str, "for"))
if (!strcmp(Str, "for"))
return KW_FOR;
break;
case 'i':
// alias char, int and long types
if(!strcmp(Str, "i8"))
if (!strcmp(Str, "i8"))
return TY_CHAR;
if(!strcmp(Str, "i32"))
if (!strcmp(Str, "i32"))
return TY_INT;
if(!strcmp(Str, "i64"))
if (!strcmp(Str, "i64"))
return TY_LONG;
if(!strcmp(Str, "int"))
if (!strcmp(Str, "int"))
return TY_INT;
if(!strcmp(Str, "if"))
if (!strcmp(Str, "if"))
return KW_IF;
break;
case 'l':
if(!strcmp(Str, "long"))
if (!strcmp(Str, "long"))
return TY_LONG;
break;
case 'p':
if(!strcmp(Str, "print"))
if (!strcmp(Str, "print"))
return KW_PRINT;
break;
case 'r':
if(!strcmp(Str, "return"))
if (!strcmp(Str, "return"))
return KW_RETURN;
break;
case 's':
if(!strcmp(Str, "struct"))
if (!strcmp(Str, "struct"))
return KW_STRUCT;
break;
case 'v':
if(!strcmp(Str, "void"))
if (!strcmp(Str, "void"))
return TY_VOID;
break;
case 'w':
if(!strcmp(Str, "while"))
if (!strcmp(Str, "while"))
return KW_WHILE;
break;
}
return 0;
@ -364,7 +374,7 @@ void Tokenise() {
int Char, TokenType;
struct Token* Token = &CurrentToken;
if(RejectedToken != NULL) {
if (RejectedToken != NULL) {
Token = RejectedToken;
RejectedToken = NULL;
return;
@ -372,7 +382,7 @@ void Tokenise() {
Char = FindChar();
switch(Char) {
switch (Char) {
case EOF:
Token->type = LI_EOF;
return;
@ -384,7 +394,7 @@ void Tokenise() {
case '+':
// + can be either "+" or "++".
Char = NextChar();
if(Char == '+') {
if (Char == '+') {
Token->type = PPMM_PLUS;
} else {
Token->type = AR_PLUS;
@ -395,9 +405,9 @@ void Tokenise() {
case '-':
// - can be either "-" or "--" or "->"
Char = NextChar();
if(Char == '-') {
if (Char == '-') {
Token->type = PPMM_MINUS;
} else if(Char == '>') {
} else if (Char == '>') {
Token->type = LI_ARROW;
} else {
Token->type = AR_MINUS;
@ -415,28 +425,28 @@ void Tokenise() {
case '&':
Char = NextChar();
if(Char == '&') {
if (Char == '&') {
Token->type = BOOL_AND;
} else {
Token->type = BIT_AND;
ReturnCharToStream(Char);
}
break;
case '|':
Char = NextChar();
if(Char == '|') {
if (Char == '|') {
Token->type = BOOL_OR;
} else {
Token->type = BIT_OR;
ReturnCharToStream(Char);
}
break;
case '^':
Token->type = BIT_XOR;
break;
case '~':
Token->type = BIT_NOT;
break;
@ -444,40 +454,40 @@ void Tokenise() {
case ',':
Token->type = LI_COM;
break;
case '=':
Char = NextChar();
// If the next char is =, we have ==, the compare equality token.
if(Char == '?') {
if (Char == '?') {
Token->type = CMP_EQUAL;
// if the next char is >, we have =>, the greater than or equal token.
} else if(Char == '>') {
// if the next char is >, we have =>, the greater than or equal token.
} else if (Char == '>') {
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 {
ReturnCharToStream(Char);
Token->type = LI_EQUAL;
}
break;
case '!':
Char = NextChar();
// If the next char is =, we have !=, the compare inequality operator.
if(Char == '=') {
if (Char == '=') {
Token->type = CMP_INEQ;
// Otherwise, we have a spare char
// Otherwise, we have a spare char
} else {
Token->type = BOOL_INVERT;
ReturnCharToStream(Char);
ReturnCharToStream(Char);
}
break;
case '<':
Char = NextChar();
// If the next char is =, we have <=, the less than or equal comparator.
if(Char == '=') {
if (Char == '=') {
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;
} else {
ReturnCharToStream(Char);
@ -488,7 +498,7 @@ void Tokenise() {
case '>':
// For >, Less than or equal is => so we can ignore it, but the Shift Right operator is >>.
Char = NextChar();
if(Char == '>') {
if (Char == '>') {
Token->type = SH_RIGHT;
} else {
Token->type = CMP_GT;
@ -503,11 +513,11 @@ void Tokenise() {
case '(':
Token->type = LI_LPARE;
break;
case ')':
Token->type = LI_RPARE;
break;
case '{':
Token->type = LI_LBRAC;
break;
@ -519,15 +529,15 @@ void Tokenise() {
case '[':
Token->type = LI_LBRAS;
break;
case ']':
Token->type = LI_RBRAS;
break;
case ':':
Char = NextChar();
if(Char == ':') {
if (Char == ':') {
Token->type = KW_FUNC;
} else {
ReturnCharToStream(Char);
@ -538,7 +548,7 @@ void Tokenise() {
Token->value = ReadCharLiteral();
Token->type = LI_INT;
if(NextChar() != '\'')
if (NextChar() != '\'')
Die("Expected '\\'' at the end of a character.");
break;
@ -548,27 +558,28 @@ void Tokenise() {
break;
default:
if(isdigit(Char)) {
if (isdigit(Char)) {
Token->value = ReadInteger(Char);
Token->type = LI_INT;
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);
if(TokenType = ReadKeyword(CurrentIdentifier)) {
if (TokenType = ReadKeyword(CurrentIdentifier)) {
Token->type = TokenType;
break;
}
Token->type = TY_IDENTIFIER;
break;
//printf("Line %d: Unrecognized symbol %s\n", CurrentIdentifier, Line);
//printf.er("Line %d: Unrecognized symbol %s\n", CurrentIdentifier, Line);
//exit(1);
}
DieChar("Unrecognized character", Char);
}

View File

@ -4,96 +4,99 @@
/*************/
#include <Defs.h>
#define extern_
#include <Data.h>
#undef extern_
#include <errno.h>
int TypeSizes[5] = { 0, 1, 4, 8, 0}; // in BYTES
char* TokenNames[] = {
"End of file",
"Equivalency",
int TypeSizes[5] = {0, 1, 4, 8, 0}; // in BYTES
"Boolean Logic OR",
"Boolean Logic AND",
char* TokenNames[] = {
"End of file",
"Equivalency",
"Bitwise OR",
"Bitwise XOR",
"Bitwise AND",
"Boolean Logic OR",
"Boolean Logic AND",
"Equality Check",
"Inequality Check",
"Less Than",
"Greater Than",
"Less Than or Equal",
"Greater Than or Equal",
"Bitwise OR",
"Bitwise XOR",
"Bitwise AND",
"Left Shift",
"Right Shift",
"Equality Check",
"Inequality Check",
"Less Than",
"Greater Than",
"Less Than or Equal",
"Greater Than or Equal",
"Addition",
"Subtraction",
"Multiplication",
"Division",
"Left Shift",
"Right Shift",
"Increment",
"Decrement",
"Addition",
"Subtraction",
"Multiplication",
"Division",
"Statement Logical Invert",
"Bitwise Invert",
"Integer literal",
"String literal",
"Statement End",
"Increment",
"Decrement",
"Compound Block Start",
"Compound Block End",
"Statement Logical Invert",
"Bitwise Invert",
"Array index start",
"Array index end",
"Integer literal",
"String literal",
"Statement End",
"Logical Block Start",
"Logical Block End",
"Compound Block Start",
"Compound Block End",
"Comma",
"Dot",
"Arrow",
"Array index start",
"Array index end",
"Identifier",
"None Type",
"Char Type",
"Int Type",
"Long Type",
"Void Type",
"Logical Block Start",
"Logical Block End",
"Function keyword",
"Print Keyword",
"If keyword",
"Else keyword",
"While keyword",
"For keyword",
"Comma",
"Dot",
"Arrow",
"Return keyword",
"Struct keyword"
"Identifier",
"None Type",
"Char Type",
"Int Type",
"Long Type",
"Void Type",
"Function keyword",
"Print Keyword",
"If keyword",
"Else keyword",
"While keyword",
"For keyword",
"Return keyword",
"Struct keyword"
};
char* ScopeNames[] = {
"INVALID",
"GLOBAL",
"STRUCT",
"ENUM",
"MEMBER",
"PARAMETER",
"LOCAL"
"INVALID",
"GLOBAL",
"STRUCT",
"ENUM",
"MEMBER",
"PARAMETER",
"LOCAL"
};
int main(int argc, char* argv[]) {
// Option initialisers
OptDumpTree = false;
OptKeepAssembly = false;
OptKeepAssembly = true;
OptAssembleFiles = false;
OptLinkFiles = true;
OptVerboseOutput = false;
@ -104,24 +107,24 @@ int main(int argc, char* argv[]) {
// Parse command line arguments.
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.
// We only care about flags in rows.
// ie. erc >> -v -T -o << test.exe src/main.er
if(*argv[i] != '-')
if (*argv[i] != '-')
break;
// 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.
switch(argv[i][j]) {
switch (argv[i][j]) {
case 'o': // output
OutputFileName = argv[++i];
break;
case 'T': // print Tree (debug)
OptDumpTree = true;
break;
case 'T': // Debug
OptDumpTree = true;
break;
case 'c': // Compile only
OptAssembleFiles = true;
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(i >= argc)
if (i >= argc)
DisplayUsage(argv[0]);
// 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
CurrentASMFile = Compile(argv[i]);
if(OptLinkFiles || OptAssembleFiles) {
if (OptLinkFiles || OptAssembleFiles) {
// If we need to assemble (or link, which requires assembly)
// then we invoke the Delegate again
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.
if(ObjectCount == 98) {
if (ObjectCount == 98) {
fprintf(stderr, "Too many inputs");
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;
}
if(!OptKeepAssembly)
if (!OptKeepAssembly)
// unlink = delete
unlink(CurrentASMFile);
i++;
}
if(OptLinkFiles) {
if (OptLinkFiles) {
// If needed, invoke the Delegate one last time.
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.
for(i = 0; ObjectFiles[i] != NULL; i++)
for (i = 0; ObjectFiles[i] != NULL; i++)
unlink(ObjectFiles[i]);
}
}

View File

@ -16,17 +16,17 @@
* This allows for things like the common Order of Operations.
*/
static int Precedence[] = {
0, 10, // EOF, ASSIGN
20, 30, // || &&
40, 50, // | ^
60, 70, // & =?
70, 80, // != <
80, 80, // > <=
80, 90, // => <<
90, 100, // >> +
0, 10, // EOF, ASSIGN
20, 30, // || &&
40, 50, // | ^
60, 70, // & =?
70, 80, // != <
80, 80, // > <=
80, 90, // => <<
90, 100, // >> +
100, 110, // - *
110 // /
};
};
/*
* Handles gathering the precedence of an operator from its token,
@ -38,8 +38,8 @@ static int Precedence[] = {
static int OperatorPrecedence(int Token) {
int Prec = Precedence[Token];
if(Prec == 0 || Token >= PPMM_PLUS) {
if(Token == TY_IDENTIFIER)
if (Prec == 0 || Token >= PPMM_PLUS) {
if (Token == TY_IDENTIFIER)
DieMessage("Attempting to determine operator precedence of identifier", CurrentIdentifier);
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) {
return (Token == LI_EQUAL);
return (Token == LI_EQUAL);
}
/* * * * * * * * * * * * * * * * * * * * * * * *
@ -92,12 +92,12 @@ struct ASTNode* ConstructASTNode(int Operation, int Type,
struct ASTNode* Right,
struct SymbolTableEntry* Symbol,
int IntValue) {
struct ASTNode* Node;
Node = (struct ASTNode*) malloc(sizeof(struct ASTNode));
if(!Node)
if (!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.
* @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);
}
@ -152,7 +153,7 @@ struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left
*/
int ParseTokenToOperation(int Token) {
if(Token > LI_EOF && Token < LI_INT)
if (Token > LI_EOF && Token < LI_INT)
return Token;
DieDecimal("ParseToken: Unknown token", Token);
@ -172,12 +173,12 @@ struct ASTNode* ParsePrimary(void) {
struct ASTNode* Node;
int ID;
switch(CurrentToken.type) {
switch (CurrentToken.type) {
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);
else
else
Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, CurrentToken.value);
break;
@ -201,7 +202,7 @@ struct ASTNode* ParsePrimary(void) {
return Node;
}
Tokenise();
return Node;
@ -223,8 +224,8 @@ struct ASTNode* ParsePrimary(void) {
*
*/
struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
struct ASTNode* LeftNode, *RightNode;
struct ASTNode* LeftTemp, *RightTemp;
struct ASTNode* LeftNode, * RightNode;
struct ASTNode* LeftTemp, * RightTemp;
// int LeftType, RightType;
int NodeType, OpType;
@ -232,13 +233,15 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
NodeType = CurrentToken.type;
if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS || NodeType == LI_COM) {
LeftNode->RVal = 1; return LeftNode;
if (NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS || NodeType == LI_COM) {
LeftNode->RVal = 1;
return LeftNode;
}
while((OperatorPrecedence(NodeType) > PreviousTokenPrecedence) || (IsRightExpr(OpType) && OperatorPrecedence(OpType) == PreviousTokenPrecedence)) {
while ((OperatorPrecedence(NodeType) > PreviousTokenPrecedence) ||
(IsRightExpr(OpType) && OperatorPrecedence(OpType) == PreviousTokenPrecedence)) {
Tokenise();
if(CurrentToken.type == LI_RPARE)
if (CurrentToken.type == LI_RPARE)
break;
RightNode = ParsePrecedenceASTNode(Precedence[NodeType]);
@ -251,13 +254,13 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
OpType = ParseTokenToOperation(NodeType);
if(OpType == OP_ASSIGN) {
if (OpType == OP_ASSIGN) {
printf("\tParsePrecedenceASTNode: Assignment statement\r\n");
RightNode->RVal = 1;
LeftNode->RVal = 0;
RightNode = MutateType(RightNode, LeftNode->ExprType, 0);
if(LeftNode == NULL)
if (RightNode == NULL)
Die("Incompatible Expression encountered in assignment");
// LeftNode holds the target, the target variable in this case
@ -266,7 +269,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
LeftTemp = LeftNode;
LeftNode = RightNode;
RightNode = LeftTemp;
// Clear temps as ensurance
RightTemp = NULL;
LeftTemp = NULL;
@ -282,19 +285,20 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
* If both are null, the types are incompatible.
*/
if(LeftTemp == NULL && RightTemp == NULL)
if (LeftTemp == NULL && RightTemp == NULL)
Die("Incompatible types in parsing nodes");
/**
* If the left was valid, or valid for
* If the left was valid, or valid for
* expansion, then it will be non-null.
*
* If it was valid, then this will be
*
* If it was valid, then this will be
* 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
@ -302,26 +306,19 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
* to the nature of widening types.
*/
if(RightTemp)
RightNode = RightTemp;
if (RightTemp != NULL)
RightNode = RightTemp; // ConstructASTBranch(RightType, LeftNode->ExprType, RightNode, 0);
}
/**
* Checks over, back to normal parsing.
*/
if(LeftTemp != NULL)
LeftNode = LeftTemp; //ConstructASTBranch(LeftType, RightNode->ExprType, LeftNode, 0);
if(RightTemp != NULL)
RightNode = RightTemp; // ConstructASTBranch(RightType, LeftNode->ExprType, RightNode, 0);
LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode, NULL, 0);
LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode,
NULL, 0);
NodeType = CurrentToken.type;
if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) {
if (NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) {
LeftNode->RVal = 1;
return LeftNode;
}
}
LeftNode->RVal = 1;
return LeftNode;
@ -348,7 +345,7 @@ struct ASTNode* CallFunction() {
struct SymbolTableEntry* Function;
//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);
VerifyToken(LI_LPARE, "(");
@ -378,16 +375,16 @@ struct ASTNode* CallFunction() {
*
*/
struct ASTNode* GetExpressionList() {
struct ASTNode* Tree = NULL, *Child = NULL;
struct ASTNode* Tree = NULL, * Child = NULL;
int Count;
while(CurrentToken.type != LI_RPARE) {
while (CurrentToken.type != LI_RPARE) {
Child = ParsePrecedenceASTNode(0);
Count++;
Tree = ConstructASTNode(OP_COMP, PointerTo(RET_VOID), Tree, NULL, Child, NULL, Count);
switch(CurrentToken.type) {
switch (CurrentToken.type) {
case LI_COM:
Tokenise();
break;
@ -420,9 +417,9 @@ struct ASTNode* GetExpressionList() {
*/
struct ASTNode* ParseStatement(void) {
int 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_LONG:
case TY_INT:
@ -435,16 +432,16 @@ struct ASTNode* ParseStatement(void) {
case KW_IF:
return IfStatement();
case KW_WHILE:
return WhileStatement();
case KW_FOR:
return ForStatement();
case KW_RETURN:
return ReturnStatement();
default:
ParsePrecedenceASTNode(0);
}
@ -468,29 +465,29 @@ struct ASTNode* ParseStatement(void) {
*
*/
struct ASTNode* ParseCompound() {
struct ASTNode* Left = NULL, *Tree;
struct ASTNode* Left = NULL, * Tree;
// Compound statements are defined by comprising
// multiple statements inside { a bracket block }
VerifyToken(LI_LBRAC, "{");
while(1) {
while (1) {
printf("\tNew branch in compound\n");
Tree = ParseStatement();
if(Tree && (Tree->Operation == OP_PRINT || Tree->Operation == OP_ASSIGN
|| Tree->Operation == OP_RET || Tree->Operation == OP_CALL))
if (Tree && (Tree->Operation == OP_PRINT || Tree->Operation == OP_ASSIGN
|| Tree->Operation == OP_RET || Tree->Operation == OP_CALL))
VerifyToken(LI_SEMIC, ";");
if(Tree) {
if(Left == NULL)
if (Tree) {
if (Left == NULL)
Left = Tree;
else
Left = ConstructASTNode(OP_COMP, RET_NONE, Left, NULL, Tree, NULL, 0);
}
if(CurrentToken.type == LI_RBRAC) {
if (CurrentToken.type == LI_RBRAC) {
VerifyToken(LI_RBRAC, "}");
return Left;
}
@ -519,35 +516,35 @@ void ParseGlobals() {
printf("Parsing global definitions\r\n");
while(1) {
// We loop early if there's a struct, and since a struct may be the last
while (1) {
// 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
if(CurrentToken.type == LI_EOF)
if (CurrentToken.type == LI_EOF)
break;
printf("New definition incoming..\r\n\n");
Type = ParseOptionalPointer(&Composite);
//TODO: converge pathways on this block?
if(CurrentToken.type == KW_FUNC) {
if (CurrentToken.type == KW_FUNC) {
VerifyToken(KW_FUNC, "::");
FunctionComing = 1;
}
// Structs are parsed fully in ParseOptionalPointer
// TODO: FIX THAT!!
if(Type == DAT_STRUCT && CurrentToken.type == LI_SEMIC) {
if (Type == DAT_STRUCT && CurrentToken.type == LI_SEMIC) {
Tokenise();
continue;
}
VerifyToken(TY_IDENTIFIER, "ident");
if(FunctionComing && CurrentToken.type == LI_LPARE) {
if (FunctionComing && CurrentToken.type == LI_LPARE) {
printf("\tParsing function\n");
Tree = ParseFunction(Type);
if(Tree) {
if (Tree) {
printf("\nBeginning assembler creation of new function %s\n", Tree->Symbol->Name);
AssembleTree(Tree, -1, 0);
FreeLocals();
@ -559,7 +556,7 @@ void ParseGlobals() {
BeginVariableDeclaration(Type, Composite, SC_GLOBAL);
VerifyToken(LI_SEMIC, ";");
}
}
}

View File

@ -36,7 +36,7 @@
*/
int PointerTo(int Type) {
if((Type & 0xf) == 0xf)
if ((Type & 0xf) == 0xf)
DieDecimal("Unrecognized type in pointerisation", Type);
printf("\t\tPointerising a %s\n", TypeNames(Type));
return (Type + 1);
@ -52,7 +52,7 @@ int PointerTo(int Type) {
int ValueAt(int Type) {
printf("\t\tDereferencing a %s\n", TypeNames(Type));
if((Type & 0xf) == 0x0)
if ((Type & 0xf) == 0x0)
DieDecimal("Unrecognized type in defererencing", Type);
return (Type - 1);
}
@ -74,8 +74,8 @@ int ValueAt(int Type) {
int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
int Type;
switch(CurrentToken.type) {
switch (CurrentToken.type) {
case TY_VOID:
Type = RET_VOID;
Tokenise();
@ -96,18 +96,18 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
Type = DAT_STRUCT;
*Composite = BeginStructDeclaration();
break;
default:
default:
DieDecimal("Illegal type for pointerisation", CurrentToken.type);
}
// Recursively scan more *s
// This makes things like:
// x = **y;
// possible.
while(1) {
while (1) {
printf("\t\t\tType on parsing is %d\n", CurrentToken.type);
if(CurrentToken.type != AR_STAR)
if (CurrentToken.type != AR_STAR)
break;
Type = PointerTo(Type);
Tokenise();
// Tokenise(); TODO: is this skipping pointers?
@ -129,13 +129,13 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
*/
struct ASTNode* AccessArray() {
struct ASTNode* LeftNode, *RightNode;
struct ASTNode* LeftNode, * RightNode;
struct SymbolTableEntry* Entry;
printf("\tAccessing array %s as requested\r\n", CurrentIdentifier);
if ((Entry = FindSymbol(CurrentIdentifier)) == NULL || Entry->Structure != ST_ARR)
DieMessage("Accessing undeclared array", CurrentIdentifier);
LeftNode = ConstructASTLeaf(OP_ADDRESS, Entry->Type, Entry, 0);
Tokenise();
@ -143,10 +143,11 @@ struct ASTNode* AccessArray() {
VerifyToken(LI_RBRAS, "]");
if(!TypeIsInt(RightNode->ExprType))
if (!TypeIsInt(RightNode->ExprType))
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);
LeftNode = ConstructASTNode(OP_ADD, Entry->Type, LeftNode, NULL, RightNode, NULL, 0);
@ -168,22 +169,22 @@ struct ASTNode* AccessArray() {
* @return the AST Node representing this statement.
*/
struct ASTNode* AccessMember(bool Deref) {
struct ASTNode* LeftNode, *RightNode;
struct SymbolTableEntry* CompositeVar, *TypePtr, *Member;
struct ASTNode* LeftNode, * RightNode;
struct SymbolTableEntry* CompositeVar, * TypePtr, * Member;
if((CompositeVar = FindSymbol(CurrentIdentifier)) == NULL)
DieMessage("Undecalred variable", CurrentIdentifier);
if(Deref && CompositeVar->Type != PointerTo(DAT_STRUCT))
if ((CompositeVar = FindSymbol(CurrentIdentifier)) == NULL)
DieMessage("Undeclared variable", CurrentIdentifier);
if (Deref && CompositeVar->Type != PointerTo(DAT_STRUCT))
DieMessage("Undeclared struct", CurrentIdentifier);
if(!Deref && CompositeVar->Type != DAT_STRUCT)
if (!Deref && CompositeVar->Type != DAT_STRUCT)
DieMessage("Undeclared struct", CurrentIdentifier);
if(Deref)
if (Deref)
LeftNode = ConstructASTLeaf(REF_IDENT, PointerTo(DAT_STRUCT), CompositeVar, 0);
else
LeftNode = ConstructASTLeaf(OP_ADDRESS, CompositeVar->Type, CompositeVar, 0);
LeftNode->RVal = true;
TypePtr = CompositeVar->CompositeType;
@ -191,15 +192,16 @@ struct ASTNode* AccessMember(bool Deref) {
Tokenise();
VerifyToken(TY_IDENTIFIER, "identifier");
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);
if(!strcmp(Member->Name, CurrentIdentifier))
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);
if (!strcmp(Member->Name, CurrentIdentifier))
break;
}
if(Member == NULL)
if (Member == NULL)
DieMessage("Invalid struct member", CurrentIdentifier);
RightNode = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, Member->SinkOffset);
LeftNode = ConstructASTNode(OP_ADD, PointerTo(Member->Type), LeftNode, NULL, RightNode, NULL, 0);

View File

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

View File

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

View File

@ -41,13 +41,16 @@ int TypeIsPtr(int Type) {
*/
int PrimitiveSize(int Type) {
if(TypeIsPtr(Type)) return 8;
switch(Type) {
case RET_CHAR: return 1;
case RET_INT: return 4;
case RET_LONG: return 8;
default:
if (TypeIsPtr(Type)) return 8;
switch (Type) {
case RET_CHAR:
return 1;
case RET_INT:
return 4;
case RET_LONG:
return 8;
default:
DieBinary("Bad type in PrimitiveSize", Type);
}
return 0;
@ -61,7 +64,7 @@ int PrimitiveSize(int Type) {
*/
int TypeSize(int Type, struct SymbolTableEntry* Composite) {
if(Type == DAT_STRUCT) return Composite->Length;
if (Type == DAT_STRUCT) return Composite->Length;
return PrimitiveSize(Type);
}
@ -76,17 +79,26 @@ static char TypeBuffer[7];
* Get the name of the input Type as a string.
*/
char* TypeNames(int Type) {
switch(Type) {
case RET_CHAR: memcpy(TypeBuffer, "Char", 4); break;
case RET_INT: memcpy(TypeBuffer, "Int ", 4); break;
case RET_LONG: memcpy(TypeBuffer, "Long", 4); break;
case RET_VOID: memcpy(TypeBuffer, "Void", 4); break;
default: break;
switch (Type) {
case RET_CHAR:
memcpy(TypeBuffer, "Char", 4);
break;
case RET_INT:
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);
else memcpy((void*)((size_t) TypeBuffer + 4), " ", 3);
if (TypeIsPtr(Type)) memcpy((void*) ((size_t) TypeBuffer + 4), "Ptr", 3);
else memcpy((void*) ((size_t) TypeBuffer + 4), " ", 3);
return TypeBuffer;
}
/*
@ -104,7 +116,7 @@ int TypesCompatible(int* Left, int* Right, int STRICT) {
int LeftSize, RightSize;
// Same types are compatible. No shrinking required
if(*Left == *Right) {
if (*Left == *Right) {
*Left = *Right = 0;
return 1;
}
@ -114,7 +126,7 @@ int TypesCompatible(int* Left, int* Right, int STRICT) {
// Types of size 0 are incompatible
if((LeftSize == 0) || (RightSize == 0))
if ((LeftSize == 0) || (RightSize == 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
* AKA, the left must be widened.
*/
if(LeftSize < RightSize) {
if (LeftSize < RightSize) {
*Left = OP_WIDEN;
*Right = 0;
return 1;
@ -145,10 +157,10 @@ int TypesCompatible(int* Left, int* Right, int STRICT) {
*
*/
if(LeftSize > RightSize) {
if(STRICT)
if (LeftSize > RightSize) {
if (STRICT)
return 0; // Not compatible if STRICT
*Left = 0;
*Right = OP_WIDEN;
return 1; // Compatible by default
@ -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);
if(TypeIsInt(LeftType) && TypeIsInt(RightType)) {
if (TypeIsInt(LeftType) && TypeIsInt(RightType)) {
// Short-circuit for valid types
if(LeftType == RightType) {
if (LeftType == RightType) {
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)
*
*/
if(LeftSize > RightSize)
if (LeftSize > RightSize)
return NULL;
/**
@ -220,19 +232,19 @@ struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation) {
* BUT it is possible!
*/
if(RightSize > LeftSize)
if (RightSize > LeftSize)
return ConstructASTBranch(OP_WIDEN, RightType, Tree, NULL, 0);
}
// Left branch pointers are compatible if we're not doing operations
if(TypeIsPtr(LeftType)) {
if(Operation == 0 && LeftType == RightType)
if (TypeIsPtr(LeftType)) {
if (Operation == 0 && LeftType == RightType)
return Tree;
}
// 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:
@ -242,11 +254,11 @@ struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation) {
* x = *(y + 1);
*/
if(TypeIsInt(LeftType) && TypeIsPtr(RightType)) {
if (TypeIsInt(LeftType) && TypeIsPtr(RightType)) {
printf("\t\t\tMutateType: Right node needs adjustment\r\n");
RightSize = PrimitiveSize(ValueAt(RightType));
if(RightSize > 1)
if (RightSize > 1)
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;
int :: main() {
int sourcefile;
int count;
long sourcefile;
long count;
textbuffer = " ";

View File

@ -3,11 +3,11 @@ struct a {
int y
};
int printf(char* fmt);
int :: printf(char* fmt);
struct a str;
int main() {
int :: main() {
str.y = 55;
printf("%d\n", str.y);
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);
}