add while loops

This commit is contained in:
zongor 2026-04-28 23:22:57 -07:00
parent ab5a7ee185
commit 3ac64d18a0
7 changed files with 194 additions and 55 deletions

View File

@ -471,16 +471,28 @@ if_statement()
consume(TOKEN_LPAREN);
expression();
consume(TOKEN_RPAREN);
emitter.emit_jump();
emitter.emit_if();
statement();
emitter.emit_patch_jump(emitter.ifs);
if (match(TOKEN_KEYWORD_ELSE)) {
emitter.emit_patch_if(emitter.ifs);
if(match(TOKEN_KEYWORD_ELSE)) {
emitter.else_if_depth++;
statement();
emitter.else_if_depth--;
}
if (emitter.else_if_depth == 0) emitter.emit_patch_jump_done(emitter.ifs++);
if(emitter.else_if_depth == 0) emitter.emit_patch_if_done(emitter.ifs++);
}
void
while_statement()
{
emitter.emit_while(emitter.loops);
consume(TOKEN_LPAREN);
expression();
consume(TOKEN_RPAREN);
emitter.emit_while_postfix();
statement();
emitter.emit_patch_while(emitter.loops++);
}
void
@ -500,6 +512,8 @@ statement()
scope_pop();
} else if(match(TOKEN_KEYWORD_IF)) {
if_statement();
} else if(match(TOKEN_KEYWORD_WHILE)) {
while_statement();
} else if(match(TOKEN_KEYWORD_PRINT)) {
print_statement();
} else if(match(TOKEN_KEYWORD_PUTCHAR)) {

11
emit.h
View File

@ -17,6 +17,8 @@ typedef struct emitter_s Emitter;
struct emitter_s {
i32 ifs;
i32 else_if_depth;
i32 loops;
i32 loop_depth;
ErrorMsg error;
VoidArgEmit prolog;
VoidArgEmit epilogue;
@ -100,9 +102,12 @@ struct emitter_s {
VoidArgEmit emit_mod;
VoidArgEmit emit_and;
VoidArgEmit emit_or;
VoidArgEmit emit_jump;
I32ArgEmit emit_patch_jump;
I32ArgEmit emit_patch_jump_done;
VoidArgEmit emit_if;
I32ArgEmit emit_patch_if;
I32ArgEmit emit_patch_if_done;
I32ArgEmit emit_while;
VoidArgEmit emit_while_postfix;
I32ArgEmit emit_patch_while;
};
Emitter rer_emitter();

View File

@ -1,3 +1,4 @@
#include "../../emit.h"
#include <stdio.h>
#include <stdlib.h>
@ -24,10 +25,7 @@ rer_prolog()
void
rer_epilogue()
{
printf("BRK\n\n@str/<print> ( str* -- )\n\
LDAk DUP ?{ POP POP2 JMP2r }\n\
#18 DEO\n\
INC2 !/<print>\n");
printf("BRK\n\n");
}
void
@ -117,7 +115,7 @@ rer_emit_neg()
void
rer_emit_not()
{
printf("#ffff EOR2 ");
printf("#0000 EQU2 ");
}
void
@ -294,9 +292,9 @@ rer_emit_str(const char *str, i32 length)
/* set a pointer to the string literal and then jump over it */
printf(";{ #0002 ADD2 } !{ ");
for(i32 i = 1; i < length - 1; i++) printf("#%02x ", str[i]);
for(i32 i = 1; i < length - 1; i++) printf("%02x ", str[i]);
printf("#00 } ");
printf("00 } ");
}
void
@ -397,6 +395,7 @@ rer_emit_stat()
void
rer_emit_end_statement()
{
printf("\n");
}
void
@ -412,46 +411,55 @@ rer_emit_plex_def()
void
rer_emit_cast_int_to_nat()
{
printf("int_to_nat_ ");
}
void
rer_emit_cast_int_to_real()
{
printf("int_to_real_ ");
}
void
rer_emit_cast_int_to_str()
{
printf("int_to_str_ ");
}
void
rer_emit_cast_nat_to_int()
{
printf("nat_to_int_ ");
}
void
rer_emit_cast_nat_to_real()
{
printf("nat_to_real_ ");
}
void
rer_emit_cast_nat_to_str()
{
printf("nat_to_str_ ");
}
void
rer_emit_cast_real_to_int()
{
printf("real_to_int_ ");
}
void
rer_emit_cast_real_to_nat()
{
printf("real_to_nat_ ");
}
void
rer_emit_cast_real_to_str()
{
printf("real_to_str_ ");
}
void
@ -543,47 +551,49 @@ rer_emit_print()
printf("str/<print> ");
}
i32
rer_emit_const_type(SymbolType type, const char *var, i32 var_length,
const char *val, i32 val_legnth, bool local)
{
if(local)
printf("&%.*s ", var_length, var);
else
printf("@%.*s ", var_length, var);
if(type == SYMBOL_STR) {
for(i32 i = 1; i < val_legnth - 1; i++) printf("#%02x ", val[i]);
} else {
i32 i = (i32)strtol(val, nil, 10);
printf("#%04x ", i);
}
return 2;
}
void
rer_emit_jump()
rer_emit_if()
{
printf("#03 JCN !{ ");
}
void
rer_emit_patch_jump(i32 local_ifs)
rer_emit_patch_if(i32 local_ifs)
{
printf("!&if_end.%d } ", local_ifs);
}
void
rer_emit_patch_jump_done(i32 local_ifs)
rer_emit_patch_if_done(i32 local_ifs)
{
printf("&if_end.%d ", local_ifs);
}
Emitter
rer_emitter()
void
rer_emit_while(i32 local_whiles)
{
printf("&while.%d ", local_whiles);
}
void
rer_emit_while_postfix()
{
printf("#03 JCN !{ ");
}
void
rer_emit_patch_while(i32 local_whiles)
{
printf("!&while.%d } ", local_whiles);
}
Emitter rer_emitter()
{
return (Emitter){
0,
0,
0,
0,
rer_emit_error,
@ -669,8 +679,11 @@ rer_emitter()
rer_emit_mod,
rer_emit_and,
rer_emit_or,
rer_emit_jump,
rer_emit_patch_jump,
rer_emit_patch_jump_done,
rer_emit_if,
rer_emit_patch_if,
rer_emit_patch_if_done,
rer_emit_while,
rer_emit_while_postfix,
rer_emit_patch_while,
};
}

