Merge remote-tracking branch 'origin/90-implement-the-struct-tree-for-the-parser' into 90-implement-the-struct-tree-for-the-parser

# Conflicts:
#	src/set/set.c
#	src/set/types.c
This commit is contained in:
Felix Müller 2024-06-08 17:28:41 +02:00
commit bfd3040df4
7 changed files with 345 additions and 610 deletions

View File

@ -179,11 +179,11 @@ void print_help(void) {
" --mode=[app|lib] set the compilation mode to either application or library", " --mode=[app|lib] set the compilation mode to either application or library",
" --output=name name of output files without extension", " --output=name name of output files without extension",
"Options:", "Options:",
" --verbose print logs with level information or higher", " --verbose print logs with level information or higher",
" --debug print debug logs (if not disabled at compile time)", " --debug print debug logs (if not disabled at compile time)",
" --version print the version", " --version print the version",
" --help print this hel dialog", " --help print this hel dialog",
" --print-memory-stats print statistics of the garbage collector" " --print-gc-stats print statistics of the garbage collector"
}; };
for (unsigned int i = 0; i < sizeof(lines) / sizeof(const char *); i++) { for (unsigned int i = 0; i < sizeof(lines) / sizeof(const char *); i++) {

View File

@ -142,12 +142,10 @@ static void build_target(ModuleFileStack *unit, const TargetConfig *target) {
if (setup_target_environment(target) == 0) { if (setup_target_environment(target) == 0) {
print_ast_to_file(ast, target); print_ast_to_file(ast, target);
Module * test = create_set(ast); Module* test = create_set(ast);
// TODO: parse AST to semantic values // TODO: parse AST to semantic values
// TODO: backend codegen // TODO: backend codegen
delete_set(test);
} }
} }

View File

@ -60,7 +60,7 @@ int main(int argc, char *argv[]) {
run_compiler(); run_compiler();
if (is_option_set("print-memory-stats")) { if (is_option_set("print-gc-stats")) {
print_memory_statistics(); print_memory_statistics();
} }

View File

@ -7,6 +7,7 @@
#include <glib.h> #include <glib.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <cfg/opt.h>
static GHashTable* namespaces = NULL; static GHashTable* namespaces = NULL;
@ -20,6 +21,17 @@ typedef struct MemoryNamespaceStatistic_t {
size_t purged_free_count; size_t purged_free_count;
} MemoryNamespaceStatistic; } MemoryNamespaceStatistic;
typedef enum MemoryBlockType_t {
GenericBlock,
GLIB_Array,
GLIB_HashTable
} MemoryBlockType;
typedef struct MemoryBlock_t {
void* block_ptr;
MemoryBlockType kind;
} MemoryBlock;
typedef struct MemoryNamespace_t { typedef struct MemoryNamespace_t {
MemoryNamespaceStatistic statistic; MemoryNamespaceStatistic statistic;
GArray* blocks; GArray* blocks;
@ -44,9 +56,11 @@ static void* namespace_malloc(MemoryNamespaceRef memoryNamespace, size_t size) {
assert(memoryNamespace != NULL); assert(memoryNamespace != NULL);
assert(size != 0); assert(size != 0);
void* block = malloc(size); MemoryBlock block;
block.block_ptr = malloc(size);
block.kind = GenericBlock;
if (block == NULL) { if (block.block_ptr == NULL) {
memoryNamespace->statistic.faulty_allocations ++; memoryNamespace->statistic.faulty_allocations ++;
} else { } else {
g_array_append_val(memoryNamespace->blocks, block); g_array_append_val(memoryNamespace->blocks, block);
@ -55,20 +69,36 @@ static void* namespace_malloc(MemoryNamespaceRef memoryNamespace, size_t size) {
memoryNamespace->statistic.bytes_allocated += size; memoryNamespace->statistic.bytes_allocated += size;
} }
return block; return block.block_ptr;
}
static void namespace_free_block(MemoryBlock block) {
switch (block.kind) {
case GenericBlock:
free(block.block_ptr);
break;
case GLIB_Array:
g_array_free(block.block_ptr, TRUE);
break;
case GLIB_HashTable:
g_hash_table_destroy(block.block_ptr);
break;
}
} }
static gboolean namespace_free(MemoryNamespaceRef memoryNamespace, void* block) { static gboolean namespace_free(MemoryNamespaceRef memoryNamespace, void* block) {
for (guint i = 0; i < memoryNamespace->blocks->len; i++) { for (guint i = 0; i < memoryNamespace->blocks->len; i++) {
void* current_block = g_array_index(memoryNamespace->blocks, void*, i); MemoryBlock current_block = g_array_index(memoryNamespace->blocks, MemoryBlock, i);
if (current_block == block) { if (current_block.block_ptr == block) {
assert(block != NULL); assert(block != NULL);
free(block); namespace_free_block(current_block);
g_array_remove_index(memoryNamespace->blocks, i); g_array_remove_index(memoryNamespace->blocks, i);
memoryNamespace->statistic.manual_free_count++; memoryNamespace->statistic.manual_free_count++;
return TRUE; return TRUE;
} }
} }
@ -79,13 +109,13 @@ static void* namespace_realloc(MemoryNamespaceRef memoryNamespace, void* block,
void* reallocated_block = NULL; void* reallocated_block = NULL;
for (guint i = 0; i < memoryNamespace->blocks->len; i++) { for (guint i = 0; i < memoryNamespace->blocks->len; i++) {
void* current_block = g_array_index(memoryNamespace->blocks, void*, i); MemoryBlock current_block = g_array_index(memoryNamespace->blocks, MemoryBlock, i);
if (current_block == block) { if (current_block.block_ptr == block) {
reallocated_block = realloc(block, size); reallocated_block = realloc(current_block.block_ptr, size);
if (reallocated_block != NULL) { if (reallocated_block != NULL) {
g_array_index(memoryNamespace->blocks, void*, i) = reallocated_block; g_array_index(memoryNamespace->blocks, MemoryBlock, i).block_ptr = reallocated_block;
memoryNamespace->statistic.bytes_allocated += size; memoryNamespace->statistic.bytes_allocated += size;
memoryNamespace->statistic.reallocation_count ++; memoryNamespace->statistic.reallocation_count ++;
} else { } else {
@ -107,9 +137,9 @@ static void namespace_delete(MemoryNamespaceRef memoryNamespace) {
static void namespace_purge(MemoryNamespaceRef memoryNamespace) { static void namespace_purge(MemoryNamespaceRef memoryNamespace) {
for (guint i = 0; i < memoryNamespace->blocks->len; i++) { for (guint i = 0; i < memoryNamespace->blocks->len; i++) {
void* current_block = g_array_index(memoryNamespace->blocks, void*, i); MemoryBlock current_block = g_array_index(memoryNamespace->blocks, MemoryBlock, i);
free(current_block); namespace_free_block(current_block);
memoryNamespace->statistic.purged_free_count ++; memoryNamespace->statistic.purged_free_count ++;
} }
@ -120,7 +150,7 @@ static void namespace_purge(MemoryNamespaceRef memoryNamespace) {
static MemoryNamespaceRef namespace_new() { static MemoryNamespaceRef namespace_new() {
MemoryNamespaceRef memoryNamespace = malloc(sizeof(MemoryNamespace)); MemoryNamespaceRef memoryNamespace = malloc(sizeof(MemoryNamespace));
memoryNamespace->blocks = g_array_new(FALSE, FALSE, sizeof(void*)); memoryNamespace->blocks = g_array_new(FALSE, FALSE, sizeof(MemoryBlock));
memoryNamespace->statistic.bytes_allocated = 0; memoryNamespace->statistic.bytes_allocated = 0;
memoryNamespace->statistic.allocation_count = 0; memoryNamespace->statistic.allocation_count = 0;
memoryNamespace->statistic.manual_free_count = 0; memoryNamespace->statistic.manual_free_count = 0;
@ -132,6 +162,30 @@ static MemoryNamespaceRef namespace_new() {
return memoryNamespace; return memoryNamespace;
} }
GArray *namespace_new_g_array(MemoryNamespaceRef namespace, guint size) {
MemoryBlock block;
block.block_ptr = g_array_new(FALSE, FALSE, size);
block.kind = GLIB_Array;
g_array_append_val(namespace->blocks, block);
namespace->statistic.bytes_allocated += sizeof(GArray*);
namespace->statistic.allocation_count ++;
return block.block_ptr;
}
GHashTable *namespace_new_g_hash_table(MemoryNamespaceRef namespace, GHashFunc hash_func, GEqualFunc key_equal_func) {
MemoryBlock block;
block.block_ptr = g_hash_table_new(hash_func, key_equal_func);
block.kind = GLIB_HashTable;
g_array_append_val(namespace->blocks, block);
namespace->statistic.bytes_allocated += sizeof(GHashTable*);
namespace->statistic.allocation_count ++;
return block.block_ptr;
}
static void cleanup() { static void cleanup() {
if (namespaces == NULL) { if (namespaces == NULL) {
printf("==> Memory cache was unused <==\n"); printf("==> Memory cache was unused <==\n");
@ -267,5 +321,25 @@ void print_memory_statistics() {
namespace_statistics_print(&total, "summary"); namespace_statistics_print(&total, "summary");
printf("Note: untracked are memory allocations from external libraries.\n"); printf("Note: untracked are memory allocations from external libraries and non-gc managed components.\n");
}
GArray* mem_new_g_array(MemoryNamespaceName name, guint element_size) {
MemoryNamespaceRef cache = check_namespace(name);
if (cache == NULL) {
PANIC("memory namespace not created");
}
return namespace_new_g_array(cache, element_size);
}
GHashTable* mem_new_g_hash_table(MemoryNamespaceName name, GHashFunc hash_func, GEqualFunc key_equal_func) {
MemoryNamespaceRef cache = check_namespace(name);
if (cache == NULL) {
PANIC("memory namespace not created");
}
return namespace_new_g_hash_table(cache, hash_func, key_equal_func);
} }

View File

@ -7,6 +7,7 @@
#include <mem/cache.h> #include <mem/cache.h>
#include <stddef.h> #include <stddef.h>
#include <glib.h>
typedef char* MemoryNamespaceName; typedef char* MemoryNamespaceName;
@ -86,4 +87,8 @@ void* mem_clone(MemoryNamespaceName name, void* data, size_t size);
void print_memory_statistics(); void print_memory_statistics();
GArray* mem_new_g_array(MemoryNamespaceName name, guint element_size);
GHashTable* mem_new_g_hash_table(MemoryNamespaceName name, GHashFunc hash_func, GEqualFunc key_equal_func);
#endif //GEMSTONE_CACHE_H #endif //GEMSTONE_CACHE_H

View File

@ -12,132 +12,58 @@
#include <set/set.h> #include <set/set.h>
#include <mem/cache.h> #include <mem/cache.h>
extern ModuleFile * current_file; extern ModuleFile *current_file;
static GHashTable *declaredComposites = NULL;//pointer to composites with names static GHashTable *declaredComposites = NULL;//pointer to composites with names
static GHashTable *declaredBoxes = NULL;//pointer to typeboxes static GHashTable *declaredBoxes = NULL;//pointer to typeboxes
static GHashTable *functionParameter = NULL; static GHashTable *functionParameter = NULL;
static GArray *Scope = NULL;//list of hashtables. last Hashtable is current depth of program. hashtable key: ident, value: Variable* to var static GArray *Scope = NULL;//list of hashtables. last Hashtable is current depth of program. hashtable key: ident, value: Variable* to var
static void delete_declared_composites() {
if (declaredComposites == NULL) {
return;
}
GHashTableIter iter;
char *name = NULL;
Type* type = NULL;
g_hash_table_iter_init(&iter, declaredComposites);
while (g_hash_table_iter_next(&iter, (gpointer)&name, (gpointer)&type)) {
delete_type(type);
mem_free(name);
}
g_hash_table_destroy(declaredComposites);
}
static void delete_declared_boxes() {
if (declaredBoxes == NULL) {
return;
}
GHashTableIter iter;
char *name = NULL;
Type* type = NULL;
g_hash_table_iter_init(&iter, declaredBoxes);
while (g_hash_table_iter_next(&iter, (gpointer)&name, (gpointer)&type)) {
delete_type(type);
mem_free(name);
}
g_hash_table_destroy(declaredBoxes);
}
static void delete_scopes() {
if (Scope == NULL) {
return;
}
for (guint i = 0; i < Scope->len; i++) {
GHashTable* scope = g_array_index(Scope, GHashTable*, i);
GHashTableIter iter;
char *name = NULL;
Variable* variable = NULL;
g_hash_table_iter_init(&iter, scope);
while (g_hash_table_iter_next(&iter, (gpointer)&name, (gpointer)&variable)) {
delete_variable(variable);
mem_free(name);
}
g_hash_table_destroy(scope);
}
g_array_free(Scope, TRUE);
}
void delete_set(Module* module) {
assert(module != NULL);
assert(declaredBoxes != NULL);
assert(declaredComposites != NULL);
assert(functionParameter != NULL);
delete_module(module);
delete_declared_composites();
delete_declared_boxes();
delete_scopes();
}
const Type ShortShortUnsingedIntType = { const Type ShortShortUnsingedIntType = {
.kind = TypeKindComposite, .kind = TypeKindComposite,
.impl = { .impl = {
.composite = { .composite = {
.sign = Unsigned, .sign = Unsigned,
.scale = 0.25, .scale = 0.25,
.primitive = Int .primitive = Int
} }
}, },
.nodePtr = NULL, .nodePtr = NULL,
}; };
const Type StringLiteralType = { const Type StringLiteralType = {
.kind = TypeKindReference, .kind = TypeKindReference,
.impl = { .impl = {
.reference = (ReferenceType) &ShortShortUnsingedIntType, .reference = (ReferenceType) &ShortShortUnsingedIntType,
}, },
.nodePtr = NULL, .nodePtr = NULL,
}; };
/** /**
* @brief Convert a string into a sign typ * @brief Convert a string into a sign typ
* @return 0 on success, 1 otherwise * @return 0 on success, 1 otherwise
*/ */
int sign_from_string(const char* string, Sign* sign) { int sign_from_string(const char *string, Sign *sign) {
assert(string != NULL); assert(string != NULL);
assert(sign != NULL); assert(sign != NULL);
if (strcmp(string, "unsigned") == 0) { if (strcmp(string, "unsigned") == 0) {
*sign = Unsigned; *sign = Unsigned;
return 0; return SEMANTIC_OK;
} else if (strcmp(string, "signed") == 0) {
*sign = Signed;
return 0;
} }
return 1; if (strcmp(string, "signed") == 0) {
*sign = Signed;
return SEMANTIC_OK;
}
return SEMANTIC_ERROR;
} }
/** /**
* @brief Convert a string into a primitive type * @brief Convert a string into a primitive type
* @return 0 on success, 1 otherwise * @return 0 on success, 1 otherwise
*/ */
int primitive_from_string(const char* string, PrimitiveType* primitive) { int primitive_from_string(const char *string, PrimitiveType *primitive) {
assert(string != NULL); assert(string != NULL);
assert(primitive != NULL); assert(primitive != NULL);
DEBUG("find primitive in string"); DEBUG("find primitive in string");
@ -155,7 +81,7 @@ int primitive_from_string(const char* string, PrimitiveType* primitive) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
int scale_factor_from(const char* string, double* factor) { int scale_factor_from(const char *string, double *factor) {
assert(string != NULL); assert(string != NULL);
assert(factor != NULL); assert(factor != NULL);
@ -179,14 +105,16 @@ int check_scale_factor(AST_NODE_PTR node, Scale scale) {
print_diagnostic(current_file, &node->location, Error, "Composite scale overflow"); print_diagnostic(current_file, &node->location, Error, "Composite scale overflow");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
if (0.25 > scale) { if (0.25 > scale) {
print_diagnostic(current_file, &node->location, Error, "Composite scale underflow"); print_diagnostic(current_file, &node->location, Error, "Composite scale underflow");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
return SEMANTIC_OK; return SEMANTIC_OK;
} }
int merge_scale_list(AST_NODE_PTR scale_list, Scale* scale) { int merge_scale_list(AST_NODE_PTR scale_list, Scale *scale) {
assert(scale_list != NULL); assert(scale_list != NULL);
assert(scale != NULL); assert(scale != NULL);
@ -208,13 +136,13 @@ int merge_scale_list(AST_NODE_PTR scale_list, Scale* scale) {
/** /**
* @brief Get an already declared type from its name * @brief Get an already declared type from its name
*/ */
int get_type_decl(const char* name, Type** type) { int get_type_decl(const char *name, Type **type) {
assert(name != NULL); assert(name != NULL);
assert(type != NULL); assert(type != NULL);
if (g_hash_table_contains(declaredComposites, name) == TRUE) { if (g_hash_table_contains(declaredComposites, name) == TRUE) {
*type = (Type*) g_hash_table_lookup(declaredComposites, name); *type = (Type *) g_hash_table_lookup(declaredComposites, name);
return SEMANTIC_OK; return SEMANTIC_OK;
} }
@ -222,7 +150,7 @@ int get_type_decl(const char* name, Type** type) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
int impl_composite_type(AST_NODE_PTR ast_type, CompositeType* composite) { int impl_composite_type(AST_NODE_PTR ast_type, CompositeType *composite) {
assert(ast_type != NULL); assert(ast_type != NULL);
assert(composite != NULL); assert(composite != NULL);
@ -230,7 +158,7 @@ int impl_composite_type(AST_NODE_PTR ast_type, CompositeType* composite) {
int status = SEMANTIC_OK; int status = SEMANTIC_OK;
int scaleNodeOffset = 0; int scaleNodeOffset = 0;
composite->sign = Signed; composite->sign = Signed;
// check if we have a sign // check if we have a sign
@ -250,7 +178,7 @@ int impl_composite_type(AST_NODE_PTR ast_type, CompositeType* composite) {
// check if we have a list of scale factors // check if we have a list of scale factors
if (ast_type->children[scaleNodeOffset]->kind == AST_List) { if (ast_type->children[scaleNodeOffset]->kind == AST_List) {
status = merge_scale_list(ast_type->children[scaleNodeOffset], &composite->scale); status = merge_scale_list(ast_type->children[scaleNodeOffset], &composite->scale);
if (status == SEMANTIC_ERROR) { if (status == SEMANTIC_ERROR) {
@ -261,12 +189,12 @@ int impl_composite_type(AST_NODE_PTR ast_type, CompositeType* composite) {
AST_NODE_PTR typeKind = ast_type->children[ast_type->child_count - 1]; AST_NODE_PTR typeKind = ast_type->children[ast_type->child_count - 1];
status = primitive_from_string(typeKind->value, &composite->primitive); status = primitive_from_string(typeKind->value, &composite->primitive);
// type kind is not primitve, must be a predefined composite // type kind is not primitve, must be a predefined composite
if (status == SEMANTIC_ERROR) { if (status == SEMANTIC_ERROR) {
// not a primitive try to resolve the type by name (must be a composite) // not a primitive try to resolve the type by name (must be a composite)
Type* nested_type = NULL; Type *nested_type = NULL;
status = get_type_decl(typeKind->value, &nested_type); status = get_type_decl(typeKind->value, &nested_type);
if (status == SEMANTIC_ERROR) { if (status == SEMANTIC_ERROR) {
@ -278,14 +206,14 @@ int impl_composite_type(AST_NODE_PTR ast_type, CompositeType* composite) {
// valid composite type // valid composite type
composite->primitive = nested_type->impl.composite.primitive; composite->primitive = nested_type->impl.composite.primitive;
// no sign was set, use sign of type // no sign was set, use sign of type
if (scaleNodeOffset == 0) { if (scaleNodeOffset == 0) {
composite->sign = nested_type->impl.composite.sign; composite->sign = nested_type->impl.composite.sign;
} }
composite->scale = composite->scale * nested_type->impl.composite.scale; composite->scale = composite->scale * nested_type->impl.composite.scale;
} else { } else {
print_diagnostic(current_file, &typeKind->location, Error, "Type must be either composite or primitive"); print_diagnostic(current_file, &typeKind->location, Error, "Type must be either composite or primitive");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
@ -301,7 +229,7 @@ int impl_composite_type(AST_NODE_PTR ast_type, CompositeType* composite) {
* @param type pointer output for the type * @param type pointer output for the type
* @return the gemstone type implementation * @return the gemstone type implementation
*/ */
int get_type_impl(AST_NODE_PTR currentNode, Type** type) { int get_type_impl(AST_NODE_PTR currentNode, Type **type) {
assert(currentNode != NULL); assert(currentNode != NULL);
assert(currentNode->kind == AST_Type); assert(currentNode->kind == AST_Type);
assert(currentNode->child_count > 0); assert(currentNode->child_count > 0);
@ -309,7 +237,7 @@ int get_type_impl(AST_NODE_PTR currentNode, Type** type) {
int status; int status;
const char *typekind = currentNode->children[currentNode->child_count -1]->value; const char *typekind = currentNode->children[currentNode->child_count - 1]->value;
//find type in composites //find type in composites
if (g_hash_table_contains(declaredComposites, typekind) == TRUE) { if (g_hash_table_contains(declaredComposites, typekind) == TRUE) {
@ -318,7 +246,6 @@ int get_type_impl(AST_NODE_PTR currentNode, Type** type) {
//TODO change composite based on other nodes //TODO change composite based on other nodes
} }
if (g_hash_table_contains(declaredBoxes, typekind) == TRUE) { if (g_hash_table_contains(declaredBoxes, typekind) == TRUE) {
*type = g_hash_table_lookup(declaredBoxes, typekind); *type = g_hash_table_lookup(declaredBoxes, typekind);
if(currentNode->child_count > 1) { if(currentNode->child_count > 1) {
@ -329,13 +256,13 @@ int get_type_impl(AST_NODE_PTR currentNode, Type** type) {
} }
// type is not yet declared, make a new one // type is not yet declared, make a new one
Type* new_type = mem_alloc(MemoryNamespaceSet,sizeof(Type)); Type *new_type = mem_alloc(MemoryNamespaceSet, sizeof(Type));
new_type->nodePtr = currentNode; new_type->nodePtr = currentNode;
// only one child means either composite or primitive // only one child means either composite or primitive
// try to implement primitive first // try to implement primitive first
// if not successfull continue building a composite // if not successfull continue building a composite
if(currentNode->child_count == 1) { if (currentNode->child_count == 1) {
// type is a primitive // type is a primitive
new_type->kind = TypeKindPrimitive; new_type->kind = TypeKindPrimitive;
@ -354,14 +281,12 @@ int get_type_impl(AST_NODE_PTR currentNode, Type** type) {
status = impl_composite_type(currentNode, &new_type->impl.composite); status = impl_composite_type(currentNode, &new_type->impl.composite);
*type = new_type; *type = new_type;
return status; return status;
} }
StorageQualifier Qualifier_from_string(const char *str) { StorageQualifier Qualifier_from_string(const char *str) {
assert(str != NULL); assert(str != NULL);
if (strcmp(str, "local") == 0) if (strcmp(str, "local") == 0)
return Local; return Local;
if (strcmp(str, "static") == 0) if (strcmp(str, "static") == 0)
@ -371,7 +296,8 @@ StorageQualifier Qualifier_from_string(const char *str) {
PANIC("Provided string is not a storagequalifier: %s", str); PANIC("Provided string is not a storagequalifier: %s", str);
} }
int addVarToScope(Variable * variable);
int addVarToScope(Variable *variable);
int createRef(AST_NODE_PTR currentNode, Type** reftype) { int createRef(AST_NODE_PTR currentNode, Type** reftype) {
assert(currentNode != NULL); assert(currentNode != NULL);
@ -396,12 +322,12 @@ int createRef(AST_NODE_PTR currentNode, Type** reftype) {
} }
int createDecl(AST_NODE_PTR currentNode, GArray** variables) { int createDecl(AST_NODE_PTR currentNode, GArray **variables) {
DEBUG("create declaration"); DEBUG("create declaration");
AST_NODE_PTR ident_list = currentNode->children[currentNode->child_count - 1]; AST_NODE_PTR ident_list = currentNode->children[currentNode->child_count - 1];
*variables = g_array_new(FALSE, FALSE, sizeof(Variable*)); *variables = mem_new_g_array(MemoryNamespaceSet, sizeof(Variable *));
VariableDeclaration decl; VariableDeclaration decl;
decl.nodePtr = currentNode; decl.nodePtr = currentNode;
@ -412,7 +338,7 @@ int createDecl(AST_NODE_PTR currentNode, GArray** variables) {
DEBUG("Child Count: %i", currentNode->child_count); DEBUG("Child Count: %i", currentNode->child_count);
for (size_t i = 0; i < currentNode->child_count; i++) { for (size_t i = 0; i < currentNode->child_count; i++) {
switch(currentNode->children[i]->kind){ switch (currentNode->children[i]->kind) {
case AST_Storage: case AST_Storage:
DEBUG("fill Qualifier"); DEBUG("fill Qualifier");
decl.qualifier = Qualifier_from_string(AST_get_node(currentNode,i)->value); decl.qualifier = Qualifier_from_string(AST_get_node(currentNode,i)->value);
@ -431,8 +357,8 @@ int createDecl(AST_NODE_PTR currentNode, GArray** variables) {
} }
} }
for(size_t i = 0; i < ident_list->child_count; i++) { for (size_t i = 0; i < ident_list->child_count; i++) {
Variable* variable = mem_alloc(MemoryNamespaceSet,sizeof(Variable)); Variable *variable = mem_alloc(MemoryNamespaceSet, sizeof(Variable));
variable->kind = VariableKindDeclaration; variable->kind = VariableKindDeclaration;
variable->nodePtr = currentNode; variable->nodePtr = currentNode;
@ -441,17 +367,17 @@ int createDecl(AST_NODE_PTR currentNode, GArray** variables) {
g_array_append_val(*variables, variable); g_array_append_val(*variables, variable);
int signal = addVarToScope(variable); int signal = addVarToScope(variable);
if (signal){ if (signal) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
} }
return status; return status;
} }
Expression* createExpression(AST_NODE_PTR currentNode); Expression *createExpression(AST_NODE_PTR currentNode);
int createDef(AST_NODE_PTR currentNode, GArray** variables) { int createDef(AST_NODE_PTR currentNode, GArray **variables) {
assert(variables != NULL); assert(variables != NULL);
assert(currentNode != NULL); assert(currentNode != NULL);
assert(currentNode->kind == AST_Def); assert(currentNode->kind == AST_Def);
@ -462,8 +388,7 @@ int createDef(AST_NODE_PTR currentNode, GArray** variables) {
AST_NODE_PTR expression = currentNode->children[1]; AST_NODE_PTR expression = currentNode->children[1];
AST_NODE_PTR ident_list = declaration->children[currentNode->child_count - 1]; AST_NODE_PTR ident_list = declaration->children[currentNode->child_count - 1];
*variables = mem_new_g_array(MemoryNamespaceSet, sizeof(Variable *));
*variables = g_array_new(FALSE, FALSE, sizeof(Variable*));
VariableDeclaration decl; VariableDeclaration decl;
VariableDefiniton def; VariableDefiniton def;
@ -474,8 +399,8 @@ int createDef(AST_NODE_PTR currentNode, GArray** variables) {
int status = SEMANTIC_OK; int status = SEMANTIC_OK;
DEBUG("Child Count: %i", declaration->child_count); DEBUG("Child Count: %i", declaration->child_count);
for (size_t i = 0; i < declaration->child_count; i++){ for (size_t i = 0; i < declaration->child_count; i++) {
switch(declaration->children[i]->kind) { switch (declaration->children[i]->kind) {
case AST_Storage: case AST_Storage:
DEBUG("fill Qualifier"); DEBUG("fill Qualifier");
decl.qualifier = Qualifier_from_string(declaration->children[i]->value); decl.qualifier = Qualifier_from_string(declaration->children[i]->value);
@ -489,27 +414,27 @@ int createDef(AST_NODE_PTR currentNode, GArray** variables) {
default: default:
PANIC("invalid node type: %ld", declaration->children[i]->kind); PANIC("invalid node type: %ld", declaration->children[i]->kind);
break; break;
} }
} }
def.declaration = decl; def.declaration = decl;
Expression * name = createExpression(expression); Expression *name = createExpression(expression);
if (name == NULL){ if (name == NULL) {
status = SEMANTIC_OK; status = SEMANTIC_OK;
} }
def.initializer = name; def.initializer = name;
for(size_t i = 0; i < ident_list->child_count; i++) { for (size_t i = 0; i < ident_list->child_count; i++) {
Variable* variable = mem_alloc(MemoryNamespaceSet,sizeof(Variable)); Variable *variable = mem_alloc(MemoryNamespaceSet, sizeof(Variable));
variable->kind = VariableKindDefinition; variable->kind = VariableKindDefinition;
variable->nodePtr = currentNode; variable->nodePtr = currentNode;
variable->name = ident_list->children[i]->value; variable->name = ident_list->children[i]->value;
variable->impl.definiton = def; variable->impl.definiton = def;
g_array_append_val(*variables, variable); g_array_append_val(*variables, variable);
int signal = addVarToScope(variable);
if (signal){ if (addVarToScope(variable) == SEMANTIC_ERROR) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
} }
@ -517,39 +442,7 @@ int createDef(AST_NODE_PTR currentNode, GArray** variables) {
return status; return status;
} }
//int: a,b,c = 5 int getVariableFromScope(const char *name, Variable **variable) {
//
//GArray.data:
// 1. Variable
// kind = VariableKindDefinition;
// name = a;
// impl.definition:
// initilizer:
// createExpression(...)
// decl:
// qulifier:
// type:
// pointer
//
//
// 2. Variable
// kind = VariableKindDefinition;
// name = b;
// impl.definition:
// initilizer: 5
// decl:
// qulifier:
// type:
// pointer
// .
// .
// .
//
int getVariableFromScope(const char* name, Variable** variable) {
assert(name != NULL); assert(name != NULL);
assert(variable != NULL); assert(variable != NULL);
assert(Scope != NULL); assert(Scope != NULL);
@ -1104,31 +997,48 @@ int createBitNotOperation(Expression* ParentExpression, AST_NODE_PTR currentNode
return SEMANTIC_OK; return SEMANTIC_OK;
} }
GArray* getBoxMember(Type* currentBoxType, GArray *names) { /**
* @brief Return a copy of all BoxMembers specified by their name in names from a boxes type
GArray *members = g_array_new(FALSE, FALSE, sizeof(BoxMember)); * Will run recursively in case the first name refers to a subbox
GHashTable* memberList = currentBoxType->impl.box->member; * @param currentBoxType
* @param names
const char* currentName = g_array_index(names,const char *,0); * @return
if(!g_hash_table_contains(memberList, currentName)) { */
// TODO: free members GArray *getBoxMember(Type *currentBoxType, GArray *names) {
return NULL;
}
BoxMember * currentMember = g_hash_table_lookup(memberList, currentName);
g_array_append_val(members, currentMember);
g_array_remove_index(names,0); GArray *members = mem_new_g_array(MemoryNamespaceSet, sizeof(BoxMember));
if (names->len == 0) { // list of members of the type
return members; GHashTable *memberList = currentBoxType->impl.box->member;
}
if (currentMember->type->kind == TypeKindBox){ // name of member to extract
GArray *otherMember = getBoxMember(currentMember->type, names); const char *currentName = g_array_index(names, const char *, 0);
if(NULL == otherMember){ // look for member of this name
return NULL; if (g_hash_table_contains(memberList, currentName)) {
// get member and store in array
BoxMember *currentMember = g_hash_table_lookup(memberList, currentName);
g_array_append_val(members, currentMember);
// last name in list, return
g_array_remove_index(names, 0);
if (names->len == 0) {
return members;
} }
g_array_append_vals(members,(BoxMember *) otherMember->data, otherMember->len);
return members; // other names may refer to members of child boxes
} if (currentMember->type->kind == TypeKindBox) {
GArray *otherMember = getBoxMember(currentMember->type, names);
if (NULL == otherMember) {
return NULL;
}
g_array_append_vals(members, (BoxMember *) otherMember->data, otherMember->len);
return members;
}
}
return NULL; return NULL;
} }
@ -1201,19 +1111,12 @@ int createTypeCast(Expression* ParentExpression, AST_NODE_PTR currentNode){
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
Type* target = mem_alloc(MemoryNamespaceSet,sizeof(Type)); Type *target = mem_alloc(MemoryNamespaceSet, sizeof(Type));
int status = get_type_impl(currentNode->children[1], &target); int status = get_type_impl(currentNode->children[1], &target);
if (status) { if (status) {
print_diagnostic(current_file, &currentNode->children[1]->location, Error, "Unknown type"); print_diagnostic(current_file, &currentNode->children[1]->location, Error, "Unknown type");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
if (target->kind != TypeKindComposite
&& target->kind != TypeKindPrimitive){
//TODO free everything
return SEMANTIC_ERROR;
}
ParentExpression->impl.typecast.targetType = target; ParentExpression->impl.typecast.targetType = target;
ParentExpression->result = target; ParentExpression->result = target;
return SEMANTIC_OK; return SEMANTIC_OK;
@ -1227,18 +1130,6 @@ int createTransmute(Expression* ParentExpression, AST_NODE_PTR currentNode){
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
//cand cast from box
if (ParentExpression->impl.transmute.operand->result->kind == TypeKindBox){
//TODO free everything
return SEMANTIC_ERROR;
}
Type * inputExpressionType = ParentExpression->impl.transmute.operand->result;
double inputSize = 1;
if(inputExpressionType->kind == TypeKindComposite) {
inputSize= inputExpressionType->impl.composite.scale;
}
Type* target = mem_alloc(MemoryNamespaceSet,sizeof(Type)); Type* target = mem_alloc(MemoryNamespaceSet,sizeof(Type));
int status = get_type_impl(currentNode->children[1], &target); int status = get_type_impl(currentNode->children[1], &target);
if (status){ if (status){
@ -1246,22 +1137,6 @@ int createTransmute(Expression* ParentExpression, AST_NODE_PTR currentNode){
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
if (target->kind != TypeKindComposite
&& target->kind != TypeKindPrimitive){
//TODO free everything
return SEMANTIC_ERROR;
}
double targetSize = 1;
if(target->kind == TypeKindComposite) {
targetSize = target->impl.composite.scale;
}
if(inputSize != targetSize) {
//TODO free everything
return SEMANTIC_ERROR;
}
ParentExpression->impl.typecast.targetType = target; ParentExpression->impl.typecast.targetType = target;
ParentExpression->result = target; ParentExpression->result = target;
@ -1337,113 +1212,112 @@ Expression *createExpression(AST_NODE_PTR currentNode){
DEBUG("create Expression"); DEBUG("create Expression");
Expression *expression = mem_alloc(MemoryNamespaceSet,sizeof(Expression)); Expression *expression = mem_alloc(MemoryNamespaceSet,sizeof(Expression));
expression->nodePtr = currentNode; expression->nodePtr = currentNode;
switch(currentNode->kind){
case AST_Int:
case AST_Float:
expression->kind = ExpressionKindConstant;
expression->impl.constant = createTypeValue(currentNode);
expression->result = expression->impl.constant.type;
break;
case AST_String:
expression->kind = ExpressionKindConstant;
expression->impl.constant = createString(currentNode);
expression->result = expression->impl.constant.type;
break;
case AST_Ident:
DEBUG("find var");
expression->kind = ExpressionKindVariable;
int status = getVariableFromScope(currentNode->value, &(expression->impl.variable) );
if(status == SEMANTIC_ERROR){
DEBUG("Identifier is not in current scope");
print_diagnostic(current_file, &currentNode->location, Error, "Variable not found");
return NULL;
}
switch (expression->impl.variable->kind) {
case VariableKindDeclaration:
expression->result = expression->impl.variable->impl.declaration.type;
DEBUG("%d",expression->impl.variable->impl.declaration.type->kind );
break;
case VariableKindDefinition:
expression->result = expression->impl.variable->impl.definiton.declaration.type;
break;
default:
PANIC("current Variable should not be an BoxMember");
break;
}
break;
case AST_Add:
case AST_Sub:
case AST_Mul:
case AST_Div:
expression->kind = ExpressionKindOperation;
if(createArithOperation(expression, currentNode, 2)){
return NULL;
}
break;
case AST_Negate:
expression->kind = ExpressionKindOperation;
if(createArithOperation(expression,currentNode, 1)){
return NULL;
}
break;
case AST_Eq:
case AST_Less:
case AST_Greater:
expression->kind = ExpressionKindOperation;
if(createRelationalOperation(expression,currentNode)){
return NULL;
}
break;
case AST_BoolAnd:
case AST_BoolOr:
case AST_BoolXor:
expression->kind = ExpressionKindOperation;
if(createBoolOperation(expression,currentNode)){
return NULL;
}
break;
case AST_BoolNot:
expression->kind= ExpressionKindOperation;
if(createBoolNotOperation(expression, currentNode)){
return NULL;
}
break;
case AST_BitAnd:
case AST_BitOr:
case AST_BitXor:
expression->kind= ExpressionKindOperation;
if(createBitOperation(expression, currentNode)){
return NULL;
}
break;
case AST_BitNot:
expression->kind = ExpressionKindOperation;
if(createBitNotOperation(expression, currentNode)){
return NULL;
}
break;
case AST_IdentList: switch (currentNode->kind) {
case AST_List: case AST_Int:
expression->kind = ExpressionKindVariable; case AST_Float:
if(createBoxAccess(expression, currentNode)){ expression->kind = ExpressionKindConstant;
return NULL; expression->impl.constant = createTypeValue(currentNode);
} expression->result = expression->impl.constant.type;
break; break;
case AST_Typecast: case AST_String:
expression->kind = ExpressionKindTypeCast; expression->kind = ExpressionKindConstant;
if(createTypeCast(expression, currentNode)){ expression->impl.constant = createString(currentNode);
return NULL; expression->result = expression->impl.constant.type;
} break;
break; case AST_Ident:
case AST_Transmute: DEBUG("find var");
expression->kind = ExpressionKindTransmute; expression->kind = ExpressionKindVariable;
if(createTransmute(expression, currentNode)){ int status = getVariableFromScope(currentNode->value, &(expression->impl.variable));
return NULL; if (status == SEMANTIC_ERROR) {
} DEBUG("Identifier is not in current scope");
break; print_diagnostic(current_file, &currentNode->location, Error, "Variable not found");
case AST_Dereference: return NULL;
}
switch (expression->impl.variable->kind) {
case VariableKindDeclaration:
expression->result = expression->impl.variable->impl.declaration.type;
DEBUG("%d", expression->impl.variable->impl.declaration.type->kind);
break;
case VariableKindDefinition:
expression->result = expression->impl.variable->impl.definiton.declaration.type;
break;
default:
PANIC("current Variable should not be an BoxMember");
break;
}
break;
case AST_Add:
case AST_Sub:
case AST_Mul:
case AST_Div:
expression->kind = ExpressionKindOperation;
if (createArithOperation(expression, currentNode, 2)) {
return NULL;
}
break;
case AST_Negate:
expression->kind = ExpressionKindOperation;
if (createArithOperation(expression, currentNode, 1)) {
return NULL;
}
break;
case AST_Eq:
case AST_Less:
case AST_Greater:
expression->kind = ExpressionKindOperation;
if (createRelationalOperation(expression, currentNode)) {
return NULL;
}
break;
case AST_BoolAnd:
case AST_BoolOr:
case AST_BoolXor:
expression->kind = ExpressionKindOperation;
if (createBoolOperation(expression, currentNode)) {
return NULL;
}
break;
case AST_BoolNot:
expression->kind = ExpressionKindOperation;
if (createBoolNotOperation(expression, currentNode)) {
return NULL;
}
break;
case AST_BitAnd:
case AST_BitOr:
case AST_BitXor:
expression->kind = ExpressionKindOperation;
if (createBitOperation(expression, currentNode)) {
return NULL;
}
break;
case AST_BitNot:
expression->kind = ExpressionKindOperation;
if (createBitNotOperation(expression, currentNode)) {
return NULL;
}
break;
case AST_IdentList:
case AST_List:
expression->kind = ExpressionKindVariable;
if (createBoxAccess(expression, currentNode)) {
return NULL;
}
break;
case AST_Typecast:
expression->kind = ExpressionKindTypeCast;
if (createTypeCast(expression, currentNode)) {
return NULL;
}
break;
case AST_Transmute:
expression->kind = ExpressionKindTransmute;
if (createTransmute(expression, currentNode)) {
return NULL;
}
break;
case AST_Dereference:
expression->kind = ExpressionKindDereference; expression->kind = ExpressionKindDereference;
if(createDeref(expression, currentNode)) { if(createDeref(expression, currentNode)) {
//TODO free expression //TODO free expression
@ -1466,7 +1340,7 @@ Expression *createExpression(AST_NODE_PTR currentNode){
DEBUG("successfully created Expression"); DEBUG("successfully created Expression");
return expression; return expression;
} }
bool compareTypes(Type * leftType, Type * rightType) { bool compareTypes(Type * leftType, Type * rightType) {
if (leftType->kind != rightType->kind) { if (leftType->kind != rightType->kind) {
@ -1524,19 +1398,6 @@ bool compareTypes(Type * leftType, Type * rightType) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
Type * varType = NULL;
if(assign.variable->kind == VariableKindDeclaration) {
varType = assign.variable->impl.declaration.type;
}else if(assign.variable->kind == VariableKindDefinition) {
varType = assign.variable->impl.definiton.declaration.type;
}else {
PANIC("the vartype should be a declaration or a definition");
}
if(!compareTypes(varType,assign.value->result)) {
//TODO free everything
return SEMANTIC_ERROR;
}
ParentStatement->impl.assignment = assign; ParentStatement->impl.assignment = assign;
return SEMANTIC_OK; return SEMANTIC_OK;
} }
@ -2014,16 +1875,6 @@ int createBox(GHashTable *boxes, AST_NODE_PTR currentNode){
} }
g_hash_table_insert(boxes, (gpointer)boxName, box); g_hash_table_insert(boxes, (gpointer)boxName, box);
Type* boxType = malloc(sizeof(Type));
boxType->nodePtr = currentNode;
boxType->kind = TypeKindBox;
boxType->impl.box = box;
if(g_hash_table_contains(declaredBoxes, (gpointer)boxName)){
return SEMANTIC_ERROR;
}
g_hash_table_insert(declaredBoxes, (gpointer)boxName, boxType);
return SEMANTIC_OK; return SEMANTIC_OK;
@ -2110,51 +1961,46 @@ Module *create_set(AST_NODE_PTR currentNode){
for (size_t i = 0; i < currentNode->child_count; i++){ for (size_t i = 0; i < currentNode->child_count; i++){
DEBUG("created Child with type: %i" ,currentNode->children[i]->kind); DEBUG("created Child with type: %i", currentNode->children[i]->kind);
switch(currentNode->children[i]->kind){ switch (currentNode->children[i]->kind) {
case AST_Decl: { case AST_Decl: {
GArray* vars; GArray *vars;
int status = createDecl(currentNode->children[i], &vars); int status = createDecl(currentNode->children[i], &vars);
if (status){ if (status) {
// TODO: free vars return NULL;
return NULL; }
} if (fillTablesWithVars(variables, vars) == SEMANTIC_ERROR) {
if (fillTablesWithVars(variables, vars) == SEMANTIC_ERROR) { // TODO: this diagnostic will highlight entire declaration of
// TODO: this diagnostic will highlight entire declaration of // of variables even if just one of the declared variables
// of variables even if just one of the declared variables // is duplicate. Consider moving this diagnostic to
// is duplicate. Consider moving this diagnostic to // `fillTablesWithVars` for more precise messaging.
// `fillTablesWithVars` for more precise messaging. print_diagnostic(current_file, &currentNode->children[i]->location, Error,
print_diagnostic(current_file, &currentNode->children[i]->location, Error, "Variable already declared"); "Variable already declared");
INFO("var already exists"); INFO("var already exists");
// TODO: free vars break;
}
DEBUG("filled successfull the module and scope with vars");
break; break;
} }
// TODO: free vars case AST_Def: {
DEBUG("filled successfull the module and scope with vars"); GArray *vars;
break; int status = createDef(currentNode->children[i], &vars);
} if (status) {
case AST_Def: { return NULL;
GArray* vars; }
int status = createDef(currentNode->children[i], &vars);
if (status){
// TODO: free vars // TODO: free vars
// TODO: cleanup global memory DEBUG("created Definition successfully");
return NULL; break;
} }
// TODO: free vars case AST_Box: {
DEBUG("created Definition successfully"); int status = createBox(boxes, currentNode->children[i]);
break; if (status) {
}
case AST_Box:{
int status = createBox(boxes, currentNode->children[i]);
if (status){
// TODO: cleanup global memory
return NULL; return NULL;
} }
DEBUG("created Box successfully"); DEBUG("created Box successfully");
break; break;
} }
case AST_Fun:{ case AST_Fun:{
DEBUG("start function"); DEBUG("start function");

View File

@ -1,188 +0,0 @@
//
// Created by servostar on 6/7/24.
//
#include <mem/cache.h>
#include <set/types.h>
void delete_box(BoxType *box) {
g_hash_table_destroy(box->member);
mem_free(box);
}
static void delete_box_table(GHashTable *box_table) {
GHashTableIter iter;
char *name = NULL;
BoxType *box = NULL;
g_hash_table_iter_init(&iter, box_table);
while (g_hash_table_iter_next(&iter, (gpointer)&name, (gpointer)&box)) {
delete_box(box);
mem_free(name);
}
g_hash_table_destroy(box_table);
}
static void delete_imports(GArray *imports) { g_array_free(imports, TRUE); }
void delete_box_member(BoxMember *member) {
member->box = NULL;
delete_expression(member->initalizer);
delete_type(member->type);
mem_free((void *)member->name);
}
void delete_box_type(BoxType *box_type) {
GHashTableIter iter;
char *name = NULL;
BoxMember *member = NULL;
g_hash_table_iter_init(&iter, box_type->member);
while (g_hash_table_iter_next(&iter, (gpointer)&name, (gpointer)&member)) {
delete_box_member(member);
mem_free(name);
}
g_hash_table_destroy(box_type->member);
}
void delete_composite([[maybe_unused]] CompositeType *composite) {}
void delete_type(Type *type) {
switch (type->kind) {
case TypeKindBox:
delete_box_type(type->impl.box);
break;
case TypeKindReference:
delete_type(type->impl.reference);
break;
case TypeKindPrimitive:
break;
case TypeKindComposite:
delete_composite(&type->impl.composite);
break;
}
}
static void delete_type_table(GHashTable *type_table) {
GHashTableIter iter;
char *name = NULL;
Type *type = NULL;
g_hash_table_iter_init(&iter, type_table);
while (g_hash_table_iter_next(&iter, (gpointer)&name, (gpointer)&type)) {
delete_type(type);
mem_free(name);
}
g_hash_table_destroy(type_table);
}
void delete_box_access(BoxAccess *access) {
delete_variable(access->variable);
for (guint i = 0; i < access->member->len; i++) {
delete_box_member(g_array_index(access->member, BoxMember *, i));
}
g_array_free(access->member, TRUE);
}
void delete_variable(Variable *variable) {
switch (variable->kind) {
case VariableKindBoxMember:
delete_box_access(&variable->impl.member);
break;
case VariableKindDeclaration:
delete_declaration(&variable->impl.declaration);
break;
case VariableKindDefinition:
delete_definition(&variable->impl.definiton);
break;
}
}
void delete_declaration(VariableDeclaration *decl) { delete_type(decl->type); }
void delete_definition(VariableDefiniton *definition) {
delete_declaration(&definition->declaration);
delete_expression(definition->initializer);
}
void delete_type_value(TypeValue *value) {
delete_type(value->type);
mem_free(value);
}
void delete_operation(Operation *operation) {
for (guint i = 0; i < operation->operands->len; i++) {
delete_expression(g_array_index(operation->operands, Expression *, i));
}
g_array_free(operation->operands, TRUE);
}
void delete_transmute(Transmute *trans) {
delete_expression(trans->operand);
delete_type(trans->targetType);
}
void delete_typecast(TypeCast *cast) {
delete_expression(cast->operand);
delete_type(cast->targetType);
}
void delete_expression(Expression *expr) {
delete_type(expr->result);
switch (expr->kind) {
case ExpressionKindConstant:
delete_type_value(&expr->impl.constant);
break;
case ExpressionKindOperation:
delete_operation(&expr->impl.operation);
break;
case ExpressionKindTransmute:
delete_transmute(&expr->impl.transmute);
break;
case ExpressionKindTypeCast:
delete_typecast(&expr->impl.typecast);
break;
case ExpressionKindVariable:
delete_variable(expr->impl.variable);
default:
//TODO free Reference and AddressOf
break;
}
}
static void delete_variable_table(GHashTable *variable_table) {
GHashTableIter iter;
char *name = NULL;
Variable *variable = NULL;
g_hash_table_iter_init(&iter, variable_table);
while (g_hash_table_iter_next(&iter, (gpointer)&name, (gpointer)&variable)) {
delete_variable(variable);
mem_free(name);
}
g_hash_table_destroy(variable_table);
}
void delete_module(Module *module) {
delete_box_table(module->boxes);
delete_imports(module->imports);
delete_type_table(module->types);
delete_variable_table(module->variables);
mem_free(module);
}