diff --git a/src/main.c b/src/main.c index 5eb71bf..bfffeae 100644 --- a/src/main.c +++ b/src/main.c @@ -44,6 +44,8 @@ #include #endif #include "err.h" +#include +#include #if defined(_WIN32) || defined(_WIN64) @@ -152,7 +154,8 @@ 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, char*source_path) { +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"); @@ -376,6 +379,9 @@ Execution execute(char *path, Stack *stack) { printf("Translation time taken: %f seconds\n", time_spent); darray_free(&ast, free_parsed); + + malloc_trim(0); + ensure_dir_exists(cache_folder_path); file = fopen(cache_file_path, "wb"); @@ -417,20 +423,18 @@ Execution execute(char *path, Stack *stack) { } hashmap_free(translated.constants.hashmap, NULL); Translated gc_translated = { - translated.registerCount, - NULL, - {}, - {}, - translated.path - }; + translated.registerCount, NULL, {}, {}, translated.path}; gc_translated.bytecode.data = ar_alloc(translated.bytecode.capacity); - memcpy(gc_translated.bytecode.data, translated.bytecode.data, translated.bytecode.capacity); + memcpy(gc_translated.bytecode.data, translated.bytecode.data, + translated.bytecode.capacity); gc_translated.bytecode.element_size = translated.bytecode.element_size; gc_translated.bytecode.size = translated.bytecode.size; gc_translated.bytecode.resizable = false; - gc_translated.bytecode.capacity = translated.bytecode.size*translated.bytecode.element_size; + gc_translated.bytecode.capacity = + translated.bytecode.size * translated.bytecode.element_size; gc_translated.constants.data = ar_alloc(translated.constants.capacity); - memcpy(gc_translated.constants.data, translated.constants.data, translated.constants.capacity); + memcpy(gc_translated.constants.data, translated.constants.data, + translated.constants.capacity); gc_translated.constants.size = translated.constants.size; gc_translated.constants.capacity = translated.constants.capacity; darray_free(&translated.bytecode, NULL); @@ -440,7 +444,6 @@ Execution execute(char *path, Stack *stack) { RuntimeState state = init_runtime_state(gc_translated, path); Stack *main_scope = create_scope(stack); ArErr err = runtime(gc_translated, state, main_scope); - free_runtime_state(state); end = clock(); time_spent = (double)(end - start) / CLOCKS_PER_SEC; total_time_spent += time_spent; @@ -453,6 +456,7 @@ Execution execute(char *path, Stack *stack) { int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); ar_memory_init(); + generate_siphash_key(siphash_key); bootstrap_types(); bootstrap_globals(); @@ -470,5 +474,6 @@ int main(int argc, char *argv[]) { output_err(resp.err); return 1; } + // Your main thread code return 0; } \ No newline at end of file diff --git a/src/memory.c b/src/memory.c index d1b2882..baecd61 100644 --- a/src/memory.c +++ b/src/memory.c @@ -5,7 +5,7 @@ */ #include "memory.h" -#include +#include #include #include #include // for malloc/free (temp arena fallback) @@ -38,11 +38,12 @@ void ar_memory_init() { void *ar_alloc(size_t size) { return GC_MALLOC(size); } -void *ar_realloc(void * old,size_t size) { return GC_REALLOC(old, size); } +void *ar_realloc(void *old, size_t size) { return GC_REALLOC(old, size); } void ar_finalizer(void *obj, GC_finalization_proc fn, void *client_data, GC_finalization_proc *old_fn, void **old_client_data) { - return GC_register_finalizer_no_order(obj, fn, client_data, old_fn, old_client_data); + return GC_register_finalizer_no_order(obj, fn, client_data, old_fn, + old_client_data); } void *ar_alloc_atomic(size_t size) { return GC_MALLOC_ATOMIC(size); } diff --git a/src/runtime/call/call.c b/src/runtime/call/call.c index 18dde23..9aaf948 100644 --- a/src/runtime/call/call.c +++ b/src/runtime/call/call.c @@ -88,19 +88,17 @@ ArErr run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv, object = call_method; } } - bool to_free_args = false; if (object->type == TYPE_METHOD) { ArgonObject *binding_object = get_field(object, "__binding__", false, false); if (binding_object) { - ArgonObject **new_call_args = malloc(sizeof(ArgonObject *) * (argc + 1)); + ArgonObject **new_call_args = ar_alloc(sizeof(ArgonObject *) * (argc + 1)); new_call_args[0] = binding_object; if (argc > 0) { memcpy(new_call_args + 1, argv, argc * sizeof(ArgonObject *)); } argv = new_call_args; argc++; - to_free_args = true; } ArgonObject *function_object = get_field(object, "__function__", false, false); @@ -131,8 +129,6 @@ ArErr run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv, hashmap_insert_GC(scope->scope, hash, new_string_object(key.data, key.length), value, 0); } - if (to_free_args) - free(argv); StackFrame new_stackFrame = { {object->value.argon_fn.translated.registerCount, NULL, @@ -157,7 +153,7 @@ ArErr run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv, if (((*state->currentStackFramePointer)->depth + 1) % STACKFRAME_CHUNKS == 0) { *state->currentStackFramePointer = - checked_malloc(sizeof(StackFrame) * STACKFRAME_CHUNKS); + ar_alloc(sizeof(StackFrame) * STACKFRAME_CHUNKS); } else { *state->currentStackFramePointer = *state->currentStackFramePointer + 1; } @@ -185,8 +181,6 @@ ArErr run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv, } else if (object->type == TYPE_NATIVE_FUNCTION) { ArErr err = no_err; state->registers[0] = object->value.native_fn(argc, argv, &err, state); - if (to_free_args) - free(argv); if (err.exists && strlen(err.path) == 0) { err.line = state->source_location.line; err.column = state->source_location.column; @@ -195,8 +189,6 @@ ArErr run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv, } return err; } - if (to_free_args) - free(argv); ArgonObject *type_object_name = get_field_for_class(get_field(original_object, "__class__", false, false), "__name__", original_object); diff --git a/src/runtime/internals/dynamic_array_armem/darray_armem.c b/src/runtime/internals/dynamic_array_armem/darray_armem.c index b6157f0..7d3202e 100644 --- a/src/runtime/internals/dynamic_array_armem/darray_armem.c +++ b/src/runtime/internals/dynamic_array_armem/darray_armem.c @@ -123,7 +123,6 @@ void darray_armem_free(darray_armem *arr, void (*free_data)(void *)) { free_data(element); } } - free(arr->data); arr->data = NULL; arr->size = 0; arr->capacity = 0; diff --git a/src/runtime/internals/hashmap/hashmap.c b/src/runtime/internals/hashmap/hashmap.c index 9af04bb..ce6fe9a 100644 --- a/src/runtime/internals/hashmap/hashmap.c +++ b/src/runtime/internals/hashmap/hashmap.c @@ -15,7 +15,8 @@ struct hashmap_GC *createHashmap_GC() { size_t size = 8; - struct hashmap_GC *t = (struct hashmap_GC *)ar_alloc(sizeof(struct hashmap_GC)); + struct hashmap_GC *t = + (struct hashmap_GC *)ar_alloc(sizeof(struct hashmap_GC)); t->size = size; t->order = 1; t->list = (struct node_GC **)ar_alloc(sizeof(struct node_GC *) * size); @@ -41,13 +42,15 @@ void resize_hashmap_GC(struct hashmap_GC *t) { struct node_GC *temp = old_list[i]; while (temp) { hashmap_insert_GC(t, temp->hash, temp->key, temp->val, - temp->order); // Will increment count + temp->order); // Will increment count temp = temp->next; } } } -int hashCode_GC(struct hashmap_GC *t, uint64_t hash) { return hash & (t->size - 1); } +int hashCode_GC(struct hashmap_GC *t, uint64_t hash) { + return hash & (t->size - 1); +} int hashmap_remove_GC(struct hashmap_GC *t, uint64_t hash) { int pos = hashCode_GC(t, hash); @@ -72,7 +75,7 @@ int hashmap_remove_GC(struct hashmap_GC *t, uint64_t hash) { } void hashmap_insert_GC(struct hashmap_GC *t, uint64_t hash, void *key, - void *val, size_t order) { + void *val, size_t order) { if (!order) { order = t->order++; } diff --git a/src/runtime/objects/object.c b/src/runtime/objects/object.c index f08d6dc..a31230f 100644 --- a/src/runtime/objects/object.c +++ b/src/runtime/objects/object.c @@ -63,6 +63,7 @@ ArgonObject *get_field_for_class_l(ArgonObject *target, char *name, ArgonObject *get_field_l(ArgonObject *target, char *name, size_t length, bool recursive, bool disable_method_wrapper) { + if(!target|| !target->dict) return NULL; char *field = "__class__"; size_t field_size = strlen(field); ArgonObject *object = hashmap_lookup_GC( diff --git a/src/runtime/objects/term/term.c b/src/runtime/objects/term/term.c new file mode 100644 index 0000000..c86a6f3 --- /dev/null +++ b/src/runtime/objects/term/term.c @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2025 William Bell + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ +#include "term.h" +#include +#include +#include "../../call/call.h" + +ArgonObject *term_log(size_t argc, ArgonObject **argv, ArErr *err, + RuntimeState *state) { + for (size_t i = 0; i < argc; i++) { + if (i != 0) + printf(" "); + ArgonObject *string_convert_method = get_field_for_class( + get_field(argv[i], "__class__", false, false), "__string__", argv[i]); + + if (string_convert_method) { + ArgonObject *string_object = + argon_call(string_convert_method, 0, NULL, err, state); + fwrite(string_object->value.as_str.data, sizeof(char), + string_object->value.as_str.length, stdout); + } + } + printf("\n"); + return ARGON_NULL; +} \ No newline at end of file diff --git a/src/runtime/objects/term/term.h b/src/runtime/objects/term/term.h new file mode 100644 index 0000000..1298e07 --- /dev/null +++ b/src/runtime/objects/term/term.h @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2025 William Bell + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef runtime_term_H +#define runtime_term_H +#include "../../objects/literals/literals.h" +#include "../../objects/object.h" +#include "../../runtime.h" + +ArgonObject *term_log(size_t argc, ArgonObject **argv, ArErr *err, + RuntimeState *state); + +#endif // runtime_term_H \ No newline at end of file diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 926d399..d00fc8b 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -8,6 +8,7 @@ #include "../err.h" #include "../hash_data/hash_data.h" #include "../translator/translator.h" +#include "access/access.h" #include "call/call.h" #include "declaration/declaration.h" #include "internals/hashmap/hashmap.h" @@ -15,8 +16,8 @@ #include "objects/literals/literals.h" #include "objects/object.h" #include "objects/string/string.h" +#include "objects/term/term.h" #include "objects/type/type.h" -#include "access/access.h" #include #include #include @@ -29,7 +30,7 @@ ArgonObject *ARGON_METHOD_TYPE; Stack *Global_Scope = NULL; -ArgonObject*ACCESS_FUNCTION; +ArgonObject *ACCESS_FUNCTION; ArgonObject *ARGON_TYPE_TYPE___call__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { @@ -108,6 +109,23 @@ ArgonObject *BASE_CLASS___init__(size_t argc, ArgonObject **argv, ArErr *err, return ARGON_NULL; } +ArgonObject *BASE_CLASS___string__(size_t argc, ArgonObject **argv, ArErr *err, + RuntimeState *state) { + (void)state; + if (argc != 1) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "__string__ expects 1 arguments, got %" PRIu64, argc); + } + + ArgonObject *object_name = get_field_for_class(argv[0], "__name__", NULL); + ArgonObject *class_name = get_field_for_class( + get_field(argv[0], "__class__", false, false), "__name__", NULL); + + char buffer[100]; + snprintf(buffer, sizeof(buffer), "<%.*s %.*s at %p>", (int)class_name->value.as_str.length, class_name->value.as_str.data, (int)object_name->value.as_str.length, object_name->value.as_str.data,argv[0]); + return new_string_object_null_terminated(buffer); +} + ArgonObject *ARGON_STRING_TYPE___init__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { if (argc != 2) { @@ -128,11 +146,11 @@ ArgonObject *ARGON_STRING_TYPE___init__(size_t argc, ArgonObject **argv, argon_call(string_convert_method, 0, NULL, err, state); if (err->exists) return ARGON_NULL; - object->value.as_str.data = + self->value.as_str.data = ar_alloc_atomic(string_object->value.as_str.length); - memcpy(object->value.as_str.data, string_object->value.as_str.data, + memcpy(self->value.as_str.data, string_object->value.as_str.data, string_object->value.as_str.length); - object->value.as_str.length = string_object->value.as_str.length; + self->value.as_str.length = string_object->value.as_str.length; } return ARGON_NULL; } @@ -165,7 +183,7 @@ ArgonObject *ARGON_STRING_TYPE___string__(size_t argc, ArgonObject **argv, (void)state; if (argc != 1) { *err = create_err(0, 0, 0, "", "Runtime Error", - "__init__ expects 1 arguments, got %" PRIu64, argc); + "__string__ expects 1 arguments, got %" PRIu64, argc); } return argv[0]; } @@ -218,6 +236,8 @@ void bootstrap_types() { create_argon_native_function("__new__", BASE_CLASS___new__)); add_field(BASE_CLASS, "__init__", create_argon_native_function("__init__", BASE_CLASS___new__)); + add_field(BASE_CLASS, "__string__", + create_argon_native_function("__string__", BASE_CLASS___string__)); add_field(ARGON_TYPE_TYPE, "__call__", create_argon_native_function("__call__", ARGON_TYPE_TYPE___call__)); add_field( @@ -228,7 +248,8 @@ void bootstrap_types() { create_argon_native_function("__string__", ARGON_STRING_TYPE___string__)); add_field(ARGON_BOOL_TYPE, "__new__", create_argon_native_function("__new__", ARGON_BOOL_TYPE___new__)); - ACCESS_FUNCTION = create_argon_native_function("ACCESS_FUNCTION", ARGON_TYPE_TYPE___get_attr__); + ACCESS_FUNCTION = create_argon_native_function("ACCESS_FUNCTION", + ARGON_TYPE_TYPE___get_attr__); } void add_to_scope(Stack *stack, char *name, ArgonObject *value) { @@ -243,6 +264,11 @@ void bootstrap_globals() { add_to_scope(Global_Scope, "string", ARGON_STRING_TYPE); add_to_scope(Global_Scope, "type", ARGON_TYPE_TYPE); add_to_scope(Global_Scope, "boolean", ARGON_BOOL_TYPE); + + ArgonObject *argon_term = new_object(); + add_field(argon_term, "__init__", ARGON_NULL); + add_field(argon_term, "log", create_argon_native_function("log", term_log)); + add_to_scope(Global_Scope, "term", argon_term); } int compare_by_order(const void *a, const void *b) { @@ -340,8 +366,9 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, case OP_BOOL:; ArErr err = no_err; uint8_t to_register = pop_byte(translated, state); - ArgonObject* args[] = {ARGON_BOOL_TYPE, state->registers[0]}; - state->registers[to_register] = ARGON_BOOL_TYPE___new__(2, args, &err, state); + ArgonObject *args[] = {ARGON_BOOL_TYPE, state->registers[0]}; + state->registers[to_register] = + ARGON_BOOL_TYPE___new__(2, args, &err, state); return err; case OP_JUMP_IF_FALSE:; uint8_t from_register = pop_byte(translated, state); @@ -384,8 +411,8 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, 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)); + ar_alloc(length * sizeof(ArgonObject *)), length}; + state->call_instance = ar_alloc(sizeof(call_instance)); *state->call_instance = call_instance; break; case OP_INSERT_ARG:; @@ -394,12 +421,9 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, break; case OP_CALL:; err = run_call(state->call_instance->to_call, - state->call_instance->args_length, - state->call_instance->args, state, false); - free(state->call_instance->args); - call_instance = *state->call_instance; - free(state->call_instance); - state->call_instance = call_instance.previous; + state->call_instance->args_length, + state->call_instance->args, state, false); + state->call_instance = (*state->call_instance).previous; return err; // ArgonObject *object = state->registers[from_register]; // char *field = "__class__"; @@ -426,7 +450,8 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, pop_bytecode(translated, state)}; break; case OP_LOAD_BOOL: - state->registers[0] = pop_byte(translated, state)?ARGON_TRUE:ARGON_FALSE; + state->registers[0] = + pop_byte(translated, state) ? ARGON_TRUE : ARGON_FALSE; break; case OP_LOAD_ACCESS_FUNCTION: state->registers[0] = ACCESS_FUNCTION; @@ -440,7 +465,7 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, RuntimeState init_runtime_state(Translated translated, char *path) { RuntimeState runtime = { - checked_malloc(translated.registerCount * sizeof(ArgonObject *)), + ar_alloc(translated.registerCount * sizeof(ArgonObject *)), 0, path, NULL, @@ -450,10 +475,6 @@ RuntimeState init_runtime_state(Translated translated, char *path) { return runtime; } -void free_runtime_state(RuntimeState runtime_state) { - free(runtime_state.registers); -} - Stack *create_scope(Stack *prev) { Stack *stack = ar_alloc(sizeof(Stack)); stack->scope = createHashmap_GC(); @@ -465,7 +486,7 @@ ArErr runtime(Translated translated, RuntimeState state, Stack *stack) { state.head = 0; StackFrame *currentStackFrame = - checked_malloc(sizeof(StackFrame) * STACKFRAME_CHUNKS); + ar_alloc(sizeof(StackFrame) * STACKFRAME_CHUNKS); *currentStackFrame = (StackFrame){translated, state, stack, NULL, 0}; currentStackFrame->state.currentStackFramePointer = ¤tStackFrame; ArErr err = no_err; @@ -477,19 +498,7 @@ ArErr runtime(Translated translated, RuntimeState state, Stack *stack) { run_instruction(¤tStackFrame->translated, ¤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); - } } return err; } \ No newline at end of file diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 6e26b9c..0bee9fd 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -73,8 +73,6 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, RuntimeState init_runtime_state(Translated translated, char *path); -void free_runtime_state(RuntimeState runtime_state); - Stack *create_scope(Stack *prev); ArErr runtime(Translated translated, RuntimeState state, Stack *stack); diff --git a/src/translator/call/call.c b/src/translator/call/call.c index 541a580..98de730 100644 --- a/src/translator/call/call.c +++ b/src/translator/call/call.c @@ -11,6 +11,8 @@ size_t translate_parsed_call(Translated *translated, ParsedCall *call, translate_parsed(translated, call->to_call, err); size_t first = push_instruction_byte(translated, OP_INIT_CALL); push_instruction_code(translated, call->args.size); + + push_instruction_byte(translated, OP_NEW_SCOPE); for (size_t i = 0; i < call->args.size; i++) { translate_parsed(translated, darray_get(&call->args, i), err); if (err->exists) @@ -27,5 +29,6 @@ size_t translate_parsed_call(Translated *translated, ParsedCall *call, push_instruction_code(translated, 1); push_instruction_byte(translated, OP_CALL); + push_instruction_byte(translated, OP_POP_SCOPE); return first; } \ No newline at end of file diff --git a/testing.ar b/testing.ar index f2814e0..a5290ce 100644 --- a/testing.ar +++ b/testing.ar @@ -1,6 +1,4 @@ -# SPDX-FileCopyrightText: 2025 William Bell -# -# SPDX-License-Identifier: GPL-3.0-or-later - -let f()="hello world" -type(string(f()))(10) \ No newline at end of file +let split(url) = do + let split = url.splitN("?", 2) + if (split.length != 2) return {path: split[0], query: {}} + else return {path: split[0], query: decodeURLQuery(split[1])} \ No newline at end of file