From 1a5abd9543653642d583664b0eec286388fcce4b Mon Sep 17 00:00:00 2001 From: William Bell <62452284+Ugric@users.noreply.github.com> Date: Tue, 9 Sep 2025 18:41:19 +0100 Subject: [PATCH] impliment micro optimisations by reordering and restructing the structs so they are smaller. --- src/arobject.h | 32 ++-- src/returnTypes.h | 6 +- src/runtime/call/call.c | 36 ++-- src/runtime/objects/functions/functions.c | 21 +-- src/runtime/objects/number/number.c | 161 +++++++++--------- src/runtime/objects/object.c | 5 +- src/runtime/objects/string/string.c | 11 +- src/runtime/objects/term/term.c | 4 +- src/runtime/runtime.c | 190 +++++++++++----------- tests/iteration-test.ar | 2 +- 10 files changed, 239 insertions(+), 229 deletions(-) diff --git a/src/arobject.h b/src/arobject.h index 497bc3e..48c6ea2 100644 --- a/src/arobject.h +++ b/src/arobject.h @@ -12,7 +12,6 @@ #include "runtime/internals/hashmap/hashmap.h" #include - typedef enum { __base__, __class__, @@ -76,9 +75,9 @@ typedef struct { struct string_struct { uint64_t prehash; uint64_t hash; - bool hash_computed; char *data; size_t length; + bool hash_computed; }; typedef struct Stack { @@ -100,30 +99,31 @@ struct argon_function_struct { struct built_in_slot { built_in_fields field; - ArgonObject*value; + ArgonObject *value; +}; + +struct as_number { + union { + mpq_t *mpq; + int64_t i64; + } n; + bool is_int64; }; // full definition of ArgonObject (no typedef again!) struct ArgonObject { - ArgonType type; - ArgonType child_type; struct hashmap_GC *dict; - struct built_in_slot* built_in_slot; size_t built_in_slot_size; size_t built_in_slot_length; - bool as_bool; + struct built_in_slot *built_in_slot; union { - struct as_number { - bool is_int64; - union { - mpq_t *mpq; - int64_t i64; - } n; - }as_number; - struct string_struct as_str; + struct as_number *as_number; + struct string_struct* as_str; native_fn native_fn; - struct argon_function_struct argon_fn; + struct argon_function_struct *argon_fn; } value; + ArgonType type; + bool as_bool; }; #endif // AROBJECT_H \ No newline at end of file diff --git a/src/returnTypes.h b/src/returnTypes.h index 7130006..0478c97 100644 --- a/src/returnTypes.h +++ b/src/returnTypes.h @@ -9,15 +9,15 @@ #include #include "arobject.h" -#define ERR_MSG_MAX_LEN 64 +#define ERR_MSG_MAX_LEN 32 typedef struct ArErr { - bool exists; char *path; int64_t line; int64_t column; int length; - char type[32]; char message[ERR_MSG_MAX_LEN]; + char type[16]; + bool exists; } ArErr; #endif // RETURN_TYPES_ \ No newline at end of file diff --git a/src/runtime/call/call.c b/src/runtime/call/call.c index bf3ea4f..93f15e7 100644 --- a/src/runtime/call/call.c +++ b/src/runtime/call/call.c @@ -110,7 +110,7 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv, object = function_object; } if (object->type == TYPE_FUNCTION) { - if (argc != object->value.argon_fn.number_of_parameters) { + if (argc != object->value.argon_fn->number_of_parameters) { ArgonObject *type_object_name = get_builtin_field_for_class( get_builtin_field(object, __class__), __name__, original_object); @@ -120,14 +120,14 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv, 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, argc); + (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, argc); } - Stack *scope = create_scope(object->value.argon_fn.stack, true); + Stack *scope = create_scope(object->value.argon_fn->stack, true); for (size_t i = 0; i < argc; i++) { - struct string_struct key = object->value.argon_fn.parameters[i]; + struct string_struct key = object->value.argon_fn->parameters[i]; ArgonObject *value = argv[i]; uint64_t hash = siphash64_bytes(key.data, key.length, siphash_key); hashmap_insert_GC(scope->scope, hash, @@ -135,18 +135,18 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv, 0); } StackFrame new_stackFrame = { - {object->value.argon_fn.translated.registerCount, - object->value.argon_fn.translated.registerAssignment, + {object->value.argon_fn->translated.registerCount, + object->value.argon_fn->translated.registerAssignment, 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}, - {ar_alloc(object->value.argon_fn.translated.registerCount * + {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}, + {ar_alloc(object->value.argon_fn->translated.registerCount * sizeof(ArgonObject *)), 0, - object->value.argon_fn.translated.path, + object->value.argon_fn->translated.path, NULL, state->currentStackFramePointer, {}, @@ -201,6 +201,6 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv, *err = 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); + (int)type_object_name->value.as_str->length, + type_object_name->value.as_str->data); } \ No newline at end of file diff --git a/src/runtime/objects/functions/functions.c b/src/runtime/objects/functions/functions.c index f5bc757..eff8b94 100644 --- a/src/runtime/objects/functions/functions.c +++ b/src/runtime/objects/functions/functions.c @@ -32,22 +32,23 @@ void load_argon_function(Translated *translated, RuntimeState *state, add_builtin_field(object, __name__, new_string_object(arena_get(&translated->constants, offset), length, 0, 0)); - 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 * + object->value.argon_fn = ar_alloc(sizeof(struct argon_function_struct)); + 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)); - for (size_t i = 0; i < object->value.argon_fn.number_of_parameters; i++) { + for (size_t i = 0; i < object->value.argon_fn->number_of_parameters; i++) { offset = pop_bytecode(translated, state); length = pop_bytecode(translated, state); - object->value.argon_fn.parameters[i].data = + object->value.argon_fn->parameters[i].data = arena_get(&translated->constants, offset); - object->value.argon_fn.parameters[i].length = length; + object->value.argon_fn->parameters[i].length = length; } offset = pop_bytecode(translated, state); length = pop_bytecode(translated, state); - object->value.argon_fn.bytecode = arena_get(&translated->constants, offset); - object->value.argon_fn.bytecode_length = length; - object->value.argon_fn.stack = stack; + object->value.argon_fn->bytecode = arena_get(&translated->constants, offset); + object->value.argon_fn->bytecode_length = length; + object->value.argon_fn->stack = stack; state->registers[0] = object; } \ No newline at end of file diff --git a/src/runtime/objects/number/number.c b/src/runtime/objects/number/number.c index d773bd4..99bcd0b 100644 --- a/src/runtime/objects/number/number.c +++ b/src/runtime/objects/number/number.c @@ -49,7 +49,7 @@ ArgonObject *ARGON_NUMBER_TYPE___new__(size_t argc, ArgonObject **argv, get_builtin_field(object, __class__), __name__, object); *err = create_err( 0, 0, 0, "", "Runtime Error", "cannot convert type '%.*s' to number", - type_name->value.as_str.length, type_name->value.as_str.data); + type_name->value.as_str->length, type_name->value.as_str->data); return ARGON_NULL; } @@ -89,12 +89,12 @@ ArgonObject *ARGON_NUMBER_TYPE___add__(size_t argc, ArgonObject **argv, *err = create_err( 0, 0, 0, "", "Runtime Error", "__add__ cannot perform addition between a number and %.*s", - type_name->value.as_str.length, type_name->value.as_str.data); + type_name->value.as_str->length, type_name->value.as_str->data); return ARGON_NULL; } - if (argv[0]->value.as_number.is_int64 && argv[1]->value.as_number.is_int64) { - int64_t a = argv[0]->value.as_number.n.i64; - int64_t b = argv[1]->value.as_number.n.i64; + if (argv[0]->value.as_number->is_int64 && argv[1]->value.as_number->is_int64) { + int64_t a = argv[0]->value.as_number->n.i64; + int64_t b = argv[1]->value.as_number->n.i64; bool gonna_overflow = (a > 0 && b > 0 && a > INT64_MAX - b) || (a < 0 && b < 0 && a < INT64_MIN - b); if (!gonna_overflow) { @@ -110,12 +110,12 @@ ArgonObject *ARGON_NUMBER_TYPE___add__(size_t argc, ArgonObject **argv, mpq_clear(a_GMP); mpq_clear(b_GMP); return result; - } else if (!argv[0]->value.as_number.is_int64 && - !argv[1]->value.as_number.is_int64) { + } else if (!argv[0]->value.as_number->is_int64 && + !argv[1]->value.as_number->is_int64) { mpq_t r; mpq_init(r); - mpq_add(r, *argv[0]->value.as_number.n.mpq, - *argv[1]->value.as_number.n.mpq); + mpq_add(r, *argv[0]->value.as_number->n.mpq, + *argv[1]->value.as_number->n.mpq); ArgonObject *result = new_number_object(r); mpq_clear(r); return result; @@ -123,12 +123,12 @@ ArgonObject *ARGON_NUMBER_TYPE___add__(size_t argc, ArgonObject **argv, mpq_t a_GMP, b_GMP; mpq_init(a_GMP); mpq_init(b_GMP); - if (argv[0]->value.as_number.is_int64) { - mpq_set_si(a_GMP, argv[0]->value.as_number.n.i64, 1); - mpq_set(b_GMP, *argv[1]->value.as_number.n.mpq); + if (argv[0]->value.as_number->is_int64) { + mpq_set_si(a_GMP, argv[0]->value.as_number->n.i64, 1); + mpq_set(b_GMP, *argv[1]->value.as_number->n.mpq); } else { - mpq_set(a_GMP, *argv[0]->value.as_number.n.mpq); - mpq_set_si(b_GMP, argv[1]->value.as_number.n.i64, 1); + mpq_set(a_GMP, *argv[0]->value.as_number->n.mpq); + mpq_set_si(b_GMP, argv[1]->value.as_number->n.i64, 1); } mpq_add(a_GMP, a_GMP, b_GMP); ArgonObject *result = new_number_object(a_GMP); @@ -152,13 +152,13 @@ ArgonObject *ARGON_NUMBER_TYPE___subtract__(size_t argc, ArgonObject **argv, *err = create_err( 0, 0, 0, "", "Runtime Error", "__subtract__ cannot perform subtraction between number and %.*s", - type_name->value.as_str.length, type_name->value.as_str.data); + type_name->value.as_str->length, type_name->value.as_str->data); return ARGON_NULL; } - if (argv[0]->value.as_number.is_int64 && argv[1]->value.as_number.is_int64) { - int64_t a = argv[0]->value.as_number.n.i64; - int64_t b = argv[1]->value.as_number.n.i64; + if (argv[0]->value.as_number->is_int64 && argv[1]->value.as_number->is_int64) { + int64_t a = argv[0]->value.as_number->n.i64; + int64_t b = argv[1]->value.as_number->n.i64; int64_t neg_a = -a; bool gonna_overflow = (neg_a > 0 && b > 0 && b > INT64_MAX - neg_a) || (neg_a < 0 && b < 0 && b < INT64_MIN - neg_a); @@ -175,12 +175,12 @@ ArgonObject *ARGON_NUMBER_TYPE___subtract__(size_t argc, ArgonObject **argv, mpq_clear(a_GMP); mpq_clear(b_GMP); return result; - } else if (!argv[0]->value.as_number.is_int64 && - !argv[1]->value.as_number.is_int64) { + } else if (!argv[0]->value.as_number->is_int64 && + !argv[1]->value.as_number->is_int64) { mpq_t r; mpq_init(r); - mpq_sub(r, *argv[0]->value.as_number.n.mpq, - *argv[1]->value.as_number.n.mpq); + mpq_sub(r, *argv[0]->value.as_number->n.mpq, + *argv[1]->value.as_number->n.mpq); ArgonObject *result = new_number_object(r); mpq_clear(r); return result; @@ -188,12 +188,12 @@ ArgonObject *ARGON_NUMBER_TYPE___subtract__(size_t argc, ArgonObject **argv, mpq_t a_GMP, b_GMP; mpq_init(a_GMP); mpq_init(b_GMP); - if (argv[0]->value.as_number.is_int64) { - mpq_set_si(a_GMP, argv[0]->value.as_number.n.i64, 1); - mpq_set(b_GMP, *argv[1]->value.as_number.n.mpq); + if (argv[0]->value.as_number->is_int64) { + mpq_set_si(a_GMP, argv[0]->value.as_number->n.i64, 1); + mpq_set(b_GMP, *argv[1]->value.as_number->n.mpq); } else { - mpq_set(a_GMP, *argv[0]->value.as_number.n.mpq); - mpq_set_si(b_GMP, argv[1]->value.as_number.n.i64, 1); + mpq_set(a_GMP, *argv[0]->value.as_number->n.mpq); + mpq_set_si(b_GMP, argv[1]->value.as_number->n.i64, 1); } mpq_sub(a_GMP, a_GMP, b_GMP); ArgonObject *result = new_number_object(a_GMP); @@ -217,13 +217,13 @@ ArgonObject *ARGON_NUMBER_TYPE___multiply__(size_t argc, ArgonObject **argv, *err = create_err( 0, 0, 0, "", "Runtime Error", "__multiply__ cannot perform multiplication between number and %.*s", - type_name->value.as_str.length, type_name->value.as_str.data); + type_name->value.as_str->length, type_name->value.as_str->data); return ARGON_NULL; } - if (argv[0]->value.as_number.is_int64 && argv[1]->value.as_number.is_int64) { - int64_t a = argv[0]->value.as_number.n.i64; - int64_t b = argv[1]->value.as_number.n.i64; + if (argv[0]->value.as_number->is_int64 && argv[1]->value.as_number->is_int64) { + int64_t a = argv[0]->value.as_number->n.i64; + int64_t b = argv[1]->value.as_number->n.i64; bool gonna_overflow = a > 0 ? (b > 0 ? a > INT64_MAX / b : b < INT64_MIN / a) : (b > 0 ? a < INT64_MIN / b : a != 0 && b < INT64_MAX / a); @@ -240,12 +240,12 @@ ArgonObject *ARGON_NUMBER_TYPE___multiply__(size_t argc, ArgonObject **argv, mpq_clear(a_GMP); mpq_clear(b_GMP); return result; - } else if (!argv[0]->value.as_number.is_int64 && - !argv[1]->value.as_number.is_int64) { + } else if (!argv[0]->value.as_number->is_int64 && + !argv[1]->value.as_number->is_int64) { mpq_t r; mpq_init(r); - mpq_mul(r, *argv[0]->value.as_number.n.mpq, - *argv[1]->value.as_number.n.mpq); + mpq_mul(r, *argv[0]->value.as_number->n.mpq, + *argv[1]->value.as_number->n.mpq); ArgonObject *result = new_number_object(r); mpq_clear(r); return result; @@ -253,12 +253,12 @@ ArgonObject *ARGON_NUMBER_TYPE___multiply__(size_t argc, ArgonObject **argv, mpq_t a_GMP, b_GMP; mpq_init(a_GMP); mpq_init(b_GMP); - if (argv[0]->value.as_number.is_int64) { - mpq_set_si(a_GMP, argv[0]->value.as_number.n.i64, 1); - mpq_set(b_GMP, *argv[1]->value.as_number.n.mpq); + if (argv[0]->value.as_number->is_int64) { + mpq_set_si(a_GMP, argv[0]->value.as_number->n.i64, 1); + mpq_set(b_GMP, *argv[1]->value.as_number->n.mpq); } else { - mpq_set(a_GMP, *argv[0]->value.as_number.n.mpq); - mpq_set_si(b_GMP, argv[1]->value.as_number.n.i64, 1); + mpq_set(a_GMP, *argv[0]->value.as_number->n.mpq); + mpq_set_si(b_GMP, argv[1]->value.as_number->n.i64, 1); } mpq_mul(a_GMP, a_GMP, b_GMP); ArgonObject *result = new_number_object(a_GMP); @@ -282,12 +282,12 @@ ArgonObject *ARGON_NUMBER_TYPE___division__(size_t argc, ArgonObject **argv, *err = create_err( 0, 0, 0, "", "Runtime Error", "__division__ cannot perform division between number and %.*s", - type_name->value.as_str.length, type_name->value.as_str.data); + type_name->value.as_str->length, type_name->value.as_str->data); return ARGON_NULL; } - if (argv[0]->value.as_number.is_int64 && argv[1]->value.as_number.is_int64) { - int64_t a = argv[0]->value.as_number.n.i64; - int64_t b = argv[1]->value.as_number.n.i64; + if (argv[0]->value.as_number->is_int64 && argv[1]->value.as_number->is_int64) { + int64_t a = argv[0]->value.as_number->n.i64; + int64_t b = argv[1]->value.as_number->n.i64; if (!b) { *err = create_err(state->source_location.line, state->source_location.column, @@ -296,12 +296,12 @@ ArgonObject *ARGON_NUMBER_TYPE___division__(size_t argc, ArgonObject **argv, return NULL; } return new_number_object_from_num_and_den(a, b); - } else if (!argv[0]->value.as_number.is_int64 && - !argv[1]->value.as_number.is_int64) { + } else if (!argv[0]->value.as_number->is_int64 && + !argv[1]->value.as_number->is_int64) { mpq_t r; mpq_init(r); - mpq_div(r, *argv[0]->value.as_number.n.mpq, - *argv[1]->value.as_number.n.mpq); + mpq_div(r, *argv[0]->value.as_number->n.mpq, + *argv[1]->value.as_number->n.mpq); ArgonObject *result = new_number_object(r); mpq_clear(r); return result; @@ -309,19 +309,19 @@ ArgonObject *ARGON_NUMBER_TYPE___division__(size_t argc, ArgonObject **argv, mpq_t a_GMP, b_GMP; mpq_init(a_GMP); mpq_init(b_GMP); - if (argv[0]->value.as_number.is_int64) { - mpq_set_si(a_GMP, argv[0]->value.as_number.n.i64, 1); - mpq_set(b_GMP, *argv[1]->value.as_number.n.mpq); + if (argv[0]->value.as_number->is_int64) { + mpq_set_si(a_GMP, argv[0]->value.as_number->n.i64, 1); + mpq_set(b_GMP, *argv[1]->value.as_number->n.mpq); } else { - mpq_set(a_GMP, *argv[0]->value.as_number.n.mpq); - if (!argv[1]->value.as_number.n.i64) { + mpq_set(a_GMP, *argv[0]->value.as_number->n.mpq); + if (!argv[1]->value.as_number->n.i64) { *err = create_err(state->source_location.line, state->source_location.column, state->source_location.length, state->path, "Zero Division Error", "division by zero"); return NULL; } - mpq_set_si(b_GMP, argv[1]->value.as_number.n.i64, 1); + mpq_set_si(b_GMP, argv[1]->value.as_number->n.i64, 1); } mpq_div(a_GMP, a_GMP, b_GMP); ArgonObject *result = new_number_object(a_GMP); @@ -340,13 +340,13 @@ ArgonObject *ARGON_NUMBER_TYPE___string__(size_t argc, ArgonObject **argv, return NULL; } - if (argv[0]->value.as_number.is_int64) { + if (argv[0]->value.as_number->is_int64) { char buf[32]; - snprintf(buf, sizeof(buf), "%" PRId64, argv[0]->value.as_number.n.i64); + snprintf(buf, sizeof(buf), "%" PRId64, argv[0]->value.as_number->n.i64); return new_string_object_null_terminated(buf); } - mpq_t *num = argv[0]->value.as_number.n.mpq; + mpq_t *num = argv[0]->value.as_number->n.mpq; /* If denominator == 1, print numerator as full integer */ if (mpz_cmp_ui(mpq_denref(*num), 1) == 0) { @@ -491,15 +491,20 @@ ArgonObject *ARGON_NUMBER_TYPE___string__(size_t argc, ArgonObject **argv, #define small_ints_min -256 #define small_ints_max 256 ArgonObject small_ints[small_ints_max - small_ints_min + 1]; +struct as_number small_ints_as_number[small_ints_max - small_ints_min + 1]; void init_small_ints() { for (int64_t i = 0; i <= small_ints_max - small_ints_min; i++) { int64_t n = i + small_ints_min; small_ints[i].type = TYPE_NUMBER; - small_ints[i].dict = createHashmap_GC(); + small_ints[i].built_in_slot = NULL; + small_ints[i].built_in_slot_length = 0; + small_ints[i].built_in_slot_size = 0; + small_ints[i].dict = NULL; + small_ints[i].value.as_number = &small_ints_as_number[i]; add_builtin_field(&small_ints[i], __class__, ARGON_NUMBER_TYPE); - small_ints[i].value.as_number.is_int64 = true; - small_ints[i].value.as_number.n.i64 = n; + small_ints[i].value.as_number->is_int64 = true; + small_ints[i].value.as_number->n.i64 = n; small_ints[i].as_bool = n; } } @@ -614,13 +619,14 @@ ArgonObject *new_number_object(mpq_t number) { return &small_ints[i64 - small_ints_min]; } ArgonObject *object = new_instance(ARGON_NUMBER_TYPE); + object->value.as_number = ar_alloc(sizeof(struct as_number)); object->type = TYPE_NUMBER; - object->value.as_number.n.i64 = i64; - object->value.as_number.is_int64 = is_int64; - if (object->value.as_number.is_int64) { - object->as_bool = object->value.as_number.n.i64; + object->value.as_number->n.i64 = i64; + object->value.as_number->is_int64 = is_int64; + if (object->value.as_number->is_int64) { + object->as_bool = object->value.as_number->n.i64; } else { - object->value.as_number.n.mpq = mpq_new_gc_from(number); + object->value.as_number->n.mpq = mpq_new_gc_from(number); object->as_bool = mpq_cmp_si(number, 0, 1) != 0; } return object; @@ -631,17 +637,18 @@ ArgonObject *new_number_object_from_num_and_den(int64_t n, uint64_t d) { return &small_ints[n - small_ints_min]; } ArgonObject *object = new_instance(ARGON_NUMBER_TYPE); + object->value.as_number = ar_alloc(sizeof(struct as_number)); object->type = TYPE_NUMBER; if (d == 1) { - object->value.as_number.is_int64 = true; - object->value.as_number.n.i64 = n; + object->value.as_number->is_int64 = true; + object->value.as_number->n.i64 = n; object->as_bool = n; } else { - object->value.as_number.is_int64 = false; + object->value.as_number->is_int64 = false; mpq_t r; mpq_init(r); mpq_set_si(r, n, d); - object->value.as_number.n.mpq = mpq_new_gc_from(r); + object->value.as_number->n.mpq = mpq_new_gc_from(r); object->as_bool = n != 0; mpq_clear(r); } @@ -653,9 +660,10 @@ ArgonObject *new_number_object_from_int64(int64_t i64) { return &small_ints[i64 - small_ints_min]; } ArgonObject *object = new_instance(ARGON_NUMBER_TYPE); + object->value.as_number = ar_alloc(sizeof(struct as_number)); object->type = TYPE_NUMBER; - object->value.as_number.is_int64 = true; - object->value.as_number.n.i64 = i64; + object->value.as_number->is_int64 = true; + object->value.as_number->n.i64 = i64; object->as_bool = i64; return object; } @@ -667,16 +675,17 @@ ArgonObject *new_number_object_from_double(double d) { return &small_ints[i64 - small_ints_min]; } ArgonObject *object = new_instance(ARGON_NUMBER_TYPE); + object->value.as_number = ar_alloc(sizeof(struct as_number)); object->type = TYPE_NUMBER; - object->value.as_number.n.i64 = i64; - object->value.as_number.is_int64 = is_int64; - if (object->value.as_number.is_int64) { - object->as_bool = object->value.as_number.n.i64; + object->value.as_number->n.i64 = i64; + object->value.as_number->is_int64 = is_int64; + if (object->value.as_number->is_int64) { + object->as_bool = object->value.as_number->n.i64; } else { mpq_t r; mpq_init(r); mpq_set_d(r, d); - object->value.as_number.n.mpq = mpq_new_gc_from(r); + object->value.as_number->n.mpq = mpq_new_gc_from(r); object->as_bool = d != 0; mpq_clear(r); } diff --git a/src/runtime/objects/object.c b/src/runtime/objects/object.c index e1e9410..e86aac0 100644 --- a/src/runtime/objects/object.c +++ b/src/runtime/objects/object.c @@ -67,8 +67,7 @@ inline void add_builtin_field(ArgonObject *target, built_in_fields field, return; } } - size_t position = target->built_in_slot_length++; - if (target->built_in_slot_length > target->built_in_slot_size) { + if (target->built_in_slot_length >= target->built_in_slot_size) { target->built_in_slot_size *= 2; if (target->built_in_slot_size == 0) target->built_in_slot_size = 2; else if (target->built_in_slot_size>BUILT_IN_FIELDS_COUNT) target->built_in_slot_size = BUILT_IN_FIELDS_COUNT; @@ -76,7 +75,7 @@ inline void add_builtin_field(ArgonObject *target, built_in_fields field, ar_realloc(target->built_in_slot, target->built_in_slot_size * sizeof(struct built_in_slot)); } - target->built_in_slot[position] = (struct built_in_slot){field, object}; + target->built_in_slot[target->built_in_slot_length++] = (struct built_in_slot){field, object}; // hashmap_insert_GC(target->dict, built_in_field_hashes[field], // (char *)built_in_field_names[field], object, 0); } diff --git a/src/runtime/objects/string/string.c b/src/runtime/objects/string/string.c index 5b1b889..f46c9c6 100644 --- a/src/runtime/objects/string/string.c +++ b/src/runtime/objects/string/string.c @@ -19,11 +19,12 @@ ArgonObject *new_string_object_without_memcpy(char *data, size_t length, uint64_ add_builtin_field(object, field_length, new_number_object_from_int64(length)); object->type = TYPE_STRING; - object->value.as_str.data = data; - object->value.as_str.prehash = prehash; - object->value.as_str.hash_computed = hash; - object->value.as_str.hash = hash; - object->value.as_str.length = length; + object->value.as_str = ar_alloc(sizeof(struct string_struct)); + object->value.as_str->data = data; + object->value.as_str->prehash = prehash; + object->value.as_str->hash_computed = hash; + object->value.as_str->hash = hash; + object->value.as_str->length = length; object->as_bool = length; return object; } diff --git a/src/runtime/objects/term/term.c b/src/runtime/objects/term/term.c index 75fd6e5..827110e 100644 --- a/src/runtime/objects/term/term.c +++ b/src/runtime/objects/term/term.c @@ -19,8 +19,8 @@ ArgonObject *term_log(size_t argc, ArgonObject **argv, ArErr *err, 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); + fwrite(string_object->value.as_str->data, sizeof(char), + string_object->value.as_str->length, stdout); } } printf("\n"); diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index e985f1e..ad679b9 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -55,17 +55,17 @@ ArgonObject *BASE_CLASS___getattribute__(size_t argc, ArgonObject **argv, if (check_field) { ArgonObject *access = argv[2]; uint64_t hash; - if (access->value.as_str.hash_computed) { - hash = access->value.as_str.hash; + if (access->value.as_str->hash_computed) { + hash = access->value.as_str->hash; } else { hash = - runtime_hash(access->value.as_str.data, access->value.as_str.length, - access->value.as_str.prehash); - access->value.as_str.hash = hash; - access->value.as_str.hash_computed = true; + runtime_hash(access->value.as_str->data, access->value.as_str->length, + access->value.as_str->prehash); + access->value.as_str->hash = hash; + access->value.as_str->hash_computed = true; } - ArgonObject *value = get_field_l(to_access, access->value.as_str.data, hash, - access->value.as_str.length, true, false); + ArgonObject *value = get_field_l(to_access, access->value.as_str->data, hash, + access->value.as_str->length, true, false); if (value) return value; ArgonObject *cls__get_attr__ = get_builtin_field_for_class( @@ -83,8 +83,8 @@ ArgonObject *BASE_CLASS___getattribute__(size_t argc, ArgonObject **argv, to_access); *err = create_err( 0, 0, 0, "", "Runtime Error", "'%.*s' object has no attribute '%.*s'", - (int)name->value.as_str.length, name->value.as_str.data, - (int)access->value.as_str.length, access->value.as_str.data); + (int)name->value.as_str->length, name->value.as_str->data, + (int)access->value.as_str->length, access->value.as_str->data); } return ARGON_NULL; } @@ -105,8 +105,8 @@ ArgonObject *ARGON_ADDITION_FUNCTION(size_t argc, ArgonObject **argv, get_builtin_field(output, __name__); *err = create_err(0, 0, 0, "", "Runtime Error", "Object '%.*s' is missing __add__ method", - (int)cls___name__->value.as_str.length, - cls___name__->value.as_str.data); + (int)cls___name__->value.as_str->length, + cls___name__->value.as_str->data); return ARGON_NULL; } output = @@ -133,8 +133,8 @@ ArgonObject *ARGON_SUBTRACTION_FUNCTION(size_t argc, ArgonObject **argv, get_builtin_field(output, __name__); *err = create_err(0, 0, 0, "", "Runtime Error", "Object '%.*s' is missing __subtract__ method", - (int)cls___name__->value.as_str.length, - cls___name__->value.as_str.data); + (int)cls___name__->value.as_str->length, + cls___name__->value.as_str->data); return ARGON_NULL; } output = argon_call(function__subtract__, 1, (ArgonObject *[]){argv[i]}, @@ -161,8 +161,8 @@ ArgonObject *ARGON_MULTIPLY_FUNCTION(size_t argc, ArgonObject **argv, get_builtin_field(output, __name__); *err = create_err(0, 0, 0, "", "Runtime Error", "Object '%.*s' is missing __multiply__ method", - (int)cls___name__->value.as_str.length, - cls___name__->value.as_str.data); + (int)cls___name__->value.as_str->length, + cls___name__->value.as_str->data); return ARGON_NULL; } output = argon_call(function__multiply__, 1, (ArgonObject *[]){argv[i]}, @@ -189,8 +189,8 @@ ArgonObject *ARGON_DIVISION_FUNCTION(size_t argc, ArgonObject **argv, get_builtin_field(output, __name__); *err = create_err(0, 0, 0, "", "Runtime Error", "Object '%.*s' is missing __division__ method", - (int)cls___name__->value.as_str.length, - cls___name__->value.as_str.data); + (int)cls___name__->value.as_str->length, + cls___name__->value.as_str->data); return ARGON_NULL; } output = argon_call(function__division__, 1, (ArgonObject *[]){argv[i]}, @@ -223,8 +223,8 @@ ArgonObject *ARGON_TYPE_TYPE___call__(size_t argc, ArgonObject **argv, *err = create_err( 0, 0, 0, "", "Runtime Error", "Object '%.*s' is missing __new__ method, so cannot be initialised", - (int)cls___name__->value.as_str.length, - cls___name__->value.as_str.data); + (int)cls___name__->value.as_str->length, + cls___name__->value.as_str->data); return ARGON_NULL; } @@ -244,8 +244,8 @@ ArgonObject *ARGON_TYPE_TYPE___call__(size_t argc, ArgonObject **argv, *err = create_err( 0, 0, 0, "", "Runtime Error", "Object '%.*s' is missing __init__ method, so cannot be initialised", - (int)cls___name__->value.as_str.length, - cls___name__->value.as_str.data); + (int)cls___name__->value.as_str->length, + cls___name__->value.as_str->data); } argon_call(cls___init__, argc - 1, argv + 1, err, state); if (err->exists) @@ -309,10 +309,10 @@ ArgonObject *BASE_CLASS___string__(size_t argc, ArgonObject **argv, ArErr *err, char buffer[100]; if (class_name && object_name) 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]); + (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]); else snprintf(buffer, sizeof(buffer), "", argv[0]); return new_string_object_null_terminated(buffer); @@ -339,8 +339,8 @@ ArgonObject *ARGON_STRING_TYPE___init__(size_t argc, ArgonObject **argv, ArgonObject *self = argv[0]; ArgonObject *object = argv[1]; - self->value.as_str.data = NULL; - self->value.as_str.length = 0; + self->value.as_str->data = NULL; + self->value.as_str->length = 0; self->type = TYPE_STRING; ArgonObject *string_convert_method = get_builtin_field_for_class( get_builtin_field(object, __class__), __string__, object); @@ -349,11 +349,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; - self->value.as_str.data = - ar_alloc_atomic(string_object->value.as_str.length); - memcpy(self->value.as_str.data, string_object->value.as_str.data, - string_object->value.as_str.length); - self->value.as_str.length = string_object->value.as_str.length; + self->value.as_str->data = + ar_alloc_atomic(string_object->value.as_str->length); + memcpy(self->value.as_str->data, string_object->value.as_str->data, + string_object->value.as_str->length); + self->value.as_str->length = string_object->value.as_str->length; } return ARGON_NULL; } @@ -382,7 +382,7 @@ ArgonObject *ARGON_BOOL_TYPE___new__(size_t argc, ArgonObject **argv, get_builtin_field(object, __class__), __name__, object); *err = create_err( 0, 0, 0, "", "Runtime Error", "cannot convert type '%.*s' to bool", - type_name->value.as_str.length, type_name->value.as_str.data); + type_name->value.as_str->length, type_name->value.as_str->data); return ARGON_NULL; } @@ -400,14 +400,14 @@ ArgonObject *ARGON_STRING_TYPE___add__(size_t argc, ArgonObject **argv, *err = create_err( 0, 0, 0, "", "Runtime Error", "__add__ cannot perform concatenation between a string and %.*s", - type_name->value.as_str.length, type_name->value.as_str.data); + type_name->value.as_str->length, type_name->value.as_str->data); return ARGON_NULL; } - size_t length = argv[0]->value.as_str.length + argv[1]->value.as_str.length; + size_t length = argv[0]->value.as_str->length + argv[1]->value.as_str->length; char *concat = ar_alloc_atomic(length); - memcpy(concat, argv[0]->value.as_str.data, argv[0]->value.as_str.length); - memcpy(concat + argv[0]->value.as_str.length, argv[1]->value.as_str.data, - argv[1]->value.as_str.length); + memcpy(concat, argv[0]->value.as_str->data, argv[0]->value.as_str->length); + memcpy(concat + argv[0]->value.as_str->length, argv[1]->value.as_str->data, + argv[1]->value.as_str->length); ArgonObject *object = new_string_object_without_memcpy(concat, length, 0, 0); return object; } @@ -456,8 +456,8 @@ ArgonObject *ARGON_STRING_TYPE___number__(size_t argc, ArgonObject **argv, mpq_t r; mpq_init(r); - int result = mpq_set_decimal_str_exp(r, argv[0]->value.as_str.data, - argv[0]->value.as_str.length); + int result = mpq_set_decimal_str_exp(r, argv[0]->value.as_str->data, + argv[0]->value.as_str->length); if (result != 0) { mpq_clear(r); *err = create_err(0, 0, 0, "", "Runtime Error", "Unable to parse number", @@ -476,7 +476,7 @@ ArgonObject *ARGON_STRING_TYPE___boolean__(size_t argc, ArgonObject **argv, *err = create_err(0, 0, 0, "", "Runtime Error", "__boolean__ expects 1 arguments, got %" PRIu64, argc); } - return argv[0]->value.as_str.length == 0 ? ARGON_FALSE : ARGON_TRUE; + return argv[0]->value.as_str->length == 0 ? ARGON_FALSE : ARGON_TRUE; } ArgonObject *ARGON_BOOL_TYPE___boolean__(size_t argc, ArgonObject **argv, @@ -898,10 +898,10 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, ArgonObject *valueB = state->registers[registerB]; if (likely(valueA->type == TYPE_NUMBER && valueB->type == TYPE_NUMBER)) { - if (likely(valueA->value.as_number.is_int64 && - valueB->value.as_number.is_int64)) { - int64_t a = valueA->value.as_number.n.i64; - int64_t b = valueB->value.as_number.n.i64; + if (likely(valueA->value.as_number->is_int64 && + valueB->value.as_number->is_int64)) { + int64_t a = valueA->value.as_number->n.i64; + int64_t b = valueB->value.as_number->n.i64; bool gonna_overflow = (a > 0 && b > 0 && a > INT64_MAX - b) || (a < 0 && b < 0 && a < INT64_MIN - b); if (!gonna_overflow) { @@ -917,24 +917,24 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, state->registers[registerC] = new_number_object(a_GMP); mpq_clear(a_GMP); mpq_clear(b_GMP); - } else if (!valueA->value.as_number.is_int64 && - !valueB->value.as_number.is_int64) { + } else if (!valueA->value.as_number->is_int64 && + !valueB->value.as_number->is_int64) { mpq_t r; mpq_init(r); - mpq_add(r, *valueA->value.as_number.n.mpq, - *valueB->value.as_number.n.mpq); + mpq_add(r, *valueA->value.as_number->n.mpq, + *valueB->value.as_number->n.mpq); state->registers[registerC] = new_number_object(r); mpq_clear(r); } else { mpq_t a_GMP, b_GMP; mpq_init(a_GMP); mpq_init(b_GMP); - if (valueA->value.as_number.is_int64) { - mpq_set_si(a_GMP, valueA->value.as_number.n.i64, 1); - mpq_set(b_GMP, *valueB->value.as_number.n.mpq); + if (valueA->value.as_number->is_int64) { + mpq_set_si(a_GMP, valueA->value.as_number->n.i64, 1); + mpq_set(b_GMP, *valueB->value.as_number->n.mpq); } else { - mpq_set(a_GMP, *valueA->value.as_number.n.mpq); - mpq_set_si(b_GMP, valueB->value.as_number.n.i64, 1); + mpq_set(a_GMP, *valueA->value.as_number->n.mpq); + mpq_set_si(b_GMP, valueB->value.as_number->n.i64, 1); } mpq_add(a_GMP, a_GMP, b_GMP); state->registers[registerC] = new_number_object(a_GMP); @@ -958,10 +958,10 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, ArgonObject *valueB = state->registers[registerB]; if (likely(valueA->type == TYPE_NUMBER && valueB->type == TYPE_NUMBER)) { - if (likely(valueA->value.as_number.is_int64 && - valueB->value.as_number.is_int64)) { - int64_t a = valueA->value.as_number.n.i64; - int64_t b = valueB->value.as_number.n.i64; + if (likely(valueA->value.as_number->is_int64 && + valueB->value.as_number->is_int64)) { + int64_t a = valueA->value.as_number->n.i64; + int64_t b = valueB->value.as_number->n.i64; int64_t neg_a = -a; bool gonna_overflow = (neg_a > 0 && b > 0 && b > INT64_MAX - neg_a) || (neg_a < 0 && b < 0 && b < INT64_MIN - neg_a); @@ -978,24 +978,24 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, state->registers[registerC] = new_number_object(a_GMP); mpq_clear(a_GMP); mpq_clear(b_GMP); - } else if (!valueA->value.as_number.is_int64 && - !valueB->value.as_number.is_int64) { + } else if (!valueA->value.as_number->is_int64 && + !valueB->value.as_number->is_int64) { mpq_t r; mpq_init(r); - mpq_sub(r, *valueA->value.as_number.n.mpq, - *valueB->value.as_number.n.mpq); + mpq_sub(r, *valueA->value.as_number->n.mpq, + *valueB->value.as_number->n.mpq); state->registers[registerC] = new_number_object(r); mpq_clear(r); } else { mpq_t a_GMP, b_GMP; mpq_init(a_GMP); mpq_init(b_GMP); - if (valueA->value.as_number.is_int64) { - mpq_set_si(a_GMP, valueA->value.as_number.n.i64, 1); - mpq_set(b_GMP, *valueB->value.as_number.n.mpq); + if (valueA->value.as_number->is_int64) { + mpq_set_si(a_GMP, valueA->value.as_number->n.i64, 1); + mpq_set(b_GMP, *valueB->value.as_number->n.mpq); } else { - mpq_set(a_GMP, *valueA->value.as_number.n.mpq); - mpq_set_si(b_GMP, valueB->value.as_number.n.i64, 1); + mpq_set(a_GMP, *valueA->value.as_number->n.mpq); + mpq_set_si(b_GMP, valueB->value.as_number->n.i64, 1); } mpq_sub(a_GMP, a_GMP, b_GMP); state->registers[registerC] = new_number_object(a_GMP); @@ -1019,10 +1019,10 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, ArgonObject *valueB = state->registers[registerB]; if (likely(valueA->type == TYPE_NUMBER && valueB->type == TYPE_NUMBER)) { - if (likely(valueA->value.as_number.is_int64 && - valueB->value.as_number.is_int64)) { - int64_t a = valueA->value.as_number.n.i64; - int64_t b = valueB->value.as_number.n.i64; + if (likely(valueA->value.as_number->is_int64 && + valueB->value.as_number->is_int64)) { + int64_t a = valueA->value.as_number->n.i64; + int64_t b = valueB->value.as_number->n.i64; bool gonna_overflow = a > 0 ? (b > 0 ? a > INT64_MAX / b : b < INT64_MIN / a) : (b > 0 ? a < INT64_MIN / b : a != 0 && b < INT64_MAX / a); @@ -1039,24 +1039,24 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, state->registers[registerC] = new_number_object(a_GMP); mpq_clear(a_GMP); mpq_clear(b_GMP); - } else if (!valueA->value.as_number.is_int64 && - !valueB->value.as_number.is_int64) { + } else if (!valueA->value.as_number->is_int64 && + !valueB->value.as_number->is_int64) { mpq_t r; mpq_init(r); - mpq_mul(r, *valueA->value.as_number.n.mpq, - *valueB->value.as_number.n.mpq); + mpq_mul(r, *valueA->value.as_number->n.mpq, + *valueB->value.as_number->n.mpq); state->registers[registerC] = new_number_object(r); mpq_clear(r); } else { mpq_t a_GMP, b_GMP; mpq_init(a_GMP); mpq_init(b_GMP); - if (valueA->value.as_number.is_int64) { - mpq_set_si(a_GMP, valueA->value.as_number.n.i64, 1); - mpq_set(b_GMP, *valueB->value.as_number.n.mpq); + if (valueA->value.as_number->is_int64) { + mpq_set_si(a_GMP, valueA->value.as_number->n.i64, 1); + mpq_set(b_GMP, *valueB->value.as_number->n.mpq); } else { - mpq_set(a_GMP, *valueA->value.as_number.n.mpq); - mpq_set_si(b_GMP, valueB->value.as_number.n.i64, 1); + mpq_set(a_GMP, *valueA->value.as_number->n.mpq); + mpq_set_si(b_GMP, valueB->value.as_number->n.i64, 1); } mpq_mul(a_GMP, a_GMP, b_GMP); state->registers[registerC] = new_number_object(a_GMP); @@ -1080,10 +1080,10 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, ArgonObject *valueB = state->registers[registerB]; if (likely(valueA->type == TYPE_NUMBER && valueB->type == TYPE_NUMBER)) { - if (likely(valueA->value.as_number.is_int64 && - valueB->value.as_number.is_int64)) { - int64_t a = valueA->value.as_number.n.i64; - int64_t b = valueB->value.as_number.n.i64; + if (likely(valueA->value.as_number->is_int64 && + valueB->value.as_number->is_int64)) { + int64_t a = valueA->value.as_number->n.i64; + int64_t b = valueB->value.as_number->n.i64; if (!b) { *err = create_err(state->source_location.line, state->source_location.column, @@ -1093,31 +1093,31 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, } state->registers[registerC] = new_number_object_from_num_and_den(a, b); - } else if (!valueA->value.as_number.is_int64 && - !valueB->value.as_number.is_int64) { + } else if (!valueA->value.as_number->is_int64 && + !valueB->value.as_number->is_int64) { mpq_t r; mpq_init(r); - mpq_div(r, *valueA->value.as_number.n.mpq, - *valueB->value.as_number.n.mpq); + mpq_div(r, *valueA->value.as_number->n.mpq, + *valueB->value.as_number->n.mpq); state->registers[registerC] = new_number_object(r); mpq_clear(r); } else { mpq_t a_GMP, b_GMP; mpq_init(a_GMP); mpq_init(b_GMP); - if (valueA->value.as_number.is_int64) { - mpq_set_si(a_GMP, valueA->value.as_number.n.i64, 1); - mpq_set(b_GMP, *valueB->value.as_number.n.mpq); + if (valueA->value.as_number->is_int64) { + mpq_set_si(a_GMP, valueA->value.as_number->n.i64, 1); + mpq_set(b_GMP, *valueB->value.as_number->n.mpq); } else { - mpq_set(a_GMP, *valueA->value.as_number.n.mpq); - if (!valueB->value.as_number.n.i64) { + mpq_set(a_GMP, *valueA->value.as_number->n.mpq); + if (!valueB->value.as_number->n.i64) { *err = create_err(state->source_location.line, state->source_location.column, state->source_location.length, state->path, "Zero Division Error", "division by zero"); continue; } - mpq_set_si(b_GMP, valueB->value.as_number.n.i64, 1); + mpq_set_si(b_GMP, valueB->value.as_number->n.i64, 1); } mpq_div(a_GMP, a_GMP, b_GMP); state->registers[registerC] = new_number_object(a_GMP); diff --git a/tests/iteration-test.ar b/tests/iteration-test.ar index 2c929db..0f7853b 100644 --- a/tests/iteration-test.ar +++ b/tests/iteration-test.ar @@ -1,3 +1,3 @@ -let i = 1e7 +let i = 1e6 while (i) do i=i-1 \ No newline at end of file