diff --git a/arch/linux/main.c b/arch/linux/main.c index aa7ab62..8d91d2a 100644 --- a/arch/linux/main.c +++ b/arch/linux/main.c @@ -49,7 +49,7 @@ main(int argc, char **argv) return EXIT_SUCCESS; } - if(argc != 3) { + if(argc < 3) { print_help(); return EXIT_FAILURE; } diff --git a/compiler.c b/compiler.c index c7fc494..428fd6f 100644 --- a/compiler.c +++ b/compiler.c @@ -443,8 +443,8 @@ print_statement() { expression(); consume(TOKEN_SEMICOLON); - emitter.emit_end_statement(); emitter.emit_print(); + emitter.emit_end_statement(); } void @@ -473,7 +473,14 @@ if_statement() consume(TOKEN_RPAREN); emitter.emit_jump(); statement(); - emitter.emit_patch_jump(); + + emitter.emit_patch_jump(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++); } void diff --git a/emit.h b/emit.h index 46d4d76..0aa3ccf 100644 --- a/emit.h +++ b/emit.h @@ -11,94 +11,98 @@ typedef void (*StrArgEmit)(const char *str, i32 length); typedef i32 (*TypeVariableEmit)(const char *str, i32 length, bool local); typedef void (*ConstEmit)(const char *str, i32 length, bool local); typedef void (*VarEmit)(Symbol *sym, bool local); +typedef void (*I32ArgEmit)(i32 val); typedef struct emitter_s Emitter; struct emitter_s { - ErrorMsg error; - VoidArgEmit prolog; - VoidArgEmit epilogue; - VoidArgEmit emit_add; - VoidArgEmit emit_sub; - VoidArgEmit emit_mul; - VoidArgEmit emit_div; - VoidArgEmit emit_lt; - VoidArgEmit emit_le; - VoidArgEmit emit_gt; - VoidArgEmit emit_ge; - VoidArgEmit emit_ne; - VoidArgEmit emit_eq; - VoidArgEmit emit_false; - VoidArgEmit emit_true; - VoidArgEmit emit_nil; - VoidArgEmit emit_void; - StrArgEmit emit_int; - StrArgEmit emit_nat; - StrArgEmit emit_real; - StrArgEmit emit_byte; - StrArgEmit emit_str; - TypeVariableEmit emit_bool_type; - TypeVariableEmit emit_byte_type; - TypeVariableEmit emit_int_type; - TypeVariableEmit emit_nat_type; - TypeVariableEmit emit_real_type; - TypeVariableEmit emit_str_type; - TypeVariableEmit emit_u8_type; - TypeVariableEmit emit_i8_type; - TypeVariableEmit emit_i16_type; - TypeVariableEmit emit_u16_type; - TypeVariableEmit emit_i32_type; - TypeVariableEmit emit_u32_type; - TypeVariableEmit emit_f32_type; - VoidArgEmit emit_array; - VoidArgEmit emit_function; - VoidArgEmit emit_plex; - VoidArgEmit emit_method; - VoidArgEmit emit_trait; - VoidArgEmit emit_const; - VoidArgEmit emit_print; - VoidArgEmit emit_putchar; - VoidArgEmit emit_getchar; - VoidArgEmit emit_neg; - VoidArgEmit emit_not; - VoidArgEmit emit_open_paren; - VoidArgEmit emit_close_paren; - ConstEmit emit_constant; - VarEmit emit_variable; - VoidArgEmit emit_write; - VoidArgEmit emit_read; - VoidArgEmit emit_open; - VoidArgEmit emit_close; - VoidArgEmit emit_stat; - VoidArgEmit emit_end_statement; - VoidArgEmit emit_set_value; - VoidArgEmit emit_plex_def; - VoidArgEmit emit_cast_int_to_nat; - VoidArgEmit emit_cast_int_to_real; - VoidArgEmit emit_cast_int_to_str; - VoidArgEmit emit_cast_nat_to_int; - VoidArgEmit emit_cast_nat_to_real; - VoidArgEmit emit_cast_nat_to_str; - VoidArgEmit emit_cast_real_to_int; - VoidArgEmit emit_cast_real_to_nat; - VoidArgEmit emit_cast_real_to_str; - VoidArgEmit emit_strbuf_init; - VoidArgEmit emit_strbuf_append; - VoidArgEmit emit_strbuf_to_str; - VoidArgEmit emit_arena_fn_call; - VoidArgEmit emit_arena_fn_return_plex; - VoidArgEmit emit_arena_fn_return_array; - VoidArgEmit emit_arena_fn_return_strbuf; - VoidArgEmit emit_cast_str_to_int; - VoidArgEmit emit_cast_str_to_nat; - VoidArgEmit emit_cast_str_to_real; - VoidArgEmit emit_sll; - VoidArgEmit emit_srl; - VoidArgEmit emit_xor; - VoidArgEmit emit_mod; - VoidArgEmit emit_and; - VoidArgEmit emit_or; - VoidArgEmit emit_jump; - VoidArgEmit emit_patch_jump; + i32 ifs; + i32 else_if_depth; + ErrorMsg error; + VoidArgEmit prolog; + VoidArgEmit epilogue; + VoidArgEmit emit_add; + VoidArgEmit emit_sub; + VoidArgEmit emit_mul; + VoidArgEmit emit_div; + VoidArgEmit emit_lt; + VoidArgEmit emit_le; + VoidArgEmit emit_gt; + VoidArgEmit emit_ge; + VoidArgEmit emit_ne; + VoidArgEmit emit_eq; + VoidArgEmit emit_false; + VoidArgEmit emit_true; + VoidArgEmit emit_nil; + VoidArgEmit emit_void; + StrArgEmit emit_int; + StrArgEmit emit_nat; + StrArgEmit emit_real; + StrArgEmit emit_byte; + StrArgEmit emit_str; + TypeVariableEmit emit_bool_type; + TypeVariableEmit emit_byte_type; + TypeVariableEmit emit_int_type; + TypeVariableEmit emit_nat_type; + TypeVariableEmit emit_real_type; + TypeVariableEmit emit_str_type; + TypeVariableEmit emit_u8_type; + TypeVariableEmit emit_i8_type; + TypeVariableEmit emit_i16_type; + TypeVariableEmit emit_u16_type; + TypeVariableEmit emit_i32_type; + TypeVariableEmit emit_u32_type; + TypeVariableEmit emit_f32_type; + VoidArgEmit emit_array; + VoidArgEmit emit_function; + VoidArgEmit emit_plex; + VoidArgEmit emit_method; + VoidArgEmit emit_trait; + VoidArgEmit emit_const; + VoidArgEmit emit_print; + VoidArgEmit emit_putchar; + VoidArgEmit emit_getchar; + VoidArgEmit emit_neg; + VoidArgEmit emit_not; + VoidArgEmit emit_open_paren; + VoidArgEmit emit_close_paren; + ConstEmit emit_constant; + VarEmit emit_variable; + VoidArgEmit emit_write; + VoidArgEmit emit_read; + VoidArgEmit emit_open; + VoidArgEmit emit_close; + VoidArgEmit emit_stat; + VoidArgEmit emit_end_statement; + VoidArgEmit emit_set_value; + VoidArgEmit emit_plex_def; + VoidArgEmit emit_cast_int_to_nat; + VoidArgEmit emit_cast_int_to_real; + VoidArgEmit emit_cast_int_to_str; + VoidArgEmit emit_cast_nat_to_int; + VoidArgEmit emit_cast_nat_to_real; + VoidArgEmit emit_cast_nat_to_str; + VoidArgEmit emit_cast_real_to_int; + VoidArgEmit emit_cast_real_to_nat; + VoidArgEmit emit_cast_real_to_str; + VoidArgEmit emit_strbuf_init; + VoidArgEmit emit_strbuf_append; + VoidArgEmit emit_strbuf_to_str; + VoidArgEmit emit_arena_fn_call; + VoidArgEmit emit_arena_fn_return_plex; + VoidArgEmit emit_arena_fn_return_array; + VoidArgEmit emit_arena_fn_return_strbuf; + VoidArgEmit emit_cast_str_to_int; + VoidArgEmit emit_cast_str_to_nat; + VoidArgEmit emit_cast_str_to_real; + VoidArgEmit emit_sll; + VoidArgEmit emit_srl; + VoidArgEmit emit_xor; + VoidArgEmit emit_mod; + VoidArgEmit emit_and; + VoidArgEmit emit_or; + VoidArgEmit emit_jump; + I32ArgEmit emit_patch_jump; + I32ArgEmit emit_patch_jump_done; }; Emitter rer_emitter(); diff --git a/emit/rer/emit.c b/emit/rer/emit.c index 7d50e01..6fb5f21 100644 --- a/emit/rer/emit.c +++ b/emit/rer/emit.c @@ -294,9 +294,7 @@ 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 } "); } @@ -545,31 +543,18 @@ rer_emit_print() printf("str/ "); } - -void -rer_emit_jump() -{ - printf("?{ "); -} - -void -rer_emit_patch_jump() -{ - printf("} "); -} - i32 -rer_emit_const_type(SymbolType type, const char *var, i32 var_length, const char *val, i32 val_legnth, bool local) { +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]); - } + 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); @@ -577,11 +562,30 @@ rer_emit_const_type(SymbolType type, const char *var, i32 var_length, const char return 2; } +void +rer_emit_jump() +{ + printf("#03 JCN !{ "); +} + +void +rer_emit_patch_jump(i32 local_ifs) +{ + printf("!&if_end.%d } ", local_ifs); +} + +void +rer_emit_patch_jump_done(i32 local_ifs) +{ + printf("&if_end.%d ", local_ifs); +} Emitter rer_emitter() { return (Emitter){ + 0, + 0, rer_emit_error, rer_prolog, rer_epilogue, @@ -666,6 +670,7 @@ rer_emitter() rer_emit_and, rer_emit_or, rer_emit_jump, - rer_emit_patch_jump, + rer_emit_patch_jump, + rer_emit_patch_jump_done, }; } diff --git a/emit/uxn/emit.c b/emit/uxn/emit.c index 96e3b9b..5765af9 100644 --- a/emit/uxn/emit.c +++ b/emit/uxn/emit.c @@ -168,7 +168,7 @@ uxn_prolog() void uxn_epilogue() { - printf("\n\n"); + printf("BRK\n\n"); for (u32 i = 0; i < __lib_undar_len; i++) { putchar(__lib_undar[i]); } @@ -261,7 +261,7 @@ uxn_emit_neg() void uxn_emit_not() { - printf("#ffff EOR2 "); + printf("#0000 EQU2 "); } void @@ -700,19 +700,27 @@ uxn_emit_print() void uxn_emit_jump() { - printf("?{ "); + printf("#03 JCN !{ "); } void -uxn_emit_patch_jump() +uxn_emit_patch_jump(i32 local_ifs) { - printf("} "); + printf("!&if_end.%d } ", local_ifs); +} + +void +uxn_emit_patch_jump_done(i32 local_ifs) +{ + printf("&if_end.%d ", local_ifs); } Emitter uxn_emitter() { return (Emitter){ + 0, + 0, uxn_emit_error, uxn_prolog, uxn_epilogue, @@ -798,5 +806,6 @@ uxn_emitter() uxn_emit_or, uxn_emit_jump, uxn_emit_patch_jump, + uxn_emit_patch_jump_done, }; } diff --git a/test/bang.tal b/test/bang.tal index 8e1fcd8..da6ed9f 100644 --- a/test/bang.tal +++ b/test/bang.tal @@ -1,8 +1,69 @@ |100 -!{ @flag $1 } #0000 ;flag STA2 ;flag LDA2 #ffff EOR2 ?{ ;{ #0002 ADD2 } !{ #66 #6c #61 #67 #20 #69 #73 #20 #66 #61 #6c #73 #65 #00 } str/ } BRK +!{ @flag $1 } #0000 ;flag STA2 +;flag LDA2 #0000 EQU2 #03 JCN !{ ;{ #0002 ADD2 } !{ 66 6c 61 67 20 69 73 20 66 61 6c 73 65 00 } str/ +!&if_end.0 } &if_end.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/ ( str* -- ) - LDAk DUP ?{ POP POP2 JMP2r } - #18 DEO - INC2 !/ + LDAk DUP ?{ POP POP2 JMP2r } + #18 DEO + INC2 !/ +@mem_length_ #0000 +@mem_ diff --git a/test/if.tal b/test/if.tal new file mode 100644 index 0000000..90beac6 --- /dev/null +++ b/test/if.tal @@ -0,0 +1,71 @@ +|100 +!{ @x $2 } #0014 ;x STA2 +;x LDA2 #000a EQU2 #03 JCN !{ ;{ #0002 ADD2 } !{ 78 20 69 73 20 31 30 00 } str/ +!&if_end.0 } ;x LDA2 #0014 EQU2 #03 JCN !{ ;{ #0002 ADD2 } !{ 78 20 69 73 20 32 30 00 } str/ +!&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/ +&if_end.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/ ( str* -- ) + LDAk DUP ?{ POP POP2 JMP2r } + #18 DEO + INC2 !/ + +@mem_length_ #0000 +@mem_ diff --git a/test/if.ul b/test/if.ul index f007804..4de67b7 100755 --- a/test/if.ul +++ b/test/if.ul @@ -1,4 +1,4 @@ -nat x = 10; +nat x = 20; if (x == 10) { print("x is 10"); diff --git a/test/str.c b/test/str.c index 3f3ad38..09c9ede 100755 --- a/test/str.c +++ b/test/str.c @@ -1,7 +1,7 @@ #include char* msg = " damage inflicted!\n"; -int main() { +void main() { unsigned AT = 14; unsigned accuracy = 150; diff --git a/test/str.ul b/test/str.ul index 3384cd3..5b193e1 100755 --- a/test/str.ul +++ b/test/str.ul @@ -5,4 +5,4 @@ nat accuracy = 150; nat dmg = ((AT * accuracy) / 20) - 3; print(dmg as str); -print(msg); \ No newline at end of file +print(msg);