feat: Add support for array subscripts

This commit is contained in:
overflowerror 2024-05-02 14:28:08 +02:00
parent aa28a78102
commit 14edad9a88
10 changed files with 100 additions and 16 deletions

View file

@ -135,11 +135,25 @@ struct expression* literal_expression_array_new(size_t length, struct expression
}
struct expression* variable_expression_new(char* id) {
_new(expr, expression);
expr->kind = VARIABLE;
expr->type = UNKNOWN_TYPE;
expr->variable = (struct variable_expression) {
.id = id,
.is_offset = false,
.offset = 0,
};
return expr;
}
struct expression* variable_expression_new_offset(char* id, size_t offset) {
_new(expr, expression);
expr->kind = VARIABLE;
expr->type = UNKNOWN_TYPE;
expr->variable = (struct variable_expression) {
.id = id,
.is_offset = true,
.offset = offset,
};
return expr;
}

View file

@ -2,6 +2,7 @@
#define AST_H
#include <stdlib.h>
#include <stdbool.h>
enum literal_kind {
NUMBER_LITERAL,
@ -50,6 +51,8 @@ struct literal_expression {
struct variable_expression {
char* id;
bool is_offset;
size_t offset;
};
struct macro_expression {
@ -147,6 +150,7 @@ struct expression* literal_expression_str_new(char*);
struct expression* literal_expression_num_new(long long);
struct expression* literal_expression_array_new(size_t, struct expression**);
struct expression* variable_expression_new(char*);
struct expression* variable_expression_new_offset(char*, size_t);
struct expression* macro_expression_new(char*, char*);
struct expression* builtin_call_expression_new(void);
void builtin_call_expression_add_argument(struct expression*, struct expression*);

View file

@ -60,12 +60,20 @@ size_t band_find_empty_region_index(band_t* band) {
region_t* band_allocate_region(band_t* band, size_t size) {
region_t* region = safe_malloc(sizeof(region_t));
band_addr_t addr = band_find_gap(band, size);
size_t regions_index = band_find_empty_region_index(band);
size_t regions_index = band_find_empty_region_index(band);
band_addr_t addr;
if (size != 0) {
addr = band_find_gap(band, size);
} else {
addr = 0;
}
region->start = addr;
region->size = size;
region->index = regions_index;
region->ref_count = 1;
region->parent = NULL;
band->regions[regions_index] = region;
for (size_t i = 0; i < size; i++) {
@ -91,13 +99,38 @@ region_t* band_allocate_tmp(band_t* band, size_t size) {
return region;
}
void band_region_free(band_t* band, region_t* region) {
band->regions[region->index] = NULL;
for (size_t i = 0; i < region->size; i++) {
band->band[region->start + i] = NULL;
}
region_t* band_allocate_ref(band_t* band, region_t* parent) {
region_t* region = band_allocate_region(band, 0);
region->name = NULL;
region->is_temp = true;
free(region);
parent->ref_count++;
region->parent = parent;
region->size = parent->size;
region->start = parent->start;
return region;
}
void band_region_free(band_t* band, region_t* region) {
region->ref_count--;
if (region->ref_count == 0) {
if (region->parent == NULL) {
band->regions[region->index] = NULL;
for (size_t i = 0; i < region->size; i++) {
band->band[region->start + i] = NULL;
}
free(region);
} else {
band_region_free(band, region->parent);
band->regions[region->index] = NULL;
free(region);
}
}
}
void band_region_free_raw(band_t* band, band_addr_t addr) {

View file

@ -8,12 +8,14 @@
typedef size_t band_addr_t;
typedef struct {
typedef struct region {
band_addr_t start;
size_t index;
size_t size;
const char* name;
bool is_temp;
bool is_temp;
size_t ref_count;
struct region* parent;
} region_t;
typedef struct {
@ -28,6 +30,7 @@ region_t* band_region_for_addr(band_t*, band_addr_t);
region_t* band_allocate(band_t*, size_t);
region_t* band_allocate_tmp(band_t*, size_t);
region_t* band_allocate_ref(band_t*, region_t*);
void band_region_free(band_t*, region_t*);
void band_region_free_raw(band_t*, band_addr_t);

View file

@ -67,6 +67,16 @@ static region_t* codegen_variable_expr(FILE* _, scope_t* scope, struct variable_
fprintf(stderr, "unknown variable: %s\n", expr.id);
exit(1);
}
if (expr.is_offset) {
if (expr.offset >= region->size) {
fprintf(stderr, "index out of bounds (%zu >= %zu)\n", expr.offset, region->size);
exit(1);
}
region = scope_add_ref(scope, region, expr.offset, 1);
}
return region;
}

View file

@ -260,6 +260,16 @@ literal: NUM
| arrayliteral
;
variable: ID
{
$$ = variable_expression_new($1);
}
| ID OPENING_SQ_BRACKETS NUM CLOSING_SQ_BRACKETS
{
$$ = variable_expression_new_offset($1, $3);
}
;
arrayliteral: OPENING_SQ_BRACKETS NUM CLOSING_SQ_BRACKETS
{
$$ = literal_expression_array_new($2, NULL);
@ -273,12 +283,6 @@ arrayliteral: OPENING_SQ_BRACKETS NUM CLOSING_SQ_BRACKETS
}
;
variable: ID
{
$$ = variable_expression_new($1);
}
;
macroexpr: ID MACRO_CONTENT
{
$$ = macro_expression_new($1, $2);

View file

@ -46,6 +46,14 @@ region_t* scope_add_tmp(scope_t* scope, size_t size) {
return region;
}
region_t* scope_add_ref(scope_t* scope, region_t* parent, size_t offset, size_t size) {
region_t* region = band_allocate_ref(scope->band, parent);
region->start += offset;
region->size = size;
return region;
}
region_t* scope_get(scope_t* scope, const char* name) {
region_t* region = dict_get(scope->variables, name);

View file

@ -17,6 +17,7 @@ scope_t* scope_new(scope_t*);
region_t* scope_add(scope_t*, const char*, size_t);
region_t* scope_existing(scope_t*, region_t*, const char*);
region_t* scope_add_tmp(scope_t*, size_t);
region_t* scope_add_ref(scope_t*, region_t*, size_t, size_t);
region_t* scope_get(scope_t*, const char*);

View file

@ -0,0 +1,4 @@
var a = []{'a', 'b', 'c'};
print(a[0], '\n');
print(a[1], '\n');

View file

@ -0,0 +1,3 @@
>>>[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>[-]<[-<<<+>>>>+<]>[-<+>]<[-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>[-]<[-<<+>>>+<]>[-<+>]<[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>[-]<[-<+>>+<]>[-<+>]
<[-]++++++++++<<<.>>>.
[-]++++++++++<<.>>.