Begin refactor for multiplexed compilation

This commit is contained in:
Curle 2022-03-05 01:13:45 +00:00
parent f2d2d07709
commit 37cdaacc71
15 changed files with 295 additions and 144 deletions

4
.gitignore vendored
View File

@ -1,6 +1,10 @@
.idea .idea
.vscode .vscode
.cache
out out
bin bin
build
Erythro
test

View File

@ -17,4 +17,5 @@ add_executable(Erythro
src/Pointers.c src/Pointers.c
src/Statements.c src/Statements.c
src/Symbols.c src/Symbols.c
src/Types.c) src/Types.c
src/Importer.c)

View File

@ -16,42 +16,48 @@
#define TEXTLEN 512 #define TEXTLEN 512
#define SYMBOLS 1024 #define SYMBOLS 1024
// All currently open source files.
extern_ struct FileData** Files;
// The source file currently being operated on.
extern_ struct FileData* CurrentFile;
// The file we are writing into; CurrentFile -> OutputFile
extern_ FILE* OutputFile;
// Symbol tables.
extern_ struct SymbolTableEntry* Globals, * GlobalsEnd; extern_ struct SymbolTableEntry* Globals, * GlobalsEnd;
extern_ struct SymbolTableEntry* Locals, * LocalsEnd; extern_ struct SymbolTableEntry* Locals, * LocalsEnd;
extern_ struct SymbolTableEntry* Params, * ParamsEnd; extern_ struct SymbolTableEntry* Params, * ParamsEnd;
extern_ struct SymbolTableEntry* Structs, * StructsEnd; extern_ struct SymbolTableEntry* Structs, * StructsEnd;
extern_ struct SymbolTableEntry* CompositeMembers, * CompositeMembersEnd; extern_ struct SymbolTableEntry* CompositeMembers, * CompositeMembersEnd;
extern_ struct SymbolTableEntry* EnumMembers, * EnumMembersEnd; extern_ struct SymbolTableEntry* EnumMembers, * EnumMembersEnd;
extern_ struct SymbolTableEntry* Unions, * UnionsEnd; extern_ struct SymbolTableEntry* Unions, * UnionsEnd;
extern_ struct SymbolTableEntry* Enums, * EnumsEnd; extern_ struct SymbolTableEntry* Enums, * EnumsEnd;
extern_ struct SymbolTableEntry* Types, * TypesEnd; extern_ struct SymbolTableEntry* Types, * TypesEnd;
// Whether we should dump the syntax tree before starting to assemble the file.
extern_ bool OptDumpTree; extern_ bool OptDumpTree;
// Whether we should keep the assembly files after successfully linking.
extern_ bool OptKeepAssembly; extern_ bool OptKeepAssembly;
// Whether to stop at compilation and dumping - skip assembly and binary creation altogether.
extern_ bool OptAssembleFiles; extern_ bool OptAssembleFiles;
// Whether to stop at assembly - skip linking into a binary.
extern_ bool OptLinkFiles; extern_ bool OptLinkFiles;
// Whether to output extended debugging information.
extern_ bool OptVerboseOutput; extern_ bool OptVerboseOutput;
// The name of the binary we want to create.
extern_ char* OutputFileName; extern_ char* OutputFileName;
extern_ char* CurrentASMFile, * CurrentObjectFile; // The sizes of each of the core types, in bytes.
extern_ int TypeSizes[5]; extern_ int TypeSizes[5];
// The names of each token in the language, synchronized to the TokenTypes enum.
extern_ char* TokenNames[]; extern_ char* TokenNames[];
// The names of the storage scopes.
extern_ char* ScopeNames[]; extern_ char* ScopeNames[];
extern_ int CurrentFunction;
extern_ struct SymbolTableEntry* FunctionEntry;
extern_ int Line;
extern_ int Overread; extern_ int Overread;
extern_ FILE* SourceFile;
extern_ FILE* OutputFile;
extern_ struct Token CurrentToken;
extern_ char CurrentIdentifier[TEXTLEN + 1]; extern_ char CurrentIdentifier[TEXTLEN + 1];
extern_ int CurrentGlobal; extern_ int CurrentGlobal;

View File

