From 537246daae344f1d3bc5569974be7265356cc8ea Mon Sep 17 00:00:00 2001 From: Curle Date: Thu, 3 Mar 2022 00:05:10 +0000 Subject: [PATCH] CLion reformatting pass, finish struct implementation --- CMakeLists.txt | 20 ++ include/Data.h | 19 +- include/Defs.h | 109 ++++++++--- src/Assembler.c | 363 ++++++++++++++++++++---------------- src/Delegate.c | 42 ++--- src/Dump.c | 187 +++++++++++++------ src/Lexer.c | 177 +++++++++--------- src/Main.c | 161 ++++++++-------- src/Parser.c | 157 ++++++++-------- src/Pointers.c | 56 +++--- src/Statements.c | 144 +++++++------- src/Symbols.c | 46 ++--- src/Types.c | 76 ++++---- tests/calls.c | 6 + tests/cat.er | 4 +- tests/{ => old}/arguments | 0 tests/{ => old}/arrays | 0 tests/{ => old}/arrays1 | 0 tests/{ => old}/comparison1 | 0 tests/{ => old}/for | 0 tests/{ => old}/funcs | 0 tests/{ => old}/funcs2 | 0 tests/{ => old}/funcs3 | 0 tests/{ => old}/funcs4 | 0 tests/{ => old}/globals | 0 tests/{ => old}/if | 0 tests/{ => old}/inv_neg | 0 tests/{ => old}/locals | 0 tests/{ => old}/parameters | 0 tests/{ => old}/parser1 | 0 tests/{ => old}/pointers | 0 tests/{ => old}/pointers2 | 0 tests/{ => old}/print | 0 tests/{ => old}/strings | 0 tests/{ => old}/tokeniser1 | 0 tests/{ => old}/tokeniser2 | 0 tests/{ => old}/tokeniser3 | 0 tests/{ => old}/types | 0 tests/{ => old}/vars1 | 0 tests/{ => old}/while | 0 tests/{printf => printf.er} | 0 tests/struct.er | 4 +- tests/structbrutal.er | 23 +++ 43 files changed, 929 insertions(+), 665 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 tests/calls.c rename tests/{ => old}/arguments (100%) rename tests/{ => old}/arrays (100%) rename tests/{ => old}/arrays1 (100%) rename tests/{ => old}/comparison1 (100%) rename tests/{ => old}/for (100%) rename tests/{ => old}/funcs (100%) rename tests/{ => old}/funcs2 (100%) rename tests/{ => old}/funcs3 (100%) rename tests/{ => old}/funcs4 (100%) rename tests/{ => old}/globals (100%) rename tests/{ => old}/if (100%) rename tests/{ => old}/inv_neg (100%) rename tests/{ => old}/locals (100%) rename tests/{ => old}/parameters (100%) rename tests/{ => old}/parser1 (100%) rename tests/{ => old}/pointers (100%) rename tests/{ => old}/pointers2 (100%) rename tests/{ => old}/print (100%) rename tests/{ => old}/strings (100%) rename tests/{ => old}/tokeniser1 (100%) rename tests/{ => old}/tokeniser2 (100%) rename tests/{ => old}/tokeniser3 (100%) rename tests/{ => old}/types (100%) rename tests/{ => old}/vars1 (100%) rename tests/{ => old}/while (100%) rename tests/{printf => printf.er} (100%) create mode 100644 tests/structbrutal.er diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e56db3c --- /dev/null +++ b/CMakeLists.txt @@ -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) diff --git a/include/Data.h b/include/Data.h index 47acb49..c368a7c 100644 --- a/include/Data.h +++ b/include/Data.h @@ -4,6 +4,7 @@ /*************/ #pragma once + #include #include #include @@ -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[]; diff --git a/include/Defs.h b/include/Defs.h index 99481d8..6dc7bd5 100644 --- a/include/Defs.h +++ b/include/Defs.h @@ -4,6 +4,7 @@ /*************/ #pragma once + #include #include #include @@ -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(); diff --git a/src/Assembler.c b/src/Assembler.c index 4b16ce3..2457e38 100644 --- a/src/Assembler.c +++ b/src/Assembler.c @@ -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); } diff --git a/src/Delegate.c b/src/Delegate.c index 188a5bc..764bca2 100644 --- a/src/Delegate.c +++ b/src/Delegate.c @@ -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); } diff --git a/src/Dump.c b/src/Dump.c index 218af32..1ee5d00 100644 --- a/src/Dump.c +++ b/src/Dump.c @@ -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); diff --git a/src/Lexer.c b/src/Lexer.c index c379d24..73b5aeb 100644 --- a/src/Lexer.c +++ b/src/Lexer.c @@ -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); } diff --git a/src/Main.c b/src/Main.c index 52323f2..d810716 100644 --- a/src/Main.c +++ b/src/Main.c @@ -4,96 +4,99 @@ /*************/ #include + #define extern_ + #include + #undef extern_ -#include -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]); } } diff --git a/src/Parser.c b/src/Parser.c index 9435f45..b055c27 100644 --- a/src/Parser.c +++ b/src/Parser.c @@ -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, ";"); } - + } } diff --git a/src/Pointers.c b/src/Pointers.c index 9e237e5..72539b9 100644 --- a/src/Pointers.c +++ b/src/Pointers.c @@ -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); diff --git a/src/Statements.c b/src/Statements.c index 22b58bb..71e6bcf 100644 --- a/src/Statements.c +++ b/src/Statements.c @@ -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; diff --git a/src/Symbols.c b/src/Symbols.c index 3831211..0023348 100644 --- a/src/Symbols.c +++ b/src/Symbols.c @@ -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; } \ No newline at end of file diff --git a/src/Types.c b/src/Types.c index c4e440a..f22acf4 100644 --- a/src/Types.c +++ b/src/Types.c @@ -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); } } diff --git a/tests/calls.c b/tests/calls.c new file mode 100644 index 0000000..4a7009a --- /dev/null +++ b/tests/calls.c @@ -0,0 +1,6 @@ +#include + +int main() { + printf("%d\n", 55); + puts("more sup\n"); +} \ No newline at end of file diff --git a/tests/cat.er b/tests/cat.er index 65d6577..e49c9bf 100644 --- a/tests/cat.er +++ b/tests/cat.er @@ -6,8 +6,8 @@ int :: close(int fd); char* textbuffer; int :: main() { - int sourcefile; - int count; + long sourcefile; + long count; textbuffer = " "; diff --git a/tests/arguments b/tests/old/arguments similarity index 100% rename from tests/arguments rename to tests/old/arguments diff --git a/tests/arrays b/tests/old/arrays similarity index 100% rename from tests/arrays rename to tests/old/arrays diff --git a/tests/arrays1 b/tests/old/arrays1 similarity index 100% rename from tests/arrays1 rename to tests/old/arrays1 diff --git a/tests/comparison1 b/tests/old/comparison1 similarity index 100% rename from tests/comparison1 rename to tests/old/comparison1 diff --git a/tests/for b/tests/old/for similarity index 100% rename from tests/for rename to tests/old/for diff --git a/tests/funcs b/tests/old/funcs similarity index 100% rename from tests/funcs rename to tests/old/funcs diff --git a/tests/funcs2 b/tests/old/funcs2 similarity index 100% rename from tests/funcs2 rename to tests/old/funcs2 diff --git a/tests/funcs3 b/tests/old/funcs3 similarity index 100% rename from tests/funcs3 rename to tests/old/funcs3 diff --git a/tests/funcs4 b/tests/old/funcs4 similarity index 100% rename from tests/funcs4 rename to tests/old/funcs4 diff --git a/tests/globals b/tests/old/globals similarity index 100% rename from tests/globals rename to tests/old/globals diff --git a/tests/if b/tests/old/if similarity index 100% rename from tests/if rename to tests/old/if diff --git a/tests/inv_neg b/tests/old/inv_neg similarity index 100% rename from tests/inv_neg rename to tests/old/inv_neg diff --git a/tests/locals b/tests/old/locals similarity index 100% rename from tests/locals rename to tests/old/locals diff --git a/tests/parameters b/tests/old/parameters similarity index 100% rename from tests/parameters rename to tests/old/parameters diff --git a/tests/parser1 b/tests/old/parser1 similarity index 100% rename from tests/parser1 rename to tests/old/parser1 diff --git a/tests/pointers b/tests/old/pointers similarity index 100% rename from tests/pointers rename to tests/old/pointers diff --git a/tests/pointers2 b/tests/old/pointers2 similarity index 100% rename from tests/pointers2 rename to tests/old/pointers2 diff --git a/tests/print b/tests/old/print similarity index 100% rename from tests/print rename to tests/old/print diff --git a/tests/strings b/tests/old/strings similarity index 100% rename from tests/strings rename to tests/old/strings diff --git a/tests/tokeniser1 b/tests/old/tokeniser1 similarity index 100% rename from tests/tokeniser1 rename to tests/old/tokeniser1 diff --git a/tests/tokeniser2 b/tests/old/tokeniser2 similarity index 100% rename from tests/tokeniser2 rename to tests/old/tokeniser2 diff --git a/tests/tokeniser3 b/tests/old/tokeniser3 similarity index 100% rename from tests/tokeniser3 rename to tests/old/tokeniser3 diff --git a/tests/types b/tests/old/types similarity index 100% rename from tests/types rename to tests/old/types diff --git a/tests/vars1 b/tests/old/vars1 similarity index 100% rename from tests/vars1 rename to tests/old/vars1 diff --git a/tests/while b/tests/old/while similarity index 100% rename from tests/while rename to tests/old/while diff --git a/tests/printf b/tests/printf.er similarity index 100% rename from tests/printf rename to tests/printf.er diff --git a/tests/struct.er b/tests/struct.er index ae0ea64..90e6055 100644 --- a/tests/struct.er +++ b/tests/struct.er @@ -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); diff --git a/tests/structbrutal.er b/tests/structbrutal.er new file mode 100644 index 0000000..3b2107c --- /dev/null +++ b/tests/structbrutal.er @@ -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); +} \ No newline at end of file