View File

@ -698,27 +698,48 @@ uxn_emit_print()
}
void
uxn_emit_jump()
uxn_emit_if()
{
printf("#03 JCN !{ ");
}
void
uxn_emit_patch_jump(i32 local_ifs)
uxn_emit_patch_if(i32 local_ifs)
{
printf("!&if_end.%d } ", local_ifs);
}
void
uxn_emit_patch_jump_done(i32 local_ifs)
uxn_emit_patch_if_done(i32 local_ifs)
{
printf("&if_end.%d ", local_ifs);
}
Emitter
uxn_emitter()
void
uxn_emit_while(i32 local_whiles)
{
printf("&while.%d ", local_whiles);
}
void
uxn_emit_while_postfix()
{
printf("#03 JCN !{ ");
}
void
uxn_emit_patch_while(i32 local_whiles)
{
printf("!&while.%d } ", local_whiles);
}
Emitter uxn_emitter()
{
return (Emitter){
0,
0,
0,
0,
uxn_emit_error,
@ -804,8 +825,11 @@ uxn_emitter()
uxn_emit_mod,
uxn_emit_and,
uxn_emit_or,
uxn_emit_jump,
uxn_emit_patch_jump,
uxn_emit_patch_jump_done,
uxn_emit_if,
uxn_emit_patch_if,
uxn_emit_patch_if_done,
uxn_emit_while,
uxn_emit_while_postfix,
uxn_emit_patch_while,
};
}

13
test/hardcoded-while.tal Normal file
View File

@ -0,0 +1,13 @@
|100
!{ @i $2 } #0000 ;i STA2
&while.1 [ ;i LDA2 #0008 LTH2 ] #03 JCN !{ ( Loop while iterator is less than limit. )
;i LDA2 print-num ( Run function to print number )
;i LDA2 INC2 ;i STA2 ( incriment counter )
!&while.1 }
BRK ( Halt. )
@print-num ( int -- )
LIT "0 ADD ( Add number to ascii character 0 )
#18 DEO ( Send to Console/write )
JMP2r

