From c0eb9e3a04f4fcc72e6e7a02aebce11d57f18805 Mon Sep 17 00:00:00 2001 From: Ugric Date: Sat, 12 Jul 2025 03:33:59 +0100 Subject: [PATCH] add hashmap to scope and identifier loading at runtime --- src/arobject.h | 3 +- src/err.c | 6 ++- src/main.c | 40 ++++++++++++++---- src/parser/assignable/access/access.c | 4 +- src/parser/assignable/identifier/identifier.c | 15 ++++++- src/parser/assignable/identifier/identifier.h | 8 ++++ src/parser/dowrap/dowrap.c | 5 +-- src/parser/parser.c | 4 ++ src/runtime/runtime.c | 42 ++++++++++++++++--- src/runtime/runtime.h | 3 +- src/translator/bytecode_spec.md | 8 ++++ src/translator/declaration/declaration.h | 3 +- src/translator/function/function.h | 4 +- src/translator/identifier/identifier.c | 13 ++++-- src/translator/identifier/identifier.h | 2 +- src/translator/translator.c | 4 +- src/translator/translator.h | 11 ++++- testing.ar | 1 - 18 files changed, 141 insertions(+), 35 deletions(-) delete mode 100644 testing.ar diff --git a/src/arobject.h b/src/arobject.h index 6242745..ecf08aa 100644 --- a/src/arobject.h +++ b/src/arobject.h @@ -3,6 +3,7 @@ #include #include "runtime/internals/dynamic_array_armem/darray_armem.h" +#include "runtime/internals/hashmap/hashmap.h" typedef struct ArgonObject ArgonObject; // forward declaration @@ -22,7 +23,7 @@ struct string_struct { }; typedef struct Stack { - ArgonObject *scope; + struct hashmap_GC *scope; struct Stack *prev; } Stack; diff --git a/src/err.c b/src/err.c index a46dd3e..719b6ad 100644 --- a/src/err.c +++ b/src/err.c @@ -80,6 +80,7 @@ void output_err(ArErr err) { while ((len = getline(&buffer, &size, file)) != -1) { if (current_line == err.line) { + printf("bruh\n"); break; } current_line++; @@ -89,12 +90,13 @@ void output_err(ArErr err) { fprintf(stderr, " "); } fprintf(stderr, "|\n"); - getline(&buffer, &size, file); char *line_starts = buffer; + size_t skipped_chars = 0; while (*line_starts && isspace((unsigned char)*line_starts) && line_starts-buffer < err.column-1) { line_starts++; err.column--; + skipped_chars++; } fprintf(stderr, " %zu | ", err.line); if (err.length) { @@ -104,7 +106,7 @@ void output_err(ArErr err) { fprintf(stderr, "%.*s", err.length, line_starts + err.column - 1); dye_style(stderr, DYE_STYLE_RESET); dyefg(stderr, DYE_RESET); - fprintf(stderr, "%s", line_starts + (int)err.column + err.length - 1); + fprintf(stderr, "%.*s", (int)len - (int)skipped_chars-(int)err.column-(int)err.length, line_starts + (int)err.column + err.length - 1); for (int64_t i = 0; i < err.column - 1; i++) { fprintf(stderr, " "); } diff --git a/src/main.c b/src/main.c index d808e69..343b2b7 100644 --- a/src/main.c +++ b/src/main.c @@ -84,6 +84,7 @@ const char BYTECODE_EXTENTION[] = "arbin"; const uint32_t version_number = 0; int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash) { + bool translated_inited = false; FILE *bytecode_file = fopen(joined_paths, "rb"); if (!bytecode_file) return 1; @@ -138,6 +139,16 @@ int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash) { } bytecodeSize = le64toh(bytecodeSize); + uint64_t sourceLocationSize; + if (fread(&sourceLocationSize, 1, sizeof(sourceLocationSize), + bytecode_file) != sizeof(sourceLocationSize)) { + goto FAILED; + } + sourceLocationSize = le64toh(sourceLocationSize); + + *translated_dest = init_translator(); + translated_inited = true; + arena_resize(&translated_dest->constants, constantsSize); if (fread(translated_dest->constants.data, 1, constantsSize, bytecode_file) != @@ -152,16 +163,24 @@ int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash) { goto FAILED; } + darray_resize(&translated_dest->source_locations, sourceLocationSize); + + if (fread(translated_dest->source_locations.data, sizeof(SourceLocation), sourceLocationSize, bytecode_file) != + sourceLocationSize) { + goto FAILED; + } + translated_dest->registerCount = register_count; fclose(bytecode_file); return 0; FAILED: + if (translated_inited) free_translator(translated_dest); fclose(bytecode_file); return 1; } -Execution execute(char *absolute_path) { +Execution execute(char *absolute_path, Stack *stack) { clock_t start, end; double time_spent, total_time_spent = 0; @@ -213,10 +232,9 @@ Execution execute(char *absolute_path) { uint64_t hash = XXH3_64bits_digest(hash_state); XXH3_freeState(hash_state); - Translated translated = init_translator(); + Translated translated; if (load_cache(&translated, cache_file_path, hash) != 0) { - free_translator(&translated); translated = init_translator(); DArray tokens; @@ -266,13 +284,15 @@ Execution execute(char *absolute_path) { file = fopen(cache_file_path, "wb"); - uint64_t constantsSize = (uint64_t)translated.constants.size; - uint64_t bytecodeSize = (uint64_t)translated.bytecode.size; + uint64_t constantsSize = translated.constants.size; + uint64_t bytecodeSize = translated.bytecode.size; + uint64_t sourceLocationSize = translated.source_locations.size; uint32_t version_number_htole32ed = htole32(version_number); uint64_t net_hash = htole64(hash); constantsSize = htole64(constantsSize); bytecodeSize = htole64(bytecodeSize); + sourceLocationSize = htole64(sourceLocationSize); fwrite(&FILE_IDENTIFIER, sizeof(char), strlen(FILE_IDENTIFIER), file); fwrite(&version_number_htole32ed, sizeof(uint32_t), 1, file); @@ -280,16 +300,20 @@ Execution execute(char *absolute_path) { fwrite(&translated.registerCount, sizeof(uint8_t), 1, file); fwrite(&constantsSize, sizeof(uint64_t), 1, file); fwrite(&bytecodeSize, sizeof(uint64_t), 1, file); + fwrite(&sourceLocationSize, sizeof(uint64_t), 1, file); fwrite(translated.constants.data, 1, translated.constants.size, file); fwrite(translated.bytecode.data, translated.bytecode.element_size, translated.bytecode.size, file); + fwrite(translated.source_locations.data, + translated.source_locations.element_size, + translated.source_locations.size, file); fclose(file); } start = clock(); - RuntimeState state = init_runtime_state(translated); - Stack main_scope = create_scope(NULL); + RuntimeState state = init_runtime_state(translated, absolute_path); + Stack main_scope = create_scope(stack); ArErr err = runtime(translated, state, main_scope); free(state.registers); end = clock(); @@ -314,7 +338,7 @@ int main(int argc, char *argv[]) { char path[FILENAME_MAX]; cwk_path_get_absolute(CWD, path_non_absolute, path, sizeof(path)); free(CWD); - Execution resp = execute(path); + Execution resp = execute(path, NULL); if (resp.err.exists) { output_err(resp.err); return -1; diff --git a/src/parser/assignable/access/access.c b/src/parser/assignable/access/access.c index de97378..f0e66ac 100644 --- a/src/parser/assignable/access/access.c +++ b/src/parser/assignable/access/access.c @@ -50,8 +50,8 @@ ParsedValueReturn parse_access(char *file, DArray *tokens, size_t *index, "Syntax Error", "expected value"), NULL}; } - darray_push(&parsedAccess->access, parsedValue); - free(parsedValue); + darray_push(&parsedAccess->access, parsedAccessValue.value); + free(parsedAccessValue.value); skip_newlines_and_indents(tokens, index); error_if_finished(file, tokens, index); token = darray_get(tokens, *index); diff --git a/src/parser/assignable/identifier/identifier.c b/src/parser/assignable/identifier/identifier.c index 347fef9..1a9e14a 100644 --- a/src/parser/assignable/identifier/identifier.c +++ b/src/parser/assignable/identifier/identifier.c @@ -4,9 +4,22 @@ #include #include "../../../memory.h" + + ParsedValueReturn parse_identifier(Token *token) { ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); + ParsedIdentifier *parsedIdentifier = checked_malloc(sizeof(ParsedIdentifier)); + parsedIdentifier->name = strcpy(checked_malloc(token->length + 1), token->value); + parsedIdentifier->line = token->line; + parsedIdentifier->column = token->column; parsedValue->type = AST_IDENTIFIER; - parsedValue->data = strcpy(checked_malloc(strlen(token->value) + 1), token->value); + parsedValue->data = parsedIdentifier; return (ParsedValueReturn){no_err, parsedValue}; +} + +void free_identifier(void *ptr) { + ParsedValue *parsedValue = ptr; + ParsedIdentifier *parsed = parsedValue->data; + free(parsed->name); + free(parsed); } \ No newline at end of file diff --git a/src/parser/assignable/identifier/identifier.h b/src/parser/assignable/identifier/identifier.h index 26f064e..cdbfbbe 100644 --- a/src/parser/assignable/identifier/identifier.h +++ b/src/parser/assignable/identifier/identifier.h @@ -3,7 +3,15 @@ #include "../../parser.h" #include "../../../lexer/token.h" // for Token +typedef struct { + char * name; + size_t line; + size_t column; +} ParsedIdentifier; + // Function declaration for parsing an identifier ParsedValueReturn parse_identifier(Token *token); +void free_identifier(void *ptr); + #endif // IDENTIFIER_H \ No newline at end of file diff --git a/src/parser/dowrap/dowrap.c b/src/parser/dowrap/dowrap.c index e920a57..feefd44 100644 --- a/src/parser/dowrap/dowrap.c +++ b/src/parser/dowrap/dowrap.c @@ -35,13 +35,12 @@ ParsedValueReturn parse_dowrap(char *file, DArray *tokens, size_t *index) { return (ParsedValueReturn){no_err, parsedValue}; Token *token = darray_get(tokens, *index); if (token->type != TOKEN_NEW_LINE) { + free_parsed(parsedValue); + free(parsedValue); return (ParsedValueReturn){create_err(token->line, token->column, token->length, file, "Syntax Error", "expected body"), NULL}; - fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line, - token->column); - exit(EXIT_FAILURE); } size_t indent_depth = 0; bool temp_indent_depth_toggle = false; diff --git a/src/parser/parser.c b/src/parser/parser.c index aaba98c..9e5bdb6 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -179,6 +179,7 @@ ArErr parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) { ParsedValueReturn parsed_code = parse_token(file, tokens, &index, inline_flag); if (parsed_code.err.exists) { + printf("%zu\n", old_index); return parsed_code.err; } else if (parsed_code.value) { if (expecting_new_line) { @@ -194,6 +195,7 @@ ArErr parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) { expecting_new_line = false; } } + return no_err; } void free_parsed(void *ptr) { @@ -205,6 +207,8 @@ void free_parsed(void *ptr) { ParsedValue *parsed = ptr; switch (parsed->type) { case AST_IDENTIFIER: + free_identifier(parsed); + break; case AST_NUMBER: free(parsed->data); break; diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 83ca44a..877c37c 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -1,5 +1,6 @@ #include "runtime.h" #include "../err.h" +#include "../hash_data/hash_data.h" #include "../translator/translator.h" #include "objects/functions/functions.h" #include "objects/null/null.h" @@ -63,6 +64,31 @@ void load_const(Translated *translated, RuntimeState *state) { state->registers[to_register] = object; } +ArErr load_variable(Translated *translated, RuntimeState *state, + struct Stack stack) { + int64_t length = pop_bytecode(translated, state); + int64_t offset = pop_bytecode(translated, state); + int64_t source_location_index = pop_bytecode(translated, state); + char *name = checked_malloc(length); + memcpy(name, arena_get(&translated->constants, offset), length); + uint64_t hash = siphash64_bytes(name, length, siphash_key); + struct Stack *current_stack = &stack; + while (current_stack) { + ArgonObject *result = hashmap_lookup_GC(current_stack->scope, hash); + if (result) { + state->registers[0] = result; + free(name); + return no_err; + } + current_stack = current_stack->prev; + } + SourceLocation *source_location = darray_get(&translated->source_locations, source_location_index); + ArErr err = create_err(source_location->line, source_location->column, length, state->path, "Name Error", "name '%.*s' is not defined", + (int)length, name); + free(name); + return err; +} + ArErr run_instruction(Translated *translated, RuntimeState *state, struct Stack stack) { OperationType opcode = pop_byte(translated, state); @@ -76,18 +102,25 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, case OP_LOAD_FUNCTION: load_argon_function(translated, state, stack); break; + case OP_IDENTIFIER: + return load_variable(translated, state, stack); default: - return create_err(0, 0, 0, NULL, "Runtime Error", "Invalid Opcode %#x", opcode); + return create_err(0, 0, 0, NULL, "Runtime Error", "Invalid Opcode %#x", + opcode); } return no_err; } -RuntimeState init_runtime_state(Translated translated) { +RuntimeState init_runtime_state(Translated translated, char *path) { return (RuntimeState){ - checked_malloc(translated.registerCount * sizeof(ArgonObject *)), 0}; + checked_malloc(translated.registerCount * sizeof(ArgonObject *)), 0, + path}; } -Stack create_scope(Stack *prev) { return (Stack){NULL, prev}; } +Stack create_scope(Stack *prev) { + struct hashmap_GC *scope = createHashmap_GC(); + return (Stack){scope, prev}; +} ArErr runtime(Translated translated, RuntimeState state, Stack stack) { state.head = 0; @@ -97,6 +130,5 @@ ArErr runtime(Translated translated, RuntimeState state, Stack stack) { return err; } } - free(state.registers); return no_err; } \ No newline at end of file diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 278197c..17d9ee6 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -7,6 +7,7 @@ typedef struct { ArgonObject **registers; size_t head; + char*path; } RuntimeState; void init_types(); @@ -16,7 +17,7 @@ uint64_t pop_bytecode(Translated *translated, RuntimeState *state); ArErr run_instruction(Translated *translated, RuntimeState *state, struct Stack stack); -RuntimeState init_runtime_state(Translated translated); +RuntimeState init_runtime_state(Translated translated, char *path); Stack create_scope(Stack *prev); diff --git a/src/translator/bytecode_spec.md b/src/translator/bytecode_spec.md index a13f029..8c5177f 100644 --- a/src/translator/bytecode_spec.md +++ b/src/translator/bytecode_spec.md @@ -43,3 +43,11 @@ initilises a function to a given register. 6. instruction 4 and 5 loop for each argument. 7. the offset of the bytecode of the function. 8. the length of the bytecode of the function. + +## OP_IDENTIFIER + +initilises a function to a given register. + +1. the length of the identifer. +2. the offset of the identifier. +3. the index of the source location. diff --git a/src/translator/declaration/declaration.h b/src/translator/declaration/declaration.h index 3fae2c2..a626463 100644 --- a/src/translator/declaration/declaration.h +++ b/src/translator/declaration/declaration.h @@ -2,7 +2,6 @@ #define BYTECODE_DECLARATION_H #include "../translator.h" -size_t translate_parsed_declaration(Translated *translated, - DArray delcarations); +size_t translate_parsed_declaration(Translated *translated, DArray delcarations); #endif \ No newline at end of file diff --git a/src/translator/function/function.h b/src/translator/function/function.h index 1cbc051..b035837 100644 --- a/src/translator/function/function.h +++ b/src/translator/function/function.h @@ -1,9 +1,9 @@ #ifndef BYTECODE_FUNCTION_H #define BYTECODE_FUNCTION_H -#include "../translator.h" #include "../../parser/function/function.h" +#include "../translator.h" size_t translate_parsed_function(Translated *translated, - ParsedFunction *parsedFunction); + ParsedFunction *parsedFunction); #endif \ No newline at end of file diff --git a/src/translator/identifier/identifier.c b/src/translator/identifier/identifier.c index 47c8b76..990ad0c 100644 --- a/src/translator/identifier/identifier.c +++ b/src/translator/identifier/identifier.c @@ -4,12 +4,19 @@ #include #include -size_t translate_parsed_identifier(Translated *translated, char* identifier) { - size_t length = strlen(identifier); - size_t identifier_pos = arena_push(&translated->constants, identifier, length); +size_t translate_parsed_identifier(Translated *translated, ParsedIdentifier *parsedIdentifier) { + size_t length = strlen(parsedIdentifier->name); + size_t identifier_pos = arena_push(&translated->constants, parsedIdentifier->name, length); set_registers(translated, 1); size_t start = push_instruction_byte(translated, OP_IDENTIFIER); push_instruction_code(translated,length); push_instruction_code(translated, identifier_pos); + SourceLocation source_locations = { + parsedIdentifier->line, + parsedIdentifier->column, + length + }; + push_instruction_code(translated, translated->source_locations.size); + darray_push(&translated->source_locations, &source_locations); return start; } \ No newline at end of file diff --git a/src/translator/identifier/identifier.h b/src/translator/identifier/identifier.h index 83728c8..3974759 100644 --- a/src/translator/identifier/identifier.h +++ b/src/translator/identifier/identifier.h @@ -3,6 +3,6 @@ #include "../translator.h" #include "../../parser/assignable/identifier/identifier.h" -size_t translate_parsed_identifier(Translated *translated, char* identifier); +size_t translate_parsed_identifier(Translated *translated, ParsedIdentifier *parsedIdentifier); #endif \ No newline at end of file diff --git a/src/translator/translator.c b/src/translator/translator.c index 176829f..f5cc225 100644 --- a/src/translator/translator.c +++ b/src/translator/translator.c @@ -80,6 +80,7 @@ Translated init_translator() { Translated translated; translated.registerCount = 0; darray_init(&translated.bytecode, sizeof(uint8_t)); + darray_init(&translated.source_locations, sizeof(SourceLocation)); arena_init(&translated.constants); return translated; } @@ -124,7 +125,7 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue) { return translate_parsed_function(translated, (ParsedFunction *)parsedValue->data); case AST_IDENTIFIER: - return translate_parsed_identifier(translated, (char *)parsedValue->data); + return translate_parsed_identifier(translated, (ParsedIdentifier *)parsedValue->data); } return 0; } @@ -138,5 +139,6 @@ void translate(Translated *translated, DArray *ast) { void free_translator(Translated *translated) { darray_free(&translated->bytecode, NULL); + darray_free(&translated->source_locations, NULL); arena_free(&translated->constants); } \ No newline at end of file diff --git a/src/translator/translator.h b/src/translator/translator.h index 95b44df..109363f 100644 --- a/src/translator/translator.h +++ b/src/translator/translator.h @@ -21,9 +21,16 @@ typedef struct { typedef struct { uint8_t registerCount; DArray bytecode; + DArray source_locations; ConstantArena constants; } Translated; +typedef struct { + uint64_t line; + uint64_t column; + uint64_t length; +} SourceLocation; + void arena_resize(ConstantArena *arena, size_t new_size); void *arena_get(ConstantArena *arena, size_t offset); @@ -38,9 +45,9 @@ void set_registers(Translated *translator, uint8_t count); Translated init_translator(); -size_t translate_parsed(Translated * translator, ParsedValue * parsedValue); +size_t translate_parsed(Translated *translated, ParsedValue *parsedValue); -void translate(Translated *translator, DArray *ast); +void translate(Translated *translated, DArray *ast); void free_translator(Translated *translated); diff --git a/testing.ar b/testing.ar deleted file mode 100644 index 04f8b72..0000000 --- a/testing.ar +++ /dev/null @@ -1 +0,0 @@ -let x = 10 \ No newline at end of file