get rid of all static functions and all globals, use pointers instead. fix alignment bug in aalloc

This commit is contained in:
zongor 2026-06-29 17:32:54 -07:00
parent 63a5b737fc
commit aee7191f59
6 changed files with 240 additions and 235 deletions

View File

@ -72,7 +72,7 @@ main(int argc, char **argv)
List *memory = 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, code, memory, &e, source);
Node *curr = code->head; Node *curr = code->head;
while (curr) { while (curr) {

View File

@ -28,6 +28,9 @@ static void list2buffer(List *list, char *buffer, size_t *offset) {
EMSCRIPTEN_KEEPALIVE EMSCRIPTEN_KEEPALIVE
char *undar_compile(int emitter_type, char *source) { char *undar_compile(int emitter_type, char *source) {
u8 tape[MEM_SIZE];
Arena a = {tape, 0, MEM_SIZE};
Emitter e; Emitter e;
if (emitter_type == 0) { if (emitter_type == 0) {
e = rer_emitter(); e = rer_emitter();
@ -37,13 +40,10 @@ char *undar_compile(int emitter_type, char *source) {
return NULL; return NULL;
} }
u8 tape[MEM_SIZE];
Arena a = {tape, 0, MEM_SIZE};
List *code = List_init(&a); List *code = List_init(&a);
List *memory = List_init(&a); List *memory = List_init(&a);
compile(&a, code, memory, e, source); compile(&a, code, memory, &e, source);
size_t code_size = List_size(code); size_t code_size = List_size(code);
size_t mem_size = List_size(memory); size_t mem_size = List_size(memory);

View File

@ -5,8 +5,8 @@
#include "libc.h" #include "libc.h"
#include "list.h" #include "list.h"
Emitter emitter = {0}; Parser *parser;
Parser parser = {0}; Emitter *emitter;
Arena *arena; Arena *arena;
List *code; List *code;
List *memory; List *memory;
@ -22,8 +22,8 @@ scopes_init(void)
child.symbols = List_init(arena); child.symbols = List_init(arena);
child.locals_offset = 0; child.locals_offset = 0;
current = (Scope *)List_push(arena, parser.scopes, &child, sizeof(Scope)); current = (Scope *)List_push(arena, parser->scopes, &child, sizeof(Scope));
parser.current_scope = current; parser->current_scope = current;
} }
Scope * Scope *
@ -32,32 +32,32 @@ scope_new(void)
Scope *current; Scope *current;
Scope child = {0}; Scope child = {0};
child.symbols = List_init(arena); child.symbols = List_init(arena);
child.parent = parser.current_scope; child.parent = parser->current_scope;
child.locals_offset = 0; child.locals_offset = 0;
current = (Scope *)List_push(arena, parser.scopes, &child, sizeof(Scope)); current = (Scope *)List_push(arena, parser->scopes, &child, sizeof(Scope));
parser.current_scope = current; parser->current_scope = current;
parser.scope_idx++; parser->scope_idx++;
parser.depth++; parser->depth++;
return current; return current;
} }
void void
scope_pop(void) scope_pop(void)
{ {
if(parser.current_scope) { if(parser->current_scope) {
parser.current_scope = parser.current_scope->parent; parser->current_scope = parser->current_scope->parent;
parser.depth--; parser->depth--;
} }
} }
void void
scope_push(void) scope_push(void)
{ {
Scope *scope = List_get(parser.scopes, parser.scope_idx); Scope *scope = List_get(parser->scopes, parser->scope_idx);
parser.current_scope = scope; parser->current_scope = scope;
parser.depth++; parser->depth++;
parser.scope_idx++; parser->scope_idx++;
} }
Symbol * Symbol *
@ -80,12 +80,12 @@ Symbol *
scope_add_symbol(const char *name, u32 name_length, SymbolType type, u32 size) scope_add_symbol(const char *name, u32 name_length, SymbolType type, u32 size)
{ {
Symbol new_sym = {0}; Symbol new_sym = {0};
Symbol *sym = scope_get_symbol(parser.current_scope, name, name_length); Symbol *sym = scope_get_symbol(parser->current_scope, name, name_length);
if(sym != nil) { if(sym != nil) {
if(parser.pass) if(parser->pass)
return sym; return sym;
else else
emitter.error("duplicate found", 14, parser.previous.line); emitter->error("duplicate found", 14, parser->previous.line);
} }
scpy(new_sym.name, name, name_length); scpy(new_sym.name, name, name_length);
@ -93,9 +93,9 @@ scope_add_symbol(const char *name, u32 name_length, SymbolType type, u32 size)
new_sym.type = type; new_sym.type = type;
new_sym.secondary_type = SYMBOL_VOID; new_sym.secondary_type = SYMBOL_VOID;
new_sym.size = size; new_sym.size = size;
new_sym.ref = parser.current_scope->locals_offset; new_sym.ref = parser->current_scope->locals_offset;
new_sym.scope = parser.scope_idx; new_sym.scope = parser->scope_idx;
parser.current_scope->locals_offset += size; parser->current_scope->locals_offset += size;
if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT || if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT ||
type == SYMBOL_FUNCTION) { type == SYMBOL_FUNCTION) {
new_sym.args = List_init(arena); new_sym.args = List_init(arena);
@ -104,21 +104,21 @@ scope_add_symbol(const char *name, u32 name_length, SymbolType type, u32 size)
if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT) if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT)
new_sym.fields = List_init(arena); new_sym.fields = List_init(arena);
return List_push(arena, parser.current_scope->symbols, &new_sym, return List_push(arena, parser->current_scope->symbols, &new_sym,
sizeof(Symbol)); sizeof(Symbol));
} }
bool bool
is_global(void) is_global(void)
{ {
return parser.current_scope != nil && parser.current_scope->parent == nil; return parser->current_scope != nil && parser->current_scope->parent == nil;
} }
bool bool
is_type(void) is_type(void)
{ {
return parser.previous.type >= TOKEN_TYPE_I8 && return parser->previous.type >= TOKEN_TYPE_I8 &&
parser.previous.type <= TOKEN_TYPE_PTR; parser->previous.type <= TOKEN_TYPE_PTR;
} }
SymbolType SymbolType
@ -158,11 +158,11 @@ token_type_to_sym_type(TokenType t)
bool bool
advance(void) advance(void)
{ {
parser.previous = parser.current; parser->previous = parser->current;
for(;;) { for(;;) {
parser.current = next_token(); parser->current = next_token();
if(parser.current.type != TOKEN_ERROR) return true; if(parser->current.type != TOKEN_ERROR) return true;
return false; return false;
} }
@ -170,7 +170,7 @@ advance(void)
bool bool
check(TokenType type) check(TokenType type)
{ {
return parser.current.type == type; return parser->current.type == type;
} }
bool bool
@ -207,8 +207,8 @@ void
expect(TokenType type) expect(TokenType type)
{ {
if(!consume(type)) { if(!consume(type)) {
emitter.error(parser.previous.start, parser.previous.length, emitter->error(parser->previous.start, parser->previous.length,
parser.previous.line); parser->previous.line);
} }
} }
@ -230,7 +230,7 @@ define_function(void)
Symbol *fn; Symbol *fn;
u32 size = 0; u32 size = 0;
advance(); advance();
fn = scope_add_symbol(parser.previous.start, parser.previous.length, fn = scope_add_symbol(parser->previous.start, parser->previous.length,
SYMBOL_FUNCTION, 0); SYMBOL_FUNCTION, 0);
/* need to push scope early because the variables need to be a part of the fn /* need to push scope early because the variables need to be a part of the fn
@ -250,20 +250,20 @@ define_function(void)
if(is_type()) { if(is_type()) {
/* get return slot */ /* get return slot */
fn->secondary_type = token_type_to_sym_type(parser.previous.type); fn->secondary_type = token_type_to_sym_type(parser->previous.type);
/* now parse the fn body */ /* now parse the fn body */
} }
expect(TOKEN_LBRACE); expect(TOKEN_LBRACE);
/* get the size of all the locals for the function in the body */ /* get the size of all the locals for the function in the body */
while(parser.depth > 0) { while(parser->depth > 0) {
if(match(TOKEN_LBRACE)) { if(match(TOKEN_LBRACE)) {
scope_new(); scope_new();
continue; continue;
} else if(match(TOKEN_RBRACE)) { } else if(match(TOKEN_RBRACE)) {
scope_pop(); scope_pop();
continue; continue;
} else if(is_type() && parser.current.type == TOKEN_IDENTIFIER) } else if(is_type() && parser->current.type == TOKEN_IDENTIFIER)
size += variable_declaration(nil); size += variable_declaration(nil);
advance(); advance();
} }
@ -292,7 +292,7 @@ calculate_strides(List *dims, List *strides)
if (num){ if (num){
current_stride *= (*num); current_stride *= (*num);
} else { } else {
emitter.error("Tried to get a dimension that did not exist", 43, parser.previous.line); emitter->error("Tried to get a dimension that did not exist", 43, parser->previous.line);
} }
} }
} }
@ -301,7 +301,7 @@ void
define_array(void) define_array(void)
{ {
i32 size = 0, n = 0, flat_array_length = 1; i32 size = 0, n = 0, flat_array_length = 1;
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 *array; Symbol *array;
@ -310,8 +310,8 @@ define_array(void)
advance(); advance();
while(!match(TOKEN_RBRACKET)) { while(!match(TOKEN_RBRACKET)) {
if(parser.current.type == TOKEN_LITERAL_INT) { if(parser->current.type == TOKEN_LITERAL_INT) {
n = ston(parser.current.start, parser.current.length); n = ston(parser->current.start, parser->current.length);
flat_array_length *= n; flat_array_length *= n;
List_push(arena, dims, &n, sizeof(u32)); List_push(arena, dims, &n, sizeof(u32));
} }
@ -322,9 +322,9 @@ define_array(void)
} }
} }
size = emitter.get_size(st) * flat_array_length; size = emitter->get_size(st) * flat_array_length;
array = scope_add_symbol(parser.current.start, parser.current.length, array = scope_add_symbol(parser->current.start, parser->current.length,
SYMBOL_ARRAY, size); SYMBOL_ARRAY, size);
array->secondary_type = st; array->secondary_type = st;
calculate_strides(dims, strides); calculate_strides(dims, strides);
@ -351,8 +351,8 @@ build_symbol_table(char *source)
define_plex(); define_plex();
} else if(match(TOKEN_KEYWORD_TRAIT)) { } else if(match(TOKEN_KEYWORD_TRAIT)) {
define_trait(); define_trait();
} else if (parser.current.type >= TOKEN_TYPE_I8 && } else if (parser->current.type >= TOKEN_TYPE_I8 &&
parser.current.type <= TOKEN_TYPE_PTR) { parser->current.type <= TOKEN_TYPE_PTR) {
advance(); advance();
if (check(TOKEN_LBRACKET)) { if (check(TOKEN_LBRACKET)) {
define_array(); define_array();
@ -375,22 +375,22 @@ u32
variable_declaration(Symbol *def) variable_declaration(Symbol *def)
{ {
i32 size = 0; i32 size = 0;
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; List *array_literal;
if (parser.current.type == TOKEN_LBRACKET) { if (parser->current.type == TOKEN_LBRACKET) {
while(!check(TOKEN_RBRACKET)) { while(!check(TOKEN_RBRACKET)) {
advance(); advance();
} }
advance(); advance();
variable = scope_get_symbol(parser.current_scope, variable = scope_get_symbol(parser->current_scope,
parser.current.start, parser->current.start,
parser.current.length); parser->current.length);
if (!variable) { if (!variable) {
emitter.error("cannot find array symbol", 24, parser.current.line); emitter->error("cannot find array symbol", 24, parser->current.line);
return 0; return 0;
} }
advance(); advance();
@ -401,119 +401,119 @@ variable_declaration(Symbol *def)
while (!match(TOKEN_RBRACKET)) { while (!match(TOKEN_RBRACKET)) {
StrBuf_append_exactly(arena, array_literal, StrBuf_append_exactly(arena, array_literal,
(char*)parser.current.start, (char*)parser->current.start,
parser.current.length); parser->current.length);
advance(); advance();
if(match(TOKEN_RBRACKET)) break; if(match(TOKEN_RBRACKET)) break;
expect(TOKEN_COMMA); expect(TOKEN_COMMA);
} }
expect(TOKEN_SEMICOLON); expect(TOKEN_SEMICOLON);
emitter.emit_array(arena, memory, variable, array_literal); emitter->emit_array(arena, memory, variable, array_literal);
} else { } else {
expect(TOKEN_SEMICOLON); expect(TOKEN_SEMICOLON);
emitter.emit_array(arena, memory, variable, nil); emitter->emit_array(arena, memory, variable, nil);
emitter.emit_zero_block(arena, memory, variable->size * emitter.get_size(variable->secondary_type)); emitter->emit_zero_block(arena, memory, variable->size * emitter->get_size(variable->secondary_type));
} }
return variable->size; return variable->size;
} }
if(st != SYMBOL_UNDEFINED) { if(st != SYMBOL_UNDEFINED) {
size = emitter.get_size(st); size = emitter->get_size(st);
variable = scope_add_symbol(parser.current.start, parser.current.length, st, size); variable = scope_add_symbol(parser->current.start, parser->current.length, st, size);
if(!def && (parser.pass == 0)) return size; if(!def && (parser->pass == 0)) return size;
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(arena, code, variable, parser->depth);
parser.current_type = st; parser->current_type = st;
} }
} else { } else {
/* we need to look up the type */ /* we need to look up the type */
emitter.error("Not implemented", 16, parser.previous.line); emitter->error("Not implemented", 16, parser->previous.line);
} }
advance(); advance();
if(def && (check(TOKEN_COMMA) || check(TOKEN_RPAREN))) return size; if(def && (check(TOKEN_COMMA) || check(TOKEN_RPAREN))) return size;
if(def) if(def)
emitter.error(parser.previous.start, parser.previous.length, emitter->error(parser->previous.start, parser->previous.length,
parser.previous.line); parser->previous.line);
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(arena, code);
expression(); expression();
emitter.emit_constant(arena, code, variable, parser.depth); emitter->emit_constant(arena, code, variable, parser->depth);
} }
consume(TOKEN_SEMICOLON); consume(TOKEN_SEMICOLON);
emitter.emit_end_statement(arena, code); emitter->emit_end_statement(arena, code);
parser.current_type = SYMBOL_UNDEFINED; parser->current_type = SYMBOL_UNDEFINED;
return size; return size;
} }
void void
binary(void) binary(void)
{ {
TokenType operatorType = parser.previous.type; TokenType operatorType = parser->previous.type;
ParseRule *rule = get_rule(operatorType); ParseRule *rule = get_rule(operatorType);
parse_precedence((Precedence)(rule->precedence + 1)); parse_precedence((Precedence)(rule->precedence + 1));
switch(operatorType) { switch(operatorType) {
case TOKEN_BANG_EQ: case TOKEN_BANG_EQ:
emitter.emit_ne(arena, code); emitter->emit_ne(arena, code);
break; break;
case TOKEN_EQ_EQ: case TOKEN_EQ_EQ:
emitter.emit_eq(arena, code); emitter->emit_eq(arena, code);
break; break;
case TOKEN_GT: case TOKEN_GT:
emitter.emit_gt(arena, code); emitter->emit_gt(arena, code);
break; break;
case TOKEN_GTE: case TOKEN_GTE:
emitter.emit_ge(arena, code); emitter->emit_ge(arena, code);
break; break;
case TOKEN_LT: case TOKEN_LT:
emitter.emit_lt(arena, code); emitter->emit_lt(arena, code);
break; break;
case TOKEN_LTE: case TOKEN_LTE:
emitter.emit_le(arena, code); emitter->emit_le(arena, code);
break; break;
case TOKEN_PLUS: case TOKEN_PLUS:
emitter.emit_add(arena, code); emitter->emit_add(arena, code);
break; break;
case TOKEN_MINUS: case TOKEN_MINUS:
emitter.emit_sub(arena, code); emitter->emit_sub(arena, code);
break; break;
case TOKEN_STAR: case TOKEN_STAR:
emitter.emit_mul(arena, code); emitter->emit_mul(arena, code);
break; break;
case TOKEN_SLASH: case TOKEN_SLASH:
emitter.emit_div(arena, code); emitter->emit_div(arena, code);
break; break;
case TOKEN_OPERATOR_AND: case TOKEN_OPERATOR_AND:
emitter.emit_and(arena, code); emitter->emit_and(arena, code);
break; break;
case TOKEN_OPERATOR_OR: case TOKEN_OPERATOR_OR:
emitter.emit_or(arena, code); emitter->emit_or(arena, code);
break; break;
case TOKEN_OPERATOR_XOR: case TOKEN_OPERATOR_XOR:
emitter.emit_xor(arena, code); emitter->emit_xor(arena, code);
break; break;
case TOKEN_OPERATOR_MOD: case TOKEN_OPERATOR_MOD:
emitter.emit_mod(arena, code); emitter->emit_mod(arena, code);
break; break;
case TOKEN_SLL: case TOKEN_SLL:
emitter.emit_sll(arena, code); emitter->emit_sll(arena, code);
break; break;
case TOKEN_SRL: case TOKEN_SRL:
emitter.emit_srl(arena, code); emitter->emit_srl(arena, code);
break; break;
default: default:
return; return;
@ -523,15 +523,15 @@ binary(void)
void void
literal(void) literal(void)
{ {
switch(parser.previous.type) { switch(parser->previous.type) {
case TOKEN_KEYWORD_FALSE: case TOKEN_KEYWORD_FALSE:
emitter.emit_false(arena, code); emitter->emit_false(arena, code);
break; break;
case TOKEN_KEYWORD_TRUE: case TOKEN_KEYWORD_TRUE:
emitter.emit_true(arena, code); emitter->emit_true(arena, code);
break; break;
case TOKEN_KEYWORD_NIL: case TOKEN_KEYWORD_NIL:
emitter.emit_nil(arena, code); emitter->emit_nil(arena, code);
break; break;
default: default:
return; return;
@ -547,83 +547,83 @@ expression(void)
void void
variable(void) variable(void)
{ {
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);
if(sym == nil) { if(sym == nil) {
emitter.error(parser.previous.start, parser.previous.length, emitter->error(parser->previous.start, parser->previous.length,
parser.previous.line); parser->previous.line);
} }
if(sym->type == SYMBOL_FUNCTION) { if(sym->type == SYMBOL_FUNCTION) {
parser.call_fn = sym; parser->call_fn = sym;
return; return;
} }
if (sym->type == SYMBOL_ARRAY) { if (sym->type == SYMBOL_ARRAY) {
emitter.emit_deref_prolog(arena, code, sym); emitter->emit_deref_prolog(arena, code, sym);
if (match(TOKEN_LBRACKET)) { if (match(TOKEN_LBRACKET)) {
expression(); expression();
emitter.emit_address(arena, code, emitter.get_size(sym->secondary_type)); emitter->emit_address(arena, code, emitter->get_size(sym->secondary_type));
emitter.emit_mul(arena, code); emitter->emit_mul(arena, code);
emitter.emit_add(arena, code); emitter->emit_add(arena, code);
/* add offset of "length"*/ /* add offset of "length"*/
emitter.emit_nat(arena, code, "2", 1); emitter->emit_nat(arena, code, "2", 1);
emitter.emit_add(arena, code); emitter->emit_add(arena, code);
emitter.emit_deref(arena, code); emitter->emit_deref(arena, code);
while (!match(TOKEN_RBRACKET)) { while (!match(TOKEN_RBRACKET)) {
} }
} else if (match(TOKEN_DOT)) { } else if (match(TOKEN_DOT)) {
if (sleq("length", parser.current.start, parser.current.length)) { if (sleq("length", parser->current.start, parser->current.length)) {
emitter.emit_deref(arena, code); emitter->emit_deref(arena, code);
} else { } else {
emitter.error("arrays currently can only get their length, don't do anything fancy yet...", 75, parser.current.line); emitter->error("arrays currently can only get their length, don't do anything fancy yet...", 75, parser->current.line);
} }
advance(); advance();
} }
return; return;
} }
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(arena, code, sym, sym->scope);
} else { } else {
emitter.emit_variable(arena, code, sym, sym->scope); emitter->emit_variable(arena, code, sym, sym->scope);
} }
} }
void void
cast_type(void) cast_type(void)
{ {
SymbolType st = parser.current_type; SymbolType st = parser->current_type;
TokenType cast_type; TokenType cast_type;
if(!(parser.current.type >= TOKEN_TYPE_I8 && if(!(parser->current.type >= TOKEN_TYPE_I8 &&
parser.current.type <= TOKEN_TYPE_PTR)) { parser->current.type <= TOKEN_TYPE_PTR)) {
emitter.error("Expect type name after 'as'.", 26, parser.current.line); emitter->error("Expect type name after 'as'.", 26, parser->current.line);
return; return;
} }
cast_type = parser.current.type; cast_type = parser->current.type;
advance(); advance();
switch(st) { switch(st) {
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(arena, code);
break; break;
} }
case TOKEN_TYPE_REAL: { case TOKEN_TYPE_REAL: {
emitter.emit_cast_int_to_real(arena, code); emitter->emit_cast_int_to_real(arena, code);
break; break;
} }
case TOKEN_TYPE_STR: { case TOKEN_TYPE_STR: {
emitter.emit_cast_int_to_str(arena, code); emitter->emit_cast_int_to_str(arena, code);
break; break;
} }
default: default:
emitter.error("Not castable to int", 19, parser.previous.line); emitter->error("Not castable to int", 19, parser->previous.line);
} }
break; break;
@ -631,69 +631,69 @@ cast_type(void)
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(arena, code);
break; break;
} }
case TOKEN_TYPE_REAL: { case TOKEN_TYPE_REAL: {
emitter.emit_cast_nat_to_real(arena, code); emitter->emit_cast_nat_to_real(arena, code);
break; break;
} }
case TOKEN_TYPE_STR: { case TOKEN_TYPE_STR: {
emitter.emit_cast_nat_to_str(arena, code); emitter->emit_cast_nat_to_str(arena, code);
break; break;
} }
default: default:
emitter.error("Not castable to nat", 19, parser.previous.line); emitter->error("Not castable to nat", 19, parser->previous.line);
} }
break; break;
} }
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(arena, code);
break; break;
} }
case TOKEN_TYPE_INT: { case TOKEN_TYPE_INT: {
emitter.emit_cast_real_to_int(arena, code); emitter->emit_cast_real_to_int(arena, code);
break; break;
} }
case TOKEN_TYPE_STR: { case TOKEN_TYPE_STR: {
emitter.emit_cast_real_to_str(arena, code); emitter->emit_cast_real_to_str(arena, code);
break; break;
} }
default: default:
emitter.error("Not castable to real", 20, parser.previous.line); emitter->error("Not castable to real", 20, parser->previous.line);
} }
break; break;
} }
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(arena, code);
break; break;
} }
case TOKEN_TYPE_REAL: { case TOKEN_TYPE_REAL: {
emitter.emit_cast_str_to_real(arena, code); emitter->emit_cast_str_to_real(arena, code);
break; break;
} }
case TOKEN_TYPE_INT: { case TOKEN_TYPE_INT: {
emitter.emit_cast_str_to_int(arena, code); emitter->emit_cast_str_to_int(arena, code);
break; break;
} }
default: default:
emitter.error("Not castable to str", 19, parser.previous.line); emitter->error("Not castable to str", 19, parser->previous.line);
} }
break; break;
} }
default: default:
emitter.error("Type cast not implemented for this type (oops)", 46, parser.previous.line); emitter->error("Type cast not implemented for this type (oops)", 46, parser->previous.line);
} }
} }
void void
declaration(void) declaration(void)
{ {
if(is_type() && (parser.current.type == TOKEN_IDENTIFIER || parser.current.type == TOKEN_LBRACKET) ) if(is_type() && (parser->current.type == TOKEN_IDENTIFIER || parser->current.type == TOKEN_LBRACKET) )
variable_declaration(nil); variable_declaration(nil);
else else
statement(); statement();
@ -704,8 +704,8 @@ print_statement(void)
{ {
expression(); expression();
consume(TOKEN_SEMICOLON); consume(TOKEN_SEMICOLON);
emitter.emit_print(arena, code); emitter->emit_print(arena, code);
emitter.emit_end_statement(arena, code); emitter->emit_end_statement(arena, code);
} }
void void
@ -714,29 +714,29 @@ if_statement(void)
consume(TOKEN_LPAREN); consume(TOKEN_LPAREN);
expression(); expression();
consume(TOKEN_RPAREN); consume(TOKEN_RPAREN);
emitter.emit_if(arena, code); emitter->emit_if(arena, code);
statement(); statement();
emitter.emit_patch_if(arena, code, 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(arena, code, emitter.ifs++); if(emitter->else_if_depth == 0) emitter->emit_patch_if_done(arena, code, emitter->ifs++);
} }
void void
while_statement(void) while_statement(void)
{ {
u32 this_while = emitter.loops++; u32 this_while = emitter->loops++;
emitter.emit_while(arena, code, this_while); emitter->emit_while(arena, code, this_while);
consume(TOKEN_LPAREN); consume(TOKEN_LPAREN);
expression(); expression();
consume(TOKEN_RPAREN); consume(TOKEN_RPAREN);
emitter.emit_while_postfix(arena, code); emitter->emit_while_postfix(arena, code);
statement(); statement();
emitter.emit_patch_while(arena, code, this_while); emitter->emit_patch_while(arena, code, this_while);
} }
void void
@ -750,15 +750,15 @@ block(void)
void void
function(void) function(void)
{ {
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(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(arena, code); emitter->emit_arena_fn_return(arena, code);
} }
void void
@ -771,8 +771,8 @@ call(void)
} }
consume(TOKEN_RPAREN); consume(TOKEN_RPAREN);
emitter.emit_arena_fn_call(arena, code, 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;
} }
@ -780,11 +780,11 @@ void
return_statement(void) return_statement(void)
{ {
if(match(TOKEN_SEMICOLON)) { if(match(TOKEN_SEMICOLON)) {
emitter.emit_early_return(arena, code); emitter->emit_early_return(arena, code);
} else { } else {
expression(); expression();
consume(TOKEN_SEMICOLON); consume(TOKEN_SEMICOLON);
emitter.emit_early_return(arena, code); emitter->emit_early_return(arena, code);
} }
} }
@ -807,7 +807,7 @@ statement(void)
} 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(arena, code);
} else { } else {
expression(); expression();
} }
@ -816,44 +816,44 @@ statement(void)
void void
grouping(void) grouping(void)
{ {
emitter.emit_open_paren(arena, code); emitter->emit_open_paren(arena, code);
expression(); expression();
emitter.emit_close_paren(arena, code); emitter->emit_close_paren(arena, code);
consume(TOKEN_RPAREN); consume(TOKEN_RPAREN);
} }
void void
number(void) number(void)
{ {
emitter.emit_int(arena, code, parser.previous.start, parser.previous.length); emitter->emit_int(arena, code, parser->previous.start, parser->previous.length);
} }
void void
string(void) string(void)
{ {
emitter.emit_str(arena, code, parser.previous.start, parser.previous.length); emitter->emit_str(arena, code, parser->previous.start, parser->previous.length);
} }
void void
character(void) character(void)
{ {
emitter.emit_char(arena, code, parser.previous.start, parser.previous.length); emitter->emit_char(arena, code, parser->previous.start, parser->previous.length);
} }
void void
unary(void) unary(void)
{ {
TokenType operatorType = parser.previous.type; TokenType operatorType = parser->previous.type;
parse_precedence(PREC_UNARY); parse_precedence(PREC_UNARY);
switch(operatorType) { switch(operatorType) {
case TOKEN_MINUS: case TOKEN_MINUS:
emitter.emit_neg(arena, code); emitter->emit_neg(arena, code);
break; break;
case TOKEN_BANG: case TOKEN_BANG:
emitter.emit_not(arena, code); emitter->emit_not(arena, code);
break; break;
default: default:
return; return;
@ -863,7 +863,7 @@ unary(void)
void void
read(void) read(void)
{ {
emitter.emit_read(arena, code); emitter->emit_read(arena, code);
} }
void void
@ -872,7 +872,7 @@ write(void)
consume(TOKEN_EQ); consume(TOKEN_EQ);
advance(); advance();
variable(); variable();
emitter.emit_write(arena, code); emitter->emit_write(arena, code);
} }
ParseRule rules[] = { ParseRule rules[] = {
@ -971,14 +971,14 @@ parse_precedence(Precedence precedence)
ParseFn infixRule; ParseFn infixRule;
advance(); advance();
prefixRule = get_rule(parser.previous.type)->prefix; prefixRule = get_rule(parser->previous.type)->prefix;
if(prefixRule == nil) return; if(prefixRule == nil) return;
prefixRule(); prefixRule();
while(precedence <= get_rule(parser.current.type)->precedence) { while(precedence <= get_rule(parser->current.type)->precedence) {
advance(); advance();
infixRule = get_rule(parser.previous.type)->infix; infixRule = get_rule(parser->previous.type)->infix;
infixRule(); infixRule();
} }
} }
@ -995,25 +995,27 @@ emit_program(char *source)
init_lexer(source); init_lexer(source);
advance(); advance();
emitter.prolog(arena, code); emitter->prolog(arena, code);
while(!match(TOKEN_EOF)) declaration(); while(!match(TOKEN_EOF)) declaration();
emitter.epilogue(arena, code); emitter->epilogue(arena, code);
} }
bool bool
compile(Arena *a, List *c, List* m, Emitter e, char *source) compile(Arena *a, List *c, List* m, Emitter *e, char *source)
{ {
Parser p = {0};
arena = a; arena = a;
emitter = e; emitter = e;
code = c; code = c;
memory = m; memory = m;
parser.scopes = List_init(arena); parser = &p;
parser->scopes = List_init(arena);
build_symbol_table(source); build_symbol_table(source);
parser.pass++; parser->pass++;
parser.scope_idx = 0; parser->scope_idx = 0;
emit_program(source); emit_program(source);
return true; return true;

View File

@ -51,6 +51,6 @@ struct parser_s {
u8 pass; u8 pass;
}; };
bool compile(Arena *a, List *c, List *m, Emitter e, char *source); bool compile(Arena *a, List *c, List *m, Emitter *e, char *source);
#endif #endif

108
lexer.c
View File

@ -17,26 +17,26 @@ init_lexer(const char *source)
lexer.line = 1; lexer.line = 1;
} }
static bool bool
is_alpha(char c) lex_is_alpha(char c)
{ {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
} }
static bool bool
is_digit(char c) lex_is_digit(char c)
{ {
return c >= '0' && c <= '9'; return c >= '0' && c <= '9';
} }
static bool bool
is_at_end(void) is_at_end(void)
{ {
return *lexer.current == '\0'; return *lexer.current == '\0';
} }
static char char
advance(void) lex_advance(void)
{ {
lexer.current++; lexer.current++;
return lexer.current[-1]; return lexer.current[-1];
@ -48,15 +48,15 @@ peek(void)
return *lexer.current; return *lexer.current;
} }
static char char
peek_next(void) peek_next(void)
{ {
if(is_at_end()) return '\0'; if(is_at_end()) return '\0';
return lexer.current[1]; return lexer.current[1];
} }
static bool bool
match(char expected) lex_match(char expected)
{ {
if(is_at_end()) return false; if(is_at_end()) return false;
if(*lexer.current != expected) return false; if(*lexer.current != expected) return false;
@ -64,7 +64,7 @@ match(char expected)
return true; return true;
} }
static Token Token
make_token(TokenType type) make_token(TokenType type)
{ {
Token token; Token token;
@ -75,7 +75,7 @@ make_token(TokenType type)
return token; return token;
} }
static Token Token
error_token(const char *message) error_token(const char *message)
{ {
Token token; Token token;
@ -86,7 +86,7 @@ error_token(const char *message)
return token; return token;
} }
static void void
skip_whitespace(void) skip_whitespace(void)
{ {
for(;;) { for(;;) {
@ -95,29 +95,29 @@ skip_whitespace(void)
case ' ': case ' ':
case '\r': case '\r':
case '\t': case '\t':
advance(); lex_advance();
break; break;
case '\n': case '\n':
lexer.line++; lexer.line++;
advance(); lex_advance();
break; break;
case '/': case '/':
if(peek_next() == '/') { if(peek_next() == '/') {
/* Single-line comment: skip until newline or end of file */ /* Single-line comment: skip until newline or end of file */
advance(); lex_advance();
while(peek() != '\n' && !is_at_end()) advance(); while(peek() != '\n' && !is_at_end()) lex_advance();
} else if(peek_next() == '*') { } else if(peek_next() == '*') {
/* Multi-line comment: skip until '* /' or end of file */ /* Multi-line comment: skip until '* /' or end of file */
advance(); lex_advance();
advance(); lex_advance();
while(!is_at_end()) { while(!is_at_end()) {
if(peek() == '\n') lexer.line++; if(peek() == '\n') lexer.line++;
if(peek() == '*' && peek_next() == '/') { if(peek() == '*' && peek_next() == '/') {
advance(); lex_advance();
advance(); lex_advance();
break; /* Exit loop, comment ended */ break; /* Exit loop, comment ended */
} }
advance(); lex_advance();
} }
} else { } else {
return; /* Not a comment, let tokenization handle it */ return; /* Not a comment, let tokenization handle it */
@ -129,7 +129,7 @@ skip_whitespace(void)
} }
} }
static TokenType TokenType
check_keyword(i32 start, i32 length, const char *rest, TokenType type) check_keyword(i32 start, i32 length, const char *rest, TokenType type)
{ {
i32 s1 = lexer.current - lexer.start; i32 s1 = lexer.current - lexer.start;
@ -139,7 +139,7 @@ check_keyword(i32 start, i32 length, const char *rest, TokenType type)
return TOKEN_IDENTIFIER; return TOKEN_IDENTIFIER;
} }
static TokenType TokenType
identifierType(void) identifierType(void)
{ {
switch(lexer.start[0]) { switch(lexer.start[0]) {
@ -342,24 +342,24 @@ identifierType(void)
return TOKEN_IDENTIFIER; return TOKEN_IDENTIFIER;
} }
static Token Token
identifier(void) identifier(void)
{ {
while(is_alpha(peek()) || is_digit(peek())) advance(); while(lex_is_alpha(peek()) || lex_is_digit(peek())) lex_advance();
return make_token(identifierType()); return make_token(identifierType());
} }
static Token Token
number(void) lex_number(void)
{ {
while(is_digit(peek())) advance(); while(lex_is_digit(peek())) lex_advance();
/* Look for a fractional part. */ /* Look for a fractional part. */
if(peek() == '.' && is_digit(peek_next())) { if(peek() == '.' && lex_is_digit(peek_next())) {
/* Consume the ".". */ /* Consume the ".". */
advance(); lex_advance();
while(is_digit(peek())) advance(); while(lex_is_digit(peek())) lex_advance();
return make_token(TOKEN_LITERAL_REAL); return make_token(TOKEN_LITERAL_REAL);
} }
@ -367,33 +367,33 @@ number(void)
return make_token(TOKEN_LITERAL_INT); return make_token(TOKEN_LITERAL_INT);
} }
static Token Token
string(void) lex_string(void)
{ {
while(peek() != '"' && !is_at_end()) { while(peek() != '"' && !is_at_end()) {
if(peek() == '\n') lexer.line++; if(peek() == '\n') lexer.line++;
advance(); lex_advance();
} }
if(is_at_end()) return error_token("Unterminated string."); if(is_at_end()) return error_token("Unterminated string.");
/* The closing quote. */ /* The closing quote. */
advance(); lex_advance();
return make_token(TOKEN_LITERAL_STR); return make_token(TOKEN_LITERAL_STR);
} }
static Token Token
character(void) lex_character(void)
{ {
advance(); lex_advance();
if(peek() != '\'' && !is_at_end()) { if(peek() != '\'' && !is_at_end()) {
advance(); lex_advance();
} }
if(is_at_end()) return error_token("Unterminated string."); if(is_at_end()) return error_token("Unterminated string.");
/* The closing quote. */ /* The closing quote. */
advance(); lex_advance();
return make_token(TOKEN_LITERAL_CHAR); return make_token(TOKEN_LITERAL_CHAR);
} }
@ -407,10 +407,10 @@ next_token(void)
if(is_at_end()) return make_token(TOKEN_EOF); if(is_at_end()) return make_token(TOKEN_EOF);
c = advance(); c = lex_advance();
if(is_alpha(c)) return identifier(); if(lex_is_alpha(c)) return identifier();
next = peek(); next = peek();
if((c == '-' && is_digit(next)) || is_digit(c)) return number(); if((c == '-' && lex_is_digit(next)) || lex_is_digit(c)) return lex_number();
switch(c) { switch(c) {
case '(': case '(':
@ -432,13 +432,13 @@ next_token(void)
case '.': case '.':
return make_token(TOKEN_DOT); return make_token(TOKEN_DOT);
case '-': case '-':
return make_token(match('>') ? TOKEN_ARROW_RIGHT : TOKEN_MINUS); return make_token(lex_match('>') ? TOKEN_ARROW_RIGHT : TOKEN_MINUS);
case '+': case '+':
return make_token(TOKEN_PLUS); return make_token(TOKEN_PLUS);
case '/': case '/':
return make_token(TOKEN_SLASH); return make_token(TOKEN_SLASH);
case '&': case '&':
return make_token(match('&') ? TOKEN_AND_AND : TOKEN_AND); return make_token(lex_match('&') ? TOKEN_AND_AND : TOKEN_AND);
case '#': case '#':
return make_token(TOKEN_MESH); return make_token(TOKEN_MESH);
case '$': case '$':
@ -446,21 +446,21 @@ next_token(void)
case '*': case '*':
return make_token(TOKEN_STAR); return make_token(TOKEN_STAR);
case '!': case '!':
return make_token(match('=') ? TOKEN_BANG_EQ : TOKEN_BANG); return make_token(lex_match('=') ? TOKEN_BANG_EQ : TOKEN_BANG);
case '=': case '=':
return make_token(match('=') ? TOKEN_EQ_EQ : TOKEN_EQ); return make_token(lex_match('=') ? TOKEN_EQ_EQ : TOKEN_EQ);
case '<': case '<':
return make_token(match('=') ? TOKEN_LTE return make_token(lex_match('=') ? TOKEN_LTE
: match('<') ? TOKEN_SLL : lex_match('<') ? TOKEN_SLL
: TOKEN_LT); : TOKEN_LT);
case '>': case '>':
return make_token(match('=') ? TOKEN_GTE return make_token(lex_match('=') ? TOKEN_GTE
: match('>') ? TOKEN_SRL : lex_match('>') ? TOKEN_SRL
: TOKEN_GT); : TOKEN_GT);
case '"': case '"':
return string(); return lex_string();
case '\'': case '\'':
return character(); return lex_character();
} }
return error_token("Unexpected character."); return error_token("Unexpected character.");

15
libc.c
View File

@ -78,13 +78,16 @@ snlen(const char *str, u32 max_len)
void * void *
aalloc(Arena *arena, u32 size) aalloc(Arena *arena, u32 size)
{ {
u32 pos; u32 pos, aligned;
if(arena == nil) return nil; if(arena == nil) return nil;
if(arena->count + size > arena->capacity) return nil;
pos = arena->count; aligned = (arena->count + 7) & ~7;
arena->count += size;
return (void *)&arena->tape[pos]; if(aligned + size > arena->capacity) return nil;
pos = aligned;
arena->count = pos + size;
return (void *)&arena->tape[pos];
} }
u32 u32