WIP array fixes

This commit is contained in:
zongor 2026-07-04 15:01:14 -07:00
parent 0ab7ef872b
commit 9c746ad15b
1 changed files with 102 additions and 83 deletions

View File

@ -209,7 +209,7 @@ 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);
} }
} }
@ -278,20 +278,21 @@ calculate_strides(List *dims, List *strides)
u32 num_dims = dims->count; u32 num_dims = dims->count;
u32 current_stride = 1; u32 current_stride = 1;
if (num_dims == 1) { if(num_dims == 1) {
List_push(arena, strides, &current_stride, sizeof(u32)); List_push(arena, strides, &current_stride, sizeof(u32));
return; return;
} }
for(i = num_dims - 1; i > 0; i--) { for(i = num_dims - 1; i > 0; i--) {
List_push(arena, strides, &current_stride, sizeof(u32)); List_push(arena, strides, &current_stride, sizeof(u32));
/* this is very slow but for small numbers of dimensions its fine */ /* this is very slow but for small numbers of dimensions its fine */
num = (u32*)List_get(dims, i); num = (u32 *)List_get(dims, i);
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);
} }
} }
} }
@ -303,7 +304,7 @@ define_array(void)
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;
List *dims = List_init(arena); List *dims = List_init(arena);
List *strides = List_init(arena); List *strides = List_init(arena);
advance(); advance();
@ -324,7 +325,7 @@ 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);
array->args = dims; array->args = dims;
@ -334,9 +335,8 @@ define_array(void)
void void
define_string(void) define_string(void)
{ {
scope_add_symbol(parser->current.start, scope_add_symbol(parser->current.start, parser->current.length, SYMBOL_STR,
parser->current.length, 0);
SYMBOL_STR, 0);
} }
void void
@ -358,14 +358,13 @@ 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->previous.type != TOKEN_KEYWORD_AS && match(TOKEN_TYPE_STR)) { } else if(parser->previous.type != TOKEN_KEYWORD_AS &&
match(TOKEN_TYPE_STR)) {
define_string(); define_string();
} 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();
}
} else { } else {
/* in binary bytecode output mode we need to count the bytes here */ /* in binary bytecode output mode we need to count the bytes here */
/* otherwise ignore everything */ /* otherwise ignore everything */
@ -389,51 +388,47 @@ variable_declaration(Symbol *def)
Symbol *variable; Symbol *variable;
List *array_literal; List *array_literal;
if(tt == TOKEN_TYPE_STR) {
if (tt == TOKEN_TYPE_STR) { variable = scope_get_symbol(parser->current_scope, parser->current.start,
variable = scope_get_symbol(parser->current_scope, parser->current.length);
parser->current.start, if(!variable) {
parser->current.length);
if (!variable) {
emitter->error("cannot find str symbol", 23, parser->current.line); emitter->error("cannot find str symbol", 23, parser->current.line);
return 0; return 0;
} }
advance(); advance();
if (match(TOKEN_EQ)) { if(match(TOKEN_EQ)) {
expect(TOKEN_LITERAL_STR); expect(TOKEN_LITERAL_STR);
variable->size = parser->previous.length - 2; variable->size = parser->previous.length - 2;
emitter->emit_str(arena, memory, variable, parser->previous.start, parser->previous.length); emitter->emit_str(arena, memory, variable, parser->previous.start,
parser->previous.length);
expect(TOKEN_SEMICOLON); expect(TOKEN_SEMICOLON);
} }
parser->current_type = st; parser->current_type = st;
return emitter->get_size(st); return emitter->get_size(st);
} }
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", 25, parser->current.line); emitter->error("cannot find array symbol", 25, parser->current.line);
return 0; return 0;
} }
advance(); advance();
if (match(TOKEN_EQ)) { if(match(TOKEN_EQ)) {
expect(TOKEN_LBRACKET); expect(TOKEN_LBRACKET);
array_literal = List_init(arena); array_literal = List_init(arena);
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);
@ -443,11 +438,13 @@ variable_declaration(Symbol *def)
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));
} }
parser->current_type = st; parser->current_type = st;
return emitter->get_size(st); return emitter->get_size(st);
} }
@ -455,7 +452,8 @@ variable_declaration(Symbol *def)
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;
@ -475,7 +473,7 @@ variable_declaration(Symbol *def)
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)) {
@ -583,7 +581,7 @@ dot(void)
parser->before.length); parser->before.length);
if(sym == nil) { if(sym == nil) {
emitter->error(parser->current.start, parser->current.length, emitter->error(parser->current.start, parser->current.length,
parser->current.line); parser->current.line);
} }
} }
@ -595,7 +593,7 @@ variable(void)
if(sym == nil) { if(sym == nil) {
return; return;
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) {
@ -603,83 +601,87 @@ variable(void)
return; return;
} }
if (sym->type == SYMBOL_STR) { if(sym->type == SYMBOL_STR) {
emitter->emit_deref_prolog(arena, code, sym); emitter->emit_deref_prolog(arena, code, sym);
if (match(TOKEN_LBRACKET)) { if(match(TOKEN_LBRACKET)) {
/* 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, 2); emitter->emit_add(arena, code, 2);
expression(); expression();
emitter->emit_add(arena, code, 2); emitter->emit_add(arena, code, 2);
while (!match(TOKEN_RBRACKET)) { while(!match(TOKEN_RBRACKET)) {
} }
if (match(TOKEN_EQ)) { if(match(TOKEN_EQ)) {
expression(); expression();
emitter->emit_stack_rot(arena, code, 1); emitter->emit_stack_rot(arena, code, 1);
emitter->emit_stack_rot(arena, code, 1); emitter->emit_stack_rot(arena, code, 1);
emitter->emit_ref_store(arena, code, 1); emitter->emit_ref_store(arena, code, 1);
} else { } else {
emitter->emit_deref(arena, code, 1); emitter->emit_deref(arena, code, 1);
} }
parser->current_type = SYMBOL_BYTE; parser->current_type = SYMBOL_BYTE;
} 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, 2); emitter->emit_deref(arena, code, 2);
} 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);
} }
parser->current_type = SYMBOL_NAT; parser->current_type = SYMBOL_NAT;
advance(); advance();
} else { } else {
emitter->emit_nat(arena, code, "2", 1); emitter->emit_nat(arena, code, "2", 1);
emitter->emit_add(arena, code, 2); emitter->emit_add(arena, code, 2);
/* emitter->emit_deref(arena, code); */ /* emitter->emit_deref(arena, code); */
} }
return; return;
} }
if (sym->type == SYMBOL_ARRAY) { if(sym->type == SYMBOL_ARRAY) {
u32 size = emitter->get_size(sym->secondary_type); u32 size = emitter->get_size(sym->secondary_type);
if (match(TOKEN_LBRACKET)) { if(match(TOKEN_LBRACKET)) {
emitter->emit_deref_prolog(arena, code, sym); emitter->emit_deref_prolog(arena, code, sym);
expression(); expression();
emitter->emit_address(arena, code, 2); emitter->emit_address(arena, code, 2);
emitter->emit_mul(arena, code, 2); emitter->emit_mul(arena, code, 2);
emitter->emit_add(arena, code, 2); emitter->emit_add(arena, code, 2);
/* 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, 2); emitter->emit_add(arena, code, 2);
while (!match(TOKEN_RBRACKET)) { while(!match(TOKEN_RBRACKET)) {
/* eventually do something with multidimensional arrays */ /* eventually do something with multidimensional arrays */
} }
if (match(TOKEN_EQ)) { if(match(TOKEN_EQ)) {
expression(); expression();
if (size == 1) { if(size == 1) {
emitter->emit_stack_rot(arena, code, 1); emitter->emit_stack_rot(arena, code, 1);
emitter->emit_stack_rot(arena, code, 1); emitter->emit_stack_rot(arena, code, 1);
} else { } else {
emitter->emit_stack_swap(arena, code, 2); emitter->emit_stack_swap(arena, code, 2);
} }
emitter->emit_ref_store(arena, code, size); emitter->emit_ref_store(arena, code, size);
} else { } else {
emitter->emit_deref(arena, code, size); emitter->emit_deref(arena, code, size);
} }
parser->current_type = sym->secondary_type; parser->current_type = sym->secondary_type;
} else if (match(TOKEN_DOT)) { } else if(match(TOKEN_DOT)) {
emitter->emit_deref_prolog(arena, code, sym); emitter->emit_deref_prolog(arena, code, sym);
if (sleq("length", parser->current.start, parser->current.length)) { if(sleq("length", parser->current.start, parser->current.length)) {
emitter->emit_deref(arena, code, size); emitter->emit_deref(arena, code, size);
} 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);
} }
parser->current_type = SYMBOL_NAT; parser->current_type = SYMBOL_NAT;
advance(); advance();
@ -789,14 +791,16 @@ cast_type(void)
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();
@ -826,7 +830,8 @@ if_statement(void)
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
@ -930,19 +935,33 @@ grouping(void)
void void
number(void) number(void)
{ {
emitter->emit_int(arena, code, parser->previous.start, parser->previous.length); switch(parser->current_type) {
case SYMBOL_BOOL:
case SYMBOL_BYTE:
case SYMBOL_U8:
case SYMBOL_I8:
emitter->emit_char(arena, code, parser->previous.start,
parser->previous.length);
break;
default:
emitter->emit_nat(arena, code, parser->previous.start,
parser->previous.length);
break;
}
} }
void void
string(void) string(void)
{ {
emitter->emit_inline_str(arena, code, parser->previous.start, parser->previous.length); emitter->emit_inline_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
@ -992,7 +1011,7 @@ ParseRule rules[] = {
/* TOKEN_RBRACE */ {nil, nil, PREC_NONE}, /* TOKEN_RBRACE */ {nil, nil, PREC_NONE},
/* TOKEN_LBRACKET */ {nil, nil, PREC_NONE}, /* TOKEN_LBRACKET */ {nil, nil, PREC_NONE},
/* TOKEN_RBRACKET */ {nil, nil, PREC_NONE}, /* TOKEN_RBRACKET */ {nil, nil, PREC_NONE},
/* TOKEN_DOT */ {nil, dot, PREC_CALL}, /* TOKEN_DOT */ {nil, dot, PREC_CALL},
/* TOKEN_IDENTIFIER */ {variable, nil, PREC_NONE}, /* TOKEN_IDENTIFIER */ {variable, nil, PREC_NONE},
/* TOKEN_LITERAL_INT */ {number, nil, PREC_NONE}, /* TOKEN_LITERAL_INT */ {number, nil, PREC_NONE},
/* TOKEN_LITERAL_NAT */ {number, nil, PREC_NONE}, /* TOKEN_LITERAL_NAT */ {number, nil, PREC_NONE},
@ -1025,7 +1044,7 @@ ParseRule rules[] = {
/* TOKEN_KEYWORD_THIS */ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_THIS */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_OPEN */ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_OPEN */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_READ */ {read, nil, PREC_NONE}, /* TOKEN_KEYWORD_READ */ {read, nil, PREC_NONE},
/* TOKEN_KEYWORD_WRITE */ { write, nil, PREC_NONE}, /* TOKEN_KEYWORD_WRITE */ {write, nil, PREC_NONE},
/* TOKEN_KEYWORD_STAT */ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_STAT */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_CLOSE */ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_CLOSE */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_LOOP */ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_LOOP */ {nil, nil, PREC_NONE},
@ -1070,7 +1089,7 @@ ParseRule rules[] = {
/* TOKEN_KEYWORD_DEVMAP*/ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_DEVMAP*/ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_BYTE*/ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_BYTE*/ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_CHAR*/ {character, nil, PREC_NONE}, /* TOKEN_KEYWORD_CHAR*/ {character, nil, PREC_NONE},
}; };
void void
parse_precedence(Precedence precedence) parse_precedence(Precedence precedence)
@ -1106,12 +1125,12 @@ emit_program(char *source)
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}; Parser p = {0};
arena = a; arena = a;