Change to output a string buffer instead of raw printf

This commit is contained in:
zongor 2026-06-28 14:01:13 -07:00
parent 1ec9f7a2d1
commit 974d282d7a
10 changed files with 1270 additions and 1038 deletions

View File

@ -1,6 +1,7 @@
#include "../../compiler.h" #include "../../compiler.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
static char * static char *
readFile(const char *path) readFile(const char *path)
@ -67,10 +68,28 @@ main(int argc, char **argv)
u8 tape[MEM_SIZE]; u8 tape[MEM_SIZE];
Arena a = {tape, 0, MEM_SIZE}; Arena a = {tape, 0, MEM_SIZE};
List *code = List_init(&a);
List *memory = List_init(&a);
char *source = readFile(argv[2]); char *source = readFile(argv[2]);
compile(&a, e, source); compile(&a, code, memory, e, source);
Node *curr = code->head;
while (curr) {
char* tmp_str = node_value(curr);
write(STDOUT_FILENO, tmp_str, curr->size);
curr = curr->next;
}
curr = memory->head;
while (curr) {
char* tmp_str = node_value(curr);
write(STDOUT_FILENO, tmp_str, curr->size);
curr = curr->next;
}
afree(&a);
free(source); free(source);
printf("\n");
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -8,6 +8,8 @@
Emitter emitter = {0}; Emitter emitter = {0};
Parser parser = {0}; Parser parser = {0};
Arena *arena; Arena *arena;
List *code;
List *memory;
/**************************************************** /****************************************************
* Scope * Scope
@ -371,6 +373,20 @@ variable_declaration(Symbol *def)
while(!check(TOKEN_RBRACKET)) { while(!check(TOKEN_RBRACKET)) {
advance(); advance();
} }
variable = scope_get_symbol(parser.current_scope,
parser.previous.start,
parser.previous.length);
if (check(TOKEN_EQ)) {
}
while(!check(TOKEN_SEMICOLON)) {
advance();
}
return variable->size;
} }
if(st != SYMBOL_UNDEFINED) { if(st != SYMBOL_UNDEFINED) {
@ -383,7 +399,7 @@ variable_declaration(Symbol *def)
if(def) { if(def) {
List_push(arena, def->args, variable, sizeof(Symbol)); List_push(arena, def->args, variable, sizeof(Symbol));
} else { } else {
emitter.emit_type(variable, parser.depth); emitter.emit_type(arena, code, variable, parser.depth);
parser.current_type = st; parser.current_type = st;
} }
} else { } else {
@ -400,13 +416,13 @@ variable_declaration(Symbol *def)
if(parser.pass == 0) return size; if(parser.pass == 0) return size;
if(match(TOKEN_EQ)) { if(match(TOKEN_EQ)) {
emitter.emit_set_value(); emitter.emit_set_value(arena, code);
expression(); expression();
emitter.emit_constant(variable, parser.depth); emitter.emit_constant(arena, code, variable, parser.depth);
} }
consume(TOKEN_SEMICOLON); consume(TOKEN_SEMICOLON);
emitter.emit_end_statement(); emitter.emit_end_statement(arena, code);
parser.current_type = SYMBOL_UNDEFINED; parser.current_type = SYMBOL_UNDEFINED;
return size; return size;
} }
@ -421,52 +437,52 @@ binary()
switch(operatorType) { switch(operatorType) {
case TOKEN_BANG_EQ: case TOKEN_BANG_EQ:
emitter.emit_ne(); emitter.emit_ne(arena, code);
break; break;
case TOKEN_EQ_EQ: case TOKEN_EQ_EQ:
emitter.emit_eq(); emitter.emit_eq(arena, code);
break; break;
case TOKEN_GT: case TOKEN_GT:
emitter.emit_gt(); emitter.emit_gt(arena, code);
break; break;
case TOKEN_GTE: case TOKEN_GTE:
emitter.emit_ge(); emitter.emit_ge(arena, code);
break; break;
case TOKEN_LT: case TOKEN_LT:
emitter.emit_lt(); emitter.emit_lt(arena, code);
break; break;
case TOKEN_LTE: case TOKEN_LTE:
emitter.emit_le(); emitter.emit_le(arena, code);
break; break;
case TOKEN_PLUS: case TOKEN_PLUS:
emitter.emit_add(); emitter.emit_add(arena, code);
break; break;
case TOKEN_MINUS: case TOKEN_MINUS:
emitter.emit_sub(); emitter.emit_sub(arena, code);
break; break;
case TOKEN_STAR: case TOKEN_STAR:
emitter.emit_mul(); emitter.emit_mul(arena, code);
break; break;
case TOKEN_SLASH: case TOKEN_SLASH:
emitter.emit_div(); emitter.emit_div(arena, code);
break; break;
case TOKEN_OPERATOR_AND: case TOKEN_OPERATOR_AND:
emitter.emit_and(); emitter.emit_and(arena, code);
break; break;
case TOKEN_OPERATOR_OR: case TOKEN_OPERATOR_OR:
emitter.emit_or(); emitter.emit_or(arena, code);
break; break;
case TOKEN_OPERATOR_XOR: case TOKEN_OPERATOR_XOR:
emitter.emit_xor(); emitter.emit_xor(arena, code);
break; break;
case TOKEN_OPERATOR_MOD: case TOKEN_OPERATOR_MOD:
emitter.emit_mod(); emitter.emit_mod(arena, code);
break; break;
case TOKEN_SLL: case TOKEN_SLL:
emitter.emit_sll(); emitter.emit_sll(arena, code);
break; break;
case TOKEN_SRL: case TOKEN_SRL:
emitter.emit_srl(); emitter.emit_srl(arena, code);
break; break;
default: default:
return; return;
@ -478,13 +494,13 @@ literal()
{ {
switch(parser.previous.type) { switch(parser.previous.type) {
case TOKEN_KEYWORD_FALSE: case TOKEN_KEYWORD_FALSE:
emitter.emit_false(); emitter.emit_false(arena, code);
break; break;
case TOKEN_KEYWORD_TRUE: case TOKEN_KEYWORD_TRUE:
emitter.emit_true(); emitter.emit_true(arena, code);
break; break;
case TOKEN_KEYWORD_NIL: case TOKEN_KEYWORD_NIL:
emitter.emit_nil(); emitter.emit_nil(arena, code);
break; break;
default: default:
return; return;
@ -515,9 +531,9 @@ variable()
parser.current_type = sym->type; parser.current_type = sym->type;
if(match(TOKEN_EQ)) { if(match(TOKEN_EQ)) {
expression(); expression();
emitter.emit_set_variable(sym, sym->scope); emitter.emit_set_variable(arena, code, sym, sym->scope);
} else { } else {
emitter.emit_variable(sym, sym->scope); emitter.emit_variable(arena, code, sym, sym->scope);
} }
} }
@ -539,15 +555,15 @@ cast_type()
case SYMBOL_INT: { case SYMBOL_INT: {
switch(cast_type) { switch(cast_type) {
case TOKEN_TYPE_NAT: { case TOKEN_TYPE_NAT: {
emitter.emit_cast_int_to_nat(); emitter.emit_cast_int_to_nat(arena, code);
break; break;
} }
case TOKEN_TYPE_REAL: { case TOKEN_TYPE_REAL: {
emitter.emit_cast_int_to_real(); emitter.emit_cast_int_to_real(arena, code);
break; break;
} }
case TOKEN_TYPE_STR: { case TOKEN_TYPE_STR: {
emitter.emit_cast_int_to_str(); emitter.emit_cast_int_to_str(arena, code);
break; break;
} }
default: default:
@ -559,15 +575,15 @@ cast_type()
case SYMBOL_NAT: { case SYMBOL_NAT: {
switch(cast_type) { switch(cast_type) {
case TOKEN_TYPE_INT: { case TOKEN_TYPE_INT: {
emitter.emit_cast_nat_to_int(); emitter.emit_cast_nat_to_int(arena, code);
break; break;
} }
case TOKEN_TYPE_REAL: { case TOKEN_TYPE_REAL: {
emitter.emit_cast_nat_to_real(); emitter.emit_cast_nat_to_real(arena, code);
break; break;
} }
case TOKEN_TYPE_STR: { case TOKEN_TYPE_STR: {
emitter.emit_cast_nat_to_str(); emitter.emit_cast_nat_to_str(arena, code);
break; break;
} }
default: default:
@ -578,15 +594,15 @@ cast_type()
case SYMBOL_REAL: { case SYMBOL_REAL: {
switch(cast_type) { switch(cast_type) {
case TOKEN_TYPE_NAT: { case TOKEN_TYPE_NAT: {
emitter.emit_cast_real_to_nat(); emitter.emit_cast_real_to_nat(arena, code);
break; break;
} }
case TOKEN_TYPE_INT: { case TOKEN_TYPE_INT: {
emitter.emit_cast_real_to_int(); emitter.emit_cast_real_to_int(arena, code);
break; break;
} }
case TOKEN_TYPE_STR: { case TOKEN_TYPE_STR: {
emitter.emit_cast_real_to_str(); emitter.emit_cast_real_to_str(arena, code);
break; break;
} }
default: default:
@ -597,15 +613,15 @@ cast_type()
case SYMBOL_STR: { case SYMBOL_STR: {
switch(cast_type) { switch(cast_type) {
case TOKEN_TYPE_NAT: { case TOKEN_TYPE_NAT: {
emitter.emit_cast_str_to_nat(); emitter.emit_cast_str_to_nat(arena, code);
break; break;
} }
case TOKEN_TYPE_REAL: { case TOKEN_TYPE_REAL: {
emitter.emit_cast_str_to_real(); emitter.emit_cast_str_to_real(arena, code);
break; break;
} }
case TOKEN_TYPE_INT: { case TOKEN_TYPE_INT: {
emitter.emit_cast_str_to_int(); emitter.emit_cast_str_to_int(arena, code);
break; break;
} }
default: default:
@ -632,8 +648,8 @@ print_statement()
{ {
expression(); expression();
consume(TOKEN_SEMICOLON); consume(TOKEN_SEMICOLON);
emitter.emit_print(); emitter.emit_print(arena, code);
emitter.emit_end_statement(); emitter.emit_end_statement(arena, code);
} }
void void
@ -642,28 +658,28 @@ if_statement()
consume(TOKEN_LPAREN); consume(TOKEN_LPAREN);
expression(); expression();
consume(TOKEN_RPAREN); consume(TOKEN_RPAREN);
emitter.emit_if(); emitter.emit_if(arena, code);
statement(); statement();
emitter.emit_patch_if(emitter.ifs); emitter.emit_patch_if(arena, code, emitter.ifs);
if(match(TOKEN_KEYWORD_ELSE)) { if(match(TOKEN_KEYWORD_ELSE)) {
emitter.else_if_depth++; emitter.else_if_depth++;
statement(); statement();
emitter.else_if_depth--; emitter.else_if_depth--;
} }
if(emitter.else_if_depth == 0) emitter.emit_patch_if_done(emitter.ifs++); if(emitter.else_if_depth == 0) emitter.emit_patch_if_done(arena, code, emitter.ifs++);
} }
void void
while_statement() while_statement()
{ {
emitter.emit_while(emitter.loops); emitter.emit_while(arena, code, emitter.loops);
consume(TOKEN_LPAREN); consume(TOKEN_LPAREN);
expression(); expression();
consume(TOKEN_RPAREN); consume(TOKEN_RPAREN);
emitter.emit_while_postfix(); emitter.emit_while_postfix(arena, code);
statement(); statement();
emitter.emit_patch_while(emitter.loops++); emitter.emit_patch_while(arena, code, emitter.loops++);
} }
void void
@ -679,13 +695,13 @@ function()
{ {
Symbol *sym = scope_get_symbol(parser.current_scope, parser.previous.start, Symbol *sym = scope_get_symbol(parser.current_scope, parser.previous.start,
parser.previous.length); parser.previous.length);
emitter.emit_function(sym); emitter.emit_function(arena, code, sym);
scope_push(); scope_push();
while(!check(TOKEN_RPAREN)) advance(); while(!check(TOKEN_RPAREN)) advance();
consume(TOKEN_RPAREN); consume(TOKEN_RPAREN);
consume(TOKEN_LBRACE); consume(TOKEN_LBRACE);
block(); block();
emitter.emit_arena_fn_return(); emitter.emit_arena_fn_return(arena, code);
} }
void void
@ -698,7 +714,7 @@ call()
} }
consume(TOKEN_RPAREN); consume(TOKEN_RPAREN);
emitter.emit_arena_fn_call(parser.call_fn); emitter.emit_arena_fn_call(arena, code, parser.call_fn);
parser.current_type = parser.call_fn->secondary_type; parser.current_type = parser.call_fn->secondary_type;
return; return;
} }
@ -707,11 +723,11 @@ void
return_statement() return_statement()
{ {
if(match(TOKEN_SEMICOLON)) { if(match(TOKEN_SEMICOLON)) {
emitter.emit_early_return(); emitter.emit_early_return(arena, code);
} else { } else {
expression(); expression();
consume(TOKEN_SEMICOLON); consume(TOKEN_SEMICOLON);
emitter.emit_early_return(); emitter.emit_early_return(arena, code);
} }
} }
@ -734,7 +750,7 @@ statement()
} else if(match(TOKEN_KEYWORD_PRINT)) { } else if(match(TOKEN_KEYWORD_PRINT)) {
print_statement(); print_statement();
} else if(match(TOKEN_KEYWORD_HALT)) { } else if(match(TOKEN_KEYWORD_HALT)) {
emitter.emit_halt(); emitter.emit_halt(arena, code);
} else { } else {
expression(); expression();
} }
@ -743,24 +759,24 @@ statement()
void void
grouping() grouping()
{ {
emitter.emit_open_paren(); emitter.emit_open_paren(arena, code);
expression(); expression();
emitter.emit_close_paren(); emitter.emit_close_paren(arena, code);
consume(TOKEN_RPAREN); consume(TOKEN_RPAREN);
} }
void void
number() number()
{ {
emitter.emit_int(parser.previous.start, parser.previous.length); emitter.emit_int(arena, code, parser.previous.start, parser.previous.length);
} }
void void
string() string()
{ {
emitter.emit_str(parser.previous.start, parser.previous.length); emitter.emit_str(arena, code, parser.previous.start, parser.previous.length);
} }
void void
@ -771,10 +787,10 @@ unary()
switch(operatorType) { switch(operatorType) {
case TOKEN_MINUS: case TOKEN_MINUS:
emitter.emit_neg(); emitter.emit_neg(arena, code);
break; break;
case TOKEN_BANG: case TOKEN_BANG:
emitter.emit_not(); emitter.emit_not(arena, code);
break; break;
default: default:
return; return;
@ -895,18 +911,19 @@ emit_program(char *source)
init_lexer(source); init_lexer(source);
advance(); advance();
emitter.prolog(); emitter.prolog(arena, code);
emitter.epilogue(arena, memory);
while(!match(TOKEN_EOF)) declaration(); while(!match(TOKEN_EOF)) declaration();
emitter.epilogue();
} }
bool bool
compile(Arena *a, Emitter e, char *source) compile(Arena *a, List *c, List* m, Emitter e, char *source)
{ {
arena = a; arena = a;
emitter = e; emitter = e;
code = c;
memory = m;
parser.scopes = List_init(arena); parser.scopes = List_init(arena);
build_symbol_table(source); build_symbol_table(source);

View File

@ -42,15 +42,15 @@ struct parse_rule_s {
struct parser_s { struct parser_s {
Symbol *call_fn; Symbol *call_fn;
Scope *current_scope; Scope *current_scope;
u32 scope_idx;
List *scopes; List *scopes;
Token current; Token current;
Token previous; Token previous;
SymbolType current_type; SymbolType current_type;
u32 scope_idx;
u32 depth; u32 depth;
u8 pass; u8 pass;
}; };
bool compile(Arena *a, Emitter e, char *source); bool compile(Arena *a, List *c, List *m, Emitter e, char *source);
#endif #endif

11
emit.h
View File

@ -2,15 +2,16 @@
#define UNDAR_EMIT_H #define UNDAR_EMIT_H
#include "common.h" #include "common.h"
#include "strbuf.h"
#include "libc.h" #include "libc.h"
typedef u32 (*SymbolSize)(SymbolType t); typedef u32 (*SymbolSize)(SymbolType t);
typedef void (*SymbolEmit)(Symbol *sym);
typedef void (*ErrorMsg)(const char *str, i32 length, i32 line); typedef void (*ErrorMsg)(const char *str, i32 length, i32 line);
typedef void (*VoidArgEmit)(); typedef void (*SymbolEmit)(Arena *a, List *out, Symbol *sym);
typedef void (*StrArgEmit)(const char *str, i32 length); typedef void (*VoidArgEmit)(Arena *a, List *out);
typedef void (*VarEmit)(Symbol *sym, bool local); typedef void (*StrArgEmit)(Arena *a, List *out, const char *str, i32 length);
typedef void (*I32ArgEmit)(i32 val); typedef void (*VarEmit)(Arena *a, List *out, Symbol *sym, bool local);
typedef void (*I32ArgEmit)(Arena *a, List *out, i32 val);
typedef struct emitter_s Emitter; typedef struct emitter_s Emitter;
struct emitter_s { struct emitter_s {

View File

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

View File

@ -2,6 +2,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
char uxn_temp_strbuf[256];
#define UXN_OP_2 (1 << 5) #define UXN_OP_2 (1 << 5)
#define UXN_OP_R (1 << 6) #define UXN_OP_R (1 << 6)
#define UXN_OP_K (1 << 7) #define UXN_OP_K (1 << 7)
@ -44,7 +46,7 @@ enum uxn_opcode {
JMI = 0x40, JMI = 0x40,
JSI = 0x60, JSI = 0x60,
}; };
unsigned char emit_uxn_lib_undar_tal[] = { char emit_uxn_lib_undar_tal[] = {
0x40, 0x73, 0x65, 0x78, 0x74, 0x0a, 0x20, 0x20, 0x23, 0x38, 0x30, 0x20, 0x40, 0x73, 0x65, 0x78, 0x74, 0x0a, 0x20, 0x20, 0x23, 0x38, 0x30, 0x20,
0x41, 0x4e, 0x44, 0x6b, 0x20, 0x45, 0x51, 0x55, 0x20, 0x23, 0x66, 0x66, 0x41, 0x4e, 0x44, 0x6b, 0x20, 0x45, 0x51, 0x55, 0x20, 0x23, 0x66, 0x66,
0x20, 0x4d, 0x55, 0x4c, 0x20, 0x53, 0x57, 0x50, 0x20, 0x4a, 0x4d, 0x50, 0x20, 0x4d, 0x55, 0x4c, 0x20, 0x53, 0x57, 0x50, 0x20, 0x4a, 0x4d, 0x50,
@ -562,8 +564,7 @@ unsigned char emit_uxn_lib_undar_tal[] = {
0x49, 0x4e, 0x43, 0x32, 0x20, 0x21, 0x2f, 0x3c, 0x70, 0x72, 0x69, 0x6e, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x21, 0x2f, 0x3c, 0x70, 0x72, 0x69, 0x6e,
0x74, 0x3e, 0x0a, 0x0a, 0x40, 0x6d, 0x65, 0x6d, 0x5f, 0x6c, 0x65, 0x6e, 0x74, 0x3e, 0x0a, 0x0a, 0x40, 0x6d, 0x65, 0x6d, 0x5f, 0x6c, 0x65, 0x6e,
0x67, 0x74, 0x68, 0x5f, 0x20, 0x23, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x40, 0x67, 0x74, 0x68, 0x5f, 0x20, 0x23, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x40,
0x6d, 0x65, 0x6d, 0x5f, 0x20, 0x20, 0x20, 0x20 0x6d, 0x65, 0x6d, 0x5f, 0x20, 0x20, 0x20, 0x20};
};
unsigned int emit_uxn_lib_undar_tal_len = 6212; unsigned int emit_uxn_lib_undar_tal_len = 6212;
void void
@ -580,111 +581,114 @@ uxn_mem(u32 a)
} }
void void
uxn_prolog() uxn_prolog(Arena *a, List *out)
{ {
/*printf("|100\n\tLIT2r 0000 main_ POP2r BRK\n\n");*/ /*StrBuf_append(a, out, "|100\n\tLIT2r 0000 main_ POP2r BRK\n\n");*/
printf("|100\n\tLIT2r 0000\n\n"); StrBuf_append(a, out, "|100\n\tLIT2r 0000\n\n");
} }
void void
uxn_epilogue() uxn_epilogue(Arena *a, List *out)
{ {
for(u32 i = 0; i < emit_uxn_lib_undar_tal_len; i++) putchar(emit_uxn_lib_undar_tal[i]); StrBuf_append_exactly(a, out, emit_uxn_lib_undar_tal,
emit_uxn_lib_undar_tal_len);
} }
void void
uxn_emit_add() uxn_emit_add(Arena *a, List *out)
{ {
printf("ADD2 "); StrBuf_append(a, out, "ADD2 ");
} }
void void
uxn_emit_sub() uxn_emit_sub(Arena *a, List *out)
{ {
printf("SUB2 "); StrBuf_append(a, out, "SUB2 ");
} }
void void
uxn_emit_mul() uxn_emit_mul(Arena *a, List *out)
{ {
printf("MUL2 "); StrBuf_append(a, out, "MUL2 ");
} }
void void
uxn_emit_div() uxn_emit_div(Arena *a, List *out)
{ {
printf("DIV2 "); StrBuf_append(a, out, "DIV2 ");
} }
void void
uxn_emit_lt() uxn_emit_lt(Arena *a, List *out)
{ {
printf("LTH2 "); StrBuf_append(a, out, "LTH2 ");
} }
void void
uxn_emit_le() uxn_emit_le(Arena *a, List *out)
{ {
printf("ROT SWP LTH ?{ LTH #00 EQU JMPr } GTH JMPr "); StrBuf_append(a, out, "ROT SWP LTH ?{ LTH #00 EQU JMPr } GTH JMPr ");
} }
void void
uxn_emit_gt() uxn_emit_gt(Arena *a, List *out)
{ {
printf("GTH2 "); StrBuf_append(a, out, "GTH2 ");
} }
void void
uxn_emit_ge() uxn_emit_ge(Arena *a, List *out)
{ {
printf("ROT SWP GTH ?{ GTH #00 EQU JMPr } LTH JMPr "); StrBuf_append(a, out, "ROT SWP GTH ?{ GTH #00 EQU JMPr } LTH JMPr ");
} }
void void
uxn_emit_ne() uxn_emit_ne(Arena *a, List *out)
{ {
printf("NEQ2 "); StrBuf_append(a, out, "NEQ2 ");
} }
void void
uxn_emit_eq() uxn_emit_eq(Arena *a, List *out)
{ {
printf("EQU2 "); StrBuf_append(a, out, "EQU2 ");
} }
void void
uxn_emit_false() uxn_emit_false(Arena *a, List *out)
{ {
printf("#0000 "); StrBuf_append(a, out, "#0000 ");
} }
void void
uxn_emit_true() uxn_emit_true(Arena *a, List *out)
{ {
printf("#0001 "); StrBuf_append(a, out, "#0001 ");
} }
void void
uxn_emit_nil() uxn_emit_nil(Arena *a, List *out)
{ {
printf("#0000 "); StrBuf_append(a, out, "#0000 ");
} }
void void
uxn_emit_neg() uxn_emit_neg(Arena *a, List *out)
{ {
printf("#0000 SUB2 "); StrBuf_append(a, out, "#0000 SUB2 ");
} }
void void
uxn_emit_not() uxn_emit_not(Arena *a, List *out)
{ {
printf("#0000 EQU2 "); StrBuf_append(a, out, "#0000 EQU2 ");
} }
void void
uxn_emit_void() uxn_emit_void(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
u32 u32
@ -725,54 +729,65 @@ uxn_get_size(SymbolType t)
} }
void void
uxn_emit_type(Symbol *sym, bool local) uxn_emit_type(Arena *a, List *out, Symbol *sym, bool local)
{ {
if(local) if(local) {
if(sym->ref) if(sym->ref) {
printf("\tSTH2kr #%04x ADD2 LDA2\n", sym->ref); sprintf(uxn_temp_strbuf, "\tSTH2kr #%04x ADD2 LDA2\n", sym->ref);
else StrBuf_append(a, out, uxn_temp_strbuf);
printf("\tSTH2kr LDA2\n"); } else {
else sprintf(uxn_temp_strbuf, "\tSTH2kr LDA2\n");
printf("!{ @%.*s $%d } ", sym->name_length, sym->name, uxn_get_size(sym->type)); StrBuf_append(a, out, uxn_temp_strbuf);
}
} else {
sprintf(uxn_temp_strbuf, "!{ @%.*s $%d } ", sym->name_length, sym->name,
uxn_get_size(sym->type));
StrBuf_append(a, out, uxn_temp_strbuf);
}
} }
void void
uxn_emit_int(const char *str, i32 length) uxn_emit_int(Arena *a, List *out, const char *str, i32 length)
{ {
i32 i = (i32)strtol(str, nil, 10); i32 i = (i32)strtol(str, nil, 10);
printf("#%04x ", i); sprintf(uxn_temp_strbuf, "#%04x ", i);
StrBuf_append(a, out, uxn_temp_strbuf);
USED(length); USED(length);
} }
void void
uxn_emit_nat(const char *str, i32 length) uxn_emit_nat(Arena *a, List *out, const char *str, i32 length)
{ {
u32 i = (u32)strtol(str, nil, 10); u32 i = (u32)strtol(str, nil, 10);
printf("#%04x ", i); sprintf(uxn_temp_strbuf, "#%04x ", i);
StrBuf_append(a, out, uxn_temp_strbuf);
USED(length); USED(length);
} }
void void
uxn_emit_real(const char *str, i32 length) uxn_emit_real(Arena *a, List *out, const char *str, i32 length)
{ {
USED(a);
USED(out);
USED(str); USED(str);
USED(length); USED(length);
/// TODO: implement this /// TODO: implement this
} }
void void
uxn_emit_byte(const char *str, i32 length) uxn_emit_byte(Arena *a, List *out, const char *str, i32 length)
{ {
u8 i = (u8)strtol(str, nil, 10); u8 i = (u8)strtol(str, nil, 10);
printf("#%04x ", i); sprintf(uxn_temp_strbuf, "#%04x ", i);
StrBuf_append(a, out, uxn_temp_strbuf);
USED(length); USED(length);
} }
void void
uxn_emit_str(const char *str, i32 length) uxn_emit_str(Arena *a, List *out, const char *str, i32 length)
{ {
/* set a pointer to the string literal and then jump over it */ /* set a pointer to the string literal and then jump over it */
printf(";{ #0002 ADD2 } !{ "); StrBuf_append(a, out, ";{ #0002 ADD2 } !{ ");
i32 i = 1; i32 i = 1;
while(i < length - 1) { while(i < length - 1) {
@ -796,356 +811,435 @@ uxn_emit_str(const char *str, i32 length)
i--; /* Rewind for unknown escapes */ i--; /* Rewind for unknown escapes */
} }
} }
printf("%02x ", c); sprintf(uxn_temp_strbuf, "%02x ", c);
StrBuf_append(a, out, uxn_temp_strbuf);
} }
printf("00 } "); StrBuf_append(a, out, "00 } ");
} }
void void
uxn_emit_constant(Symbol *sym, bool local) uxn_emit_constant(Arena *a, List *out, Symbol *sym, bool local)
{ {
if(local) if(local) {
if(sym->ref) if(sym->ref) {
printf("\tSTH2kr #%04x ADD2 STA2\n", sym->ref); sprintf(uxn_temp_strbuf, "\tSTH2kr #%04x ADD2 STA2\n", sym->ref);
else StrBuf_append(a, out, uxn_temp_strbuf);
printf("\tSTH2kr STA2\n"); } else {
else sprintf(uxn_temp_strbuf, "\tSTH2kr STA2\n");
printf(";%.*s STA2 ", sym->name_length, sym->name); StrBuf_append(a, out, uxn_temp_strbuf);
}
} else {
sprintf(uxn_temp_strbuf, ";%.*s STA2 ", sym->name_length, sym->name);
StrBuf_append(a, out, uxn_temp_strbuf);
}
} }
void void
uxn_emit_array() uxn_emit_array(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
bool bool
fn_loop_emit_args(void *data) fn_loop_emit_args(Arena *a, List *out, void *data)
{ {
Symbol *sym = ((Symbol *)data); Symbol *sym = ((Symbol *)data);
if(sym->ref) if(sym->ref) {
printf("\tSTH2kr #%04x ADD2 STA2\n", sym->ref); sprintf(uxn_temp_strbuf, "\tSTH2kr #%04x ADD2 STA2\n", sym->ref);
else StrBuf_append(a, out, uxn_temp_strbuf);
printf("\tSTH2kr STA2\n"); } else {
sprintf(uxn_temp_strbuf, "\tSTH2kr STA2\n");
StrBuf_append(a, out, uxn_temp_strbuf);
}
return true; return true;
} }
bool bool
fn_loop_emit_args_comment(void *data) fn_loop_emit_args_comment(Arena *a, List *out, void *data)
{ {
Symbol *sym = ((Symbol *)data); Symbol *sym = ((Symbol *)data);
printf("%.*s ", sym->name_length, sym->name); sprintf(uxn_temp_strbuf, "%.*s ", sym->name_length, sym->name);
StrBuf_append(a, out, uxn_temp_strbuf);
return true; return true;
} }
void void
uxn_emit_function(Symbol *sym) uxn_emit_function(Arena *a, List *out, Symbol *sym)
{ {
printf("@%.*s_ ( ", sym->name_length, sym->name); sprintf(uxn_temp_strbuf, "@%.*s_ ( ", sym->name_length, sym->name);
List_map(sym->args, fn_loop_emit_args_comment); StrBuf_append(a, out, uxn_temp_strbuf);
printf(" -- "); List_map_out(a, out, sym->args, fn_loop_emit_args_comment);
sprintf(uxn_temp_strbuf, " -- ");
StrBuf_append(a, out, uxn_temp_strbuf);
if(sym->secondary_type != SYMBOL_UNDEFINED && if(sym->secondary_type != SYMBOL_UNDEFINED &&
sym->secondary_type != SYMBOL_VOID) sym->secondary_type != SYMBOL_VOID) {
printf(" res "); sprintf(uxn_temp_strbuf, " res ");
printf(")\n"); StrBuf_append(a, out, uxn_temp_strbuf);
if (sym->size > 0) }
printf("\tOVR2r LIT2r %04x SUB2r\n", sym->size); sprintf(uxn_temp_strbuf, ")\n");
List_map(sym->args, fn_loop_emit_args); StrBuf_append(a, out, uxn_temp_strbuf);
printf("\n"); if(sym->size > 0) {
sprintf(uxn_temp_strbuf, "\tOVR2r LIT2r %04x SUB2r\n", sym->size);
StrBuf_append(a, out, uxn_temp_strbuf);
}
List_map_out(a, out, sym->args, fn_loop_emit_args);
StrBuf_append(a, out, "\n");
} }
void void
uxn_emit_arena_fn_return() uxn_emit_arena_fn_return(Arena *a, List *out)
{ {
printf("\t&return\n\t\tPOP2r JMP2r\n\n"); StrBuf_append(a, out, "\t&return\n\t\tPOP2r JMP2r\n\n");
} }
void void
uxn_emit_arena_fn_call(Symbol *sym) uxn_emit_arena_fn_call(Arena *a, List *out, Symbol *sym)
{ {
printf("%.*s_ ", sym->name_length, sym->name); sprintf(uxn_temp_strbuf, "%.*s_ ", sym->name_length, sym->name);
StrBuf_append(a, out, uxn_temp_strbuf);
} }
void void
uxn_emit_plex() uxn_emit_plex(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_method() uxn_emit_method(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_trait() uxn_emit_trait(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_const() uxn_emit_const(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_open_paren() uxn_emit_open_paren(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_close_paren() uxn_emit_close_paren(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_variable(Symbol *sym, bool local) uxn_emit_variable(Arena *a, List *out, Symbol *sym, bool local)
{ {
if(local) if(local) {
if(sym->ref) if(sym->ref) {
printf("\tSTH2kr #%04x ADD2 LDA2 ", sym->ref); sprintf(uxn_temp_strbuf, "\tSTH2kr #%04x ADD2 LDA2 ", sym->ref);
else StrBuf_append(a, out, uxn_temp_strbuf);
printf("\tSTH2kr LDA2 "); } else {
else sprintf(uxn_temp_strbuf, "\tSTH2kr LDA2 ");
printf(";%.*s LDA2 ", sym->name_length, sym->name); StrBuf_append(a, out, uxn_temp_strbuf);
}
} else {
sprintf(uxn_temp_strbuf, ";%.*s LDA2 ", sym->name_length, sym->name);
StrBuf_append(a, out, uxn_temp_strbuf);
}
} }
void void
uxn_emit_set_variable(Symbol *sym, bool local) uxn_emit_set_variable(Arena *a, List *out, Symbol *sym, bool local)
{ {
if(local) if(local) {
if(sym->ref) if(sym->ref) {
printf("\tSTH2kr #%04x ADD2 STA2 ", sym->ref); sprintf(uxn_temp_strbuf, "\tSTH2kr #%04x ADD2 STA2 ", sym->ref);
else StrBuf_append(a, out, uxn_temp_strbuf);
printf("\tSTH2kr STA2 "); } else {
else sprintf(uxn_temp_strbuf, "\tSTH2kr STA2 ");
printf(";%.*s STA2 ", sym->name_length, sym->name); StrBuf_append(a, out, uxn_temp_strbuf);
}
} else {
sprintf(uxn_temp_strbuf, ";%.*s STA2 ", sym->name_length, sym->name);
StrBuf_append(a, out, uxn_temp_strbuf);
}
} }
void void
uxn_emit_write() uxn_emit_write(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_read() uxn_emit_read(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_open() uxn_emit_open(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_close() uxn_emit_close(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_stat() uxn_emit_stat(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_end_statement() uxn_emit_end_statement(Arena *a, List *out)
{ {
printf("\n"); StrBuf_append(a, out, "\n");
} }
void void
uxn_emit_set_value() uxn_emit_set_value(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_plex_def() uxn_emit_plex_def(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_cast_int_to_nat() uxn_emit_cast_int_to_nat(Arena *a, List *out)
{ {
printf("int_to_nat_ "); StrBuf_append(a, out, "int_to_nat_ ");
} }
void void
uxn_emit_cast_int_to_real() uxn_emit_cast_int_to_real(Arena *a, List *out)
{ {
printf("int_to_real_ "); StrBuf_append(a, out, "int_to_real_ ");
} }
void void
uxn_emit_cast_int_to_str() uxn_emit_cast_int_to_str(Arena *a, List *out)
{ {
printf("int_to_str_ "); StrBuf_append(a, out, "int_to_str_ ");
} }
void void
uxn_emit_cast_nat_to_int() uxn_emit_cast_nat_to_int(Arena *a, List *out)
{ {
printf("nat_to_int_ "); StrBuf_append(a, out, "nat_to_int_ ");
} }
void void
uxn_emit_cast_nat_to_real() uxn_emit_cast_nat_to_real(Arena *a, List *out)
{ {
printf("nat_to_real_ "); StrBuf_append(a, out, "nat_to_real_ ");
} }
void void
uxn_emit_cast_nat_to_str() uxn_emit_cast_nat_to_str(Arena *a, List *out)
{ {
printf("nat_to_str_ "); StrBuf_append(a, out, "nat_to_str_ ");
} }
void void
uxn_emit_cast_real_to_int() uxn_emit_cast_real_to_int(Arena *a, List *out)
{ {
printf("real_to_int_ "); StrBuf_append(a, out, "real_to_int_ ");
} }
void void
uxn_emit_cast_real_to_nat() uxn_emit_cast_real_to_nat(Arena *a, List *out)
{ {
printf("real_to_nat_ "); StrBuf_append(a, out, "real_to_nat_ ");
} }
void void
uxn_emit_cast_real_to_str() uxn_emit_cast_real_to_str(Arena *a, List *out)
{ {
printf("real_to_str_ "); StrBuf_append(a, out, "real_to_str_ ");
} }
void void
uxn_emit_strbuf_init() uxn_emit_strbuf_init(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_strbuf_append() uxn_emit_strbuf_append(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_strbuf_to_str() uxn_emit_strbuf_to_str(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_arena_fn_return_plex() uxn_emit_arena_fn_return_plex(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_arena_fn_return_array() uxn_emit_arena_fn_return_array(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_arena_fn_return_strbuf() uxn_emit_arena_fn_return_strbuf(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_cast_str_to_int() uxn_emit_cast_str_to_int(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_cast_str_to_nat() uxn_emit_cast_str_to_nat(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_cast_str_to_real() uxn_emit_cast_str_to_real(Arena *a, List *out)
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_sll() uxn_emit_sll(Arena *a, List *out)
{ {
printf("#40 SFT SFT "); StrBuf_append(a, out, "#40 SFT SFT ");
} }
void void
uxn_emit_srl() uxn_emit_srl(Arena *a, List *out)
{ {
printf("SFT "); StrBuf_append(a, out, "SFT ");
} }
void void
uxn_emit_xor() uxn_emit_xor(Arena *a, List *out)
{ {
printf("EOR2 "); StrBuf_append(a, out, "EOR2 ");
} }
void void
uxn_emit_mod() uxn_emit_mod(Arena *a, List *out)
{ {
printf("DIV2k MUL2 SUB2 "); StrBuf_append(a, out, "DIV2k MUL2 SUB2 ");
} }
void void
uxn_emit_or() uxn_emit_or(Arena *a, List *out)
{ {
printf("ORA2 "); StrBuf_append(a, out, "ORA2 ");
} }
void void
uxn_emit_and() uxn_emit_and(Arena *a, List *out)
{ {
printf("AND2 "); StrBuf_append(a, out, "AND2 ");
} }
void void
uxn_emit_print() uxn_emit_print(Arena *a, List *out)
{ {
printf("str/<print> "); StrBuf_append(a, out, "str/<print> ");
} }
void void
uxn_emit_if() uxn_emit_if(Arena *a, List *out)
{ {
printf("#03 JCN !{ \n"); StrBuf_append(a, out, "#03 JCN !{ \n");
} }
void void
uxn_emit_patch_if(i32 local_ifs) uxn_emit_patch_if(Arena *a, List *out, i32 local_ifs)
{ {
printf("!&if_end.%d } ", local_ifs); sprintf(uxn_temp_strbuf, "!&if_end.%d } ", local_ifs);
StrBuf_append(a, out, uxn_temp_strbuf);
} }
void void
uxn_emit_patch_if_done(i32 local_ifs) uxn_emit_patch_if_done(Arena *a, List *out, i32 local_ifs)
{ {
printf("&if_end.%d \n", local_ifs); sprintf(uxn_temp_strbuf, "&if_end.%d \n", local_ifs);
StrBuf_append(a, out, uxn_temp_strbuf);
} }
void void
uxn_emit_while(i32 local_whiles) uxn_emit_while(Arena *a, List *out, i32 local_whiles)
{ {
printf("&while.%d ", local_whiles); sprintf(uxn_temp_strbuf, "&while.%d ", local_whiles);
StrBuf_append(a, out, uxn_temp_strbuf);
} }
void void
uxn_emit_while_postfix() uxn_emit_while_postfix(Arena *a, List *out)
{ {
printf("#03 JCN !{ \n"); StrBuf_append(a, out, "#03 JCN !{ \n");
} }
void void
uxn_emit_patch_while(i32 local_whiles) uxn_emit_patch_while(Arena *a, List *out, i32 local_whiles)
{ {
printf("!&while.%d } \n", local_whiles); sprintf(uxn_temp_strbuf, "!&while.%d } \n", local_whiles);
StrBuf_append(a, out, uxn_temp_strbuf);
} }
void void
uxn_emit_early_return() uxn_emit_early_return(Arena *a, List *out)
{ {
printf("!&return "); StrBuf_append(a, out, "!&return ");
} }
void void
uxn_emit_halt() uxn_emit_halt(Arena *a, List *out)
{ {
printf("POP2r BRK "); StrBuf_append(a, out, "POP2r BRK ");
} }
Emitter Emitter

13
list.c
View File

@ -59,6 +59,19 @@ List_map(List *list, list_iter_fn func)
} }
} }
void
List_map_out(Arena *a, List *out, List *list, list_iter_out_fn func)
{
Node *curr;
if(!list || !func) return;
curr = list->head;
while(curr) {
if(!func(a, out, node_value(curr))) break;
curr = curr->next;
}
}
void * void *
List_get(List *list, u32 index) List_get(List *list, u32 index)
{ {

2
list.h
View File

@ -18,11 +18,13 @@ struct list_s {
typedef bool (*compare_fn)(void *data, void *target); typedef bool (*compare_fn)(void *data, void *target);
typedef bool (*list_iter_fn)(void *data); typedef bool (*list_iter_fn)(void *data);
typedef bool (*list_iter_out_fn)(Arena *a, List *out, void *data);
List *List_init(Arena *arena); List *List_init(Arena *arena);
void *node_value(Node *n); void *node_value(Node *n);
void *List_push(Arena *arena, List *list, void *data, u32 data_size); void *List_push(Arena *arena, List *list, void *data, u32 data_size);
void List_map(List *list, list_iter_fn func); void List_map(List *list, list_iter_fn func);
void List_map_out(Arena *a, List *out, List *list, list_iter_out_fn func);
void *List_find(List *list, compare_fn compare, void *target); void *List_find(List *list, compare_fn compare, void *target);
void *List_get(List *list, u32 index); void *List_get(List *list, u32 index);
void List_set(List *list, u32 index, void *data, u32 size); void List_set(List *list, u32 index, void *data, u32 size);

View File

@ -1,9 +1,9 @@
#include "strbuf.h" #include "strbuf.h"
StrBuf * List *
StrBuf_init(Arena *a) StrBuf_init(Arena *a)
{ {
StrBuf *l = (StrBuf*)aalloc(a, sizeof(StrBuf)); List *l = (List*)aalloc(a, sizeof(List));
if (!l) return nil; if (!l) return nil;
l->head = nil; l->head = nil;
@ -14,10 +14,8 @@ StrBuf_init(Arena *a)
} }
void * void *
StrBuf_append(Arena *a, StrBuf *buf, char *str) StrBuf_append_exactly(Arena *a, List *buf, char *str, u32 length)
{ {
u32 length = slen(str);
void *dest; void *dest;
void *ptr = aalloc(a, sizeof(Node) + length); void *ptr = aalloc(a, sizeof(Node) + length);
Node *node = (Node *)ptr; Node *node = (Node *)ptr;
@ -44,8 +42,14 @@ StrBuf_append(Arena *a, StrBuf *buf, char *str)
return dest; return dest;
} }
void *
StrBuf_append(Arena *a, List *buf, char *str)
{
return StrBuf_append_exactly(a, buf, str, slen(str));
}
char * char *
StrBuf_toS(Arena *a, StrBuf *buf, u32 *out_length) StrBuf_toS(Arena *a, List *buf, u32 *out_length)
{ {
Node *curr; Node *curr;
char *tmp_str; char *tmp_str;

View File

@ -3,15 +3,9 @@
#include "list.h" #include "list.h"
typedef struct strbuf_s StrBuf; List *StrBuf_init(Arena *a);
struct strbuf_s { void *StrBuf_append(Arena *a, List *buf, char *str);
Node *head; void *StrBuf_append_exactly(Arena *a, List *buf, char *str, u32 length);
Node *tail; char *StrBuf_toS(Arena *a, List *buf, u32 *out_length);
u32 count;
};
StrBuf *StrBuf_init(Arena *a);
void *StrBuf_append(Arena *a, StrBuf *buf, char *str);
char *StrBuf_toS(Arena *a, StrBuf *buf, u32 *out_length);
#endif #endif