View File

@ -1,8 +1,8 @@
|100
!{ @x $2 } #0014 ;x STA2
;x LDA2 #000a EQU2 #03 JCN !{ ;{ #0002 ADD2 } !{ 78 20 69 73 20 31 30 00 } str/<print>
!&if_end.0 } ;x LDA2 #0014 EQU2 #03 JCN !{ ;{ #0002 ADD2 } !{ 78 20 69 73 20 32 30 00 } str/<print>
!&if_end.0 } ;{ #0002 ADD2 } !{ 78 20 69 73 20 73 6f 6d 65 74 68 69 6e 67 20 65 6c 73 65 00 } str/<print>
;x LDA2 #000a EQU2 #03 JCN !{ ;{ #0002 ADD2 } !{ 78 20 69 73 20 31 30 00 } str/<print> !&if_end.0 }
;x LDA2 #0014 EQU2 #03 JCN !{ ;{ #0002 ADD2 } !{ 78 20 69 73 20 32 30 00 } str/<print> !&if_end.0 }
;{ #0002 ADD2 } !{ 78 20 69 73 20 73 6f 6d 65 74 68 69 6e 67 20 65 6c 73 65 00 } str/<print>
&if_end.0 BRK
@sext

70
test/while.tal Normal file
View File

@ -0,0 +1,70 @@
|100
!{ @i $2 } #0000 ;i STA2
&loop.0 ;i LDA2 #000a LTH2 #03 JCN !{ ;i LDA2 nat_to_str_ str/<print>
;i LDA2 ;i LDA2 #0001 ADD2 ;i STA2 !&loop.0 } BRK
@sext
#80 ANDk EQU #ff MUL SWP JMP2r
@aalloc_ ( size* -- result* )
OVR2r LIT2r 0004 SUB2r STH2kr INC2 INC2 STA2
;mem_length_ LDA2 STH2kr STA2
;mem_length_ LDA2k STH2kr INC2 INC2 LDA2 ADD2 SWP2 STA2
;mem_ STH2kr LDA2 ADD2 !&return
#0000
&return
POP2r JMP2r
@amcpy_ ( length* from* -- result* )
OVR2r LIT2r 0008 SUB2r STH2kr #0006 ADD2 STA2
STH2kr #0004 ADD2 STA2
STH2kr #0004 ADD2 LDA2 aalloc_
STH2kr INC2 INC2 STA2
#0000 STH2kr STA2
&begin.1
STH2kr LDA2 STH2kr #0004 ADD2 LDA2 LTH2 #00 EQU ?&break.1
STH2kr #0006 ADD2 LDA2 STH2kr LDA2 ADD2 LDA sext
STH2kr INC2 INC2 LDA2 STH2kr LDA2 ADD2 STA
POP
&continue.1
STH2kr LDA2k INC2k ROT2 STA2
POP2 !&begin.1
&break.1
STH2kr INC2 INC2 LDA2 !&return
#0000
&return
POP2r JMP2r
@nat_to_str_ ( n* -- result* )
OVR2r LIT2r 000a SUB2r STH2kr #0008 ADD2 STA2
#0005 STH2kr STA2
&begin.1
STH2kr #0008 ADD2 LDA2 #000a OVR2 OVR2 DIV2 MUL2 SUB2 #0030 ADD2 STH2kr INC2 INC2 STH2kr LDA2k #0001 SUB2 SWP2 STA2k
POP2 ADD2 STA
POP STH2kr #0008 ADD2 LDA2k #000a DIV2 SWP2 STA2
&continue.1
#0000 STH2kr #0008 ADD2 LDA2 LTH2 ?&begin.1
&break.1
#0005 STH2kr LDA2 SUB2 STH2kr INC2 INC2 STH2kr LDA2 ADD2 amcpy_
!&return
#0000
&return
POP2r JMP2r
@str/<print> ( str* -- )
LDAk DUP ?{ POP POP2 JMP2r }
#18 DEO
INC2 !/<print>
@mem_length_ #0000
@mem_