/* * SPDX-FileCopyrightText: 2025 William Bell * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "dictionary.h" #include "../../call/call.h" #include "../functions/functions.h" #include "../literals/literals.h" #include "../string/string.h" #include #include #include #include #include ArgonObject *ARGON_DICTIONARY_TYPE = NULL; ArgonObject *create_ARGON_DICTIONARY_TYPE___init__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { (void)state; if (argc != 1) { *err = create_err(0, 0, 0, "", "Runtime Error", "__init__ expects 1 argument, got %" PRIu64, argc); return ARGON_NULL; } ArgonObject *object = argv[0]; object->type = TYPE_DICTIONARY; object->value.as_hashmap = createHashmap_GC(); return object; } ArgonObject *create_ARGON_DICTIONARY_TYPE___string__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { (void)state; if (argc != 1) { *err = create_err(0, 0, 0, "", "Runtime Error", "__init__ expects 1 argument, got %" PRIu64, argc); return ARGON_NULL; } ArgonObject *object = argv[0]; size_t string_length = 0; char *string = NULL; size_t nodes_length; struct node_GC ** nodes = hashmap_GC_to_array(object->value.as_hashmap, &nodes_length); char *string_obj = "{"; size_t length = strlen(string_obj); string = realloc(string, string_length + length); memcpy(string + string_length, string_obj, length); string_length += length; for (size_t i = 0; i < nodes_length; i++) { struct node_GC *node = nodes[i]; ArgonObject *key = node->key; ArgonObject *value = node->val; if (!key) { fprintf(stderr, "NULL key at node %zu\n", i); continue; } if (!value) { fprintf(stderr, "NULL value at node %zu\n", i); continue; } ArgonObject *string_convert_method = get_builtin_field_for_class( get_builtin_field(key, __class__), __repr__, key); if (string_convert_method) { ArgonObject *string_object = argon_call(string_convert_method, 0, NULL, err, state); string = realloc(string, string_length + string_object->value.as_str->length); memcpy(string + string_length, string_object->value.as_str->data, string_object->value.as_str->length); string_length += string_object->value.as_str->length; } else { char *string_obj = ""; size_t length = strlen(string_obj); string = realloc(string, string_length + length); memcpy(string + string_length, string_obj, length); string_length += length; } char *string_obj = ": "; size_t length = strlen(string_obj); string = realloc(string, string_length + length); memcpy(string + string_length, string_obj, length); string_length += length; string_convert_method = get_builtin_field_for_class( get_builtin_field(value, __class__), __repr__, value); if (string_convert_method && value != object) { ArgonObject *string_object = argon_call(string_convert_method, 0, NULL, err, state); string = realloc(string, string_length + string_object->value.as_str->length); memcpy(string + string_length, string_object->value.as_str->data, string_object->value.as_str->length); string_length += string_object->value.as_str->length; } else { char *string_obj = "{...}"; size_t length = strlen(string_obj); string = realloc(string, string_length + length); memcpy(string + string_length, string_obj, length); string_length += length; } if (i != nodes_length - 1) { char *string_obj = ", "; size_t length = strlen(string_obj); string = realloc(string, string_length + length); memcpy(string + string_length, string_obj, length); string_length += length; } } string_obj = "}"; length = strlen(string_obj); string = realloc(string, string_length + length); memcpy(string + string_length, string_obj, length); string_length += length; ArgonObject* result = new_string_object(string, string_length, 0, 0); free(string); return result; } ArgonObject *create_ARGON_DICTIONARY_TYPE___getattr__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { (void)state; if (argc != 2) { *err = create_err(0, 0, 0, "", "Runtime Error", "__getattr__ expects 2 argument, got %" PRIu64, argc); return ARGON_NULL; } ArgonObject *object = argv[0]; ArgonObject *key = argv[1]; int64_t hash = hash_object(key, err, state); if (err->exists) { return ARGON_NULL; } ArgonObject *result = hashmap_lookup_GC(object->value.as_hashmap, hash); if (!result) { *err = create_err(0, 0, 0, NULL, "Attribute Error", "Dictionary has no attribute '%.*s'", key->value.as_str->length, key->value.as_str->data); return ARGON_NULL; } return result; } ArgonObject *create_ARGON_DICTIONARY_TYPE___setattr__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { (void)state; if (argc != 3) { *err = create_err(0, 0, 0, "", "Runtime Error", "__setattr__ expects 2 argument, got %" PRIu64, argc); return ARGON_NULL; } ArgonObject *object = argv[0]; ArgonObject *key = argv[1]; ArgonObject *value = argv[2]; int64_t hash = hash_object(key, err, state); if (err->exists) { return ARGON_NULL; } hashmap_insert_GC(object->value.as_hashmap, hash, key, value, 0); return value; } ArgonObject *create_ARGON_DICTIONARY_TYPE___getitem__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { (void)state; if (argc != 2) { *err = create_err(0, 0, 0, "", "Runtime Error", "__getitem__ expects 2 argument, got %" PRIu64, argc); return ARGON_NULL; } ArgonObject *object = argv[0]; ArgonObject *key = argv[1]; int64_t hash = hash_object(key, err, state); if (err->exists) { return ARGON_NULL; } ArgonObject *result = hashmap_lookup_GC(object->value.as_hashmap, hash); if (!result) { char *object_str = argon_object_to_null_terminated_string(key, err, state); *err = create_err(0, 0, 0, NULL, "Attribute Error", "Dictionary has no item '%s'", object_str); return ARGON_NULL; } return result; } ArgonObject *create_ARGON_DICTIONARY_TYPE___setitem__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { (void)state; if (argc != 3) { *err = create_err(0, 0, 0, "", "Runtime Error", "__setitem__ expects 2 argument, got %" PRIu64, argc); return ARGON_NULL; } ArgonObject *object = argv[0]; ArgonObject *key = argv[1]; ArgonObject *value = argv[2]; int64_t hash = hash_object(key, err, state); if (err->exists) { return ARGON_NULL; } hashmap_insert_GC(object->value.as_hashmap, hash, key, value, 0); return value; } void create_ARGON_DICTIONARY_TYPE() { ARGON_DICTIONARY_TYPE = new_class(); add_builtin_field(ARGON_DICTIONARY_TYPE, __name__, new_string_object_null_terminated("dictionary")); add_builtin_field(ARGON_DICTIONARY_TYPE, __init__, create_argon_native_function( "__init__", create_ARGON_DICTIONARY_TYPE___init__)); add_builtin_field( ARGON_DICTIONARY_TYPE, __getattr__, create_argon_native_function("__getattr__", create_ARGON_DICTIONARY_TYPE___getattr__)); add_builtin_field( ARGON_DICTIONARY_TYPE, __setattr__, create_argon_native_function("__setattr__", create_ARGON_DICTIONARY_TYPE___setattr__)); add_builtin_field( ARGON_DICTIONARY_TYPE, __setitem__, create_argon_native_function("__setitem__", create_ARGON_DICTIONARY_TYPE___setitem__)); add_builtin_field( ARGON_DICTIONARY_TYPE, __getitem__, create_argon_native_function("__getitem__", create_ARGON_DICTIONARY_TYPE___getitem__)); add_builtin_field(ARGON_DICTIONARY_TYPE, __string__, create_argon_native_function( "__string__", create_ARGON_DICTIONARY_TYPE___string__)); } ArgonObject *create_dictionary(struct hashmap_GC *hashmap) { ArgonObject *object = new_instance(ARGON_DICTIONARY_TYPE); object->type = TYPE_DICTIONARY; object->value.as_hashmap = hashmap; return object; }