#include "compiler.h" #include size_t common_string_hash_djb2(const unsigned char* value, size_t length) { size_t hash = 5381; for (size_t i = 0; i < length && value[i] != '\0'; ++i) hash = ((hash << 5) + hash) + value[i]; return hash; } int string_symbol_map_construct(StringSymbolMap* map) { const size_t start_capacity = 4; *map = (StringSymbolMap) { .data = malloc(sizeof(StringSymbolMap) * start_capacity), .length = 0, .capacity = start_capacity, }; if (map->data == NULL) { return -1; } return 0; } void string_symbol_map_destroy(StringSymbolMap* map) { if (map->data != NULL) { free(map->data); } } Symbol* string_symbol_map_get(const StringSymbolMap* map, size_t key_hash) { for (size_t i = 0; i < map->length; ++i) { if (map->data[i].key_hash == key_hash) { return &map->data[i].value; } } return NULL; } int string_symbol_map_set(StringSymbolMap* map, size_t key_hash, Symbol value) { Symbol* existing = string_symbol_map_get(map, key_hash); if (existing != NULL) { *existing = value; return 0; } if (map->length + 1 >= map->capacity) { map->capacity *= 2; StringSymbolMapEntry* data = realloc(map->data, sizeof(StringSymbolMapEntry) * map->capacity); if (data == NULL) { return -1; } map->data = data; } map->data[map->length] = (StringSymbolMapEntry) { key_hash, value }; map->length += 1; return 0; } int statements_symbols_vec_construct(StatementsSymbolsVec* vec) { const size_t start_capacity = 4; StatementsSymbols* data = malloc(start_capacity * sizeof(StatementsSymbols)); if (data == NULL) { return -1; } *vec = (StatementsSymbolsVec) { .data = data, .length = 0, .capacity = start_capacity, }; return 0; } void statements_symbols_vec_destroy(StatementsSymbolsVec* vec) { if (vec->data != NULL) { free(vec->data); } } int statements_symbols_vec_push( StatementsSymbolsVec* vec, StatementsSymbols pair) { if (vec->length + 1 > vec->capacity) { StatementsSymbols* new_data = realloc(vec->data, vec->capacity * 2 * sizeof(StatementsSymbols)); if (new_data == NULL) { return -1; } vec->capacity *= 2; vec->data = new_data; } vec->data[vec->length] = pair; vec->length += 1; return 0; } void symbol_table_construct(SymbolTable* table, SymbolTable* parent) { *table = (SymbolTable) { .parent = parent, .map = { 0 }, }; string_symbol_map_construct(&table->map); } void symbol_table_destroy(SymbolTable* table) { string_symbol_map_destroy(&table->map); } void checker_construct(Checker* checker) { *checker = (Checker) { .failed = false, .statements_symbols = { 0 }, }; statements_symbols_vec_construct(&checker->statements_symbols); } void checker_destroy(Checker* checker) { (void)checker; } bool checker_failed(const Checker* checker) { return checker->failed; } CheckerResult checker_result(Checker* checker) { return (CheckerResult) { .head_table = checker->head_table, .statements_symbols = checker->statements_symbols, }; } void checker_check_statements(Checker* checker, ASTNode* node) { SymbolTable table; symbol_table_construct(&table, &checker->head_table); for (size_t i = 0; i < node->statements.length; ++i) { checker_check_statement(checker, &table, node->statements.data[i]); } statements_symbols_vec_push(&checker->statements_symbols, (StatementsSymbols) { .table = table, .statements = node, }); } void checker_check_statement( Checker* checker, SymbolTable* table, ASTNode* node) { switch (node->node_type) { case ASTNodeType_Block: checker_check_statements(checker, node); case ASTNodeType_If: case ASTNodeType_Loop: case ASTNodeType_Assign: case ASTNodeType_Let: case ASTNodeType_Break: case ASTNodeType_Fn: case ASTNodeType_Return: break; default: break; } }