refactor: Change to scope based system

This commit is contained in:
overflowerror 2024-02-19 23:15:53 +01:00
parent f0a04a6a65
commit 19ed35d535
11 changed files with 289 additions and 154 deletions

View file

@ -11,7 +11,7 @@ LEXFLAGS =
PLUGINS = obj/macros/numbers.o
OBJS = obj/lex.yy.o obj/y.tab.o obj/codegen.o obj/error.o \
obj/ast.o obj/alloc.o obj/dict.o obj/list.o obj/band.o \
obj/plugins.o $(PLUGINS) obj/main.o
obj/plugins.o obj/scope.o $(PLUGINS) obj/main.o
DEPS = $(OBJS:%.o=%.d)
-include $(DEPS)

View file

@ -3,14 +3,12 @@
#include "band.h"
#include "list.h"
#include "dict.h"
#include "alloc.h"
band_t* band_init(void) {
band_t* band = safe_malloc(sizeof(band_t));
band->position = 0;
band->regions = list_new(region_t);
band->variables = dict_new();
band->band = list_new(region_t);
return band;
}
@ -24,10 +22,6 @@ region_t* band_region_for_addr(band_t* band, band_addr_t addr) {
}
}
region_t* band_region_for_var(band_t* band, const char* variable) {
return dict_get(band->variables, variable);
}
band_addr_t band_find_gap(band_t* band, size_t size) {
size_t band_size = list_size(band->band);
@ -80,24 +74,17 @@ region_t* band_allocate_region(band_t* band, size_t size) {
return region;
}
void band_make_var(band_t* band, region_t* region, const char* variable) {
region->variable = variable;
region->is_temp = false;
dict_put(band->variables, variable, region);
}
region_t* band_allocate_var(band_t* band, size_t size, const char* variable) {
region_t* band_allocate(band_t* band, size_t size) {
region_t* region = band_allocate_region(band, size);
band_make_var(band, region, variable);
region->name = NULL;
region->is_temp = false;
return region;
}
region_t* band_allocate_tmp(band_t* band, size_t size) {
region_t* region = band_allocate_region(band, size);
region->variable = NULL;
region->name = NULL;
region->is_temp = true;
return region;
@ -109,10 +96,6 @@ void band_region_free(band_t* band, region_t* region) {
band->band[region->start + i] = NULL;
}
if (region->variable) {
dict_remove(band->variables, region->variable);
}
free(region);
}

View file

@ -5,7 +5,6 @@
#include <stdlib.h>
#include "list.h"
#include "dict.h"
typedef size_t band_addr_t;
@ -13,25 +12,22 @@ typedef struct {
band_addr_t start;
size_t index;
size_t size;
const char* variable;
const char* name;
bool is_temp;
} region_t;
typedef struct {
size_t position;
region_t** regions;
dict_t* variables;
region_t** band;
} band_t;
band_t* band_init(void);
region_t* band_region_for_addr(band_t*, band_addr_t);
region_t* band_region_for_var(band_t*, const char*);
region_t* band_allocate_var(band_t*, size_t, const char*);
region_t* band_allocate(band_t*, size_t);
region_t* band_allocate_tmp(band_t*, size_t);
void band_make_var(band_t*, region_t*, const char*);
void band_region_free(band_t*, region_t*);
void band_region_free_raw(band_t*, band_addr_t);

View file

@ -5,28 +5,29 @@
#include "codegen.h"
#include "ast.h"
#include "band.h"
#include "scope.h"
#include "error.h"
#include "plugins.h"
void _move_to(FILE* out, band_t* band, size_t target) {
while (target > band->position) {
void _move_to(FILE* out, scope_t* scope, size_t target) {
while (target > scope->band->position) {
next();
band->position++;
scope->band->position++;
}
while (target < band->position) {
while (target < scope->band->position) {
prev();
band->position--;
scope->band->position--;
}
}
void _copy(FILE* out, band_t* band, region_t* source, region_t* target) {
void _copy(FILE* out, scope_t* scope, region_t* source, region_t* target) {
size_t size = source->size;
if (target->size < size) {
size = target->size;
}
region_t* tmp = band_allocate_tmp(band, size);
region_t* tmp = scope_add_tmp(scope, size);
move_to(tmp); reset();
for (size_t i = 0; i < size; i++) {
@ -48,41 +49,41 @@ void _copy(FILE* out, band_t* band, region_t* source, region_t* target) {
});
}
band_region_free(band, tmp);
scope_remove(scope, tmp);
}
region_t* _clone(FILE* out, band_t* band, region_t* region) {
region_t* clone = band_allocate_tmp(band, region->size);
region_t* _clone(FILE* out, scope_t* scope, region_t* region) {
region_t* clone = scope_add_tmp(scope, region->size);
move_to(clone); reset();
copy(region, clone);
return clone;
}
static void region_used(band_t* band, region_t* region) {
static void region_used(scope_t* scope, region_t* region) {
if (region->is_temp) {
band_region_free(band, region);
scope_remove(scope, region);
}
}
static void reset_position(FILE* out, band_t* band, band_addr_t position) {
static void reset_position(FILE* out, scope_t* scope, band_addr_t position) {
move(position);
reset();
}
static void reset_region(FILE* out, band_t* band, region_t* region) {
static void reset_region(FILE* out, scope_t* scope, region_t* region) {
for (size_t i = 0; i < region->size; i++) {
reset_position(out, band, region->start + i);
reset_position(out, scope, region->start + i);
}
}
void codegen_add_char(FILE* out, band_t* band, size_t position, char c) {
void codegen_add_char(FILE* out, scope_t* scope, size_t position, char c) {
move(position);
reset();
add(c);
}
region_t* codegen_literal_expr(FILE* out, band_t* band, struct literal_expression expr) {
region_t* codegen_literal_expr(FILE* out, scope_t* scope, struct literal_expression expr) {
region_t* region = NULL;
switch(expr.kind) {
case NUMBER_LITERAL:
@ -90,19 +91,19 @@ region_t* codegen_literal_expr(FILE* out, band_t* band, struct literal_expressio
fprintf(stderr, "literal %lld greater than 255\n", expr.number);
panic("number literal too big");
}
region = band_allocate_tmp(band, 1);
region = scope_add_tmp(scope, 1);
move_to(region);
reset(); add(expr.number);
break;
case CHAR_LITERAL:
region = band_allocate_tmp(band, 1);
codegen_add_char(out, band, region->start, expr.ch);
region = scope_add_tmp(scope, 1);
codegen_add_char(out, scope, region->start, expr.ch);
break;
case STRING_LITERAL: {
size_t l = strlen(expr.str); // don't copy \0
region = band_allocate_tmp(band, strlen(expr.str));
region = scope_add_tmp(scope, strlen(expr.str));
for (size_t i = 0; i < l; i++) {
codegen_add_char(out, band, region->start + i, expr.str[i]);
codegen_add_char(out, scope, region->start + i, expr.str[i]);
}
break;
}
@ -113,8 +114,8 @@ region_t* codegen_literal_expr(FILE* out, band_t* band, struct literal_expressio
return region;
}
region_t* codegen_variable_expr(FILE* _, band_t* band, struct variable_expression expr) {
region_t* region = band_region_for_var(band, expr.id);
region_t* codegen_variable_expr(FILE* _, scope_t* scope, struct variable_expression expr) {
region_t* region = scope_get(scope, expr.id);
if (!region) {
fprintf(stderr, "unknown variable: %s\n", expr.id);
exit(1);
@ -122,12 +123,12 @@ region_t* codegen_variable_expr(FILE* _, band_t* band, struct variable_expressio
return region;
}
region_t* codegen_macro_expr(FILE* out, band_t* band, struct macro_expression expr) {
region_t* codegen_macro_expr(FILE* out, scope_t* scope, struct macro_expression expr) {
macro_t macro = find_macro(expr.id);
return macro(out, band, expr.argument);
return macro(out, scope, expr.argument);
}
region_t* codegen_expr(FILE*, band_t*, struct expression*);
region_t* codegen_expr(FILE*, scope_t*, struct expression*);
#define swap_or_clone(result, op1, op2, allow_swap) \
if (op1->is_temp) { \
@ -147,10 +148,10 @@ region_t* codegen_expr(FILE*, band_t*, struct expression*);
}
#define calc_postfix() \
band_region_free(band, op2); \
scope_remove(scope, op2); \
return result;
region_t* codegen_addition(FILE* out, band_t* band, region_t* op1, region_t* op2) {
region_t* codegen_addition(FILE* out, scope_t* scope, region_t* op1, region_t* op2) {
calc_prefix(true);
move_to(op2);
@ -162,7 +163,7 @@ region_t* codegen_addition(FILE* out, band_t* band, region_t* op1, region_t* op2
calc_postfix();
}
region_t* codegen_subtraction(FILE* out, band_t* band, region_t* op1, region_t* op2) {
region_t* codegen_subtraction(FILE* out, scope_t* scope, region_t* op1, region_t* op2) {
calc_prefix(false);
move_to(op2);
@ -174,7 +175,7 @@ region_t* codegen_subtraction(FILE* out, band_t* band, region_t* op1, region_t*
calc_postfix();
}
region_t* codegen_multiplication(FILE* out, band_t* band, region_t* op1, region_t* op2) {
region_t* codegen_multiplication(FILE* out, scope_t* scope, region_t* op1, region_t* op2) {
calc_prefix(true);
// make sure to not change op1
@ -198,12 +199,12 @@ region_t* codegen_multiplication(FILE* out, band_t* band, region_t* op1, region_
move_to(op2);
});
band_region_free(band, tmp);
band_region_free(band, op1);
scope_remove(scope, tmp);
scope_remove(scope, op1);
calc_postfix();
}
region_t* codegen_division(FILE* out, band_t* band, region_t* op1, region_t* op2) {
region_t* codegen_division(FILE* out, scope_t* scope, region_t* op1, region_t* op2) {
if (!op1->is_temp) {
op1 = clone(op1);
}
@ -211,16 +212,16 @@ region_t* codegen_division(FILE* out, band_t* band, region_t* op1, region_t* op2
op2 = clone(op2);
}
region_t* result = band_allocate_tmp(band, 1);
region_t* result = scope_add_tmp(scope, 1);
move_to(result); reset();
region_t* tmp = band_allocate_tmp(band, 1);
region_t* tmp = scope_add_tmp(scope, 1);
move_to(tmp); reset();
copy(op2, tmp);
region_t* tmp2 = band_allocate_tmp(band, 1);
region_t* tmp2 = scope_add_tmp(scope, 1);
region_t* flag = band_allocate_tmp(band, 1);
region_t* flag = scope_add_tmp(scope, 1);
move_to(op1);
loop({
@ -248,14 +249,14 @@ region_t* codegen_division(FILE* out, band_t* band, region_t* op1, region_t* op2
move_to(op1);
});
band_region_free(band, flag);
band_region_free(band, tmp2);
band_region_free(band, tmp);
band_region_free(band, op1);
band_region_free(band, op2);
scope_remove(scope, flag);
scope_remove(scope, tmp2);
scope_remove(scope, tmp);
scope_remove(scope, op1);
scope_remove(scope, op2);
return result;
}
region_t* codegen_modulo(FILE* out, band_t* band, region_t* op1, region_t* op2) {
region_t* codegen_modulo(FILE* out, scope_t* scope, region_t* op1, region_t* op2) {
if (!op1->is_temp) {
op1 = clone(op1);
}
@ -263,13 +264,13 @@ region_t* codegen_modulo(FILE* out, band_t* band, region_t* op1, region_t* op2)
op2 = clone(op2);
}
region_t* tmp = band_allocate_tmp(band, 1);
region_t* tmp = scope_add_tmp(scope, 1);
move_to(tmp); reset();
copy(op2, tmp);
region_t* tmp2 = band_allocate_tmp(band, 1);
region_t* tmp2 = scope_add_tmp(scope, 1);
region_t* flag = band_allocate_tmp(band, 1);
region_t* flag = scope_add_tmp(scope, 1);
move_to(op1);
loop({
@ -314,34 +315,34 @@ region_t* codegen_modulo(FILE* out, band_t* band, region_t* op1, region_t* op2)
move_to(tmp);
});
band_region_free(band, flag);
band_region_free(band, tmp2);
band_region_free(band, tmp);
band_region_free(band, op2);
scope_remove(scope, flag);
scope_remove(scope, tmp2);
scope_remove(scope, tmp);
scope_remove(scope, op2);
return op1;
}
region_t* codegen_calc_expr(FILE* out, band_t* band, struct calc_expression expr) {
region_t* operand1 = codegen_expr(out, band, expr.operand1);
region_t* operand2 = codegen_expr(out, band, expr.operand2);
region_t* codegen_calc_expr(FILE* out, scope_t* scope, struct calc_expression expr) {
region_t* operand1 = codegen_expr(out, scope, expr.operand1);
region_t* operand2 = codegen_expr(out, scope, expr.operand2);
region_t* result;
switch (expr.operator) {
case ADDITION:
result = codegen_addition(out, band, operand1, operand2);
result = codegen_addition(out, scope, operand1, operand2);
break;
case SUBTRACTION:
result = codegen_subtraction(out, band, operand1, operand2);
result = codegen_subtraction(out, scope, operand1, operand2);
break;
case MULTIPLICATION:
result = codegen_multiplication(out, band, operand1, operand2);
result = codegen_multiplication(out, scope, operand1, operand2);
break;
case DIVISION:
result = codegen_division(out, band, operand1, operand2);
result = codegen_division(out, scope, operand1, operand2);
break;
case MODULO:
result = codegen_modulo(out, band, operand1, operand2);
result = codegen_modulo(out, scope, operand1, operand2);
break;
default:
fprintf(stderr, "unknown operator: %d\n", expr.operator);
@ -351,16 +352,16 @@ region_t* codegen_calc_expr(FILE* out, band_t* band, struct calc_expression expr
return result;
}
region_t* codegen_expr(FILE* out, band_t* band, struct expression* expr) {
region_t* codegen_expr(FILE* out, scope_t* scope, struct expression* expr) {
switch(expr->kind) {
case LITERAL:
return codegen_literal_expr(out, band, expr->literal);
return codegen_literal_expr(out, scope, expr->literal);
case VARIABLE:
return codegen_variable_expr(out, band, expr->variable);
return codegen_variable_expr(out, scope, expr->variable);
case MACRO:
return codegen_macro_expr(out, band, expr->macro);
return codegen_macro_expr(out, scope, expr->macro);
case CALCULATION:
return codegen_calc_expr(out, band, expr->calc);
return codegen_calc_expr(out, scope, expr->calc);
default:
fprintf(stderr, "expression kind: %d\n", expr->kind);
panic("unknown expression kind");
@ -368,8 +369,8 @@ region_t* codegen_expr(FILE* out, band_t* band, struct expression* expr) {
}
}
void codegen_print_statement(FILE* out, band_t* band, struct print_statement statement) {
region_t* region = codegen_expr(out, band, statement.value);
void codegen_print_statement(FILE* out, scope_t* scope, struct print_statement statement) {
region_t* region = codegen_expr(out, scope, statement.value);
move_to(region);
output();
@ -377,18 +378,18 @@ void codegen_print_statement(FILE* out, band_t* band, struct print_statement sta
next();
output();
}
band->position += region->size - 1;
scope->band->position += region->size - 1;
region_used(band, region);
region_used(scope, region);
}
region_t* clone_region(FILE* out, band_t* band, region_t* original) {
region_t* tmp = band_allocate_tmp(band, 1);
region_t* clone = band_allocate_tmp(band, original->size);
region_t* clone_region(FILE* out, scope_t* scope, region_t* original) {
region_t* tmp = scope_add_tmp(scope, 1);
region_t* clone = scope_add_tmp(scope, original->size);
reset_position(out, band, tmp->start);
reset_position(out, scope, tmp->start);
for (size_t i = 0; i < original->size; i++) {
reset_position(out, band, clone->start + i);
reset_position(out, scope, clone->start + i);
move_offset(original, i);
loop({
@ -409,13 +410,13 @@ region_t* clone_region(FILE* out, band_t* band, region_t* original) {
});
}
band_region_free(band, tmp);
scope_remove(scope, tmp);
return clone;
}
void codegen_assignment_statement(FILE* out, band_t* band, struct assignment_statement statement) {
region_t* region = codegen_expr(out, band, statement.value);
region_t* var = band_region_for_var(band, statement.id);
void codegen_assignment_statement(FILE* out, scope_t* scope, struct assignment_statement statement) {
region_t* region = codegen_expr(out, scope, statement.value);
region_t* var = scope_get(scope, statement.id);
if (!var) {
fprintf(stderr, "variable not found: %s\n", statement.id);
panic("unknown variable");
@ -424,42 +425,42 @@ void codegen_assignment_statement(FILE* out, band_t* band, struct assignment_sta
move_to(var); reset();
copy(region, var);
region_used(band, region);
region_used(scope, region);
}
void codegen_decl_statement(FILE* out, band_t* band, struct assignment_statement statement) {
if (band_region_for_var(band, statement.id)) {
void codegen_decl_statement(FILE* out, scope_t* scope, struct assignment_statement statement) {
if (scope_get(scope, statement.id)) {
fprintf(stderr, "variable exists: %s\n", statement.id);
panic("variable exists");
}
region_t* region = codegen_expr(out, band, statement.value);
region_t* region = codegen_expr(out, scope, statement.value);
if (!region->is_temp) {
region = clone_region(out, band, region);
region = clone_region(out, scope, region);
}
band_make_var(band, region, statement.id);
scope_existing(scope, region, statement.id);
}
void codegen_macro_statement(FILE* out, band_t* band, struct macro_statement statement) {
region_t* region = codegen_expr(out, band, statement.expr);
void codegen_macro_statement(FILE* out, scope_t* scope, struct macro_statement statement) {
region_t* region = codegen_expr(out, scope, statement.expr);
if (region->is_temp) {
band_region_free(band, region);
scope_remove(scope, region);
}
}
void codegen_block(FILE*, band_t*, struct block*);
void codegen_block(FILE*, scope_t*, struct block*);
void codegen_if_statement(FILE* out, band_t* band, struct if_statement statement) {
region_t* condition = codegen_expr(out, band, statement.condition);
void codegen_if_statement(FILE* out, scope_t* scope, struct if_statement statement) {
region_t* condition = codegen_expr(out, scope, statement.condition);
if (!condition->is_temp) {
condition = clone(condition);
}
region_t *inverse_condition = NULL;
if (statement.else_block) {
inverse_condition = band_allocate_tmp(band, 1);
inverse_condition = scope_add_tmp(scope, 1);
move_to(inverse_condition); reset(); inc();
}
@ -469,7 +470,7 @@ void codegen_if_statement(FILE* out, band_t* band, struct if_statement statement
move_to(inverse_condition); reset();
}
codegen_block(out, band, statement.if_block);
codegen_block(out, scope, statement.if_block);
move_to(condition); reset();
});
@ -477,33 +478,33 @@ void codegen_if_statement(FILE* out, band_t* band, struct if_statement statement
if (inverse_condition) {
move_to(inverse_condition);
loop({
codegen_block(out, band, statement.else_block);
codegen_block(out, scope, statement.else_block);
move_to(inverse_condition); reset();
});
band_region_free(band, inverse_condition);
scope_remove(scope, inverse_condition);
}
band_region_free(band, condition);
scope_remove(scope, condition);
}
void codegen_statement(FILE* out, band_t* band, struct statement* statement) {
void codegen_statement(FILE* out, scope_t* scope, struct statement* statement) {
switch(statement->kind) {
case PRINT_STATEMENT:
codegen_print_statement(out, band, statement->print);
codegen_print_statement(out, scope, statement->print);
break;
case DECL_STATEMENT:
codegen_decl_statement(out, band, statement->assignment);
codegen_decl_statement(out, scope, statement->assignment);
break;
case ASSIGNMENT_STATEMENT:
codegen_assignment_statement(out, band, statement->assignment);
codegen_assignment_statement(out, scope, statement->assignment);
break;
case MACRO_STATEMENT:
codegen_macro_statement(out, band, statement->macro);
codegen_macro_statement(out, scope, statement->macro);
break;
case IF_STATEMENT:
codegen_if_statement(out, band, statement->if_else);
codegen_if_statement(out, scope, statement->if_else);
break;
default:
fprintf(stderr, "statement kind: %d\n", statement->kind);
@ -527,26 +528,27 @@ void check_allocations(band_t* band) {
if (region->is_temp) {
fprintf(stderr, "[anonymous] (this is a bug in the compiler; %zu)\n", region->start);
} else {
fprintf(stderr, "variable %s\n", region->variable);
fprintf(stderr, "variable %s\n", region->name);
}
}
}
}
void codegen_block(FILE* out, band_t* band, struct block* block) {
void codegen_block(FILE* out, scope_t* scope, struct block* block) {
if (block == NULL) {
return;
}
for (size_t i = 0; i < block->length; i++) {
codegen_statement(out, band, block->statements[i]);
codegen_statement(out, scope, block->statements[i]);
}
}
int codegen(FILE* out, struct block* program) {
band_t* band = band_init();
scope_t* global = scope_init(band);
codegen_block(out, band, program);
codegen_block(out, global, program);
check_allocations(band);

View file

@ -3,6 +3,7 @@
#include "ast.h"
#include "band.h"
#include "scope.h"
#define next() fprintf(out, ">")
#define prev() fprintf(out, "<")
@ -16,16 +17,16 @@
#define add(v) { for (int _i = 0; _i < v; _i++) inc(); }
#define sub(v) { for (int _i = 0; _i < v; _i++) dec(); }
#define move(t) _move_to(out, band, t)
#define move(t) _move_to(out, scope, t)
#define move_to(r) move(r->start)
#define move_offset(r, o) move(r->start + o)
#define copy(s, t) _copy(out, band, s, t)
#define clone(s) _clone(out, band, s)
#define copy(s, t) _copy(out, scope, s, t)
#define clone(s) _clone(out, scope, s)
void _move_to(FILE*, band_t*, size_t);
void _copy(FILE*, band_t*, region_t*, region_t*);
region_t* _clone(FILE*, band_t*, region_t*);
void _move_to(FILE*, scope_t*, size_t);
void _copy(FILE*, scope_t*, region_t*, region_t*);
region_t* _clone(FILE*, scope_t*, region_t*);
int codegen(FILE*, struct block*);

View file

@ -106,3 +106,45 @@ void dict_remove(dict_t* dict, const char* key) {
}
}
}
static struct dict_pair* get_next(dict_t* dict, size_t bucket, size_t index) {
for (size_t i = bucket; i < NUMBER_OF_BUCKETS; i++) {
size_t bucket_size = list_size(dict->buckets[i]);
if (i == bucket && bucket_size > index) {
return dict->buckets[i] + index;
} else if (bucket_size > 0) {
return dict->buckets[i] + 0;
}
}
return NULL;
}
struct dict_pair* dict_iterate(dict_t* dict, struct dict_pair* last) {
if (!last) {
return get_next(dict, 0, 0);
} else {
uintptr_t last_ptr = (uintptr_t) last;
for (size_t i = 0; i < NUMBER_OF_BUCKETS; i++) {
uintptr_t bucket_ptr = (uintptr_t) dict->buckets[i];
size_t bucket_size = list_size(dict->buckets[i]);
if (
// probably undefined behaviour, but I'm too lazy to do it properly
last_ptr >= bucket_ptr &&
last_ptr < bucket_ptr + bucket_size * sizeof(struct dict_pair)
) {
return get_next(dict, i, (last_ptr - bucket_ptr) / sizeof(struct dict_pair));
}
}
return NULL;
}
}
void dict_free(dict_t* dict) {
for (size_t i = 0; i < NUMBER_OF_BUCKETS; i++) {
list_free(dict->buckets[i]);
}
free(dict);
}

View file

@ -23,12 +23,19 @@ typedef struct {
} dict_t;
dict_t* dict_new(void);
void dict_put(dict_t*, const char*, void*);
void dict_puti(dict_t*, const char*, long long);
bool dict_has(dict_t*, const char*);
void* dict_get(dict_t*, const char*);
long long dict_geti(dict_t*, const char*);
void dict_remove(dict_t*, const char*);
struct dict_pair* dict_iterate(dict_t*, struct dict_pair*);
void dict_free(dict_t*);
#endif

View file

@ -1,29 +1,29 @@
#include "../band.h"
#include "../scope.h"
#include "../error.h"
#include "../codegen.h"
extern region_t* to_str(FILE* out, band_t* band, const char* _arg) {
region_t* arg = band_region_for_var(band, _arg);
extern region_t* to_str(FILE* out, scope_t* scope, const char* _arg) {
region_t* arg = scope_get(scope, _arg);
if (!arg) {
panic("argument has to be a variable");
}
region_t* str = band_allocate_tmp(band, 3);
region_t* str = scope_add_tmp(scope, 3);
for (size_t i = 0; i < str->size; i++) {
move_offset(str, i); reset();
}
region_t* copy = band_allocate_tmp(band, 1);
region_t* copy = scope_add_tmp(scope, 1);
move_to(copy); reset();
region_t* ten = band_allocate_tmp(band, 1);
region_t* ten = scope_add_tmp(scope, 1);
move_to(ten); reset(); add(10);
region_t* tmp = band_allocate_tmp(band, 1);
region_t* tmp = scope_add_tmp(scope, 1);
move_to(tmp); reset();
region_t* tmp2 = band_allocate_tmp(band, 1);
region_t* tmp2 = scope_add_tmp(scope, 1);
move_to(tmp2); reset();
region_t* tmp3 = band_allocate_tmp(band, 1);
region_t* tmp3 = scope_add_tmp(scope, 1);
move_to(arg);
loop({
@ -112,11 +112,11 @@ extern region_t* to_str(FILE* out, band_t* band, const char* _arg) {
move_offset(str, i); add('0');
}
band_region_free(band, tmp3);
band_region_free(band, tmp2);
band_region_free(band, tmp);
band_region_free(band, ten);
band_region_free(band, copy);
scope_remove(scope, tmp3);
scope_remove(scope, tmp2);
scope_remove(scope, tmp);
scope_remove(scope, ten);
scope_remove(scope, copy);
return str;
}

View file

@ -3,9 +3,9 @@
#include <stdio.h>
#include "band.h"
#include "scope.h"
typedef region_t* (*macro_t)(FILE*, band_t*, const char*);
typedef region_t* (*macro_t)(FILE*, scope_t*, const char*);
void add_plugin(const char*);
void load_plugins(void);

79
src/scope.c Normal file
View file

@ -0,0 +1,79 @@
#include <stdlib.h>
#include <stdbool.h>
#include "scope.h"
#include "band.h"
#include "alloc.h"
#include "dict.h"
scope_t* scope_init(band_t* band) {
scope_t* root = scope_new(NULL);
root->band = band;
return root;
}
scope_t* scope_new(scope_t* parent) {
scope_t* scope = safe_malloc(sizeof (scope_t));
scope->parent = parent;
if (parent) {
scope->band = parent->band;
}
scope->variables = dict_new();
return scope;
}
region_t* scope_add(scope_t* scope, const char* name, size_t size) {
region_t* region = band_allocate(scope->band, size);
region->name = name;
dict_put(scope->variables, name, region);
return region;
}
region_t* scope_existing(scope_t* scope, region_t* region, const char* name) {
region->name = name;
region->is_temp = false;
dict_put(scope->variables, name, region);
return region;
}
region_t* scope_add_tmp(scope_t* scope, size_t size) {
region_t* region = band_allocate_tmp(scope->band, size);
return region;
}
region_t* scope_get(scope_t* scope, const char* name) {
region_t* region = dict_get(scope->variables, name);
if (!region) {
if (scope->parent) {
return scope_get(scope->parent, name);
} else {
return NULL;
}
} else {
return region;
}
}
void scope_remove(scope_t* scope, region_t* region) {
if (region->name) {
dict_remove(scope->variables, region->name);
}
band_region_free(scope->band, region);
}
void scope_free(scope_t* scope) {
struct dict_pair* current = NULL;
while ((current = dict_iterate(scope->variables, current)) != NULL) {
band_region_free(scope->band, current->ptr);
}
dict_free(scope->variables);
free(scope);
}

25
src/scope.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef SCOPE_H
#define SCOPE_H
#include "dict.h"
#include "band.h"
typedef struct scope {
struct scope* parent;
band_t* band;
dict_t* variables;
} scope_t;
scope_t* scope_init(band_t*);
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_get(scope_t*, const char*);
void scope_remove(scope_t*, region_t*);
void scope_free(scope_t*);
#endif