Fix break & continue implementation
This commit is contained in:
parent
0454c38a7e
commit
334b02cd76
|
@ -14,7 +14,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TEXTLEN 512
|
#define TEXTLEN 512
|
||||||
#define SYMBOLS 1024
|
|
||||||
|
|
||||||
// All currently open source files.
|
// All currently open source files.
|
||||||
extern_ struct FileData** Files;
|
extern_ struct FileData** Files;
|
||||||
|
@ -60,5 +59,3 @@ extern_ int Overread;
|
||||||
|
|
||||||
extern_ char CurrentIdentifier[TEXTLEN + 1];
|
extern_ char CurrentIdentifier[TEXTLEN + 1];
|
||||||
|
|
||||||
extern_ int CurrentGlobal;
|
|
||||||
extern_ int CurrentLocal;
|
|
||||||
|
|
|
@ -352,7 +352,7 @@ void Compile(struct FileData* InputFile);
|
||||||
|
|
||||||
void Assemble(struct FileData* InputFile);
|
void Assemble(struct FileData* InputFile);
|
||||||
|
|
||||||
void Link(char* Output, struct FileData* Objects[]);
|
void Link(char* Output, struct FileData* Objects[], int ObjectsLength);
|
||||||
|
|
||||||
void DisplayUsage(char* ProgName);
|
void DisplayUsage(char* ProgName);
|
||||||
|
|
||||||
|
|
|
@ -79,9 +79,9 @@ int AssembleTree(struct ASTNode* Node, int Register, int LoopBeginLabel, int Loo
|
||||||
return AsWhile(Node);
|
return AsWhile(Node);
|
||||||
|
|
||||||
case OP_COMP:
|
case OP_COMP:
|
||||||
AssembleTree(Node->Left, -1, -1, -1, Node->Operation);
|
AssembleTree(Node->Left, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
|
||||||
DeallocateAllRegisters();
|
DeallocateAllRegisters();
|
||||||
AssembleTree(Node->Right, -1, -1, -1, Node->Operation);
|
AssembleTree(Node->Right, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
|
||||||
DeallocateAllRegisters();
|
DeallocateAllRegisters();
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -90,17 +90,17 @@ int AssembleTree(struct ASTNode* Node, int Register, int LoopBeginLabel, int Loo
|
||||||
|
|
||||||
case OP_FUNC:
|
case OP_FUNC:
|
||||||
AsFunctionPreamble(Node->Symbol);
|
AsFunctionPreamble(Node->Symbol);
|
||||||
AssembleTree(Node->Left, -1, -1, -1, Node->Operation);
|
AssembleTree(Node->Left, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
|
||||||
AsFunctionEpilogue(Node->Symbol);
|
AsFunctionEpilogue(Node->Symbol);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (Node->Left)
|
if (Node->Left)
|
||||||
LeftVal = AssembleTree(Node->Left, -1, -1, -1, Node->Operation);
|
LeftVal = AssembleTree(Node->Left, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
|
||||||
|
|
||||||
if (Node->Right)
|
if (Node->Right)
|
||||||
RightVal = AssembleTree(Node->Right, LeftVal, -1, -1, Node->Operation);
|
RightVal = AssembleTree(Node->Right, LeftVal, LoopBeginLabel, LoopEndLabel, Node->Operation);
|
||||||
|
|
||||||
switch (Node->Operation) {
|
switch (Node->Operation) {
|
||||||
case OP_ADD:
|
case OP_ADD:
|
||||||
|
@ -132,9 +132,11 @@ int AssembleTree(struct ASTNode* Node, int Register, int LoopBeginLabel, int Loo
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_BREAK:
|
case OP_BREAK:
|
||||||
|
printf("\t\tBreaking to the end of the loop; L%d\n", LoopEndLabel);
|
||||||
AsJmp(LoopEndLabel);
|
AsJmp(LoopEndLabel);
|
||||||
return -1;
|
return -1;
|
||||||
case OP_CONTINUE:
|
case OP_CONTINUE:
|
||||||
|
printf("\t\tContinuing to the start of the loop; L%d\n", LoopBeginLabel);
|
||||||
AsJmp(LoopBeginLabel);
|
AsJmp(LoopBeginLabel);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -368,9 +370,8 @@ int AsIf(struct ASTNode* Node, int LoopStartLabel, int LoopEndLabel) {
|
||||||
if (Node->Right)
|
if (Node->Right)
|
||||||
EndLabel = NewLabel();
|
EndLabel = NewLabel();
|
||||||
|
|
||||||
|
|
||||||
// Left is the condition
|
// Left is the condition
|
||||||
AssembleTree(Node->Left, FalseLabel, -1, -1, Node->Operation);
|
AssembleTree(Node->Left, FalseLabel, LoopStartLabel, LoopEndLabel, Node->Operation);
|
||||||
DeallocateAllRegisters();
|
DeallocateAllRegisters();
|
||||||
|
|
||||||
// Middle is the true block
|
// Middle is the true block
|
||||||
|
@ -913,9 +914,14 @@ int AsCall(struct SymbolTableEntry* Entry, int Args) {
|
||||||
printf("\t\tCalling function %s with %d parameters\n", Entry->Name, Args);
|
printf("\t\tCalling function %s with %d parameters\n", Entry->Name, Args);
|
||||||
printf("\t\t\tFunction returns into %s\n", Registers[OutRegister]);
|
printf("\t\t\tFunction returns into %s\n", Registers[OutRegister]);
|
||||||
|
|
||||||
|
// Allocate shadow space
|
||||||
|
fprintf(OutputFile, "\taddq\t$-32, %rsp\n");
|
||||||
fprintf(OutputFile, "\tcall\t%s\n", Entry->Name);
|
fprintf(OutputFile, "\tcall\t%s\n", Entry->Name);
|
||||||
|
// Deallocate arguments and stack space.
|
||||||
if (Args > 4)
|
if (Args > 4)
|
||||||
fprintf(OutputFile, "\taddq\t$%d, %%rsp\n", 8 * (Args - 4));
|
fprintf(OutputFile, "\taddq\t$%d, %%rsp\n", (8 * (Args - 4)) + 32);
|
||||||
|
else
|
||||||
|
fprintf(OutputFile, "\taddq\t$32, %rsp\n");
|
||||||
|
|
||||||
fprintf(OutputFile, "\tmovq\t%%rax, %s\n", Registers[OutRegister]);
|
fprintf(OutputFile, "\tmovq\t%%rax, %s\n", Registers[OutRegister]);
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,8 @@ void Assemble(struct FileData* InputFile) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InputFile->ObjectName = OutputName;
|
||||||
|
|
||||||
snprintf(Command, TEXTLEN, "%s %s %s", "as -o ", OutputName, InputFile->AssemblyName);
|
snprintf(Command, TEXTLEN, "%s %s %s", "as -o ", OutputName, InputFile->AssemblyName);
|
||||||
if (OptVerboseOutput)
|
if (OptVerboseOutput)
|
||||||
printf("%s\n", Command);
|
printf("%s\n", Command);
|
||||||
|
@ -152,8 +154,8 @@ void Assemble(struct FileData* InputFile) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Link(char* Output, struct FileData* Objects[]) {
|
void Link(char* Output, struct FileData** Objects, int ObjectsLength) {
|
||||||
int Count, Size = TEXTLEN, Error;
|
int Count, Size = TEXTLEN, Error, ObjectIdx = 0;
|
||||||
char Command[TEXTLEN], * CommandPtr;
|
char Command[TEXTLEN], * CommandPtr;
|
||||||
|
|
||||||
CommandPtr = Command;
|
CommandPtr = Command;
|
||||||
|
@ -161,11 +163,11 @@ void Link(char* Output, struct FileData* Objects[]) {
|
||||||
CommandPtr += Count;
|
CommandPtr += Count;
|
||||||
Size -= Count;
|
Size -= Count;
|
||||||
|
|
||||||
while (*Objects != NULL) {
|
while (ObjectIdx < ObjectsLength - 1) {
|
||||||
Count = snprintf(CommandPtr, Size, "%s ", (*Objects)->ObjectName);
|
Count = snprintf(CommandPtr, Size, "%s ", Objects[ObjectIdx]->ObjectName);
|
||||||
CommandPtr += Count;
|
CommandPtr += Count;
|
||||||
Size -= Count;
|
Size -= Count;
|
||||||
Objects++;
|
ObjectIdx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OptVerboseOutput)
|
if (OptVerboseOutput)
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include <Defs.h>
|
#include <Defs.h>
|
||||||
#include <Data.h>
|
#include <Data.h>
|
||||||
#include <linux/limits.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -75,13 +74,22 @@
|
||||||
|
|
||||||
// Create a new file with the module name
|
// Create a new file with the module name
|
||||||
struct FileData* ModuleData = malloc(sizeof(struct FileData));
|
struct FileData* ModuleData = malloc(sizeof(struct FileData));
|
||||||
|
memset(ModuleData, 0, sizeof(struct FileData));
|
||||||
ModuleData->AllowDefinitions = false;
|
ModuleData->AllowDefinitions = false;
|
||||||
ModuleData->SourceName = ModulePath;
|
ModuleData->SourceName = ModulePath;
|
||||||
|
|
||||||
printf("Swapping to module %s..\n\n", ModulePath);
|
printf("Swapping to module %s..\n\n", ModulePath);
|
||||||
|
|
||||||
// Parse all relevant data from the module file...
|
// Parse all relevant data from the module file...
|
||||||
Compile(ModuleData);
|
if ((ModuleData->Stream = fopen(ModuleData->SourceName, "r")) == NULL) {
|
||||||
|
fprintf(stderr, "Unable to open %s: %s\n", ModuleData->SourceName, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
CurrentFile = ModuleData;
|
||||||
|
CurrentFile->CurrentLine = 1;
|
||||||
|
Tokenise();
|
||||||
|
ParseGlobals();
|
||||||
|
fclose(CurrentFile->Stream);
|
||||||
|
|
||||||
printf("\n\nSwapping back to file %s..\n", SavedFile->SourceName);
|
printf("\n\nSwapping back to file %s..\n", SavedFile->SourceName);
|
||||||
|
|
||||||
|
|
21
src/Main.c
21
src/Main.c
|
@ -97,7 +97,7 @@ int main(int argc, char* argv[]) {
|
||||||
// Option initialisers
|
// Option initialisers
|
||||||
OptDumpTree = false;
|
OptDumpTree = false;
|
||||||
OptKeepAssembly = true;
|
OptKeepAssembly = true;
|
||||||
OptAssembleFiles = false;
|
OptAssembleFiles = true;
|
||||||
OptLinkFiles = true;
|
OptLinkFiles = true;
|
||||||
OptVerboseOutput = false;
|
OptVerboseOutput = false;
|
||||||
|
|
||||||
|
@ -147,16 +147,21 @@ int main(int argc, char* argv[]) {
|
||||||
if (i >= argc)
|
if (i >= argc)
|
||||||
DisplayUsage(argv[0]);
|
DisplayUsage(argv[0]);
|
||||||
|
|
||||||
|
int StartOfFiles = i;
|
||||||
// Allocate enough files for the full specified source code
|
// Allocate enough files for the full specified source code
|
||||||
Files = malloc(sizeof(struct FileData) * i);
|
Files = malloc(sizeof(struct FileData*) * (argc - i) + 1);
|
||||||
|
memset(Files, 0, sizeof(struct FileData*) * (argc - i) + 1);
|
||||||
|
|
||||||
|
|
||||||
// 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
|
// Prepare the source metadata before we start compiling
|
||||||
struct FileData* Source = malloc(sizeof(struct FileData));
|
struct FileData* Source = malloc(sizeof(struct FileData));
|
||||||
|
memset(Source, 0, sizeof(struct FileData));
|
||||||
Source->SourceName = argv[i];
|
Source->SourceName = argv[i];
|
||||||
Source->AllowDefinitions = true;
|
Source->AllowDefinitions = true;
|
||||||
Files[i] = Source;
|
printf("Compiling file %d (%s)\n", i - StartOfFiles, argv[i]);
|
||||||
|
Files[i - StartOfFiles] = Source;
|
||||||
|
|
||||||
// Compile the file by invoking the Delegate
|
// Compile the file by invoking the Delegate
|
||||||
Compile(Source);
|
Compile(Source);
|
||||||
|
@ -164,12 +169,6 @@ int main(int argc, char* argv[]) {
|
||||||
// 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
|
||||||
Assemble(Source);
|
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.
|
|
||||||
if (ObjectCount == 98) {
|
|
||||||
fprintf(stderr, "Too many inputs");
|
|
||||||
return 1; // We use return because we're in main, rather than invoking Die.
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!OptKeepAssembly)
|
if (!OptKeepAssembly)
|
||||||
|
@ -181,10 +180,10 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
if (OptLinkFiles) {
|
if (OptLinkFiles) {
|
||||||
// If needed, invoke the Delegate one last time.
|
// If needed, invoke the Delegate one last time.
|
||||||
Link(OutputFileName, Files);
|
Link(OutputFileName, Files, (argc - StartOfFiles) + 1);
|
||||||
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; Files[i] != NULL; i++) {
|
for (i = 0; i < (argc - StartOfFiles) + 1; i++) {
|
||||||
unlink(Files[i]->AssemblyName);
|
unlink(Files[i]->AssemblyName);
|
||||||
unlink(Files[i]->ObjectName);
|
unlink(Files[i]->ObjectName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,7 +256,7 @@ struct ASTNode* ParseFunction(int Type) {
|
||||||
struct ASTNode* Tree;
|
struct ASTNode* Tree;
|
||||||
struct ASTNode* FinalStatement;
|
struct ASTNode* FinalStatement;
|
||||||
struct SymbolTableEntry* OldFunction, * NewFunction = NULL;
|
struct SymbolTableEntry* OldFunction, * NewFunction = NULL;
|
||||||
int SymbolSlot, BreakLabel, ParamCount, ID;
|
int BreakLabel = 0, ParamCount = 0;
|
||||||
|
|
||||||
if ((OldFunction = FindSymbol(CurrentIdentifier)) != NULL)
|
if ((OldFunction = FindSymbol(CurrentIdentifier)) != NULL)
|
||||||
if (OldFunction->Storage != ST_FUNC)
|
if (OldFunction->Storage != ST_FUNC)
|
||||||
|
|
|
@ -11,6 +11,7 @@ int :: main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x =? 10) {
|
if (x =? 10) {
|
||||||
|
x = x + 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user