From 0635ba8517d8f63fef0c994c1f05f067db84340d Mon Sep 17 00:00:00 2001 From: William Bell <62452284+Ugric@users.noreply.github.com> Date: Sat, 9 Aug 2025 06:40:16 +0100 Subject: [PATCH] work on method wrapper and native function support --- app.py | 6 +- src/arobject.h | 24 +- src/hash_data/hash_data.h | 2 +- src/main.c | 222 +++++++++++------- src/parser/assignable/call/call.c | 16 -- src/parser/declaration/declaration.c | 5 + src/runtime/call/call.c | 106 +++++---- src/runtime/declaration/declaration.c | 4 +- .../dynamic_array_armem/darray_armem.c | 1 - src/runtime/objects/functions/functions.c | 12 +- src/runtime/objects/functions/functions.h | 2 + src/runtime/objects/object.c | 38 ++- src/runtime/objects/object.h | 2 +- src/runtime/runtime.c | 115 ++++++--- src/runtime/runtime.h | 24 +- src/translator/bytecode_spec.md | 20 +- src/translator/call/call.c | 22 +- src/translator/declaration/declaration.c | 11 +- src/translator/function/function.c | 7 +- src/translator/identifier/identifier.c | 31 +-- src/translator/translator.c | 29 +-- src/translator/translator.h | 26 +- testing.ar | 3 +- 23 files changed, 404 insertions(+), 324 deletions(-) diff --git a/app.py b/app.py index a77ebe7..56404f2 100644 --- a/app.py +++ b/app.py @@ -1,6 +1,4 @@ def f(): - return g() -def g(): - return f + return f() -f()() \ No newline at end of file +f() \ No newline at end of file diff --git a/src/arobject.h b/src/arobject.h index ae4be2e..4f81a29 100644 --- a/src/arobject.h +++ b/src/arobject.h @@ -16,6 +16,8 @@ typedef struct ArErr ArErr; typedef struct ArgonObject ArgonObject; // forward declaration +typedef ArgonObject* (*native_fn)(size_t argc, ArgonObject**argv, ArErr*err); + typedef enum ArgonType { TYPE_NULL, TYPE_BOOL, @@ -24,10 +26,25 @@ typedef enum ArgonType { TYPE_FUNCTION, TYPE_NATIVE_FUNCTION, TYPE_METHOD, - TYPE_NATIVE_METHOD, TYPE_OBJECT, } ArgonType; + +typedef struct { + void *data; + size_t capacity; + size_t size; + struct hashmap_GC * hashmap; +} ConstantArena; + +typedef struct { + uint8_t registerCount; + DArray *return_jumps; + darray_armem bytecode; + ConstantArena constants; + char* path; +} Translated; + struct string_struct { char *data; size_t length; @@ -39,13 +56,12 @@ typedef struct Stack { } Stack; struct argon_function_struct { + Translated translated; uint8_t* bytecode; size_t bytecode_length; Stack *stack; size_t number_of_parameters; struct string_struct *parameters; - char* path; - DArray source_locations; uint64_t line; uint64_t column; }; @@ -60,7 +76,7 @@ struct ArgonObject { mpq_t as_number; bool as_bool; struct string_struct as_str; - ArgonObject* (*native_fn)(size_t argc, ArgonObject**argv, ArErr*err); + native_fn native_fn; struct argon_function_struct argon_fn; } value; }; diff --git a/src/hash_data/hash_data.h b/src/hash_data/hash_data.h index ad6ecac..ac628fb 100644 --- a/src/hash_data/hash_data.h +++ b/src/hash_data/hash_data.h @@ -10,7 +10,7 @@ #include extern uint8_t siphash_key[16]; -extern const uint8_t siphash_key_fixed_for_translator[16]; +extern const uint8_t siphash_key_fixed_for_translator[16]; extern uint8_t empty_siphash_key[16]; void generate_siphash_key(uint8_t siphash_key[16]); diff --git a/src/main.c b/src/main.c index aa6fa70..a754eac 100644 --- a/src/main.c +++ b/src/main.c @@ -24,13 +24,13 @@ #include #include #ifdef _WIN32 - #include - #include // for _mkdir - #include // for _stat +#include // for _mkdir +#include // for _stat +#include #else - #include - #include - #include +#include +#include +#include #endif #include "../external/cwalk/include/cwalk.h" #include @@ -48,30 +48,22 @@ // Windows / MinGW usually uses little-endian, so these can be no-ops // But define them explicitly to avoid implicit declaration warnings -static inline uint32_t le32toh(uint32_t x) { - return x; -} -static inline uint64_t le64toh(uint64_t x) { - return x; -} -static inline uint32_t htole32(uint32_t x) { - return x; -} -static inline uint64_t htole64(uint64_t x) { - return x; -} +static inline uint32_t le32toh(uint32_t x) { return x; } +static inline uint64_t le64toh(uint64_t x) { return x; } +static inline uint32_t htole32(uint32_t x) { return x; } +static inline uint64_t htole64(uint64_t x) { return x; } #elif defined(__linux__) - #include +#include #elif defined(__APPLE__) - #include - #define htole32(x) OSSwapHostToLittleInt32(x) - #define le32toh(x) OSSwapLittleToHostInt32(x) - #define htole64(x) OSSwapHostToLittleInt64(x) - #define le64toh(x) OSSwapLittleToHostInt64(x) - // Add others as needed +#include +#define htole32(x) OSSwapHostToLittleInt32(x) +#define le32toh(x) OSSwapLittleToHostInt32(x) +#define htole64(x) OSSwapHostToLittleInt64(x) +#define le64toh(x) OSSwapLittleToHostInt64(x) +// Add others as needed #else - #error "Unsupported platform" +#error "Unsupported platform" #endif char *get_current_directory() { @@ -104,31 +96,53 @@ char *get_current_directory() { int ensure_dir_exists(const char *path) { #ifdef _WIN32 - struct _stat st; - if (_stat(path, &st) != 0) { - // Directory does not exist, create it - if (_mkdir(path) != 0) { - perror("_mkdir failed"); - return -1; - } - } else if (!(st.st_mode & _S_IFDIR)) { - fprintf(stderr, "Path exists but is not a directory\n"); - return -1; + struct _stat st; + if (_stat(path, &st) != 0) { + // Directory does not exist, create it + if (_mkdir(path) != 0) { + perror("_mkdir failed"); + return -1; } + } else if (!(st.st_mode & _S_IFDIR)) { + fprintf(stderr, "Path exists but is not a directory\n"); + return -1; + } #else - struct stat st; - if (stat(path, &st) != 0) { - // Directory does not exist, create it - if (mkdir(path, 0755) != 0) { - perror("mkdir failed"); - return -1; - } - } else if (!S_ISDIR(st.st_mode)) { - fprintf(stderr, "Path exists but is not a directory\n"); - return -1; + struct stat st; + if (stat(path, &st) != 0) { + // Directory does not exist, create it + if (mkdir(path, 0755) != 0) { + perror("mkdir failed"); + return -1; } + } else if (!S_ISDIR(st.st_mode)) { + fprintf(stderr, "Path exists but is not a directory\n"); + return -1; + } #endif - return 0; + return 0; +} + +static inline void write_and_hash(FILE *file, XXH64_state_t *state, + const void *ptr, size_t size, size_t count) { + fwrite(ptr, size, count, file); + XXH64_update(state, ptr, size * count); +} + +static inline void update_hash_from_file(FILE *file, XXH64_state_t *state, + size_t size) { + char buffer[4096]; + size_t bytes_read; + size_t remaining = size; + + while (remaining > 0 && + (bytes_read = + fread(buffer, 1, + remaining > sizeof(buffer) ? sizeof(buffer) : remaining, + file)) > 0) { + XXH64_update(state, buffer, bytes_read); + remaining -= bytes_read; + } } const char CACHE_FOLDER[] = "__arcache__"; @@ -136,13 +150,52 @@ const char FILE_IDENTIFIER[5] = "ARBI"; 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; +int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash, char*source_path) { FILE *bytecode_file = fopen(joined_paths, "rb"); if (!bytecode_file) { printf("cache doesnt exist... compiling from source.\n"); return 1; } + + // Find file size + fseek(bytecode_file, 0, SEEK_END); + long file_size = ftell(bytecode_file); + if (file_size < (long)sizeof(uint64_t)) { + goto FAILED; + } + fseek(bytecode_file, 0, SEEK_SET); + + // Footer is the last 8 bytes + long data_size = file_size - sizeof(uint64_t); + + // Set up hash state + XXH64_state_t *state = XXH64_createState(); + XXH64_reset(state, 0); + + // Hash everything except last 8 bytes + update_hash_from_file(bytecode_file, state, data_size); + + // Read stored footer hash + uint64_t stored_hash_le; + if (fread(&stored_hash_le, 1, sizeof(stored_hash_le), bytecode_file) != + sizeof(stored_hash_le)) { + XXH64_freeState(state); + goto FAILED; + } + uint64_t stored_hash = le64toh(stored_hash_le); + + // Compare + uint64_t calc_hash = XXH64_digest(state); + XXH64_freeState(state); + + if (calc_hash != stored_hash) { + printf("cache hash mismatch (corrupted?)\n"); + goto FAILED; + } + + // Now actually parse the file contents + fseek(bytecode_file, 0, SEEK_SET); // rewind to start + char file_identifier_from_cache[sizeof(FILE_IDENTIFIER)] = {0}; if (fread(&file_identifier_from_cache, 1, sizeof(file_identifier_from_cache) - 1, @@ -194,15 +247,7 @@ 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; + *translated_dest = init_translator(source_path); arena_resize(&translated_dest->constants, constantsSize); @@ -211,29 +256,18 @@ int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash) { goto FAILED; } - darray_resize(&translated_dest->bytecode, bytecodeSize); + darray_armem_resize(&translated_dest->bytecode, bytecodeSize); if (fread(translated_dest->bytecode.data, 1, bytecodeSize, bytecode_file) != bytecodeSize) { 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; - printf("cache exists and is valid, so will be used.\n"); fclose(bytecode_file); return 0; FAILED: printf("cache is invalid... compiling from source.\n"); - if (translated_inited) - free_translator(translated_dest); fclose(bytecode_file); return 1; } @@ -292,7 +326,7 @@ Execution execute(char *path, Stack *stack) { Translated translated; - if (load_cache(&translated, cache_file_path, hash) != 0) { + if (load_cache(&translated, cache_file_path, hash, path) != 0) { translated = init_translator(path); DArray tokens; @@ -302,7 +336,6 @@ Execution execute(char *path, Stack *stack) { start = clock(); ArErr err = lexer(state); if (err.exists) { - free_translator(&translated); darray_free(&tokens, free_token); return (Execution){err, (Stack){NULL, NULL}}; } @@ -319,7 +352,6 @@ Execution execute(char *path, Stack *stack) { start = clock(); err = parser(path, &ast, &tokens, false); if (err.exists) { - free_translator(&translated); darray_free(&tokens, free_token); darray_free(&ast, free_parsed); return (Execution){err, (Stack){NULL, NULL}}; @@ -333,7 +365,6 @@ Execution execute(char *path, Stack *stack) { start = clock(); err = translate(&translated, &ast); if (err.exists) { - free_translator(&translated); darray_free(&ast, free_parsed); return (Execution){err, (Stack){NULL, NULL}}; } @@ -349,27 +380,36 @@ Execution execute(char *path, Stack *stack) { 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); - fwrite(&net_hash, sizeof(net_hash), 1, file); - 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); + XXH64_state_t *hash_state = XXH64_createState(); + XXH64_reset(hash_state, 0); + + write_and_hash(file, hash_state, &FILE_IDENTIFIER, sizeof(char), + strlen(FILE_IDENTIFIER)); + write_and_hash(file, hash_state, &version_number_htole32ed, + sizeof(uint32_t), 1); + write_and_hash(file, hash_state, &net_hash, sizeof(net_hash), 1); + write_and_hash(file, hash_state, &translated.registerCount, sizeof(uint8_t), + 1); + write_and_hash(file, hash_state, &constantsSize, sizeof(uint64_t), 1); + write_and_hash(file, hash_state, &bytecodeSize, sizeof(uint64_t), 1); + write_and_hash(file, hash_state, translated.constants.data, 1, + translated.constants.size); + write_and_hash(file, hash_state, translated.bytecode.data, + translated.bytecode.element_size, translated.bytecode.size); + + // Finalize the hash + uint64_t file_hash = XXH64_digest(hash_state); + XXH64_freeState(hash_state); + + // Convert to little-endian before writing if needed + uint64_t file_hash_le = htole64(file_hash); + fwrite(&file_hash_le, sizeof(file_hash_le), 1, file); fclose(file); } @@ -385,7 +425,6 @@ Execution execute(char *path, Stack *stack) { printf("Execution time taken: %f seconds\n", time_spent); printf("total time taken: %f seconds\n", total_time_spent); - free_translator(&translated); return (Execution){err, *main_scope}; } @@ -394,6 +433,7 @@ int main(int argc, char *argv[]) { ar_memory_init(); generate_siphash_key(siphash_key); bootstrap_types(); + bootstrap_globals(); char *CWD = get_current_directory(); if (argc <= 1) return -1; @@ -401,7 +441,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, NULL); + Execution resp = execute(path, Global_Scope); if (runtime_hash_table) hashmap_free(runtime_hash_table, NULL); if (resp.err.exists) { diff --git a/src/parser/assignable/call/call.c b/src/parser/assignable/call/call.c index e65c3d7..b0bdeb9 100644 --- a/src/parser/assignable/call/call.c +++ b/src/parser/assignable/call/call.c @@ -26,8 +26,6 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index, (*index)++; ArErr err = error_if_finished(file, tokens, index); if (err.exists) { - free_parsed(to_call); - free(to_call); free_parsed(parsedValue); free(parsedValue); return (ParsedValueReturn){err, NULL}; @@ -38,22 +36,16 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index, skip_newlines_and_indents(tokens, index); ArErr err = error_if_finished(file, tokens, index); if (err.exists) { - free_parsed(to_call); - free(to_call); free_parsed(parsedValue); free(parsedValue); return (ParsedValueReturn){err, NULL}; } ParsedValueReturn parsedArg = parse_token(file, tokens, index, true); if (parsedArg.err.exists) { - free_parsed(to_call); - free(to_call); free_parsed(parsedValue); free(parsedValue); return parsedArg; } else if (!parsedArg.value) { - free_parsed(to_call); - free(to_call); free_parsed(parsedValue); free(parsedValue); @@ -66,8 +58,6 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index, free(parsedArg.value); err = error_if_finished(file, tokens, index); if (err.exists) { - free_parsed(to_call); - free(to_call); free_parsed(parsedValue); free(parsedValue); return (ParsedValueReturn){err, NULL}; @@ -75,8 +65,6 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index, skip_newlines_and_indents(tokens, index); err = error_if_finished(file, tokens, index); if (err.exists) { - free_parsed(to_call); - free(to_call); free_parsed(parsedValue); free(parsedValue); return (ParsedValueReturn){err, NULL}; @@ -85,8 +73,6 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index, if (token->type == TOKEN_RPAREN) { break; } else if (token->type != TOKEN_COMMA) { - free_parsed(to_call); - free(to_call); free_parsed(parsedValue); free(parsedValue); @@ -98,8 +84,6 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index, (*index)++; err = error_if_finished(file, tokens, index); if (err.exists) { - free_parsed(to_call); - free(to_call); free_parsed(parsedValue); free(parsedValue); return (ParsedValueReturn){err, NULL}; diff --git a/src/parser/declaration/declaration.c b/src/parser/declaration/declaration.c index 2e53121..ace35c8 100644 --- a/src/parser/declaration/declaration.c +++ b/src/parser/declaration/declaration.c @@ -61,6 +61,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { (*index)++; ArErr err = error_if_finished(file, tokens, index); if (err.exists) { + hashmap_free(parameters_hashmap, NULL); darray_free(¶meters, free_parameter); free_parsed(parsedValue); free(parsedValue); @@ -70,6 +71,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { if (token->type == TOKEN_RPAREN) { (*index)++; if ((*index) >= tokens->size) { + hashmap_free(parameters_hashmap, NULL); declaration->from = create_parsed_function( declaration->name, parameters, declaration->from); return (ParsedValueReturn){no_err, parsedValue}; @@ -118,6 +120,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { (*index)++; err = error_if_finished(file, tokens, index); if (err.exists) { + hashmap_free(parameters_hashmap, NULL); darray_free(¶meters, free_parameter); free_parsed(parsedValue); free(parsedValue); @@ -126,6 +129,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { skip_newlines_and_indents(tokens, index); err = error_if_finished(file, tokens, index); if (err.exists) { + hashmap_free(parameters_hashmap, NULL); darray_free(¶meters, free_parameter); free_parsed(parsedValue); free(parsedValue); @@ -150,6 +154,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { (*index)++; err = error_if_finished(file, tokens, index); if (err.exists) { + hashmap_free(parameters_hashmap, NULL); darray_free(¶meters, free_parameter); free_parsed(parsedValue); free(parsedValue); diff --git a/src/runtime/call/call.c b/src/runtime/call/call.c index 6e66bed..ed56d10 100644 --- a/src/runtime/call/call.c +++ b/src/runtime/call/call.c @@ -71,73 +71,72 @@ double get_memory_usage_mb() { #endif ArErr run_call(Translated *translated, RuntimeState *state) { - uint8_t from_register = pop_byte(translated, state); - uint8_t source_location_index = pop_bytecode(translated, state); - ArgonObject *original_object = state->registers[from_register]; + ArgonObject *original_object = state->call_instance->to_call; ArgonObject *object = original_object; - int is_method = - object->type == TYPE_METHOD || object->type == TYPE_NATIVE_METHOD; - if (object->type != TYPE_FUNCTION && object->type != TYPE_NATIVE_FUNCTION && !is_method) { - ArgonObject *call_method = - get_field_for_class(get_field(object, "__class__", false), "__call__"); + if (object->type != TYPE_FUNCTION && object->type != TYPE_NATIVE_FUNCTION && + object->type != TYPE_METHOD) { + ArgonObject *call_method = get_field_for_class( + get_field(object, "__class__", false), "__call__", original_object); if (call_method) { object = call_method; - is_method = - object->type == TYPE_METHOD && object->type == TYPE_NATIVE_METHOD; } } - if (is_method) { - ArgonObject **new_call_args = - malloc(sizeof(ArgonObject *) * (*state->call_args_length + 1)); - new_call_args[0] = original_object; - if (*state->call_args_length > 0) { - memcpy(new_call_args + 1, *state->call_args, *state->call_args_length); + if (object->type == TYPE_METHOD) { + ArgonObject *binding_object = get_field(object, "__binding__", false); + if (binding_object) { + ArgonObject **new_call_args = malloc( + sizeof(ArgonObject *) * (state->call_instance->args_length + 1)); + new_call_args[0] = binding_object; + if (state->call_instance->args_length > 0) { + memcpy(new_call_args + 1, state->call_instance->args, + state->call_instance->args_length); + } + free(state->call_instance->args); + state->call_instance->args = new_call_args; + state->call_instance->args_length++; } - if (*state->call_args) { - free(*state->call_args); - } - *state->call_args = new_call_args; - (*state->call_args_length)++; + ArgonObject *function_object = get_field(object, "__function__", false); + if (function_object) + object = function_object; } - if (object->type == TYPE_FUNCTION || object->type == TYPE_METHOD) { - SourceLocation *source_location = - darray_get(&translated->source_locations, source_location_index); - if (*state->call_args_length != + if (object->type == TYPE_FUNCTION) { + if (state->call_instance->args_length != object->value.argon_fn.number_of_parameters) { ArgonObject *type_object_name = get_field_for_class( - get_field(object, "__class__", false), "__name__"); - ArgonObject *object_name = get_field_for_class(object, "__name__"); + get_field(object, "__class__", false), "__name__", original_object); + ArgonObject *object_name = get_field_for_class(object, "__name__", original_object); return create_err( - source_location->line, source_location->column, - source_location->length, state->path, "Type Error", + state->source_location.line, state->source_location.column, + state->source_location.length, state->path, "Type Error", "%.*s %.*s takes %" PRIu64 " argument(s) but %" PRIu64 " was given", (int)type_object_name->value.as_str.length, type_object_name->value.as_str.data, (int)object_name->value.as_str.length, object_name->value.as_str.data, object->value.argon_fn.number_of_parameters, - *state->call_args_length); + state->call_instance->args_length); } Stack *scope = create_scope(object->value.argon_fn.stack); - for (size_t i = 0; i < *state->call_args_length; i++) { + for (size_t i = 0; i < state->call_instance->args_length; i++) { struct string_struct key = object->value.argon_fn.parameters[i]; - ArgonObject *value = (*state->call_args)[i]; + ArgonObject *value = (state->call_instance->args)[i]; uint64_t hash = siphash64_bytes(key.data, key.length, siphash_key); hashmap_insert_GC(scope->scope, hash, new_string_object(key.data, key.length), value, 0); } - DArray bytecode_darray = {object->value.argon_fn.bytecode, sizeof(uint8_t), - object->value.argon_fn.bytecode_length, - object->value.argon_fn.bytecode_length, false}; StackFrame new_stackFrame = { - {translated->registerCount, NULL, bytecode_darray, - object->value.argon_fn.source_locations, translated->constants, - object->value.argon_fn.path}, + {translated->registerCount, + NULL, + {object->value.argon_fn.bytecode, sizeof(uint8_t), + object->value.argon_fn.bytecode_length, + object->value.argon_fn.bytecode_length, false}, + object->value.argon_fn.translated.constants, + object->value.argon_fn.translated.path}, {state->registers, 0, - state->path, + object->value.argon_fn.translated.path, + NULL, state->currentStackFramePointer, - state->call_args, - state->call_args_length, + {}, {}}, scope, *state->currentStackFramePointer, @@ -153,13 +152,12 @@ ArErr run_call(Translated *translated, RuntimeState *state) { if ((*state->currentStackFramePointer)->depth >= 10000) { double logval = log10((double)(*state->currentStackFramePointer)->depth); if (floor(logval) == logval) { - SourceLocation *source_location = - darray_get(&translated->source_locations, source_location_index); double memoryUsage = get_memory_usage_mb(); fprintf(stderr, "Warning: %s:%" PRIu64 ":%" PRIu64 " the call stack depth has exceeded %" PRIu64, - state->path, source_location->line, source_location->column, + state->path, state->source_location.line, + state->source_location.column, (*state->currentStackFramePointer)->depth); if (memoryUsage) { fprintf(stderr, ", memory usage at %f MB\n", memoryUsage); @@ -169,18 +167,22 @@ ArErr run_call(Translated *translated, RuntimeState *state) { } }; return no_err; - } else if (object->type == TYPE_NATIVE_FUNCTION || object->type == TYPE_NATIVE_METHOD) { + } else if (object->type == TYPE_NATIVE_FUNCTION) { ArErr err = no_err; - state->registers[0] = object->value.native_fn(*state->call_args_length, - *state->call_args, &err); + state->registers[0] = object->value.native_fn( + state->call_instance->args_length, state->call_instance->args, &err); + if (err.exists) { + err.line = state->source_location.line; + err.column = state->source_location.column; + err.length = state->source_location.length; + err.path = state->path; + } return err; } - SourceLocation *source_location = - darray_get(&translated->source_locations, source_location_index); ArgonObject *type_object_name = get_field_for_class( - get_field(original_object, "__class__", false), "__name__"); - return create_err(source_location->line, source_location->column, - source_location->length, state->path, "Type Error", + get_field(original_object, "__class__", false), "__name__", original_object); + return create_err(state->source_location.line, state->source_location.column, + state->source_location.length, state->path, "Type Error", "'%.*s' object is not callable", (int)type_object_name->value.as_str.length, type_object_name->value.as_str.data); diff --git a/src/runtime/declaration/declaration.c b/src/runtime/declaration/declaration.c index 7643bc7..e249bc6 100644 --- a/src/runtime/declaration/declaration.c +++ b/src/runtime/declaration/declaration.c @@ -12,12 +12,10 @@ ArErr runtime_declaration(Translated *translated, RuntimeState *state, int64_t offset = pop_bytecode(translated, state); int64_t prehash = pop_bytecode(translated, state); int64_t from_register = pop_byte(translated, state); - int64_t source_location_index = pop_bytecode(translated, state); uint64_t hash = runtime_hash(arena_get(&translated->constants, offset), length, prehash); ArgonObject * exists = hashmap_lookup_GC(stack->scope, hash); if (exists) { - SourceLocation *source_location = darray_get(&translated->source_locations, source_location_index); - return create_err(source_location->line, source_location->column, source_location->length, state->path, "Runtime Error", "Identifier '%.*s' has already been declared in the current scope", length, arena_get(&translated->constants, offset)); + return create_err(state->source_location.line, state->source_location.column, state->source_location.length, state->path, "Runtime Error", "Identifier '%.*s' has already been declared in the current scope", length, arena_get(&translated->constants, offset)); } ArgonObject * key = new_string_object(arena_get(&translated->constants, offset), length); hashmap_insert_GC(stack->scope, hash, key, state->registers[from_register], 0); diff --git a/src/runtime/internals/dynamic_array_armem/darray_armem.c b/src/runtime/internals/dynamic_array_armem/darray_armem.c index 2ce8aa8..b6157f0 100644 --- a/src/runtime/internals/dynamic_array_armem/darray_armem.c +++ b/src/runtime/internals/dynamic_array_armem/darray_armem.c @@ -45,7 +45,6 @@ void darray_armem_resize(darray_armem *arr, size_t new_size) { } if (new_capacity != arr->capacity) { - printf("%zu\n", new_capacity_bytes); arr->data = ar_realloc(arr->data, new_capacity_bytes); if (!arr->data) { fprintf(stderr, "darray_armem_resize: reallocation failed\n"); diff --git a/src/runtime/objects/functions/functions.c b/src/runtime/objects/functions/functions.c index 166ec7e..7ab6906 100644 --- a/src/runtime/objects/functions/functions.c +++ b/src/runtime/objects/functions/functions.c @@ -14,6 +14,15 @@ ArgonObject *ARGON_FUNCTION_TYPE = NULL; +ArgonObject *create_argon_native_function(char*name, native_fn native_fn) { + ArgonObject *object = new_object(); + add_field(object, "__class__", ARGON_FUNCTION_TYPE); + object->type = TYPE_NATIVE_FUNCTION; + add_field(object, "__name__", new_string_object(name, strlen(name))); + object->value.native_fn = native_fn; + return object; +} + void load_argon_function(Translated *translated, RuntimeState *state, struct Stack *stack) { ArgonObject *object = new_object(); @@ -22,8 +31,7 @@ void load_argon_function(Translated *translated, RuntimeState *state, uint64_t offset = pop_bytecode(translated, state); uint64_t length = pop_bytecode(translated, state); add_field(object, "__name__", new_string_object(arena_get(&translated->constants, offset), length)); - object->value.argon_fn.path = translated->path; - object->value.argon_fn.source_locations = translated->source_locations; + object->value.argon_fn.translated = *translated; object->value.argon_fn.number_of_parameters = pop_bytecode(translated, state); object->value.argon_fn.parameters = ar_alloc(object->value.argon_fn.number_of_parameters * sizeof(struct string_struct)); diff --git a/src/runtime/objects/functions/functions.h b/src/runtime/objects/functions/functions.h index d429391..630d78e 100644 --- a/src/runtime/objects/functions/functions.h +++ b/src/runtime/objects/functions/functions.h @@ -10,6 +10,8 @@ extern ArgonObject *ARGON_FUNCTION_TYPE; +ArgonObject *create_argon_native_function(char*name, native_fn native_fn); + ArgonObject *load_argon_function(Translated *translated, RuntimeState *state, struct Stack *stack); #endif // FUNCTION_H \ No newline at end of file diff --git a/src/runtime/objects/object.c b/src/runtime/objects/object.c index f4f89f0..c5fef57 100644 --- a/src/runtime/objects/object.c +++ b/src/runtime/objects/object.c @@ -9,6 +9,7 @@ #include "../../memory.h" #include "type/type.h" #include +#include #include ArgonObject *BASE_CLASS = NULL; @@ -26,13 +27,32 @@ void add_field(ArgonObject *target, char *name, ArgonObject *object) { object, 0); } -ArgonObject *get_field_for_class(ArgonObject *target, char *name) { +ArgonObject *bind_object_to_function(ArgonObject *object, + ArgonObject *function) { + ArgonObject *bound_method_wrapper = new_object(); + bound_method_wrapper->type = TYPE_METHOD; + add_field(bound_method_wrapper, "__class__", ARGON_METHOD_TYPE); + add_field(bound_method_wrapper, "__binding__", object); + add_field(bound_method_wrapper, "__function__", function); + ArgonObject *function_name = get_field(function, "__name__", false); + if (function_name) + add_field(bound_method_wrapper, "__name__", function_name); + return bound_method_wrapper; +} + +ArgonObject *get_field_for_class(ArgonObject *target, char *name, ArgonObject *binding_object) { char *field = "__base__"; while (target) { uint64_t hash = siphash64_bytes(name, strlen(name), siphash_key); ArgonObject *object = hashmap_lookup_GC(target->dict, hash); - if (object) + + if (object) { + if (object->type == TYPE_FUNCTION || + object->type == TYPE_NATIVE_FUNCTION) { + object = bind_object_to_function(binding_object, object); + } return object; + } hash = siphash64_bytes(field, strlen(field), siphash_key); target = hashmap_lookup_GC(target->dict, hash); } @@ -41,14 +61,8 @@ ArgonObject *get_field_for_class(ArgonObject *target, char *name) { ArgonObject *get_field(ArgonObject *target, char *name, bool recursive) { char *field = "__class__"; - while (target) { - uint64_t hash = siphash64_bytes(name, strlen(name), siphash_key); - ArgonObject *object = hashmap_lookup_GC(target->dict, hash); - if (!recursive || object) - return object; - hash = siphash64_bytes(field, strlen(field), siphash_key); - target = hashmap_lookup_GC(target->dict, hash); - field = "__base__"; - } - return NULL; + ArgonObject *object = hashmap_lookup_GC(target->dict, siphash64_bytes(name, strlen(name), siphash_key)); + if (!recursive || object) + return object; + return get_field_for_class(hashmap_lookup_GC(target->dict, siphash64_bytes(field, strlen(field), siphash_key)), name, target); } \ No newline at end of file diff --git a/src/runtime/objects/object.h b/src/runtime/objects/object.h index a297fcc..de32911 100644 --- a/src/runtime/objects/object.h +++ b/src/runtime/objects/object.h @@ -17,7 +17,7 @@ ArgonObject *new_object(); void add_field(ArgonObject *target, char *name, ArgonObject *object); -ArgonObject *get_field_for_class(ArgonObject *target, char *name); +ArgonObject *get_field_for_class(ArgonObject *target, char *name, ArgonObject *binding_object); ArgonObject *get_field(ArgonObject *target, char *name, bool recursive); diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 22e2569..6f0aa96 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -25,11 +25,30 @@ #include #include +ArgonObject *ARGON_METHOD_TYPE; +Stack *Global_Scope = NULL; + +ArgonObject *ARGON_TYPE_TYPE___call__(size_t argc, ArgonObject **argv, + ArErr *err) { + if (argc<1) { + *err = create_err(0, 0, 0, "", "Runtime Error", "call missing self object."); + return ARGON_NULL; + } + ArgonObject *self = argv[0]; + ArgonObject *self_name = get_field(argv[0], "__name__", true); + + printf("type: %.*s\n", (int)self_name->value.as_str.length, self_name->value.as_str.data); + return ARGON_NULL; +} + void bootstrap_types() { BASE_CLASS = new_object(); ARGON_TYPE_TYPE = new_object(); add_field(ARGON_TYPE_TYPE, "__base__", BASE_CLASS); add_field(ARGON_TYPE_TYPE, "__class__", ARGON_TYPE_TYPE); + add_field(ARGON_TYPE_TYPE, "__call__", + create_argon_native_function( + "__call__", ARGON_TYPE_TYPE___call__)); ARGON_NULL_TYPE = new_object(); add_field(ARGON_NULL_TYPE, "__base__", BASE_CLASS); @@ -63,6 +82,25 @@ void bootstrap_types() { add_field(ARGON_FUNCTION_TYPE, "__base__", BASE_CLASS); add_field(ARGON_FUNCTION_TYPE, "__name__", new_string_object_null_terminated("function")); + + ARGON_METHOD_TYPE = new_object(); + add_field(ARGON_METHOD_TYPE, "__base__", BASE_CLASS); + add_field(ARGON_METHOD_TYPE, "__name__", + new_string_object_null_terminated("method")); +} + +void add_to_scope(Stack *stack, char *name, ArgonObject *value) { + size_t length = strlen(name); + uint64_t hash = + siphash64_bytes(name, length, siphash_key); + ArgonObject *key = new_string_object(name, length); + hashmap_insert_GC(stack->scope, hash, key, value, 0); +} + +void bootstrap_globals() { + Global_Scope = create_scope(NULL); + add_to_scope(Global_Scope, "string", ARGON_STRING_TYPE); + add_to_scope(Global_Scope, "type", ARGON_TYPE_TYPE); } int compare_by_order(const void *a, const void *b) { @@ -72,7 +110,7 @@ int compare_by_order(const void *a, const void *b) { } uint8_t pop_byte(Translated *translated, RuntimeState *state) { - return *((uint8_t *)darray_get(&translated->bytecode, state->head++)); + return *((uint8_t *)darray_armem_get(&translated->bytecode, state->head++)); } uint64_t pop_bytecode(Translated *translated, RuntimeState *state) { @@ -120,8 +158,7 @@ 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 prehash = pop_bytecode(translated, state); - int64_t source_location_index = pop_bytecode(translated, state); + uint64_t prehash = pop_bytecode(translated, state); uint64_t hash = runtime_hash(arena_get(&translated->constants, offset), length, prehash); struct Stack *current_stack = stack; @@ -133,12 +170,11 @@ ArErr load_variable(Translated *translated, RuntimeState *state, } 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, - source_location->length, state->path, "Name Error", - "name '%.*s' is not defined", (int)length, - arena_get(&translated->constants, offset)); + ArErr err = + create_err(state->source_location.line, state->source_location.column, + state->source_location.length, state->path, "Name Error", + "name '%.*s' is not defined", (int)length, + arena_get(&translated->constants, offset)); return err; } @@ -200,22 +236,25 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, // free(array); *stack = (*stack)->prev; break; - case OP_INIT_ARGS:; - *state->call_args_length = pop_bytecode(translated, state); - size_t size = *state->call_args_length * sizeof(ArgonObject *); - if (*state->call_args) { - *state->call_args = realloc(*state->call_args, size); - } else { - *state->call_args = checked_malloc(size); - } + case OP_INIT_CALL:; + size_t length = pop_bytecode(translated, state); + call_instance call_instance = { + state->call_instance, state->registers[0], + checked_malloc(length * sizeof(ArgonObject *)), length}; + state->call_instance = checked_malloc(sizeof(call_instance)); + *state->call_instance = call_instance; break; case OP_INSERT_ARG:; - to_register = pop_byte(translated, state); - (*state->call_args)[pop_bytecode(translated, state)] = - state->registers[to_register]; + size_t index = pop_bytecode(translated, state); + (state->call_instance->args)[index] = state->registers[0]; break; - case OP_CALL: - return run_call(translated, state); + case OP_CALL:; + ArErr err = run_call(translated, state); + free(state->call_instance->args); + call_instance = *state->call_instance; + free(state->call_instance); + state->call_instance = call_instance.previous; + return err; // ArgonObject *object = state->registers[from_register]; // char *field = "__class__"; // uint64_t hash = siphash64_bytes(field, strlen(field), siphash_key); @@ -235,6 +274,11 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, // (int)class_name->value.as_str.length, class_name->value.as_str.data, // object); // } + case OP_SOURCE_LOCATION: + state->source_location = (SourceLocation){pop_bytecode(translated, state), + pop_bytecode(translated, state), + pop_bytecode(translated, state)}; + break; default: return create_err(0, 0, 0, NULL, "Runtime Error", "Invalid Opcode %#x", opcode); @@ -243,13 +287,13 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, } RuntimeState init_runtime_state(Translated translated, char *path) { - RuntimeState runtime = (RuntimeState){ + RuntimeState runtime = { checked_malloc(translated.registerCount * sizeof(ArgonObject *)), 0, path, NULL, NULL, - 0, + {0, 0, 0}, {}}; return runtime; } @@ -268,12 +312,6 @@ Stack *create_scope(Stack *prev) { ArErr runtime(Translated translated, RuntimeState state, Stack *stack) { state.head = 0; - ArgonObject **call_args = NULL; - size_t call_args_length = 0; - - state.call_args = &call_args; - state.call_args_length = &call_args_length; - StackFrame *currentStackFrame = checked_malloc(sizeof(StackFrame) * STACKFRAME_CHUNKS); *currentStackFrame = (StackFrame){translated, state, stack, NULL, 0}; @@ -288,19 +326,18 @@ ArErr runtime(Translated translated, RuntimeState state, Stack *stack) { ¤tStackFrame->state, ¤tStackFrame->stack); } StackFrame *tempStackFrame = currentStackFrame; + + while (currentStackFrame->state.call_instance) { + free(currentStackFrame->state.call_instance->args); + call_instance call_instance = *currentStackFrame->state.call_instance; + free(currentStackFrame->state.call_instance); + currentStackFrame->state.call_instance = call_instance.previous; + } + currentStackFrame = currentStackFrame->previousStackFrame; if (tempStackFrame->depth % STACKFRAME_CHUNKS == 0) { free(tempStackFrame); } } - - if (call_args) - free(call_args); - call_args = NULL; - call_args_length = 0; - - state.call_args = NULL; - state.call_args_length = NULL; - return err; } \ No newline at end of file diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 3d0ced9..6e26b9c 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -11,22 +11,38 @@ #include "internals/dynamic_array_armem/darray_armem.h" #include "internals/hashmap/hashmap.h" +extern ArgonObject *ARGON_METHOD_TYPE; +extern Stack *Global_Scope; + typedef struct StackFrame StackFrame; typedef struct RuntimeState RuntimeState; +typedef struct SourceLocation { + uint64_t line; + uint64_t column; + uint64_t length; +} SourceLocation; + +typedef struct call_instance { + struct call_instance *previous; + ArgonObject *to_call; + ArgonObject **args; + size_t args_length; +} call_instance; + typedef struct ErrorCatch { size_t jump_to; Stack *stack; StackFrame *stackFrame; -} ErrorCatch; +} ErrorCatch; typedef struct RuntimeState { ArgonObject **registers; size_t head; char *path; + call_instance *call_instance; StackFrame **currentStackFramePointer; - ArgonObject*** call_args; - size_t* call_args_length; + SourceLocation source_location; DArray catch_errors; // ErrorCatch[] } RuntimeState; @@ -46,6 +62,8 @@ extern struct hashmap *runtime_hash_table; uint64_t runtime_hash(const void *data, size_t len, uint64_t prehash); +void bootstrap_globals(); + uint8_t pop_byte(Translated *translated, RuntimeState *state); uint64_t pop_bytecode(Translated *translated, RuntimeState *state); diff --git a/src/translator/bytecode_spec.md b/src/translator/bytecode_spec.md index 41c261c..1d15bde 100644 --- a/src/translator/bytecode_spec.md +++ b/src/translator/bytecode_spec.md @@ -29,7 +29,6 @@ this operation takes 3 operands. 2. the offset in the constant buffer of the variable name. 3. the fixed hash of the variable name. 4. the register of the given value (*) -5. the index of the source location. ## OP_LOAD_NULL @@ -59,7 +58,6 @@ initilises a function to a given register. 1. the length of the identifer. 2. the offset of the identifier. 3. the fixed hash of the variable name. -4. the index of the source location. ## OP_BOOL @@ -89,27 +87,27 @@ creates a new stack pops the top scope off the current -## OP_INIT_ARGS +## OP_INIT_CALL -initialises the arguments buffer with a fixed number of objects on the current state +initialises a call instance struct and arguments buffer. 1. the number of objects for the arguments buffer ## OP_INSERT_ARG -1. the register to take the object from. (*) 1. index of the argument in the arguments buffer to write the object from the register into. -## OP_RESET_ARGS - -resets the arguments buffer to NULL - ## OP_CALL call a function with args -1. the register containing the function to call. (*) -4. the index of the source location. +## OP_SOURCE_LOCATION + +sets the source location onto the runtime + +3. the line +4. the column +5. the length ## OP_SWAP_REGISTERS diff --git a/src/translator/call/call.c b/src/translator/call/call.c index 59143a2..541a580 100644 --- a/src/translator/call/call.c +++ b/src/translator/call/call.c @@ -5,29 +5,27 @@ */ #include "call.h" -size_t translate_parsed_call(Translated *translated, ParsedCall* call, ArErr *err) { +size_t translate_parsed_call(Translated *translated, ParsedCall *call, + ArErr *err) { set_registers(translated, 1); - size_t first = push_instruction_byte(translated, OP_INIT_ARGS); + translate_parsed(translated, call->to_call, err); + size_t first = push_instruction_byte(translated, OP_INIT_CALL); push_instruction_code(translated, call->args.size); for (size_t i = 0; i < call->args.size; i++) { translate_parsed(translated, darray_get(&call->args, i), err); if (err->exists) return first; push_instruction_byte(translated, OP_INSERT_ARG); - push_instruction_byte(translated, 0); push_instruction_code(translated, i); } - translate_parsed(translated, call->to_call, err); if (err->exists) return first; + + push_instruction_byte(translated, OP_SOURCE_LOCATION); + push_instruction_code(translated, call->line); + push_instruction_code(translated, call->column); + push_instruction_code(translated, 1); + push_instruction_byte(translated, OP_CALL); - push_instruction_byte(translated, 0); - SourceLocation source_locations = { - call->line, - call->column, - 1 - }; - push_instruction_code(translated, translated->source_locations.size); - darray_push(&translated->source_locations, &source_locations); return first; } \ No newline at end of file diff --git a/src/translator/declaration/declaration.c b/src/translator/declaration/declaration.c index daf5fd1..2687f91 100644 --- a/src/translator/declaration/declaration.c +++ b/src/translator/declaration/declaration.c @@ -27,16 +27,17 @@ size_t translate_parsed_declaration(Translated *translated, size_t length = strlen(singleDeclaration->name); size_t offset = arena_push(&translated->constants, singleDeclaration->name, length); - + + push_instruction_byte(translated, OP_SOURCE_LOCATION); + push_instruction_code(translated, singleDeclaration->line); + push_instruction_code(translated, singleDeclaration->column); + push_instruction_code(translated, length); + push_instruction_byte(translated, OP_DECLARE); push_instruction_code(translated, length); push_instruction_code(translated, offset); push_instruction_code(translated, siphash64_bytes(singleDeclaration->name, length, siphash_key_fixed_for_translator)); push_instruction_byte(translated, 0); - SourceLocation source_locations = {singleDeclaration->line, - singleDeclaration->column, length}; - push_instruction_code(translated, translated->source_locations.size); - darray_push(&translated->source_locations, &source_locations); translated->return_jumps = old_return_jumps; } return first; diff --git a/src/translator/function/function.c b/src/translator/function/function.c index 4b3e5c3..8c97913 100644 --- a/src/translator/function/function.c +++ b/src/translator/function/function.c @@ -13,9 +13,9 @@ #include size_t translate_parsed_function(Translated *translated, ParsedFunction *parsedFunction, ArErr *err) { - DArray main_bytecode = translated->bytecode; - DArray _temp_bytecode; - darray_init(&_temp_bytecode, sizeof(uint8_t)); + darray_armem main_bytecode = translated->bytecode; + darray_armem _temp_bytecode; + darray_armem_init(&_temp_bytecode, sizeof(uint8_t)); set_registers(translated, 1); translated->bytecode = _temp_bytecode; translate_parsed(translated, parsedFunction->body, err); @@ -23,7 +23,6 @@ size_t translate_parsed_function(Translated *translated, arena_push(&translated->constants, translated->bytecode.data, translated->bytecode.size*translated->bytecode.element_size); size_t function_bytecode_length = translated->bytecode.size; - darray_free(&translated->bytecode, NULL); translated->bytecode = main_bytecode; size_t start = push_instruction_byte(translated, OP_LOAD_FUNCTION); size_t offset = arena_push(&translated->constants, parsedFunction->name, diff --git a/src/translator/identifier/identifier.c b/src/translator/identifier/identifier.c index f4263b9..a787d87 100644 --- a/src/translator/identifier/identifier.c +++ b/src/translator/identifier/identifier.c @@ -4,27 +4,30 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -#include "../translator.h" #include "identifier.h" +#include "../../hash_data/hash_data.h" +#include "../translator.h" #include #include #include -#include "../../hash_data/hash_data.h" -size_t translate_parsed_identifier(Translated *translated, ParsedIdentifier *parsedIdentifier) { +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); + 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); + + size_t start = push_instruction_byte(translated, OP_SOURCE_LOCATION); + push_instruction_code(translated, parsedIdentifier->line); + push_instruction_code(translated, parsedIdentifier->column); + push_instruction_code(translated, length); + + push_instruction_byte(translated, OP_IDENTIFIER); + push_instruction_code(translated, length); push_instruction_code(translated, identifier_pos); - push_instruction_code(translated, siphash64_bytes(parsedIdentifier->name, length, siphash_key_fixed_for_translator)); - SourceLocation source_locations = { - parsedIdentifier->line, - parsedIdentifier->column, - length - }; - push_instruction_code(translated, translated->source_locations.size); - darray_push(&translated->source_locations, &source_locations); + push_instruction_code(translated, + siphash64_bytes(parsedIdentifier->name, length, + siphash_key_fixed_for_translator)); return start; } \ No newline at end of file diff --git a/src/translator/translator.c b/src/translator/translator.c index 094f7d3..47df473 100644 --- a/src/translator/translator.c +++ b/src/translator/translator.c @@ -6,7 +6,6 @@ #include "translator.h" #include "../hash_data/hash_data.h" -#include "../hashmap/hashmap.h" #include "declaration/declaration.h" #include "call/call.h" #include "dowrap/dowrap.h" @@ -29,10 +28,10 @@ void uint64_to_bytes(uint64_t value, uint8_t bytes[8]) { } void arena_init(ConstantArena *arena) { - arena->data = checked_malloc(CHUNK_SIZE); + arena->data = ar_alloc(CHUNK_SIZE); arena->capacity = CHUNK_SIZE; arena->size = 0; - arena->hashmap = createHashmap(); + arena->hashmap = createHashmap_GC(); } void arena_resize(ConstantArena *arena, size_t new_size) { @@ -48,13 +47,6 @@ void arena_resize(ConstantArena *arena, size_t new_size) { arena->capacity = new_capacity; } -void arena_free(ConstantArena *arena) { - free(arena->data); - arena->capacity = 0; - arena->size = 0; - hashmap_free(arena->hashmap, NULL); -} - void *arena_get(ConstantArena *arena, size_t offset) { return arena->data + offset; } @@ -63,7 +55,7 @@ size_t arena_push(ConstantArena *arena, const void *data, size_t length) { uint64_t hash = siphash64_bytes(data, length, siphash_key); // Look up offset in hashmap - void *val = hashmap_lookup(arena->hashmap, hash); + void *val = hashmap_lookup_GC(arena->hashmap, hash); if (val != NULL) { size_t offset = (size_t)(uintptr_t)val - 1; // stored as pointer but really offset @@ -80,7 +72,7 @@ size_t arena_push(ConstantArena *arena, const void *data, size_t length) { arena->size += length; // Insert into hashmap: store offset as pointer-sized integer - hashmap_insert(arena->hashmap, hash, (void *)data, + hashmap_insert_GC(arena->hashmap, hash, (void *)data, (void *)(uintptr_t)offset + 1, 0); return offset; @@ -91,15 +83,14 @@ Translated init_translator(char* path) { translated.path = path; translated.registerCount = 1; translated.return_jumps=NULL; - darray_init(&translated.bytecode, sizeof(uint8_t)); - darray_init(&translated.source_locations, sizeof(SourceLocation)); + darray_armem_init(&translated.bytecode, sizeof(uint8_t)); arena_init(&translated.constants); return translated; } size_t push_instruction_byte(Translated *translator, uint8_t byte) { size_t offset = translator->bytecode.size; - darray_push(&translator->bytecode, &byte); + darray_armem_push(&translator->bytecode, &byte); return offset; } @@ -112,7 +103,7 @@ size_t push_instruction_code(Translated *translator, uint64_t code) { uint8_t bytes[8]; uint64_to_bytes(code, bytes); for (size_t i = 0; i < sizeof(bytes); i++) { - darray_push(&translator->bytecode, &(bytes[i])); + darray_armem_push(&translator->bytecode, &(bytes[i])); } return offset; } @@ -169,10 +160,4 @@ ArErr translate(Translated *translated, DArray *ast) { } } return err; -} - -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 5c68ca1..10e42e5 100644 --- a/src/translator/translator.h +++ b/src/translator/translator.h @@ -14,31 +14,9 @@ #include #include -typedef enum { OP_LOAD_CONST, OP_DECLARE, OP_LOAD_NULL, OP_LOAD_FUNCTION, OP_IDENTIFIER, OP_BOOL, OP_JUMP_IF_FALSE, OP_JUMP, OP_NEW_SCOPE, OP_POP_SCOPE, OP_INIT_ARGS, OP_INSERT_ARG, OP_RESET_ARGS, OP_CALL } OperationType; +typedef enum { OP_LOAD_CONST, OP_DECLARE, OP_LOAD_NULL, OP_LOAD_FUNCTION, OP_IDENTIFIER, OP_BOOL, OP_JUMP_IF_FALSE, OP_JUMP, OP_NEW_SCOPE, OP_POP_SCOPE, OP_INIT_CALL, OP_INSERT_ARG, OP_CALL, OP_SOURCE_LOCATION } OperationType; typedef enum { TYPE_OP_STRING, TYPE_OP_NUMBER } types; -typedef struct { - void *data; - size_t capacity; - size_t size; - struct hashmap * hashmap; -} ConstantArena; - -typedef struct { - uint8_t registerCount; - DArray *return_jumps; - DArray bytecode; - DArray source_locations; - ConstantArena constants; - char* path; -} 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); @@ -61,6 +39,4 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue, ArErr* ArErr translate(Translated *translated, DArray *ast); -void free_translator(Translated *translated); - #endif \ No newline at end of file diff --git a/testing.ar b/testing.ar index e808716..9f081ae 100644 --- a/testing.ar +++ b/testing.ar @@ -1,5 +1,4 @@ # SPDX-FileCopyrightText: 2025 William Bell # SPDX-License-Identifier: GPL-3.0-or-later -let x(hello, x, y) = "hello world" -x(10,10,10) \ No newline at end of file +type() \ No newline at end of file