@ -11,6 +11,7 @@
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
/* /*
* ARithmetic tokens are prefixed AR. * ARithmetic tokens are prefixed AR.
* LIteral tokens are prefixed LI. * LIteral tokens are prefixed LI.
@ -99,7 +100,9 @@ enum TokenTypes {
KW_STRUCT, KW_STRUCT,
KW_UNION, KW_UNION,
KW_ENUM, KW_ENUM,
KW_ALIAS KW_ALIAS,
KW_IMPORT
}; };
/* /*
@ -113,6 +116,9 @@ enum TokenTypes {
* *
* It is important that Tokens and Operations are logically separated, * It is important that Tokens and Operations are logically separated,
* but that the Operation's index is the same as the Token that invokes it. * but that the Operation's index is the same as the Token that invokes it.
*
* Every five elements, an index is assigned. These are the natural indices.
* They are marked to make navigation of the Syntax Tree easier.
*/ */
enum SyntaxOps { enum SyntaxOps {
@ -173,7 +179,17 @@ enum SyntaxOps {
}; };
// A node in a Binary Tree that forms the syntax of Erythro /**
* The way syntax is stored by the parser and assembled into a usable file.
* An ASTNode forms an item in a linked list.
*
* Thus, you can traverse up and down a tree of ASTNodes easily.
*
* Walking the tree is as simple as reading the Operation and recursively reading the Left, Middle and Right nodes as called for.
* For example, an if-else statement uses all three subnodes.
*
* This means that AST Nodes aren't exactly a binary tree, but a syntax tree nonetheless.
*/
struct ASTNode { struct ASTNode {
int Operation; // SyntaxOps Index int Operation; // SyntaxOps Index
int ExprType; // Value->IntValue's DataType int ExprType; // Value->IntValue's DataType
@ -188,6 +204,12 @@ struct ASTNode {
}; };
}; };
/**
* Describes the basic unit of syntax in the language.
* A token has a type (an index into the TokenTypes enum) and a value.
*
* The value represents the numerical value of an integer literal, etc.
*/
struct Token { struct Token {
int type; int type;
int value; int value;
@ -219,6 +241,47 @@ struct SymbolTableEntry {
struct SymbolTableEntry* Start; // The first member in a list struct SymbolTableEntry* Start; // The first member in a list
}; };
/**
* Information about a given source file.
*
* A file that starts the parsing of another file will never confuse the parser.
*
* It is the end goal that the parser will be multithreaded, operating on a single file at a time.
*
* Note that files do not contain their own symbol tables - these are global.
*/
struct FileData {
// Whether or not this file will accept definitions of functions.
bool AllowDefinitions;
// A FILE stream that we can read the file from.
FILE* Stream;
// The filename of the source code
char* SourceName;
// The filename of the assembly output
char* AssemblyName;
// The filename of the assembled object code
char* ObjectName;
// The full contents of the source file
char* Content;
// The line of the file we are currently working on, -1 if it is finished
long CurrentLine;
// The column of the file we are currently working on, -1 if it is finished
long CurrentColumn;
// The symbol currently being lexed - TokenTypes index and integer value.
struct Token CurrentSymbol;
// The function currently being parsed - null if in global scope or if finished.
struct SymbolTableEntry* FunctionEntry;
// Once ready, the full AST trees of this file.
struct ASTNode* Tree;
};
enum StorageScope { enum StorageScope {
SC_GLOBAL = 1, // Global Scope SC_GLOBAL = 1, // Global Scope
SC_STRUCT, // Struct Definitions SC_STRUCT, // Struct Definitions
@ -255,6 +318,7 @@ enum DataTypes {
DAT_UNION, // Union Data DAT_UNION, // Union Data
DAT_ENUM, // Enum Data DAT_ENUM, // Enum Data
DAT_ALIAS, // Alias Definition DAT_ALIAS, // Alias Definition
DAT_NONE, // No type, no work needed.
}; };
/* /*
@ -278,11 +342,11 @@ enum StructureType {
char* Suffixate(char* String, char Suffix); char* Suffixate(char* String, char Suffix);
char* Compile(char* InputFile); void Compile(struct FileData* InputFile);
char* Assemble(char* InputFile); void Assemble(struct FileData* InputFile);
void Link(char* Output, char* Objects[]); void Link(char* Output, struct FileData* Objects[]);
void DisplayUsage(char* ProgName); void DisplayUsage(char* ProgName);
@ -291,7 +355,6 @@ void DisplayUsage(char* ProgName);
* * * * * * * * * L E X I N G * * * * * * * * * * * * * * * * * * L E X I N G * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void Tokenise(); void Tokenise();
void VerifyToken(int Type, char* TokenExpected); void VerifyToken(int Type, char* TokenExpected);
@ -302,6 +365,8 @@ static int ReadIdentifier(int Char, char* Buffer, int Limit);
static int ReadKeyword(char* Str); static int ReadKeyword(char* Str);
void ImportModule();
/* * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * *
* * * * * T Y P E S * * * * * * * * * * * T Y P E S * * * * * *
* * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * */
@ -331,8 +396,7 @@ struct ASTNode* ConstructASTNode(int Operation, int Type,
struct ASTNode* ConstructASTLeaf(int Operation, int Type, struct SymbolTableEntry* Symbol, int IntValue); struct ASTNode* ConstructASTLeaf(int Operation, int Type, struct SymbolTableEntry* Symbol, int IntValue);
struct ASTNode* struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, struct SymbolTableEntry* Symbol, int IntValue);
ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, struct SymbolTableEntry* Symbol, int IntValue);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
@ -483,7 +547,6 @@ void AsGlobalSymbol(struct SymbolTableEntry* Entry);
int AsNewString(char* Value); int AsNewString(char* Value);
int AsLoadString(int ID); int AsLoadString(int ID);
int AsEqual(int Left, int Right); int AsEqual(int Left, int Right);

View File

@ -161,7 +161,7 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
case OP_RET: case OP_RET:
printf("\tReturning from %s\n", Node->Symbol->Name); printf("\tReturning from %s\n", Node->Symbol->Name);
AsReturn(FunctionEntry, LeftVal); AsReturn(CurrentFile->FunctionEntry, LeftVal);
return -1; return -1;
case OP_EQUAL: case OP_EQUAL:
@ -856,13 +856,13 @@ void AsGlobalSymbol(struct SymbolTableEntry* Entry) {
switch (Size) { switch (Size) {
case 1: case 1:
fprintf(OutputFile, "\t.byte\t0\r\n", Entry->Name); fprintf(OutputFile, "\t.byte\t0\r\n");
break; break;
case 4: case 4:
fprintf(OutputFile, "\t.long\t0\r\n", Entry->Name); fprintf(OutputFile, "\t.long\t0\r\n");
break; break;
case 8: case 8:
fprintf(OutputFile, "\t.quad\t0\r\n", Entry->Name); fprintf(OutputFile, "\t.quad\t0\r\n");
break; break;
default: default:
for (int i = 0; i < Size; i++) for (int i = 0; i < Size; i++)

View File

@ -62,19 +62,19 @@ char* Suffixate(char* String, char Suffix) {
* For Erythro code, this is .er * For Erythro code, this is .er
* The generated assembly will have the extension .s * The generated assembly will have the extension .s
* *
* @param InputFile: The filename of the Erythro Source code to compile * @param InputFile: A pointer to the data that we should use to compile this file.
* @return the filename of the generated PECOFF32+ assembly * @return the filename of the generated PECOFF32+ assembly
*/ */
char* Compile(char* InputFile) { void Compile(struct FileData* InputFile) {
char* OutputName; char* OutputName;
OutputName = Suffixate(InputFile, 's'); OutputName = Suffixate(InputFile->SourceName, 's');
if (OutputName == NULL) { if (OutputName == NULL) {
fprintf(stderr, "%s must have a suffix.\r\n", InputFile); fprintf(stderr, "%s must have a suffix.\r\n", InputFile->SourceName);
exit(1); exit(1);
} }
if ((SourceFile = fopen(InputFile, "r")) == NULL) { if ((InputFile->Stream = fopen(InputFile->SourceName, "r")) == NULL) {
fprintf(stderr, "Unable to open %s: %s\n", InputFile, strerror(errno)); fprintf(stderr, "Unable to open %s: %s\n", InputFile->SourceName, strerror(errno));
exit(1); exit(1);
} }
@ -83,13 +83,15 @@ char* Compile(char* InputFile) {
exit(1); exit(1);
} }
Line = 1; InputFile->AssemblyName = OutputName;
CurrentFile = InputFile;
CurrentFile->CurrentLine = 1;
Overread = '\n'; Overread = '\n';
CurrentGlobal = 0;
CurrentLocal = SYMBOLS - 1;
if (OptVerboseOutput) if (OptVerboseOutput)
printf("Compiling %s\r\n", InputFile); printf("Compiling %s\r\n", CurrentFile->SourceName);
Tokenise(); Tokenise();
@ -97,8 +99,9 @@ char* Compile(char* InputFile) {
ParseGlobals(); ParseGlobals();
// Output.Tree = ParseGlobals();
fclose(OutputFile); fclose(OutputFile);
return OutputName;
} }
/* /*
@ -115,27 +118,26 @@ char* Compile(char* InputFile) {
* *
*/ */
char* Assemble(char* InputFile) { void Assemble(struct FileData* InputFile) {
char Command[TEXTLEN]; char Command[TEXTLEN];
int Error; int Error;
char* OutputName; char* OutputName;
OutputName = Suffixate(InputFile, 'o'); OutputName = Suffixate(InputFile->AssemblyName, 'o');
if (OutputName == NULL) { if (OutputName == NULL) {
fprintf(stderr, "%s must have a suffix.\r\n", InputFile); fprintf(stderr, "%s must have a suffix.\r\n", InputFile->AssemblyName);
exit(1); exit(1);
} }
snprintf(Command, TEXTLEN, "%s %s %s", "as -o ", OutputName, InputFile); snprintf(Command, TEXTLEN, "%s %s %s", "as -o ", OutputName, InputFile->AssemblyName);
if (OptVerboseOutput) if (OptVerboseOutput)
printf("%s\n", Command); printf("%s\n", Command);
Error = system(Command); Error = system(Command);
if (Error != 0) { if (Error != 0) {
fprintf(stderr, "Assembling of %s failed with code %d\n", InputFile, Error); fprintf(stderr, "Assembling of %s failed with error code %d\n", InputFile->AssemblyName, Error);
exit(1); exit(1);
} }
return OutputName;
} }
/* /*
@ -150,7 +152,7 @@ char* Assemble(char* InputFile) {
* *
*/ */
void Link(char* Output, char* Objects[]) { void Link(char* Output, struct FileData* Objects[]) {
int Count, Size = TEXTLEN, Error; int Count, Size = TEXTLEN, Error;
char Command[TEXTLEN], * CommandPtr; char Command[TEXTLEN], * CommandPtr;
@ -160,7 +162,7 @@ void Link(char* Output, char* Objects[]) {
Size -= Count; Size -= Count;
while (*Objects != NULL) { while (*Objects != NULL) {
Count = snprintf(CommandPtr, Size, "%s ", *Objects); Count = snprintf(CommandPtr, Size, "%s ", (*Objects)->ObjectName);
CommandPtr += Count; CommandPtr += Count;
Size -= Count; Size -= Count;
Objects++; Objects++;

View File

@ -107,10 +107,7 @@ void DumpTree(struct ASTNode* Node, int level) {
fprintf(stdout, "TERM_STRLITERAL rval L%d\n", Node->IntValue); fprintf(stdout, "TERM_STRLITERAL rval L%d\n", Node->IntValue);
return; return;
case REF_IDENT: case REF_IDENT:
if (Node->RVal) fprintf(stdout, "REF_IDENT%s %s\n", Node->RVal ? " rval" : "", Node->Symbol->Name);
fprintf(stdout, "REF_IDENT rval %s\n", Node->Symbol->Name);
else
fprintf(stdout, "REF_IDENT %s\n", Node->Symbol->Name);
return; return;
case OP_ASSIGN: case OP_ASSIGN:
fprintf(stdout, "OP_ASSIGN\n"); fprintf(stdout, "OP_ASSIGN\n");

75
src/Importer.c Normal file
View File

@ -0,0 +1,75 @@
/*************/
/*GEMWIRE */
/* ERYTHRO*/
/*************/
#include <Defs.h>
#include <Data.h>
#include <linux/limits.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <limits.h>
#include <sys/stat.h>
/**
* The function of the importer is to read in definitions from a file, and store
* them into the symbol tables.
*
* The file to be imported is called a "module", which is Erythro terminology for C-like "headers".
* They contain extra metadata that allows for Erythro's enhanced debugging and error logging.
*
* Modules may also contain metadata about the contents within - allowing for multiple compile-time
* sourcesets with different arguments, all parsed at the same time as the source code.
*
* This allows Erythro to have first-class support for multiple-build-single-link situations,
* that would require the use of a build system like CMake in other languages.
*
*/
/**
* Read in the information of a module, check that it is valid, and then read the module itself.
* Import syntax looks like:
*
* > import "file"
*
* The string is appended to the current working directory and is checked.
* If the resulting path exists and resolves to a file, then the file's declarations are added to the symbol tables.
*
* Modules may not contain definitions. Only declarations
* TODO: Module metadata as described above.
*/
void ImportModule() {
// Skip the import keyword
Tokenise();
// Make sure there's a string after the import.
if (CurrentFile->CurrentSymbol.type != LI_STR)
Die("Import statement must be followed by a compile-time constant string.");
// Read in the string that we know must be there.
char* Module = strdup(CurrentIdentifier);
// Figure out the working directory
char CWD[PATH_MAX];
if (getcwd(CWD, sizeof(CWD)) == NULL)
DieMessage("Unable to find cwd when importing module", Module);
// Append the module name to the current working directory
char* ModulePath = malloc(sizeof(CWD) + sizeof(Module) + 1);
strcpy(ModulePath, CWD);
strcpy(ModulePath, Module);
printf("Scanning %s for module definitions.\n", ModulePath);
// Stat the file to see if it exists
struct stat FileInfo;
if (stat(ModulePath, &FileInfo) != 0)
DieMessage("Unable to access the imported module", ModulePath);
// At this point, the file exists and we have the path.
// Pass it to the lexer and have at it.
}

View File

@ -43,10 +43,10 @@ static int NextChar(void) {
return Char; return Char;
} }
Char = fgetc(SourceFile); Char = fgetc(CurrentFile->Stream);
if (Char == '\n') if (Char == '\n')
Line++; CurrentFile->CurrentLine++;
return Char; return Char;
} }
@ -91,10 +91,10 @@ static int FindDigitFromPos(char* String, char Char) {
*/ */
void VerifyToken(int Type, char* TokenExpected) { void VerifyToken(int Type, char* TokenExpected) {
if (CurrentToken.type == Type) if (CurrentFile->CurrentSymbol.type == Type)
Tokenise(); Tokenise();
else { else {
printf("Expected %s on line %d\n", TokenExpected, Line); printf("Expected %s on line %ld\n", TokenExpected, CurrentFile->CurrentLine);
exit(1); exit(1);
} }
} }
@ -170,7 +170,7 @@ static int ReadIdentifier(int Char, char* Buffer, int Limit) {
// This defines the valid chars in a keyword/variable/function. // This defines the valid chars in a keyword/variable/function.
while (isalpha(Char) || isdigit(Char) || Char == '_') { while (isalpha(Char) || isdigit(Char) || Char == '_') {
if (ind >= Limit - 1) { if (ind >= Limit - 1) {
printf("Identifier too long: %d\n", Line); printf("Identifier too long: %ld\n", CurrentFile->CurrentLine);
exit(1); exit(1);
} else { } else {
Buffer[ind++] = Char; Buffer[ind++] = Char;
@ -319,6 +319,9 @@ static int ReadKeyword(char* Str) {
if (!strcmp(Str, "int")) if (!strcmp(Str, "int"))
return TY_INT; return TY_INT;
if (!strcmp(Str, "import"))
return KW_IMPORT;
if (!strcmp(Str, "if")) if (!strcmp(Str, "if"))
return KW_IF; return KW_IF;
@ -384,7 +387,7 @@ static int ReadKeyword(char* Str) {
*/ */
void Tokenise() { void Tokenise() {
int Char, TokenType; int Char, TokenType;
struct Token* Token = &CurrentToken; struct Token* Token = &CurrentFile->CurrentSymbol;
if (RejectedToken != NULL) { if (RejectedToken != NULL) {
Token = RejectedToken; Token = RejectedToken;
@ -580,7 +583,7 @@ void Tokenise() {
Char == '_') { // This is what defines what a variable/function/keyword can START with. Char == '_') { // This is what defines what a variable/function/keyword can START with.
ReadIdentifier(Char, CurrentIdentifier, TEXTLEN); ReadIdentifier(Char, CurrentIdentifier, TEXTLEN);
if (TokenType = ReadKeyword(CurrentIdentifier)) { if ((TokenType = ReadKeyword(CurrentIdentifier))) {
Token->type = TokenType; Token->type = TokenType;
break; break;
} }

View File

@ -4,13 +4,10 @@
/*************/ /*************/
#include <Defs.h> #include <Defs.h>
#define extern_ #define extern_
#include <Data.h> #include <Data.h>
#undef extern_ #undef extern_
#include <unistd.h>
int TypeSizes[5] = {0, 1, 4, 8, 0}; // in BYTES int TypeSizes[5] = {0, 1, 4, 8, 0}; // in BYTES
@ -105,7 +102,6 @@ int main(int argc, char* argv[]) {
OptVerboseOutput = false; OptVerboseOutput = false;
// Temporary .o storage and counter // Temporary .o storage and counter
char* ObjectFiles[100];
int ObjectCount = 0; int ObjectCount = 0;
// Parse command line arguments. // Parse command line arguments.
@ -134,7 +130,7 @@ int main(int argc, char* argv[]) {
OptLinkFiles = false; OptLinkFiles = false;
break; break;
case 'S': // aSsemble only case 'S': // aSsemble only
OptAssembleFiles = false; OptAssembleFiles = true;
OptKeepAssembly = true; OptKeepAssembly = true;
OptLinkFiles = false; OptLinkFiles = false;
break; break;
@ -151,40 +147,45 @@ int main(int argc, char* argv[]) {
if (i >= argc) if (i >= argc)
DisplayUsage(argv[0]); DisplayUsage(argv[0]);
// Allocate enough files for the full specified source code
Files = malloc(sizeof(struct FileData) * i);
// For the rest of the files specified, we can iterate them right to left. // For the rest of the files specified, we can iterate them right to left.
while (i < argc) { while (i < argc) {
// Prepare the source metadata before we start compiling
struct FileData* Source = malloc(sizeof(struct FileData));
Files[i] = Source;
// Compile the file by invoking the Delegate // Compile the file by invoking the Delegate
CurrentASMFile = Compile(argv[i]); Compile(Source);
if (OptLinkFiles || OptAssembleFiles) { if (OptLinkFiles || OptAssembleFiles) {
// If we need to assemble (or link, which requires assembly) // If we need to assemble (or link, which requires assembly)
// then we invoke the Delegate again // then we invoke the Delegate again
CurrentObjectFile = Assemble(CurrentASMFile); Assemble(Source);
// We can only keep track of 99 objects, so we should crash at 98 to ensure we have enough room for the output file too. // We can only keep track of 99 objects, so we should crash at 98 to ensure we have enough room for the output file too.
if (ObjectCount == 98) { if (ObjectCount == 98) {
fprintf(stderr, "Too many inputs"); fprintf(stderr, "Too many inputs");
return 1; // We use return because we're in main, rather than invoking Die. return 1; // We use return because we're in main, rather than invoking Die.
} }
// Move the ObjectCount forward.
ObjectFiles[ObjectCount++] = CurrentObjectFile;
// Clear the new, forwarded index
ObjectFiles[ObjectCount] = NULL;
} }
if (!OptKeepAssembly) if (!OptKeepAssembly)
// unlink = delete // unlink = delete
unlink(CurrentASMFile); unlink(Source->AssemblyName);
i++; i++;
} }
if (OptLinkFiles) { if (OptLinkFiles) {
// If needed, invoke the Delegate one last time. // If needed, invoke the Delegate one last time.
Link(OutputFileName, ObjectFiles); Link(OutputFileName, Files);
if (!OptAssembleFiles) { if (!OptAssembleFiles) {
// Even though we need to assemble to link, we can respect the user's options and delete the intermediary files. // Even though we need to assemble to link, we can respect the user's options and delete the intermediary files.
for (i = 0; ObjectFiles[i] != NULL; i++) for (i = 0; Files[i] != NULL; i++) {
unlink(ObjectFiles[i]); unlink(Files[i]->AssemblyName);
unlink(Files[i]->ObjectName);
}
} }
} }
@ -198,7 +199,7 @@ int main(int argc, char* argv[]) {
*/ */
void Die(char* Error) { void Die(char* Error) {
fprintf(stderr, "%s on line %d\n", Error, Line); fprintf(stderr, "%s on line %ld\n", Error, CurrentFile->CurrentLine);
fclose(OutputFile); fclose(OutputFile);
unlink(OutputFileName); unlink(OutputFileName);
exit(1); exit(1);
@ -208,7 +209,7 @@ void Die(char* Error) {
* A variant of Die with an extra String attached. * A variant of Die with an extra String attached.
*/ */
void DieMessage(char* Error, char* Reason) { void DieMessage(char* Error, char* Reason) {
fprintf(stderr, "%s: %s on line %d\n", Error, Reason, Line); fprintf(stderr, "%s: %s on line %ld\n", Error, Reason, CurrentFile->CurrentLine);
fclose(OutputFile); fclose(OutputFile);
unlink(OutputFileName); unlink(OutputFileName);
exit(1); exit(1);
@ -218,19 +219,7 @@ void DieMessage(char* Error, char* Reason) {
* A variant of Die with an extra integer attached. * A variant of Die with an extra integer attached.
*/ */
void DieDecimal(char* Error, int Number) { void DieDecimal(char* Error, int Number) {
fprintf(stderr, "%s: %d on line %d\n", Error, Number, Line); fprintf(stderr, "%s: %d on line %ld\n", Error, Number, CurrentFile->CurrentLine);
fclose(OutputFile);
unlink(OutputFileName);
exit(1);
}
/**
* A variant of Die that prints the int in binary.
*/
void DieBinary(char* Error, int Number) {
char buf[33];
itoa(Number, buf, 2);
printf("%s: %s\n", Error, buf);
fclose(OutputFile); fclose(OutputFile);
unlink(OutputFileName); unlink(OutputFileName);
exit(1); exit(1);
@ -240,7 +229,7 @@ void DieBinary(char* Error, int Number) {
* A variant of Die with an extra character attached. * A variant of Die with an extra character attached.
*/ */
void DieChar(char* Error, int Char) { void DieChar(char* Error, int Char) {
fprintf(stderr, "%s: %c on line %d\n", Error, Char, Line); fprintf(stderr, "%s: %c on line %ld\n", Error, Char, CurrentFile->CurrentLine);
fclose(OutputFile); fclose(OutputFile);
unlink(OutputFileName); unlink(OutputFileName);
exit(1); exit(1);

View File

@ -230,13 +230,13 @@ struct ASTNode* ParsePrimary(void) {
struct ASTNode* Node; struct ASTNode* Node;
int ID; int ID;
switch (CurrentToken.type) { switch (CurrentFile->CurrentSymbol.type) {
case LI_INT: case LI_INT:
if ((CurrentToken.value >= 0) && (CurrentToken.value < 256)) if ((CurrentFile->CurrentSymbol.value >= 0) && (CurrentFile->CurrentSymbol.value < 256))
Node = ConstructASTLeaf(TERM_INTLITERAL, RET_CHAR, NULL, CurrentToken.value); Node = ConstructASTLeaf(TERM_INTLITERAL, RET_CHAR, NULL, CurrentFile->CurrentSymbol.value);
else else
Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, CurrentToken.value); Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, CurrentFile->CurrentSymbol.value);
break; break;
case LI_STR: case LI_STR:
@ -288,7 +288,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
LeftNode = PrefixStatement(); LeftNode = PrefixStatement();
NodeType = CurrentToken.type; NodeType = CurrentFile->CurrentSymbol.type;
if (NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS || NodeType == LI_COM) { if (NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS || NodeType == LI_COM) {
LeftNode->RVal = 1; LeftNode->RVal = 1;
@ -298,7 +298,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
while ((OperatorPrecedence(NodeType) > PreviousTokenPrecedence) || while ((OperatorPrecedence(NodeType) > PreviousTokenPrecedence) ||
(IsRightExpr(OpType) && OperatorPrecedence(OpType) == PreviousTokenPrecedence)) { (IsRightExpr(OpType) && OperatorPrecedence(OpType) == PreviousTokenPrecedence)) {
Tokenise(); Tokenise();
if (CurrentToken.type == LI_RPARE) if (CurrentFile->CurrentSymbol.type == LI_RPARE)
break; break;
RightNode = ParsePrecedenceASTNode(Precedence[NodeType]); RightNode = ParsePrecedenceASTNode(Precedence[NodeType]);
@ -331,7 +331,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
RightTemp = NULL; RightTemp = NULL;
LeftTemp = NULL; LeftTemp = NULL;
} else { } else {
printf("\t\tAttempting to handle a %d in Binary Expression parsing\r\n", CurrentToken.type); printf("\t\tAttempting to handle a %d in Binary Expression parsing\r\n", CurrentFile->CurrentSymbol.type);
LeftNode->RVal = 1; LeftNode->RVal = 1;
RightNode->RVal = 1; RightNode->RVal = 1;
@ -370,7 +370,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode, LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode,
NULL, 0); NULL, 0);
NodeType = CurrentToken.type; NodeType = CurrentFile->CurrentSymbol.type;
if (NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) { if (NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) {
LeftNode->RVal = 1; LeftNode->RVal = 1;
return LeftNode; return LeftNode;
@ -435,13 +435,13 @@ struct ASTNode* GetExpressionList() {
struct ASTNode* Tree = NULL, * Child = NULL; struct ASTNode* Tree = NULL, * Child = NULL;
int Count; int Count;
while (CurrentToken.type != LI_RPARE) { while (CurrentFile->CurrentSymbol.type != LI_RPARE) {
Child = ParsePrecedenceASTNode(0); Child = ParsePrecedenceASTNode(0);
Count++; Count++;
Tree = ConstructASTNode(OP_COMP, PointerTo(RET_VOID), Tree, NULL, Child, NULL, Count); Tree = ConstructASTNode(OP_COMP, PointerTo(RET_VOID), Tree, NULL, Child, NULL, Count);
switch (CurrentToken.type) { switch (CurrentFile->CurrentSymbol.type) {
case LI_COM: case LI_COM:
Tokenise(); Tokenise();
break; break;
@ -475,8 +475,8 @@ struct ASTNode* GetExpressionList() {
struct ASTNode* ParseStatement(void) { struct ASTNode* ParseStatement(void) {
int Type; int Type;
printf("\t\tBranch leads to here, type %s/%d\r\n", TokenNames[CurrentToken.type], CurrentToken.type); printf("\t\tBranch leads to here, type %s/%d\r\n", TokenNames[CurrentFile->CurrentSymbol.type], CurrentFile->CurrentSymbol.type);
switch (CurrentToken.type) { switch (CurrentFile->CurrentSymbol.type) {
case TY_CHAR: case TY_CHAR:
case TY_LONG: case TY_LONG:
case TY_INT: case TY_INT:
@ -544,7 +544,7 @@ struct ASTNode* ParseCompound() {
Left = ConstructASTNode(OP_COMP, RET_NONE, Left, NULL, Tree, NULL, 0); Left = ConstructASTNode(OP_COMP, RET_NONE, Left, NULL, Tree, NULL, 0);
} }
if (CurrentToken.type == LI_RBRAC) { if (CurrentFile->CurrentSymbol.type == LI_RBRAC) {
VerifyToken(LI_RBRAC, "}"); VerifyToken(LI_RBRAC, "}");
return Left; return Left;
} }
@ -577,28 +577,32 @@ void ParseGlobals() {
// We loop early if there's a struct, and since a struct may be the last // We loop early if there's a struct, and since a struct may be the last
// thing in a file, we need to check for eof before anything else // thing in a file, we need to check for eof before anything else
if (CurrentToken.type == LI_EOF) if (CurrentFile->CurrentSymbol.type == LI_EOF)
break; break;
printf("New definition incoming..\r\n\n"); printf("New definition incoming..\r\n\n");
Type = ParseOptionalPointer(&Composite); Type = ParseOptionalPointer(&Composite);
//TODO: converge pathways on this block? //TODO: converge pathways on this block?
if (CurrentToken.type == KW_FUNC) { if (CurrentFile->CurrentSymbol.type == KW_FUNC) {
VerifyToken(KW_FUNC, "::"); VerifyToken(KW_FUNC, "::");
FunctionComing = 1; FunctionComing = 1;
} }
// Structs are parsed fully in ParseOptionalPointer // Structs are parsed fully in ParseOptionalPointer
// TODO: FIX THAT!! // TODO: FIX THAT!!
if ((Type == DAT_STRUCT || Type == DAT_UNION || Type == DAT_ENUM || Type == DAT_ALIAS) && CurrentToken.type == LI_SEMIC) { if ((Type == DAT_STRUCT || Type == DAT_UNION || Type == DAT_ENUM || Type == DAT_ALIAS) && CurrentFile->CurrentSymbol.type == LI_SEMIC) {
Tokenise(); Tokenise();
continue; continue;
} }
// If we read metadata or an import, then skip all processing.
if (Type == DAT_NONE)
continue;
VerifyToken(TY_IDENTIFIER, "ident"); VerifyToken(TY_IDENTIFIER, "ident");
if (FunctionComing && CurrentToken.type == LI_LPARE) { if (FunctionComing && CurrentFile->CurrentSymbol.type == LI_LPARE) {
printf("\tParsing function\n"); printf("\tParsing function\n");
Tree = ParseFunction(Type); Tree = ParseFunction(Type);
if (Tree) { if (Tree) {

View File

@ -75,7 +75,10 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
int Type; int Type;
switch (CurrentToken.type) { switch (CurrentFile->CurrentSymbol.type) {
case KW_IMPORT:
ImportModule();
break;
case TY_VOID: case TY_VOID:
Type = RET_VOID; Type = RET_VOID;
Tokenise(); Tokenise();
@ -97,13 +100,13 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
break; break;
case KW_ALIAS: case KW_ALIAS:
Type = ReadAlias(Composite); Type = ReadAlias(Composite);
if (CurrentToken.type == LI_SEMIC) if (CurrentFile->CurrentSymbol.type == LI_SEMIC)
Type = DAT_ALIAS; Type = DAT_ALIAS;
break; break;
case KW_ENUM: case KW_ENUM:
Type = RET_INT; Type = RET_INT;
BeginEnumDeclaration(); BeginEnumDeclaration();
if (CurrentToken.type == LI_SEMIC) if (CurrentFile->CurrentSymbol.type == LI_SEMIC)
Type = DAT_ENUM; Type = DAT_ENUM;
break; break;
case KW_STRUCT: case KW_STRUCT:
@ -115,15 +118,19 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
*Composite = BeginCompositeDeclaration(Type); *Composite = BeginCompositeDeclaration(Type);
break; break;
default: default:
DieDecimal("Illegal type for pointerisation", CurrentToken.type); DieDecimal("Illegal type for pointerisation", CurrentFile->CurrentSymbol.type);
} }
// Recursively scan more *s // Recursively scan more *s
// This makes things like: // This makes things like:
// x = **y; // x = **y;
// possible. // possible.
while (1) { while (1) {
printf("\t\t\tType on parsing is %d\n", CurrentToken.type); // But, skip parsing if we're looking at an import.
if (CurrentToken.type != AR_STAR) if (CurrentFile->CurrentSymbol.type == KW_IMPORT)
break;
printf("\t\t\tType on parsing is %d\n", CurrentFile->CurrentSymbol.type);
if (CurrentFile->CurrentSymbol.type != AR_STAR)
break; break;
Type = PointerTo(Type); Type = PointerTo(Type);
@ -164,7 +171,7 @@ struct ASTNode* AccessArray() {
if (!TypeIsInt(RightNode->ExprType)) if (!TypeIsInt(RightNode->ExprType))
Die("Array index is not integer"); Die("Array index is not integer");
printf("\t\tPreparing types - RightNode of type %s must be mutated to LeftNode type %s\r\n", (RightNode->ExprType), printf("\t\tPreparing types - RightNode of type %s must be mutated to LeftNode type %s\r\n", TypeNames(RightNode->ExprType),
TypeNames(LeftNode->ExprType)); TypeNames(LeftNode->ExprType));
RightNode = MutateType(RightNode, LeftNode->ExprType, OP_ADD); RightNode = MutateType(RightNode, LeftNode->ExprType, OP_ADD);

View File

@ -33,7 +33,7 @@ static int ReadDeclarationList(struct SymbolTableEntry* FunctionSymbol, int Stor
if (FunctionSymbol != NULL) if (FunctionSymbol != NULL)
PrototypePointer = FunctionSymbol->Start; PrototypePointer = FunctionSymbol->Start;
while (CurrentToken.type != End) { while (CurrentFile->CurrentSymbol.type != End) {
TokenType = ParseOptionalPointer(&Composite); TokenType = ParseOptionalPointer(&Composite);
VerifyToken(TY_IDENTIFIER, "identifier"); VerifyToken(TY_IDENTIFIER, "identifier");
@ -48,10 +48,10 @@ static int ReadDeclarationList(struct SymbolTableEntry* FunctionSymbol, int Stor
} }
ParamCount++; ParamCount++;
if ((CurrentToken.type != LI_COM) && (CurrentToken.type != End)) if ((CurrentFile->CurrentSymbol.type != LI_COM) && (CurrentFile->CurrentSymbol.type != End))
DieDecimal("Unexpected token in parameter", CurrentToken.type); DieDecimal("Unexpected token in parameter", CurrentFile->CurrentSymbol.type);
if (CurrentToken.type == LI_COM) if (CurrentFile->CurrentSymbol.type == LI_COM)
Tokenise(); Tokenise();
} }
@ -80,12 +80,12 @@ struct SymbolTableEntry* BeginCompositeDeclaration(int Type) {
Tokenise(); Tokenise();
if (CurrentToken.type == TY_IDENTIFIER) { if (CurrentFile->CurrentSymbol.type == TY_IDENTIFIER) {
Composite = Type == DAT_STRUCT ? FindStruct(CurrentIdentifier) : FindUnion(CurrentIdentifier); Composite = Type == DAT_STRUCT ? FindStruct(CurrentIdentifier) : FindUnion(CurrentIdentifier);
Tokenise(); Tokenise();
} }
if (CurrentToken.type != LI_LBRAC) { if (CurrentFile->CurrentSymbol.type != LI_LBRAC) {
if (Composite == NULL) if (Composite == NULL)
DieMessage("Unknown Struct", CurrentIdentifier); DieMessage("Unknown Struct", CurrentIdentifier);
return Composite; return Composite;
@ -131,14 +131,14 @@ void BeginEnumDeclaration() {
Tokenise(); Tokenise();
// enum name // enum name
if (CurrentToken.type == TY_IDENTIFIER) { if (CurrentFile->CurrentSymbol.type == TY_IDENTIFIER) {
Type = FindEnum(CurrentIdentifier); Type = FindEnum(CurrentIdentifier);
Name = strdup(CurrentIdentifier); Name = strdup(CurrentIdentifier);
Tokenise(); Tokenise();
} }
// enum name {? if not, enum name var. // enum name {? if not, enum name var.
if (CurrentToken.type != LI_LBRAC) { if (CurrentFile->CurrentSymbol.type != LI_LBRAC) {
if (Type == NULL) if (Type == NULL)
DieMessage("Undeclared Enum", Name); DieMessage("Undeclared Enum", Name);
@ -162,19 +162,19 @@ void BeginEnumDeclaration() {
DieMessage("Attempting to redeclare enum value", Name); DieMessage("Attempting to redeclare enum value", Name);
// Parse equality // Parse equality
if (CurrentToken.type == LI_EQUAL) { if (CurrentFile->CurrentSymbol.type == LI_EQUAL) {
Tokenise(); Tokenise();
// Expect a number after the equals // Expect a number after the equals
if (CurrentToken.type != LI_INT) if (CurrentFile->CurrentSymbol.type != LI_INT)
Die("Expected integer to assign enum value to"); Die("Expected integer to assign enum value to");
Value = CurrentToken.value; Value = CurrentFile->CurrentSymbol.value;
Tokenise(); Tokenise();
} }
Type = AddSymbol(Name, DAT_ENUM, ST_ENUM, SC_ENUMENTRY, Value++, 0, NULL); Type = AddSymbol(Name, DAT_ENUM, ST_ENUM, SC_ENUMENTRY, Value++, 0, NULL);
// Break on right brace // Break on right brace
if (CurrentToken.type == LI_RBRAC) if (CurrentFile->CurrentSymbol.type == LI_RBRAC)
break; break;
VerifyToken(LI_COM, "Comma"); VerifyToken(LI_COM, "Comma");
@ -214,10 +214,10 @@ struct SymbolTableEntry* BeginVariableDeclaration(int Type, struct SymbolTableEn
DieMessage("Invalid redeclaration of Enum/Struct member", CurrentIdentifier); DieMessage("Invalid redeclaration of Enum/Struct member", CurrentIdentifier);
} }
if (CurrentToken.type == LI_LBRAS) { if (CurrentFile->CurrentSymbol.type == LI_LBRAS) {
Tokenise(); Tokenise();
if (CurrentToken.type == LI_INT) { if (CurrentFile->CurrentSymbol.type == LI_INT) {
switch (Scope) { switch (Scope) {
case SC_GLOBAL: case SC_GLOBAL:
Symbol = AddSymbol(CurrentIdentifier, PointerTo(Type), ST_ARR, Scope, 1, 0, NULL); Symbol = AddSymbol(CurrentIdentifier, PointerTo(Type), ST_ARR, Scope, 1, 0, NULL);
@ -284,12 +284,12 @@ struct ASTNode* ParseFunction(int Type) {
Params = ParamsEnd = NULL; Params = ParamsEnd = NULL;
if (CurrentToken.type == LI_SEMIC) { if (CurrentFile->CurrentSymbol.type == LI_SEMIC) {
Tokenise(); Tokenise();
return NULL; return NULL;
} }
FunctionEntry = OldFunction; CurrentFile->FunctionEntry = OldFunction;
Tree = ParseCompound(); Tree = ParseCompound();
@ -318,7 +318,7 @@ struct ASTNode* ReturnStatement() {
int ReturnType; int ReturnType;
if (FunctionEntry->Type == RET_VOID) if (CurrentFile->FunctionEntry->Type == RET_VOID)
Die("Attempt to return from void function"); Die("Attempt to return from void function");
VerifyToken(KW_RETURN, "return"); VerifyToken(KW_RETURN, "return");
@ -327,14 +327,14 @@ struct ASTNode* ReturnStatement() {
Tree = ParsePrecedenceASTNode(0); Tree = ParsePrecedenceASTNode(0);
Tree = MutateType(Tree, FunctionEntry->Type, 0); Tree = MutateType(Tree, CurrentFile->FunctionEntry->Type, 0);
if (Tree == NULL) if (Tree == NULL)
Die("Returning a value of incorrect type for function"); Die("Returning a value of incorrect type for function");
Tree = ConstructASTBranch(OP_RET, RET_NONE, Tree, FunctionEntry, 0); Tree = ConstructASTBranch(OP_RET, RET_NONE, Tree, CurrentFile->FunctionEntry, 0);
printf("\t\tReturning from function %s\n", FunctionEntry->Name); printf("\t\tReturning from function %s\n", CurrentFile->FunctionEntry->Name);
VerifyToken(LI_RPARE, ")"); // TODO: OPTIONALISE! VerifyToken(LI_RPARE, ")"); // TODO: OPTIONALISE!
@ -385,7 +385,7 @@ struct ASTNode* IfStatement() {
True = ParseCompound(); True = ParseCompound();
if (CurrentToken.type == KW_ELSE) { if (CurrentFile->CurrentSymbol.type == KW_ELSE) {
Tokenise(); Tokenise();
False = ParseCompound(); False = ParseCompound();
} }
@ -573,10 +573,10 @@ struct ASTNode* PostfixStatement() {
Tokenise(); Tokenise();
if (CurrentToken.type == LI_LPARE) if (CurrentFile->CurrentSymbol.type == LI_LPARE)
return CallFunction(); return CallFunction();
if (CurrentToken.type == LI_LBRAS) if (CurrentFile->CurrentSymbol.type == LI_LBRAS)
return AccessArray(); return AccessArray();
// If we get here, we must be a variable. // If we get here, we must be a variable.
@ -591,7 +591,7 @@ struct ASTNode* PostfixStatement() {
// Here we check for postincrement and postdecrement. // Here we check for postincrement and postdecrement.
switch (CurrentToken.type) { switch (CurrentFile->CurrentSymbol.type) {
case LI_DOT: case LI_DOT:
return AccessMember(false); return AccessMember(false);
case LI_ARROW: case LI_ARROW:
@ -640,7 +640,7 @@ struct ASTNode* PostfixStatement() {
struct ASTNode* PrefixStatement() { struct ASTNode* PrefixStatement() {
struct ASTNode* Tree; struct ASTNode* Tree;
switch (CurrentToken.type) { switch (CurrentFile->CurrentSymbol.type) {
case BOOL_INVERT: case BOOL_INVERT:
Tokenise(); Tokenise();
Tree = PrefixStatement(); Tree = PrefixStatement();

View File

@ -17,8 +17,8 @@ void DumpAllLists() {
printf("\nLocal symbols:\n"); printf("\nLocal symbols:\n");
DumpList(Locals); DumpList(Locals);
printf("\nParameters:\n"); printf("\nParameters:\n");
if (FunctionEntry != NULL && FunctionEntry->Start != NULL) if (CurrentFile->FunctionEntry != NULL && CurrentFile->FunctionEntry->Start != NULL)
DumpList(FunctionEntry->Start); DumpList(CurrentFile->FunctionEntry->Start);
DumpList(Params); DumpList(Params);
printf("\nStructs:\n"); printf("\nStructs:\n");
DumpList(Structs); DumpList(Structs);
@ -67,8 +67,8 @@ static struct SymbolTableEntry* SearchList(char* Name, struct SymbolTableEntry*
struct SymbolTableEntry* FindSymbol(char* Symbol) { struct SymbolTableEntry* FindSymbol(char* Symbol) {
struct SymbolTableEntry* Node; struct SymbolTableEntry* Node;
if (FunctionEntry) { if (CurrentFile->FunctionEntry) {
Node = SearchList(Symbol, FunctionEntry->Start); Node = SearchList(Symbol, CurrentFile->FunctionEntry->Start);
if (Node) if (Node)
return Node; return Node;
} }
@ -90,8 +90,8 @@ struct SymbolTableEntry* FindSymbol(char* Symbol) {
struct SymbolTableEntry* FindLocal(char* Symbol) { struct SymbolTableEntry* FindLocal(char* Symbol) {
struct SymbolTableEntry* Node; struct SymbolTableEntry* Node;
if (FunctionEntry) { if (CurrentFile->FunctionEntry) {
Node = SearchList(Symbol, FunctionEntry->Start); Node = SearchList(Symbol, CurrentFile->FunctionEntry->Start);
if (Node) if (Node)
return Node; return Node;
} }
@ -210,7 +210,7 @@ void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail
void FreeLocals() { void FreeLocals() {
Locals = LocalsEnd = NULL; Locals = LocalsEnd = NULL;
Params = ParamsEnd = NULL; Params = ParamsEnd = NULL;
FunctionEntry = NULL; CurrentFile->FunctionEntry = NULL;
} }

View File

@ -51,7 +51,7 @@ int PrimitiveSize(int Type) {
case RET_LONG: case RET_LONG:
return 8; return 8;
default: default:
DieBinary("Bad type in PrimitiveSize", Type); DieDecimal("Bad type in PrimitiveSize", Type);
} }
return 0; return 0;
} }