Compare commits

..

No commits in common. "f8008e81d5f9a98323015edad44cdff9d12800f9" and "1ec9f7a2d1a0ffd4d5b9b340bc3945b92118d658" have entirely different histories.

10 changed files with 1040 additions and 1404 deletions

View File

@ -1,7 +1,6 @@
#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)
@ -40,7 +39,7 @@ print_help()
"output, currently Uxn tal code and Reality Engine rom.\n\n"); "output, currently Uxn tal code and Reality Engine rom.\n\n");
} }
#define MEM_SIZE (1 << 16) #define MEM_SIZE 64000
int int
main(int argc, char **argv) main(int argc, char **argv)
@ -68,28 +67,10 @@ 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, code, memory, e, source); compile(&a, 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,8 +8,6 @@
Emitter emitter = {0}; Emitter emitter = {0};
Parser parser = {0}; Parser parser = {0};
Arena *arena; Arena *arena;
List *code;
List *memory;
/**************************************************** /****************************************************
* Scope * Scope
@ -361,20 +359,6 @@ ParseRule *get_rule(TokenType type);
void parse_precedence(Precedence precedence); void parse_precedence(Precedence precedence);
/**
FIXME: we need to move the string to be on the heap instead of the stack
so we need special handling in variable_dec
During the first pass we need to append the string label @variable
and then the hexed out literal.
every time we reference the string we should reference the global ptr.
If the string gets appended then we should copy and use the local varaiable
but for string conts or array conts we should use the global ref '@'
*/
u32 u32
variable_declaration(Symbol *def) variable_declaration(Symbol *def)
{ {
@ -382,33 +366,11 @@ variable_declaration(Symbol *def)
TokenType tt = parser.previous.type; TokenType tt = parser.previous.type;
SymbolType st = token_type_to_sym_type(tt); SymbolType st = token_type_to_sym_type(tt);
Symbol *variable; Symbol *variable;
List *array_literal;
if (parser.current.type == TOKEN_LBRACE) { if (parser.current.type == TOKEN_LBRACE) {
while(!check(TOKEN_RBRACKET)) { while(!check(TOKEN_RBRACKET)) {
advance(); advance();
} }
variable = scope_get_symbol(parser.current_scope,
parser.previous.start,
parser.previous.length);
if (match(TOKEN_EQ)) {
expect(TOKEN_LBRACKET);
while (!match(TOKEN_RBRACKET)) {
StrBuf_append_exactly(arena, array_literal,
(char*)parser.previous.start,
parser.previous.length);
if(match(TOKEN_RBRACKET)) break;
expect(TOKEN_COMMA);
}
}
expect(TOKEN_SEMICOLON);
emitter.emit_array(arena, memory, variable, array_literal);
return variable->size;
} }
if(st != SYMBOL_UNDEFINED) { if(st != SYMBOL_UNDEFINED) {
@ -421,7 +383,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(arena, code, variable, parser.depth); emitter.emit_type(variable, parser.depth);
parser.current_type = st; parser.current_type = st;
} }
} else { } else {
@ -438,13 +400,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(arena, code); emitter.emit_set_value();
expression(); expression();
emitter.emit_constant(arena, code, variable, parser.depth); emitter.emit_constant(variable, parser.depth);
} }
consume(TOKEN_SEMICOLON); consume(TOKEN_SEMICOLON);
emitter.emit_end_statement(arena, code); emitter.emit_end_statement();
parser.current_type = SYMBOL_UNDEFINED; parser.current_type = SYMBOL_UNDEFINED;
return size; return size;
} }
@ -459,52 +421,52 @@ binary()
switch(operatorType) { switch(operatorType) {
case TOKEN_BANG_EQ: case TOKEN_BANG_EQ:
emitter.emit_ne(arena, code); emitter.emit_ne();
break; break;
case TOKEN_EQ_EQ: case TOKEN_EQ_EQ:
emitter.emit_eq(arena, code); emitter.emit_eq();
break; break;
case TOKEN_GT: case TOKEN_GT:
emitter.emit_gt(arena, code); emitter.emit_gt();
break; break;
case TOKEN_GTE: case TOKEN_GTE:
emitter.emit_ge(arena, code); emitter.emit_ge();
break; break;
case TOKEN_LT: case TOKEN_LT:
emitter.emit_lt(arena, code); emitter.emit_lt();
break; break;
case TOKEN_LTE: case TOKEN_LTE:
emitter.emit_le(arena, code); emitter.emit_le();
break; break;
case TOKEN_PLUS: case TOKEN_PLUS:
emitter.emit_add(arena, code); emitter.emit_add();
break; break;
case TOKEN_MINUS: case TOKEN_MINUS:
emitter.emit_sub(arena, code); emitter.emit_sub();
break; break;
case TOKEN_STAR: case TOKEN_STAR:
emitter.emit_mul(arena, code); emitter.emit_mul();
break; break;
case TOKEN_SLASH: case TOKEN_SLASH:
emitter.emit_div(arena, code); emitter.emit_div();
break; break;
case TOKEN_OPERATOR_AND: case TOKEN_OPERATOR_AND:
emitter.emit_and(arena, code); emitter.emit_and();
break; break;
case TOKEN_OPERATOR_OR: case TOKEN_OPERATOR_OR:
emitter.emit_or(arena, code); emitter.emit_or();
break; break;
case TOKEN_OPERATOR_XOR: case TOKEN_OPERATOR_XOR:
emitter.emit_xor(arena, code); emitter.emit_xor();
break; break;
case TOKEN_OPERATOR_MOD: case TOKEN_OPERATOR_MOD:
emitter.emit_mod(arena, code); emitter.emit_mod();
break; break;
case TOKEN_SLL: case TOKEN_SLL:
emitter.emit_sll(arena, code); emitter.emit_sll();
break; break;
case TOKEN_SRL: case TOKEN_SRL:
emitter.emit_srl(arena, code); emitter.emit_srl();
break; break;
default: default:
return; return;
@ -516,13 +478,13 @@ literal()
{ {
switch(parser.previous.type) { switch(parser.previous.type) {
case TOKEN_KEYWORD_FALSE: case TOKEN_KEYWORD_FALSE:
emitter.emit_false(arena, code); emitter.emit_false();
break; break;
case TOKEN_KEYWORD_TRUE: case TOKEN_KEYWORD_TRUE:
emitter.emit_true(arena, code); emitter.emit_true();
break; break;
case TOKEN_KEYWORD_NIL: case TOKEN_KEYWORD_NIL:
emitter.emit_nil(arena, code); emitter.emit_nil();
break; break;
default: default:
return; return;
@ -553,9 +515,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(arena, code, sym, sym->scope); emitter.emit_set_variable(sym, sym->scope);
} else { } else {
emitter.emit_variable(arena, code, sym, sym->scope); emitter.emit_variable(sym, sym->scope);
} }
} }
@ -577,15 +539,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(arena, code); emitter.emit_cast_int_to_nat();
break; break;
} }
case TOKEN_TYPE_REAL: { case TOKEN_TYPE_REAL: {
emitter.emit_cast_int_to_real(arena, code); emitter.emit_cast_int_to_real();
break; break;
} }
case TOKEN_TYPE_STR: { case TOKEN_TYPE_STR: {
emitter.emit_cast_int_to_str(arena, code); emitter.emit_cast_int_to_str();
break; break;
} }
default: default:
@ -597,15 +559,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(arena, code); emitter.emit_cast_nat_to_int();
break; break;
} }
case TOKEN_TYPE_REAL: { case TOKEN_TYPE_REAL: {
emitter.emit_cast_nat_to_real(arena, code); emitter.emit_cast_nat_to_real();
break; break;
} }
case TOKEN_TYPE_STR: { case TOKEN_TYPE_STR: {
emitter.emit_cast_nat_to_str(arena, code); emitter.emit_cast_nat_to_str();
break; break;
} }
default: default:
@ -616,15 +578,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(arena, code); emitter.emit_cast_real_to_nat();
break; break;
} }
case TOKEN_TYPE_INT: { case TOKEN_TYPE_INT: {
emitter.emit_cast_real_to_int(arena, code); emitter.emit_cast_real_to_int();
break; break;
} }
case TOKEN_TYPE_STR: { case TOKEN_TYPE_STR: {
emitter.emit_cast_real_to_str(arena, code); emitter.emit_cast_real_to_str();
break; break;
} }
default: default:
@ -635,15 +597,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(arena, code); emitter.emit_cast_str_to_nat();
break; break;
} }
case TOKEN_TYPE_REAL: { case TOKEN_TYPE_REAL: {
emitter.emit_cast_str_to_real(arena, code); emitter.emit_cast_str_to_real();
break; break;
} }
case TOKEN_TYPE_INT: { case TOKEN_TYPE_INT: {
emitter.emit_cast_str_to_int(arena, code); emitter.emit_cast_str_to_int();
break; break;
} }
default: default:
@ -670,8 +632,8 @@ print_statement()
{ {
expression(); expression();
consume(TOKEN_SEMICOLON); consume(TOKEN_SEMICOLON);
emitter.emit_print(arena, code); emitter.emit_print();
emitter.emit_end_statement(arena, code); emitter.emit_end_statement();
} }
void void
@ -680,28 +642,28 @@ if_statement()
consume(TOKEN_LPAREN); consume(TOKEN_LPAREN);
expression(); expression();
consume(TOKEN_RPAREN); consume(TOKEN_RPAREN);
emitter.emit_if(arena, code); emitter.emit_if();
statement(); statement();
emitter.emit_patch_if(arena, code, emitter.ifs); emitter.emit_patch_if(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(arena, code, emitter.ifs++); if(emitter.else_if_depth == 0) emitter.emit_patch_if_done(emitter.ifs++);
} }
void void
while_statement() while_statement()
{ {
emitter.emit_while(arena, code, emitter.loops); emitter.emit_while(emitter.loops);
consume(TOKEN_LPAREN); consume(TOKEN_LPAREN);
expression(); expression();
consume(TOKEN_RPAREN); consume(TOKEN_RPAREN);
emitter.emit_while_postfix(arena, code); emitter.emit_while_postfix();
statement(); statement();
emitter.emit_patch_while(arena, code, emitter.loops++); emitter.emit_patch_while(emitter.loops++);
} }
void void
@ -717,13 +679,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(arena, code, sym); emitter.emit_function(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(arena, code); emitter.emit_arena_fn_return();
} }
void void
@ -736,7 +698,7 @@ call()
} }
consume(TOKEN_RPAREN); consume(TOKEN_RPAREN);
emitter.emit_arena_fn_call(arena, code, parser.call_fn); emitter.emit_arena_fn_call(parser.call_fn);
parser.current_type = parser.call_fn->secondary_type; parser.current_type = parser.call_fn->secondary_type;
return; return;
} }
@ -745,11 +707,11 @@ void
return_statement() return_statement()
{ {
if(match(TOKEN_SEMICOLON)) { if(match(TOKEN_SEMICOLON)) {
emitter.emit_early_return(arena, code); emitter.emit_early_return();
} else { } else {
expression(); expression();
consume(TOKEN_SEMICOLON); consume(TOKEN_SEMICOLON);
emitter.emit_early_return(arena, code); emitter.emit_early_return();
} }
} }
@ -772,7 +734,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(arena, code); emitter.emit_halt();
} else { } else {
expression(); expression();
} }
@ -781,24 +743,24 @@ statement()
void void
grouping() grouping()
{ {
emitter.emit_open_paren(arena, code); emitter.emit_open_paren();
expression(); expression();
emitter.emit_close_paren(arena, code); emitter.emit_close_paren();
consume(TOKEN_RPAREN); consume(TOKEN_RPAREN);
} }
void void
number() number()
{ {
emitter.emit_int(arena, code, parser.previous.start, parser.previous.length); emitter.emit_int(parser.previous.start, parser.previous.length);
} }
void void
string() string()
{ {
emitter.emit_str(arena, code, parser.previous.start, parser.previous.length); emitter.emit_str(parser.previous.start, parser.previous.length);
} }
void void
@ -809,10 +771,10 @@ unary()
switch(operatorType) { switch(operatorType) {
case TOKEN_MINUS: case TOKEN_MINUS:
emitter.emit_neg(arena, code); emitter.emit_neg();
break; break;
case TOKEN_BANG: case TOKEN_BANG:
emitter.emit_not(arena, code); emitter.emit_not();
break; break;
default: default:
return; return;
@ -933,19 +895,18 @@ emit_program(char *source)
init_lexer(source); init_lexer(source);
advance(); advance();
emitter.prolog(arena, code); emitter.prolog();
emitter.epilogue(arena, memory);
while(!match(TOKEN_EOF)) declaration(); while(!match(TOKEN_EOF)) declaration();
emitter.epilogue();
} }
bool bool
compile(Arena *a, List *c, List* m, Emitter e, char *source) compile(Arena *a, 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, List *c, List *m, Emitter e, char *source); bool compile(Arena *a, Emitter e, char *source);
#endif #endif

