undar-lang/emit/rer/emit.c

772 lines
13 KiB
C

#include "../../emit.h"
#include <stdio.h>
#include <stdlib.h>
char rer_temp_strbuf[256];
void
rer_emit_error(const char *str, i32 length, i32 line)
{
fprintf(stderr, "\n===\nError at line: %d '%.*s'\n===\n", line, length, str);
exit(1);
}
void
rer_mem(u32 a)
{
USED(a);
}
void
rer_prolog(Arena *a, List *out)
{
/*StrBuf_append(a, out, "|100\n\tLIT2r 0000 main_ POP2r BRK\n\n");*/
StrBuf_append(a, out, "|100\n\tLIT2r 0000\n\n");
}
void
rer_epilogue(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_add(Arena *a, List *out)
{
StrBuf_append(a, out, "ADD2 ");
}
void
rer_emit_sub(Arena *a, List *out)
{
StrBuf_append(a, out, "SUB2 ");
}
void
rer_emit_mul(Arena *a, List *out)
{
StrBuf_append(a, out, "MUL2 ");
}
void
rer_emit_div(Arena *a, List *out)
{
StrBuf_append(a, out, "DIV2 ");
}
void
rer_emit_lt(Arena *a, List *out)
{
StrBuf_append(a, out, "LTH2 ");
}
void
rer_emit_le(Arena *a, List *out)
{
StrBuf_append(a, out, "ROT SWP LTH ?{ LTH #00 EQU JMPr } GTH JMPr ");
}
void
rer_emit_gt(Arena *a, List *out)
{
StrBuf_append(a, out, "GTH2 ");
}
void
rer_emit_ge(Arena *a, List *out)
{
StrBuf_append(a, out, "ROT SWP GTH ?{ GTH #00 EQU JMPr } LTH JMPr ");
}
void
rer_emit_ne(Arena *a, List *out)
{
StrBuf_append(a, out, "NEQ2 ");
}
void
rer_emit_eq(Arena *a, List *out)
{
StrBuf_append(a, out, "EQU2 ");
}
void
rer_emit_false(Arena *a, List *out)
{
StrBuf_append(a, out, "#0000 ");
}
void
rer_emit_true(Arena *a, List *out)
{
StrBuf_append(a, out, "#0001 ");
}
void
rer_emit_nil(Arena *a, List *out)
{
StrBuf_append(a, out, "#0000 ");
}
void
rer_emit_neg(Arena *a, List *out)
{
StrBuf_append(a, out, "#0000 SUB2 ");
}
void
rer_emit_not(Arena *a, List *out)
{
StrBuf_append(a, out, "#0000 EQU2 ");
}
void
rer_emit_void(Arena *a, List *out)
{
USED(a);
USED(out);
}
u32
rer_get_size(SymbolType t)
{
switch(t) {
case SYMBOL_BOOL:
return 1;
case SYMBOL_BYTE:
return 1;
case SYMBOL_INT:
return 2;
case SYMBOL_NAT:
return 2;
case SYMBOL_REAL:
return 2;
case SYMBOL_STR:
return 2;
case SYMBOL_U8:
return 1;
case SYMBOL_I8:
return 1;
case SYMBOL_I16:
return 2;
case SYMBOL_U16:
return 2;
case SYMBOL_I32:
return 4;
case SYMBOL_U32:
return 4;
case SYMBOL_F32:
return 4;
default:
break;
}
return 0;
}
void
rer_emit_type(Arena *a, List *out, Symbol *sym, bool local)
{
if(local) {
if(sym->ref) {
sprintf(rer_temp_strbuf, "\tSTH2kr #%04x ADD2 LDA2\n", sym->ref);
StrBuf_append(a, out, rer_temp_strbuf);
} else {
sprintf(rer_temp_strbuf, "\tSTH2kr LDA2\n");
StrBuf_append(a, out, rer_temp_strbuf);
}
} else {
sprintf(rer_temp_strbuf, "!{ @%.*s $%d } ", sym->name_length, sym->name,
rer_get_size(sym->type));
StrBuf_append(a, out, rer_temp_strbuf);
}
}
void
rer_emit_int(Arena *a, List *out, const char *str, i32 length)
{
i32 i = (i32)strtol(str, nil, 10);
sprintf(rer_temp_strbuf, "#%04x ", i);
StrBuf_append(a, out, rer_temp_strbuf);
USED(length);
}
void
rer_emit_nat(Arena *a, List *out, const char *str, i32 length)
{
u32 i = (u32)strtol(str, nil, 10);
sprintf(rer_temp_strbuf, "#%04x ", i);
StrBuf_append(a, out, rer_temp_strbuf);
USED(length);
}
void
rer_emit_real(Arena *a, List *out, const char *str, i32 length)
{
USED(str);
USED(length);
USED(a);
USED(out);
/// TODO: implement this
}
void
rer_emit_byte(Arena *a, List *out, const char *str, i32 length)
{
u8 i = (u8)strtol(str, nil, 10);
sprintf(rer_temp_strbuf, "#%04x ", i);
StrBuf_append(a, out, rer_temp_strbuf);
USED(length);
}
void
rer_emit_str(Arena *a, List *out, const char *str, i32 length)
{
/* set a pointer to the string literal and then jump over it */
StrBuf_append(a, out, ";{ #0002 ADD2 } !{ ");
i32 i = 1;
while(i < length - 1) {
char c = str[i++];
if(c == '\\' && i < length - 1) {
switch(str[i++]) {
case 'n':
c = '\n';
break;
case 't':
c = '\t';
break;
case 'r':
c = '\r';
break;
case '\\':
case '"':
case '\'':
break;
default:
i--; /* Rewind for unknown escapes */
}
}
sprintf(rer_temp_strbuf, "%02x ", c);
StrBuf_append(a, out, rer_temp_strbuf);
}
StrBuf_append(a, out, "00 } ");
}
void
rer_emit_constant(Arena *a, List *out, Symbol *sym, bool local)
{
if(local) {
if(sym->ref) {
sprintf(rer_temp_strbuf, "\tSTH2kr #%04x ADD2 STA2\n", sym->ref);
StrBuf_append(a, out, rer_temp_strbuf);
} else {
sprintf(rer_temp_strbuf, "\tSTH2kr STA2\n");
StrBuf_append(a, out, rer_temp_strbuf);
}
} else {
sprintf(rer_temp_strbuf, ";%.*s STA2 ", sym->name_length, sym->name);
StrBuf_append(a, out, rer_temp_strbuf);
}
}
void
rer_emit_array(Arena *a, List *out)
{
USED(a);
USED(out);
}
bool
rer_fn_loop_emit_args(Arena *a, List *out, void *data)
{
Symbol *sym = ((Symbol *)data);
if(sym->ref) {
sprintf(rer_temp_strbuf, "\tSTH2kr #%04x ADD2 STA2\n", sym->ref);
StrBuf_append(a, out, rer_temp_strbuf);
} else {
sprintf(rer_temp_strbuf, "\tSTH2kr STA2\n");
StrBuf_append(a, out, rer_temp_strbuf);
}
return true;
}
bool
rer_fn_loop_emit_args_comment(Arena *a, List *out, void *data)
{
Symbol *sym = ((Symbol *)data);
sprintf(rer_temp_strbuf, "%.*s ", sym->name_length, sym->name);
StrBuf_append(a, out, rer_temp_strbuf);
return true;
}
void
rer_emit_function(Arena *a, List *out, Symbol *sym)
{
sprintf(rer_temp_strbuf, "@%.*s_ ( ", sym->name_length, sym->name);
StrBuf_append(a, out, rer_temp_strbuf);
List_map_out(a, out, sym->args, rer_fn_loop_emit_args_comment);
sprintf(rer_temp_strbuf, " -- ");
StrBuf_append(a, out, rer_temp_strbuf);
if(sym->secondary_type != SYMBOL_UNDEFINED &&
sym->secondary_type != SYMBOL_VOID) {
sprintf(rer_temp_strbuf, " res ");
StrBuf_append(a, out, rer_temp_strbuf);
}
sprintf(rer_temp_strbuf, ")\n");
StrBuf_append(a, out, rer_temp_strbuf);
if(sym->size > 0) {
sprintf(rer_temp_strbuf, "\tOVR2r LIT2r %04x SUB2r\n", sym->size);
StrBuf_append(a, out, rer_temp_strbuf);
}
List_map_out(a, out, sym->args, rer_fn_loop_emit_args);
StrBuf_append(a, out, "\n");
}
void
rer_emit_arena_fn_return(Arena *a, List *out)
{
StrBuf_append(a, out, "\t&return\n\t\tPOP2r JMP2r\n\n");
}
void
rer_emit_arena_fn_call(Arena *a, List *out, Symbol *sym)
{
sprintf(rer_temp_strbuf, "%.*s_ ", sym->name_length, sym->name);
StrBuf_append(a, out, rer_temp_strbuf);
}
void
rer_emit_plex(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_method(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_trait(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_const(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_open_paren(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_close_paren(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_variable(Arena *a, List *out, Symbol *sym, bool local)
{
if(local) {
if(sym->ref) {
sprintf(rer_temp_strbuf, "\tSTH2kr #%04x ADD2 LDA2 ", sym->ref);
StrBuf_append(a, out, rer_temp_strbuf);
} else {
sprintf(rer_temp_strbuf, "\tSTH2kr LDA2 ");
StrBuf_append(a, out, rer_temp_strbuf);
}
} else {
sprintf(rer_temp_strbuf, ";%.*s LDA2 ", sym->name_length, sym->name);
StrBuf_append(a, out, rer_temp_strbuf);
}
}
void
rer_emit_set_variable(Arena *a, List *out, Symbol *sym, bool local)
{
if(local) {
if(sym->ref) {
sprintf(rer_temp_strbuf, "\tSTH2kr #%04x ADD2 STA2 ", sym->ref);
StrBuf_append(a, out, rer_temp_strbuf);
} else {
sprintf(rer_temp_strbuf, "\tSTH2kr STA2 ");
StrBuf_append(a, out, rer_temp_strbuf);
}
} else {
sprintf(rer_temp_strbuf, ";%.*s STA2 ", sym->name_length, sym->name);
StrBuf_append(a, out, rer_temp_strbuf);
}
}
void
rer_emit_write(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_read(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_open(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_close(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_stat(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_end_statement(Arena *a, List *out)
{
StrBuf_append(a, out, "\n");
}
void
rer_emit_set_value(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_plex_def(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_cast_int_to_nat(Arena *a, List *out)
{
StrBuf_append(a, out, "int_to_nat_ ");
}
void
rer_emit_cast_int_to_real(Arena *a, List *out)
{
StrBuf_append(a, out, "int_to_real_ ");
}
void
rer_emit_cast_int_to_str(Arena *a, List *out)
{
StrBuf_append(a, out, "int_to_str_ ");
}
void
rer_emit_cast_nat_to_int(Arena *a, List *out)
{
StrBuf_append(a, out, "nat_to_int_ ");
}
void
rer_emit_cast_nat_to_real(Arena *a, List *out)
{
StrBuf_append(a, out, "nat_to_real_ ");
}
void
rer_emit_cast_nat_to_str(Arena *a, List *out)
{
StrBuf_append(a, out, "nat_to_str_ ");
}
void
rer_emit_cast_real_to_int(Arena *a, List *out)
{
StrBuf_append(a, out, "real_to_int_ ");
}
void
rer_emit_cast_real_to_nat(Arena *a, List *out)
{
StrBuf_append(a, out, "real_to_nat_ ");
}
void
rer_emit_cast_real_to_str(Arena *a, List *out)
{
StrBuf_append(a, out, "real_to_str_ ");
}
void
rer_emit_strbuf_init(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_strbuf_append(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_strbuf_to_str(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_arena_fn_return_plex(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_arena_fn_return_array(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_arena_fn_return_strbuf(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_cast_str_to_int(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_cast_str_to_nat(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_cast_str_to_real(Arena *a, List *out)
{
USED(a);
USED(out);
}
void
rer_emit_sll(Arena *a, List *out)
{
StrBuf_append(a, out, "#40 SFT SFT ");
}
void
rer_emit_srl(Arena *a, List *out)
{
StrBuf_append(a, out, "SFT ");
}
void
rer_emit_xor(Arena *a, List *out)
{
StrBuf_append(a, out, "EOR2 ");
}
void
rer_emit_mod(Arena *a, List *out)
{
StrBuf_append(a, out, "DIV2k MUL2 SUB2 ");
}
void
rer_emit_or(Arena *a, List *out)
{
StrBuf_append(a, out, "ORA2 ");
}
void
rer_emit_and(Arena *a, List *out)
{
StrBuf_append(a, out, "AND2 ");
}
void
rer_emit_print(Arena *a, List *out)
{
StrBuf_append(a, out, "str/<print> ");
}
void
rer_emit_if(Arena *a, List *out)
{
StrBuf_append(a, out, "#03 JCN !{ \n");
}
void
rer_emit_patch_if(Arena *a, List *out, i32 local_ifs)
{
sprintf(rer_temp_strbuf, "!&if_end.%d } ", local_ifs);
StrBuf_append(a, out, rer_temp_strbuf);
}
void
rer_emit_patch_if_done(Arena *a, List *out, i32 local_ifs)
{
sprintf(rer_temp_strbuf, "&if_end.%d \n", local_ifs);
StrBuf_append(a, out, rer_temp_strbuf);
}
void
rer_emit_while(Arena *a, List *out, i32 local_whiles)
{
sprintf(rer_temp_strbuf, "&while.%d ", local_whiles);
StrBuf_append(a, out, rer_temp_strbuf);
}
void
rer_emit_while_postfix(Arena *a, List *out)
{
StrBuf_append(a, out, "#03 JCN !{ \n");
}
void
rer_emit_patch_while(Arena *a, List *out, i32 local_whiles)
{
sprintf(rer_temp_strbuf, "!&while.%d } \n", local_whiles);
StrBuf_append(a, out, rer_temp_strbuf);
}
void
rer_emit_early_return(Arena *a, List *out)
{
StrBuf_append(a, out, "!&return ");
}
void
rer_emit_halt(Arena *a, List *out)
{
StrBuf_append(a, out, "POP2r BRK ");
}
Emitter
rer_emitter()
{
return (Emitter){
0,
0,
0,
0,
rer_emit_error,
rer_get_size,
rer_prolog,
rer_epilogue,
rer_emit_add,
rer_emit_sub,
rer_emit_mul,
rer_emit_div,
rer_emit_lt,
rer_emit_le,
rer_emit_gt,
rer_emit_ge,
rer_emit_ne,
rer_emit_eq,
rer_emit_false,
rer_emit_true,
rer_emit_nil,
rer_emit_void,
rer_emit_int,
rer_emit_nat,
rer_emit_real,
rer_emit_byte,
rer_emit_str,
rer_emit_type,
rer_emit_array,
rer_emit_function,
rer_emit_plex,
rer_emit_method,
rer_emit_trait,
rer_emit_const,
rer_emit_print,
rer_emit_neg,
rer_emit_not,
rer_emit_open_paren,
rer_emit_close_paren,
rer_emit_constant,
rer_emit_variable,
rer_emit_set_variable,
rer_emit_write,
rer_emit_read,
rer_emit_open,
rer_emit_close,
rer_emit_stat,
rer_emit_end_statement,
rer_emit_set_value,
rer_emit_plex_def,
rer_emit_cast_int_to_nat,
rer_emit_cast_int_to_real,
rer_emit_cast_int_to_str,
rer_emit_cast_nat_to_int,
rer_emit_cast_nat_to_real,
rer_emit_cast_nat_to_str,
rer_emit_cast_real_to_int,
rer_emit_cast_real_to_nat,
rer_emit_cast_real_to_str,
rer_emit_strbuf_init,
rer_emit_strbuf_append,
rer_emit_strbuf_to_str,
rer_emit_arena_fn_call,
rer_emit_arena_fn_return,
rer_emit_arena_fn_return_plex,
rer_emit_arena_fn_return_array,
rer_emit_arena_fn_return_strbuf,
rer_emit_cast_str_to_int,
rer_emit_cast_str_to_nat,
rer_emit_cast_str_to_real,
rer_emit_sll,
rer_emit_srl,
rer_emit_xor,
rer_emit_mod,
rer_emit_and,
rer_emit_or,
rer_emit_if,
rer_emit_patch_if,
rer_emit_patch_if_done,
rer_emit_while,
rer_emit_while_postfix,
rer_emit_patch_while,
rer_emit_early_return,
rer_emit_halt,
};
}