Implemented break and continue and improved label stack handling

This commit is contained in:
cannoli-fruit 2026-07-31 06:42:17 -04:00
commit 1606150450
3 changed files with 97 additions and 14 deletions

View file

@ -113,6 +113,8 @@ static inline bool isKW(Lz_SB *sb) {
|| SBeq(sb, "then") || SBeq(sb, "then")
|| SBeq(sb, "endif") || SBeq(sb, "endif")
|| SBeq(sb, "endwhile") || SBeq(sb, "endwhile")
|| SBeq(sb, "break")
|| SBeq(sb, "continue")
|| SBeq(sb, "==") || SBeq(sb, "==")
|| SBeq(sb, "not") || SBeq(sb, "not")
|| SBeq(sb, "bor") || 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 main(uint argc, char **argv) {
int opt; int opt;
Lz_DA(FILE *) inpfiles = {}; Lz_DA(FILE *) inpfiles = {};
@ -190,7 +202,7 @@ int main(uint argc, char **argv) {
bool isProc = false; bool isProc = false;
bool isInclude = false; bool isInclude = false;
bool isComment = false; bool isComment = false;
Lz_DA(int) labelStack = {0}; Lz_DA(AsmLabel) labelStack = {0};
uint64_t allocHead = 0x7000000000000000; uint64_t allocHead = 0x7000000000000000;
char funcName[128]; char funcName[128];
Lz_DA(Variable) vars = {0}; Lz_DA(Variable) vars = {0};
@ -379,29 +391,63 @@ codegenIR:
} }
if (SBeq(&tokenAccumulator, "while")) { if (SBeq(&tokenAccumulator, "while")) {
IRComplete(&irStatements, &irVStack); IRComplete(&irStatements, &irVStack);
lz_da_append(labelStack, counter); AsmLabel lbl = (AsmLabel) {
.num = counter,
.typ = LABEL_WHILE
};
lz_da_append(labelStack, lbl);
commentStack(&labelStack); commentStack(&labelStack);
printf("__whilehead_%d:\n", counter); printf("__whilehead_%d:\n", lbl.num);
break; break;
} }
if (SBeq(&tokenAccumulator, "do")) { if (SBeq(&tokenAccumulator, "do")) {
IRComplete(&irStatements, &irVStack); IRComplete(&irStatements, &irVStack);
vstackUnderflows = 0; 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); lz_da_append(labelStack, lbl);
// TODO: Change flag setting to IR's job // TODO: Change flag setting to IR's job
printf(" popstack 108\n"); printf(" popstack 108\n");
printf(" RSetF 108\n"); printf(" RSetF 108\n");
printf(" JmpIE __whiletail_%d\n", lbl); printf(" JmpIE __whiletail_%d\n", lbl.num);
break; break;
} }
if (SBeq(&tokenAccumulator, "endwhile")) { if (SBeq(&tokenAccumulator, "endwhile")) {
IRComplete(&irStatements, &irVStack); IRComplete(&irStatements, &irVStack);
vstackUnderflows = 0; 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); commentStack(&labelStack);
printf(" Jmp __whilehead_%d\n", lbl); printf(" Jmp __whilehead_%d\n", lbl.num);
printf("__whiletail_%d:\n", lbl); 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; break;
} }
if (SBeq(&tokenAccumulator, "if")) { if (SBeq(&tokenAccumulator, "if")) {
@ -410,14 +456,16 @@ codegenIR:
if (SBeq(&tokenAccumulator, "then")) { if (SBeq(&tokenAccumulator, "then")) {
IRComplete(&irStatements, &irVStack); IRComplete(&irStatements, &irVStack);
lz_da_append(labelStack, counter); AsmLabel lbl = (AsmLabel) {
.num = counter,
.typ = LABEL_IF
};
lz_da_append(labelStack, lbl);
commentStack(&labelStack); commentStack(&labelStack);
vstackUnderflows = 0; vstackUnderflows = 0;
int lbl = lz_da_pop(labelStack);
lz_da_append(labelStack, lbl);
printf(" popstack 123\n"); printf(" popstack 123\n");
printf(" RSetF 123\n"); printf(" RSetF 123\n");
printf(" JmpIE __iftail_%d\n", lbl); printf(" JmpIE __iftail_%d\n", lbl.num);
break; break;
} }
@ -425,8 +473,12 @@ codegenIR:
IRComplete(&irStatements, &irVStack); IRComplete(&irStatements, &irVStack);
vstackUnderflows = 0; vstackUnderflows = 0;
commentStack(&labelStack); commentStack(&labelStack);
int lbl = lz_da_pop(labelStack); AsmLabel lbl = lz_da_pop(labelStack);
printf("__iftail_%d:\n", lbl); if (lbl.typ != LABEL_IF) {
fprintf(stderr, "Unmatched endif without an if\n");
exit(1);
}
printf("__iftail_%d:\n", lbl.num);
break; break;
} }
if (SBeq(&tokenAccumulator, "==")) { if (SBeq(&tokenAccumulator, "==")) {

11
flagpole/tests/break.fp Normal file
View file

@ -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

View file

@ -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