14
emit.h
View File

@ -2,17 +2,15 @@
#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 (*SymbolEmit)(Arena *a, List *out, Symbol *sym); typedef void (*VoidArgEmit)();
typedef void (*VoidArgEmit)(Arena *a, List *out); typedef void (*StrArgEmit)(const char *str, i32 length);
typedef void (*StrArgEmit)(Arena *a, List *out, const char *str, i32 length); typedef void (*VarEmit)(Symbol *sym, bool local);
typedef void (*VarEmit)(Arena *a, List *out, Symbol *sym, bool local); typedef void (*I32ArgEmit)(i32 val);
typedef void (*MultipleEmit)(Arena *a, List *out, Symbol *sym, List* in);
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 {
@ -44,7 +42,7 @@ struct emitter_s {
StrArgEmit emit_byte; StrArgEmit emit_byte;
StrArgEmit emit_str; StrArgEmit emit_str;
VarEmit emit_type; VarEmit emit_type;
MultipleEmit emit_array; VoidArgEmit emit_array;
SymbolEmit emit_function; SymbolEmit emit_function;
VoidArgEmit emit_plex; VoidArgEmit emit_plex;
VoidArgEmit emit_method; VoidArgEmit emit_method;

View File

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

View File

@ -2,8 +2,6 @@
#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)
@ -46,7 +44,7 @@ enum uxn_opcode {
JMI = 0x40, JMI = 0x40,
JSI = 0x60, JSI = 0x60,
}; };
char emit_uxn_lib_undar_tal[] = { unsigned 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,
@ -564,7 +562,8 @@ 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
@ -581,114 +580,111 @@ uxn_mem(u32 a)
} }
void void
uxn_prolog(Arena *a, List *out) uxn_prolog()
{ {
/*StrBuf_append(a, out, "|100\n\tLIT2r 0000 main_ POP2r BRK\n\n");*/ /*printf("|100\n\tLIT2r 0000 main_ POP2r BRK\n\n");*/
StrBuf_append(a, out, "|100\n\tLIT2r 0000\n\n"); printf("|100\n\tLIT2r 0000\n\n");
} }
void void
uxn_epilogue(Arena *a, List *out) uxn_epilogue()
{ {
StrBuf_append_exactly(a, out, emit_uxn_lib_undar_tal, for(u32 i = 0; i < emit_uxn_lib_undar_tal_len; i++) putchar(emit_uxn_lib_undar_tal[i]);
emit_uxn_lib_undar_tal_len);
} }
void void
uxn_emit_add(Arena *a, List *out) uxn_emit_add()
{ {
StrBuf_append(a, out, "ADD2 "); printf("ADD2 ");
} }
void void
uxn_emit_sub(Arena *a, List *out) uxn_emit_sub()
{ {
StrBuf_append(a, out, "SUB2 "); printf("SUB2 ");
} }
void void
uxn_emit_mul(Arena *a, List *out) uxn_emit_mul()
{ {
StrBuf_append(a, out, "MUL2 "); printf("MUL2 ");
} }
void void
uxn_emit_div(Arena *a, List *out) uxn_emit_div()
{ {
StrBuf_append(a, out, "DIV2 "); printf("DIV2 ");
} }
void void
uxn_emit_lt(Arena *a, List *out) uxn_emit_lt()
{ {
StrBuf_append(a, out, "LTH2 "); printf("LTH2 ");
} }
void void
uxn_emit_le(Arena *a, List *out) uxn_emit_le()
{ {
StrBuf_append(a, out, "ROT SWP LTH ?{ LTH #00 EQU JMPr } GTH JMPr "); printf("ROT SWP LTH ?{ LTH #00 EQU JMPr } GTH JMPr ");
} }
void void
uxn_emit_gt(Arena *a, List *out) uxn_emit_gt()
{ {
StrBuf_append(a, out, "GTH2 "); printf("GTH2 ");
} }
void void
uxn_emit_ge(Arena *a, List *out) uxn_emit_ge()
{ {
StrBuf_append(a, out, "ROT SWP GTH ?{ GTH #00 EQU JMPr } LTH JMPr "); printf("ROT SWP GTH ?{ GTH #00 EQU JMPr } LTH JMPr ");
} }
void void
uxn_emit_ne(Arena *a, List *out) uxn_emit_ne()
{ {
StrBuf_append(a, out, "NEQ2 "); printf("NEQ2 ");
} }
void void
uxn_emit_eq(Arena *a, List *out) uxn_emit_eq()
{ {
StrBuf_append(a, out, "EQU2 "); printf("EQU2 ");
} }
void void
uxn_emit_false(Arena *a, List *out) uxn_emit_false()
{ {
StrBuf_append(a, out, "#0000 "); printf("#0000 ");
} }
void void
uxn_emit_true(Arena *a, List *out) uxn_emit_true()
{ {
StrBuf_append(a, out, "#0001 "); printf("#0001 ");
} }
void void
uxn_emit_nil(Arena *a, List *out) uxn_emit_nil()
{ {
StrBuf_append(a, out, "#0000 "); printf("#0000 ");
} }
void void
uxn_emit_neg(Arena *a, List *out) uxn_emit_neg()
{ {
StrBuf_append(a, out, "#0000 SUB2 "); printf("#0000 SUB2 ");
} }
void void
uxn_emit_not(Arena *a, List *out) uxn_emit_not()
{ {
StrBuf_append(a, out, "#0000 EQU2 "); printf("#0000 EQU2 ");
} }
void void
uxn_emit_void(Arena *a, List *out) uxn_emit_void()
{ {
USED(a);
USED(out);
} }
u32 u32
@ -729,65 +725,54 @@ uxn_get_size(SymbolType t)
} }
void void
uxn_emit_type(Arena *a, List *out, Symbol *sym, bool local) uxn_emit_type(Symbol *sym, bool local)
{ {
if(local) { if(local)
if(sym->ref) { if(sym->ref)
sprintf(uxn_temp_strbuf, "\tSTH2kr #%04x ADD2 LDA2\n", sym->ref); printf("\tSTH2kr #%04x ADD2 LDA2\n", sym->ref);
StrBuf_append(a, out, uxn_temp_strbuf); else
} else { printf("\tSTH2kr LDA2\n");
sprintf(uxn_temp_strbuf, "\tSTH2kr LDA2\n"); else
StrBuf_append(a, out, uxn_temp_strbuf); printf("!{ @%.*s $%d } ", sym->name_length, sym->name, uxn_get_size(sym->type));
}
} 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(Arena *a, List *out, const char *str, i32 length) uxn_emit_int(const char *str, i32 length)
{ {
i32 i = (i32)strtol(str, nil, 10); i32 i = (i32)strtol(str, nil, 10);
sprintf(uxn_temp_strbuf, "#%04x ", i); printf("#%04x ", i);
StrBuf_append(a, out, uxn_temp_strbuf);
USED(length); USED(length);
} }
void void
uxn_emit_nat(Arena *a, List *out, const char *str, i32 length) uxn_emit_nat(const char *str, i32 length)
{ {
u32 i = (u32)strtol(str, nil, 10); u32 i = (u32)strtol(str, nil, 10);
sprintf(uxn_temp_strbuf, "#%04x ", i); printf("#%04x ", i);
StrBuf_append(a, out, uxn_temp_strbuf);
USED(length); USED(length);
} }
void void
uxn_emit_real(Arena *a, List *out, const char *str, i32 length) uxn_emit_real(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(Arena *a, List *out, const char *str, i32 length) uxn_emit_byte(const char *str, i32 length)
{ {
u8 i = (u8)strtol(str, nil, 10); u8 i = (u8)strtol(str, nil, 10);
sprintf(uxn_temp_strbuf, "#%04x ", i); printf("#%04x ", i);
StrBuf_append(a, out, uxn_temp_strbuf);
USED(length); USED(length);
} }
void void
uxn_emit_str(Arena *a, List *out, const char *str, i32 length) uxn_emit_str(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 */
StrBuf_append(a, out, ";{ #0002 ADD2 } !{ "); printf(";{ #0002 ADD2 } !{ ");
i32 i = 1; i32 i = 1;
while (i < length - 1) { while (i < length - 1) {
@ -811,544 +796,356 @@ uxn_emit_str(Arena *a, List *out, const char *str, i32 length)
i--; /* Rewind for unknown escapes */ i--; /* Rewind for unknown escapes */
} }
} }
sprintf(uxn_temp_strbuf, "%02x ", c); printf("%02x ", c);
StrBuf_append(a, out, uxn_temp_strbuf);
} }
StrBuf_append(a, out, "00 } "); printf("00 } ");
} }
void void
uxn_emit_constant(Arena *a, List *out, Symbol *sym, bool local) uxn_emit_constant(Symbol *sym, bool local)
{ {
if(local) { if(local)
if(sym->ref) { if(sym->ref)
sprintf(uxn_temp_strbuf, "\tSTH2kr #%04x ADD2 STA2\n", sym->ref); printf("\tSTH2kr #%04x ADD2 STA2\n", sym->ref);
StrBuf_append(a, out, uxn_temp_strbuf); else
} else { printf("\tSTH2kr STA2\n");
sprintf(uxn_temp_strbuf, "\tSTH2kr STA2\n"); else
StrBuf_append(a, out, uxn_temp_strbuf); printf(";%.*s STA2 ", sym->name_length, sym->name);
}
} else {
sprintf(uxn_temp_strbuf, ";%.*s STA2 ", sym->name_length, sym->name);
StrBuf_append(a, out, uxn_temp_strbuf);
}
} }
void void
uxn_emit_array(Arena *a, List *out, Symbol *sym, List *in) uxn_emit_array()
{ {
Node *curr;
SymbolType t = sym->secondary_type;
sprintf(uxn_temp_strbuf, "@%.*s ", sym->name_length, sym->name);
StrBuf_append(a, out, uxn_temp_strbuf);
switch(t) {
case SYMBOL_BOOL: {
curr = in->head;
while (curr) {
char* tmp_str = node_value(curr);
if (sleq(tmp_str, "true", 4)) {
StrBuf_append(a, out, "0001 ");
} else {
StrBuf_append(a, out, "0000 ");
}
curr = curr->next;
}
break;
}
case SYMBOL_U8:
case SYMBOL_BYTE: {
curr = in->head;
while (curr) {
char* tmp_str = node_value(curr);
u8 i = (u8)strtol(tmp_str, nil, 10);
sprintf(uxn_temp_strbuf, "%04x ", i);
StrBuf_append(a, out, uxn_temp_strbuf);
curr = curr->next;
}
break;
}
case SYMBOL_INT: {
curr = in->head;
while (curr) {
char* tmp_str = node_value(curr);
i32 i = (i32)strtol(tmp_str, nil, 10);
sprintf(uxn_temp_strbuf, "%04x ", i);
StrBuf_append(a, out, uxn_temp_strbuf);
curr = curr->next;
}
break;
}
case SYMBOL_U32:
case SYMBOL_ARRAY:
case SYMBOL_PLEX:
case SYMBOL_STR:
case SYMBOL_NAT: {
curr = in->head;
while (curr) {
char* tmp_str = node_value(curr);
u32 i = (u32)strtol(tmp_str, nil, 10);
sprintf(uxn_temp_strbuf, "%04x ", i);
StrBuf_append(a, out, uxn_temp_strbuf);
curr = curr->next;
}
break;
}
case SYMBOL_I8: {
curr = in->head;
while (curr) {
char* tmp_str = node_value(curr);
i8 i = (i8)strtol(tmp_str, nil, 10);
sprintf(uxn_temp_strbuf, "%04x ", i);
StrBuf_append(a, out, uxn_temp_strbuf);
curr = curr->next;
}
break;
}
case SYMBOL_I16: {
curr = in->head;
while (curr) {
char* tmp_str = node_value(curr);
i16 i = (i16)strtol(tmp_str, nil, 10);
sprintf(uxn_temp_strbuf, "%04x ", i);
StrBuf_append(a, out, uxn_temp_strbuf);
curr = curr->next;
}
break;
}
case SYMBOL_U16: {
curr = in->head;
while (curr) {
char* tmp_str = node_value(curr);
u16 i = (u16)strtol(tmp_str, nil, 10);
sprintf(uxn_temp_strbuf, "%04x ", i);
StrBuf_append(a, out, uxn_temp_strbuf);
curr = curr->next;
}
break;
}
case SYMBOL_I32: {
curr = in->head;
while (curr) {
char* tmp_str = node_value(curr);
i32 i = (i32)strtol(tmp_str, nil, 10);
sprintf(uxn_temp_strbuf, "%08x ", i);
StrBuf_append(a, out, uxn_temp_strbuf);
curr = curr->next;
}
break;
}
case SYMBOL_F32:
case SYMBOL_REAL: {
break;
}
default: {
break;
}
}
StrBuf_append(a, out, "\n\n");
} }
bool bool
fn_loop_emit_args(Arena *a, List *out, void *data) fn_loop_emit_args(void *data)
{ {
Symbol *sym = ((Symbol *)data); Symbol *sym = ((Symbol *)data);
if(sym->ref) { if(sym->ref)
sprintf(uxn_temp_strbuf, "\tSTH2kr #%04x ADD2 STA2\n", sym->ref); printf("\tSTH2kr #%04x ADD2 STA2\n", sym->ref);
StrBuf_append(a, out, uxn_temp_strbuf); else
} else { printf("\tSTH2kr STA2\n");
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(Arena *a, List *out, void *data) fn_loop_emit_args_comment(void *data)
{ {
Symbol *sym = ((Symbol *)data); Symbol *sym = ((Symbol *)data);
sprintf(uxn_temp_strbuf, "%.*s ", sym->name_length, sym->name); printf("%.*s ", sym->name_length, sym->name);
StrBuf_append(a, out, uxn_temp_strbuf);
return true; return true;
} }
void void
uxn_emit_function(Arena *a, List *out, Symbol *sym) uxn_emit_function(Symbol *sym)
{ {
sprintf(uxn_temp_strbuf, "@%.*s_ ( ", sym->name_length, sym->name); printf("@%.*s_ ( ", sym->name_length, sym->name);
StrBuf_append(a, out, uxn_temp_strbuf); List_map(sym->args, fn_loop_emit_args_comment);
List_map_out(a, out, sym->args, fn_loop_emit_args_comment); printf(" -- ");
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)
sprintf(uxn_temp_strbuf, " res "); printf(" res ");
StrBuf_append(a, out, uxn_temp_strbuf); printf(")\n");
} if (sym->size > 0)
sprintf(uxn_temp_strbuf, ")\n"); printf("\tOVR2r LIT2r %04x SUB2r\n", sym->size);
StrBuf_append(a, out, uxn_temp_strbuf); List_map(sym->args, fn_loop_emit_args);
if(sym->size > 0) { printf("\n");
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(Arena *a, List *out) uxn_emit_arena_fn_return()
{ {
StrBuf_append(a, out, "\t&return\n\t\tPOP2r JMP2r\n\n"); printf("\t&return\n\t\tPOP2r JMP2r\n\n");
} }
void void
uxn_emit_arena_fn_call(Arena *a, List *out, Symbol *sym) uxn_emit_arena_fn_call(Symbol *sym)
{ {
sprintf(uxn_temp_strbuf, "%.*s_ ", sym->name_length, sym->name); printf("%.*s_ ", sym->name_length, sym->name);
StrBuf_append(a, out, uxn_temp_strbuf);
} }
void void
uxn_emit_plex(Arena *a, List *out) uxn_emit_plex()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_method(Arena *a, List *out) uxn_emit_method()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_trait(Arena *a, List *out) uxn_emit_trait()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_const(Arena *a, List *out) uxn_emit_const()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_open_paren(Arena *a, List *out) uxn_emit_open_paren()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_close_paren(Arena *a, List *out) uxn_emit_close_paren()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_variable(Arena *a, List *out, Symbol *sym, bool local) uxn_emit_variable(Symbol *sym, bool local)
{ {
if(local) { if(local)
if(sym->ref) { if(sym->ref)
sprintf(uxn_temp_strbuf, "\tSTH2kr #%04x ADD2 LDA2 ", sym->ref); printf("\tSTH2kr #%04x ADD2 LDA2 ", sym->ref);
StrBuf_append(a, out, uxn_temp_strbuf); else
} else { printf("\tSTH2kr LDA2 ");
sprintf(uxn_temp_strbuf, "\tSTH2kr LDA2 "); else
StrBuf_append(a, out, uxn_temp_strbuf); printf(";%.*s LDA2 ", sym->name_length, sym->name);
}
} 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(Arena *a, List *out, Symbol *sym, bool local) uxn_emit_set_variable(Symbol *sym, bool local)
{ {
if(local) { if(local)
if(sym->ref) { if(sym->ref)
sprintf(uxn_temp_strbuf, "\tSTH2kr #%04x ADD2 STA2 ", sym->ref); printf("\tSTH2kr #%04x ADD2 STA2 ", sym->ref);
StrBuf_append(a, out, uxn_temp_strbuf); else
} else { printf("\tSTH2kr STA2 ");
sprintf(uxn_temp_strbuf, "\tSTH2kr STA2 "); else
StrBuf_append(a, out, uxn_temp_strbuf); printf(";%.*s STA2 ", sym->name_length, sym->name);
}
} else {
sprintf(uxn_temp_strbuf, ";%.*s STA2 ", sym->name_length, sym->name);
StrBuf_append(a, out, uxn_temp_strbuf);
}
} }
void void
uxn_emit_write(Arena *a, List *out) uxn_emit_write()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_read(Arena *a, List *out) uxn_emit_read()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_open(Arena *a, List *out) uxn_emit_open()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_close(Arena *a, List *out) uxn_emit_close()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_stat(Arena *a, List *out) uxn_emit_stat()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_end_statement(Arena *a, List *out) uxn_emit_end_statement()
{ {
StrBuf_append(a, out, "\n"); printf("\n");
} }
void void
uxn_emit_set_value(Arena *a, List *out) uxn_emit_set_value()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_plex_def(Arena *a, List *out) uxn_emit_plex_def()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_cast_int_to_nat(Arena *a, List *out) uxn_emit_cast_int_to_nat()
{ {
StrBuf_append(a, out, "int_to_nat_ "); printf("int_to_nat_ ");
} }
void void
uxn_emit_cast_int_to_real(Arena *a, List *out) uxn_emit_cast_int_to_real()
{ {
StrBuf_append(a, out, "int_to_real_ "); printf("int_to_real_ ");
} }
void void
uxn_emit_cast_int_to_str(Arena *a, List *out) uxn_emit_cast_int_to_str()
{ {
StrBuf_append(a, out, "int_to_str_ "); printf("int_to_str_ ");
} }
void void
uxn_emit_cast_nat_to_int(Arena *a, List *out) uxn_emit_cast_nat_to_int()
{ {
StrBuf_append(a, out, "nat_to_int_ "); printf("nat_to_int_ ");
} }
void void
uxn_emit_cast_nat_to_real(Arena *a, List *out) uxn_emit_cast_nat_to_real()
{ {
StrBuf_append(a, out, "nat_to_real_ "); printf("nat_to_real_ ");
} }
void void
uxn_emit_cast_nat_to_str(Arena *a, List *out) uxn_emit_cast_nat_to_str()
{ {
StrBuf_append(a, out, "nat_to_str_ "); printf("nat_to_str_ ");
} }
void void
uxn_emit_cast_real_to_int(Arena *a, List *out) uxn_emit_cast_real_to_int()
{ {
StrBuf_append(a, out, "real_to_int_ "); printf("real_to_int_ ");
} }
void void
uxn_emit_cast_real_to_nat(Arena *a, List *out) uxn_emit_cast_real_to_nat()
{ {
StrBuf_append(a, out, "real_to_nat_ "); printf("real_to_nat_ ");
} }
void void
uxn_emit_cast_real_to_str(Arena *a, List *out) uxn_emit_cast_real_to_str()
{ {
StrBuf_append(a, out, "real_to_str_ "); printf("real_to_str_ ");
} }
void void
uxn_emit_strbuf_init(Arena *a, List *out) uxn_emit_strbuf_init()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_strbuf_append(Arena *a, List *out) uxn_emit_strbuf_append()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_strbuf_to_str(Arena *a, List *out) uxn_emit_strbuf_to_str()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_arena_fn_return_plex(Arena *a, List *out) uxn_emit_arena_fn_return_plex()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_arena_fn_return_array(Arena *a, List *out) uxn_emit_arena_fn_return_array()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_arena_fn_return_strbuf(Arena *a, List *out) uxn_emit_arena_fn_return_strbuf()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_cast_str_to_int(Arena *a, List *out) uxn_emit_cast_str_to_int()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_cast_str_to_nat(Arena *a, List *out) uxn_emit_cast_str_to_nat()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_cast_str_to_real(Arena *a, List *out) uxn_emit_cast_str_to_real()
{ {
USED(a);
USED(out);
} }
void void
uxn_emit_sll(Arena *a, List *out) uxn_emit_sll()
{ {
StrBuf_append(a, out, "#40 SFT SFT "); printf("#40 SFT SFT ");
} }
void void
uxn_emit_srl(Arena *a, List *out) uxn_emit_srl()
{ {
StrBuf_append(a, out, "SFT "); printf("SFT ");
} }
void void
uxn_emit_xor(Arena *a, List *out) uxn_emit_xor()
{ {
StrBuf_append(a, out, "EOR2 "); printf("EOR2 ");
} }
void void
uxn_emit_mod(Arena *a, List *out) uxn_emit_mod()
{ {
StrBuf_append(a, out, "DIV2k MUL2 SUB2 "); printf("DIV2k MUL2 SUB2 ");
} }
void void
uxn_emit_or(Arena *a, List *out) uxn_emit_or()
{ {
StrBuf_append(a, out, "ORA2 "); printf("ORA2 ");
} }
void void
uxn_emit_and(Arena *a, List *out) uxn_emit_and()
{ {
StrBuf_append(a, out, "AND2 "); printf("AND2 ");
} }
void void
uxn_emit_print(Arena *a, List *out) uxn_emit_print()
{ {
StrBuf_append(a, out, "str/<print> "); printf("str/<print> ");
} }
void void
uxn_emit_if(Arena *a, List *out) uxn_emit_if()
{ {
StrBuf_append(a, out, "#03 JCN !{ \n"); printf("#03 JCN !{ \n");
} }
void void
uxn_emit_patch_if(Arena *a, List *out, i32 local_ifs) uxn_emit_patch_if(i32 local_ifs)
{ {
sprintf(uxn_temp_strbuf, "!&if_end.%d } ", local_ifs); printf("!&if_end.%d } ", local_ifs);
StrBuf_append(a, out, uxn_temp_strbuf);
} }
void void
uxn_emit_patch_if_done(Arena *a, List *out, i32 local_ifs) uxn_emit_patch_if_done(i32 local_ifs)
{ {
sprintf(uxn_temp_strbuf, "&if_end.%d \n", local_ifs); printf("&if_end.%d \n", local_ifs);
StrBuf_append(a, out, uxn_temp_strbuf);
} }
void void
uxn_emit_while(Arena *a, List *out, i32 local_whiles) uxn_emit_while(i32 local_whiles)
{ {
sprintf(uxn_temp_strbuf, "&while.%d ", local_whiles); printf("&while.%d ", local_whiles);
StrBuf_append(a, out, uxn_temp_strbuf);
} }
void void
uxn_emit_while_postfix(Arena *a, List *out) uxn_emit_while_postfix()
{ {
StrBuf_append(a, out, "#03 JCN !{ \n"); printf("#03 JCN !{ \n");
} }
void void
uxn_emit_patch_while(Arena *a, List *out, i32 local_whiles) uxn_emit_patch_while(i32 local_whiles)
{ {
sprintf(uxn_temp_strbuf, "!&while.%d } \n", local_whiles); printf("!&while.%d } \n", local_whiles);
StrBuf_append(a, out, uxn_temp_strbuf);
} }
void void
uxn_emit_early_return(Arena *a, List *out) uxn_emit_early_return()
{ {
StrBuf_append(a, out, "!&return "); printf("!&return ");
} }
void void
uxn_emit_halt(Arena *a, List *out) uxn_emit_halt()
{ {
StrBuf_append(a, out, "POP2r BRK "); printf("POP2r BRK ");
} }
Emitter Emitter

13
list.c
View File

@ -59,19 +59,6 @@ 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,13 +18,11 @@ 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"
List * StrBuf *
StrBuf_init(Arena *a) StrBuf_init(Arena *a)
{ {
List *l = (List*)aalloc(a, sizeof(List)); StrBuf *l = (StrBuf*)aalloc(a, sizeof(StrBuf));
if (!l) return nil; if (!l) return nil;
l->head = nil; l->head = nil;
@ -14,8 +14,10 @@ StrBuf_init(Arena *a)
} }
void * void *
StrBuf_append_exactly(Arena *a, List *buf, char *str, u32 length) StrBuf_append(Arena *a, StrBuf *buf, char *str)
{ {
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;
@ -42,14 +44,8 @@ StrBuf_append_exactly(Arena *a, List *buf, char *str, u32 length)
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, List *buf, u32 *out_length) StrBuf_toS(Arena *a, StrBuf *buf, u32 *out_length)
{ {
Node *curr; Node *curr;
char *tmp_str; char *tmp_str;

View File

@ -3,9 +3,15 @@
#include "list.h" #include "list.h"
List *StrBuf_init(Arena *a); typedef struct strbuf_s StrBuf;
void *StrBuf_append(Arena *a, List *buf, char *str); struct strbuf_s {
void *StrBuf_append_exactly(Arena *a, List *buf, char *str, u32 length); Node *head;
char *StrBuf_toS(Arena *a, List *buf, u32 *out_length); Node *tail;
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