diff --git a/flagpole/src/main.c b/flagpole/src/main.c index 816dfb7..5953e71 100644 --- a/flagpole/src/main.c +++ b/flagpole/src/main.c @@ -113,6 +113,8 @@ static inline bool isKW(Lz_SB *sb) { || SBeq(sb, "then") || SBeq(sb, "endif") || SBeq(sb, "endwhile") + || SBeq(sb, "break") + || SBeq(sb, "continue") || SBeq(sb, "==") || SBeq(sb, "not") || SBeq(sb, "bor") @@ -158,6 +160,16 @@ static inline bool isKW(Lz_SB *sb) { }; \ } +typedef enum { + LABEL_WHILE, + LABEL_IF, +} LabelKind; + +typedef struct { + LabelKind typ; + int num; +} AsmLabel; + int main(uint argc, char **argv) { int opt; Lz_DA(FILE *) inpfiles = {}; @@ -190,7 +202,7 @@ int main(uint argc, char **argv) { bool isProc = false; bool isInclude = false; bool isComment = false; - Lz_DA(int) labelStack = {0}; + Lz_DA(AsmLabel) labelStack = {0}; uint64_t allocHead = 0x7000000000000000; char funcName[128]; Lz_DA(Variable) vars = {0}; @@ -379,29 +391,63 @@ codegenIR: } if (SBeq(&tokenAccumulator, "while")) { IRComplete(&irStatements, &irVStack); - lz_da_append(labelStack, counter); + AsmLabel lbl = (AsmLabel) { + .num = counter, + .typ = LABEL_WHILE + }; + lz_da_append(labelStack, lbl); commentStack(&labelStack); - printf("__whilehead_%d:\n", counter); + printf("__whilehead_%d:\n", lbl.num); break; } if (SBeq(&tokenAccumulator, "do")) { IRComplete(&irStatements, &irVStack); vstackUnderflows = 0; - int lbl = lz_da_pop(labelStack); + AsmLabel lbl = lz_da_pop(labelStack); + if (lbl.typ != LABEL_WHILE) { + fprintf(stderr, "Unmatched do without a while\n"); + exit(1); + } lz_da_append(labelStack, lbl); // TODO: Change flag setting to IR's job printf(" popstack 108\n"); printf(" RSetF 108\n"); - printf(" JmpIE __whiletail_%d\n", lbl); + printf(" JmpIE __whiletail_%d\n", lbl.num); break; } if (SBeq(&tokenAccumulator, "endwhile")) { IRComplete(&irStatements, &irVStack); vstackUnderflows = 0; - int lbl = lz_da_pop(labelStack); + AsmLabel lbl = lz_da_pop(labelStack); + if (lbl.typ != LABEL_WHILE) { + fprintf(stderr, "Unmatched endwhile without while\n"); + exit(1); + } commentStack(&labelStack); - printf(" Jmp __whilehead_%d\n", lbl); - printf("__whiletail_%d:\n", lbl); + printf(" Jmp __whilehead_%d\n", lbl.num); + printf("__whiletail_%d:\n", lbl.num); + break; + } + if (SBeq(&tokenAccumulator, "break")) { + IRComplete(&irStatements, &irVStack); + AsmLabel lbl; + for (int i = labelStack.cnt; i >= 0; --i) { + if (labelStack.data[i].typ == LABEL_WHILE) { + lbl = labelStack.data[i]; + } + } + printf(" Jmp __whiletail_%d\n", lbl.num); + break; + } + if (SBeq(&tokenAccumulator, "continue")) { + IRComplete(&irStatements, &irVStack); + AsmLabel lbl; + for (int i = labelStack.cnt; i >= 0; --i) { + if (labelStack.data[i].typ == LABEL_WHILE) { + lbl = labelStack.data[i]; + } + } + printf(" Jmp __whilehead_%d\n", lbl.num); break; } if (SBeq(&tokenAccumulator, "if")) { @@ -410,14 +456,16 @@ codegenIR: if (SBeq(&tokenAccumulator, "then")) { IRComplete(&irStatements, &irVStack); - lz_da_append(labelStack, counter); + AsmLabel lbl = (AsmLabel) { + .num = counter, + .typ = LABEL_IF + }; + lz_da_append(labelStack, lbl); commentStack(&labelStack); vstackUnderflows = 0; - int lbl = lz_da_pop(labelStack); - lz_da_append(labelStack, lbl); printf(" popstack 123\n"); printf(" RSetF 123\n"); - printf(" JmpIE __iftail_%d\n", lbl); + printf(" JmpIE __iftail_%d\n", lbl.num); break; } @@ -425,8 +473,12 @@ codegenIR: IRComplete(&irStatements, &irVStack); vstackUnderflows = 0; commentStack(&labelStack); - int lbl = lz_da_pop(labelStack); - printf("__iftail_%d:\n", lbl); + AsmLabel lbl = lz_da_pop(labelStack); + if (lbl.typ != LABEL_IF) { + fprintf(stderr, "Unmatched endif without an if\n"); + exit(1); + } + printf("__iftail_%d:\n", lbl.num); break; } if (SBeq(&tokenAccumulator, "==")) { diff --git a/flagpole/tests/break.fp b/flagpole/tests/break.fp new file mode 100644 index 0000000..836eb39 --- /dev/null +++ b/flagpole/tests/break.fp @@ -0,0 +1,11 @@ +$inc fvmstd.fp + +proc main + while 1 do + if :getuint 37 == then + break + endif + "Try again" :puts :newline + endwhile + "You got it!" :puts :newline +endproc diff --git a/flagpole/tests/continue.fp b/flagpole/tests/continue.fp new file mode 100644 index 0000000..6ce21a6 --- /dev/null +++ b/flagpole/tests/continue.fp @@ -0,0 +1,20 @@ +$inc fvmstd.fp + +proc main + while 1 do + if :getuint 37 == not then + "Number 1 incorrect" :puts :newline + continue + endif + if :getuint 42 == not then + "Number 2 incorrect" :puts :newline + continue + endif + if :getuint 69 == not then + "Number 3 incorrect" :puts :newline + continue + endif + break + endwhile + "You've logged in" :puts :newline +endproc