mirror of
https://github.com/sigmasternchen/macrofuck
synced 2025-03-15 07:08:56 +00:00
feat: Add support for array subscripts
This commit is contained in:
parent
aa28a78102
commit
14edad9a88
10 changed files with 100 additions and 16 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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*);
|
||||
|
||||
|
|
4
compiler/test/cases/020c-print-array-offset.in
Normal file
4
compiler/test/cases/020c-print-array-offset.in
Normal file
|
@ -0,0 +1,4 @@
|
|||
var a = []{'a', 'b', 'c'};
|
||||
|
||||
print(a[0], '\n');
|
||||
print(a[1], '\n');
|
3
compiler/test/cases/020c-print-array-offset.out
Normal file
3
compiler/test/cases/020c-print-array-offset.out
Normal file
|
@ -0,0 +1,3 @@
|
|||
>>>[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>[-]<[-<<<+>>>>+<]>[-<+>]<[-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>[-]<[-<<+>>>+<]>[-<+>]<[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>[-]<[-<+>>+<]>[-<+>]
|
||||
<[-]++++++++++<<<.>>>.
|
||||
[-]++++++++++<<.>>.
|
Loading…
Reference in a new issue