add item access

This commit is contained in:
2025-11-26 03:07:06 +00:00
parent 94b86fc416
commit f3912ae49f
22 changed files with 383 additions and 119 deletions

View File

@@ -29,13 +29,14 @@ typedef enum {
__new__, __new__,
__init__, __init__,
__boolean__, __boolean__,
__get_attr__, __getattr__,
field__address, field__address,
__call__, __call__,
__number__, __number__,
field_length, field_length,
__getattribute__, __getattribute__,
__setattr__, __setattr__,
__getitem__,
__setitem__, __setitem__,
__hash__, __hash__,
__repr__, __repr__,

View File

@@ -43,6 +43,15 @@ static inline uint64_t htole64(uint64_t x) { return x; }
#elif defined(__linux__) #elif defined(__linux__)
#include <endian.h> #include <endian.h>
#include <malloc.h> #include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int is_regular_file(const char *path) {
struct stat path_stat;
stat(path, &path_stat);
return S_ISREG(path_stat.st_mode);
}
#elif defined(__APPLE__) #elif defined(__APPLE__)
#include <libkern/OSByteOrder.h> #include <libkern/OSByteOrder.h>
#define htole32(x) OSSwapHostToLittleInt32(x) #define htole32(x) OSSwapHostToLittleInt32(x)
@@ -93,11 +102,11 @@ const uint32_t version_number = 0;
const char version_string[] = "4.0.0"; const char version_string[] = "4.0.0";
bool file_exists(const char *path) { bool file_exists(const char *path) {
struct stat st; struct stat st;
if (stat(path, &st) == 0) { if (stat(path, &st) == 0) {
return S_ISREG(st.st_mode); // true only if it's a regular file return S_ISREG(st.st_mode); // true only if it's a regular file
} }
return false; // doesn't exist, or stat failed return false; // doesn't exist, or stat failed
} }
static inline void write_and_hash(FILE *file, XXH64_state_t *state, static inline void write_and_hash(FILE *file, XXH64_state_t *state,
@@ -285,7 +294,6 @@ Translated load_argon_file(char *path, ArErr *err) {
sizeof(cache_file_path)); sizeof(cache_file_path));
cwk_path_change_extension(cache_file_path, BYTECODE_EXTENTION, cwk_path_change_extension(cache_file_path, BYTECODE_EXTENTION,
cache_file_path, sizeof(cache_file_path)); cache_file_path, sizeof(cache_file_path));
FILE *file = fopen(path, "r"); FILE *file = fopen(path, "r");
if (!file) { if (!file) {
*err = create_err(0, 0, 0, NULL, "File Error", "Unable to open file '%s'", *err = create_err(0, 0, 0, NULL, "File Error", "Unable to open file '%s'",
@@ -400,7 +408,8 @@ Translated load_argon_file(char *path, ArErr *err) {
Translated gc_translated = { Translated gc_translated = {
translated.registerCount, translated.registerAssignment, NULL, {}, {}, translated.registerCount, translated.registerAssignment, NULL, {}, {},
translated.path}; translated.path};
gc_translated.bytecode.data = ar_alloc_atomic(translated.bytecode.capacity+translated.constants.capacity); gc_translated.bytecode.data = ar_alloc_atomic(translated.bytecode.capacity +
translated.constants.capacity);
memcpy(gc_translated.bytecode.data, translated.bytecode.data, memcpy(gc_translated.bytecode.data, translated.bytecode.data,
translated.bytecode.capacity); translated.bytecode.capacity);
gc_translated.bytecode.element_size = translated.bytecode.element_size; gc_translated.bytecode.element_size = translated.bytecode.element_size;
@@ -408,7 +417,8 @@ Translated load_argon_file(char *path, ArErr *err) {
gc_translated.bytecode.resizable = false; gc_translated.bytecode.resizable = false;
gc_translated.bytecode.capacity = gc_translated.bytecode.capacity =
translated.bytecode.size * translated.bytecode.element_size; translated.bytecode.size * translated.bytecode.element_size;
gc_translated.constants.data = gc_translated.bytecode.data+translated.bytecode.capacity; gc_translated.constants.data =
gc_translated.bytecode.data + translated.bytecode.capacity;
memcpy(gc_translated.constants.data, translated.constants.data, memcpy(gc_translated.constants.data, translated.constants.data,
translated.constants.capacity); translated.constants.capacity);
gc_translated.constants.size = translated.constants.size; gc_translated.constants.size = translated.constants.size;
@@ -422,8 +432,8 @@ Translated load_argon_file(char *path, ArErr *err) {
} }
const char *PRE_PATHS_TO_TEST[] = {"", "", "argon_modules", "argon_modules"}; const char *PRE_PATHS_TO_TEST[] = {"", "", "argon_modules", "argon_modules"};
const char *POST_PATHS_TO_TEST[sizeof(PRE_PATHS_TO_TEST)/sizeof(char *)] = {"", "init.ar", "", const char *POST_PATHS_TO_TEST[sizeof(PRE_PATHS_TO_TEST) / sizeof(char *)] = {
"init.ar"}; "", "init.ar", "", "init.ar"};
struct hashmap *importing_hash_table = NULL; struct hashmap *importing_hash_table = NULL;
struct hashmap_GC *imported_hash_table = NULL; struct hashmap_GC *imported_hash_table = NULL;
@@ -431,8 +441,9 @@ struct hashmap_GC *imported_hash_table = NULL;
Stack *ar_import(char *current_directory, char *path_relative, ArErr *err) { Stack *ar_import(char *current_directory, char *path_relative, ArErr *err) {
char path[FILENAME_MAX]; char path[FILENAME_MAX];
bool found = false; bool found = false;
for (size_t i = 0; i < sizeof(PRE_PATHS_TO_TEST)/sizeof(char *); i++) { for (size_t i = 0; i < sizeof(PRE_PATHS_TO_TEST) / sizeof(char *); i++) {
cwk_path_get_absolute(current_directory, PRE_PATHS_TO_TEST[i], path, sizeof(path)); cwk_path_get_absolute(current_directory, PRE_PATHS_TO_TEST[i], path,
sizeof(path));
cwk_path_get_absolute(path, path_relative, path, sizeof(path)); cwk_path_get_absolute(path, path_relative, path, sizeof(path));
cwk_path_get_absolute(path, POST_PATHS_TO_TEST[i], path, sizeof(path)); cwk_path_get_absolute(path, POST_PATHS_TO_TEST[i], path, sizeof(path));
if (file_exists(path)) { if (file_exists(path)) {
@@ -445,9 +456,10 @@ Stack *ar_import(char *current_directory, char *path_relative, ArErr *err) {
path_relative); path_relative);
return NULL; return NULL;
} }
if (!importing_hash_table) importing_hash_table = createHashmap(); if (!importing_hash_table)
importing_hash_table = createHashmap();
uint64_t hash = siphash64_bytes(path, strlen(path), siphash_key); uint64_t hash = siphash64_bytes(path, strlen(path), siphash_key);
hashmap_insert(importing_hash_table, hash, path, (void*)true, 0); hashmap_insert(importing_hash_table, hash, path, (void *)true, 0);
Translated translated = load_argon_file(path, err); Translated translated = load_argon_file(path, err);
if (err->exists) { if (err->exists) {
return NULL; return NULL;
@@ -462,8 +474,9 @@ Stack *ar_import(char *current_directory, char *path_relative, ArErr *err) {
end = clock(); end = clock();
double time_spent = (double)(end - start) / CLOCKS_PER_SEC; double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
fprintf(stderr, "Execution time taken: %f seconds\n", time_spent); fprintf(stderr, "Execution time taken: %f seconds\n", time_spent);
hashmap_insert(importing_hash_table, hash, path, (void*)false, 0); hashmap_insert(importing_hash_table, hash, path, (void *)false, 0);
if (!imported_hash_table) imported_hash_table = createHashmap_GC(); if (!imported_hash_table)
imported_hash_table = createHashmap_GC();
hashmap_insert_GC(imported_hash_table, hash, path, main_scope, 0); hashmap_insert_GC(imported_hash_table, hash, path, main_scope, 0);
return main_scope; return main_scope;
} }

View File

@@ -6,7 +6,6 @@
#include "memory.h" #include "memory.h"
#include <gc.h> #include <gc.h>
#include <gc/gc.h>
#include <pthread.h> #include <pthread.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
@@ -22,6 +21,15 @@ void *checked_malloc(size_t size) {
return ptr; return ptr;
} }
void *checked_realloc(void *ptr, size_t size) {
void *new_ptr = realloc(ptr, size);
if (!new_ptr) {
fprintf(stderr, "fatal error: failed to allocate %zu bytes\n", size);
exit(EXIT_FAILURE);
}
return new_ptr;
}
struct allocation *memory_allocations = NULL; struct allocation *memory_allocations = NULL;
size_t memory_allocations_size = 0; size_t memory_allocations_size = 0;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

View File

@@ -9,7 +9,7 @@
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#include <stdbool.h> #include <stdbool.h>
#include <gc/gc.h> #include <gc.h>
// GC-managed allocations // GC-managed allocations
@@ -37,5 +37,6 @@ void ar_memory_init();
void ar_memory_shutdown(); void ar_memory_shutdown();
void *checked_malloc(size_t size); void *checked_malloc(size_t size);
void *checked_realloc(void *ptr, size_t size);
#endif // ARGON_MEMORY_H #endif // ARGON_MEMORY_H

View File

@@ -15,41 +15,38 @@
ParsedValueReturn parse_access(char *file, DArray *tokens, size_t *index, ParsedValueReturn parse_access(char *file, DArray *tokens, size_t *index,
ParsedValue *to_access) { ParsedValue *to_access) {
Token *first_token = darray_get(tokens, *index);
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
if (first_token->type == TOKEN_DOT) { ParsedAccess *parsedAccess = checked_malloc(sizeof(ParsedAccess));
ParsedAccess *parsedAccess = checked_malloc(sizeof(ParsedAccess)); parsedAccess->to_access = to_access;
parsedAccess->to_access = to_access; parsedAccess->access = NULL;
parsedAccess->access = NULL; parsedValue->type = AST_ACCESS;
parsedValue->type = AST_ACCESS; parsedValue->data = parsedAccess;
parsedValue->data = parsedAccess; (*index)++;
(*index)++; ArErr err = error_if_finished(file, tokens, index);
ArErr err = error_if_finished(file, tokens, index); if (err.exists) {
if (err.exists) { free_parsed(parsedValue);
free_parsed(parsedValue); free(parsedValue);
free(parsedValue); return (ParsedValueReturn){err, NULL};
return (ParsedValueReturn){err, NULL};
}
Token *token = darray_get(tokens, *index);
if (token->type != TOKEN_IDENTIFIER) {
free_parsed(parsedValue);
free(parsedValue);
return (ParsedValueReturn){create_err(token->line, token->column,
token->length, file, "Syntax Error",
"expected identifier after dot"),
NULL};
}
parsedAccess->line = token->line;
parsedAccess->column = token->column;
parsedAccess->length = token->length;
ParsedValueReturn parsedString = parse_string(token, false);
if (parsedString.err.exists) {
free_parsed(parsedValue);
free(parsedValue);
return parsedString;
}
parsedAccess->access = parsedString.value;
} }
Token *token = darray_get(tokens, *index);
if (token->type != TOKEN_IDENTIFIER) {
free_parsed(parsedValue);
free(parsedValue);
return (ParsedValueReturn){create_err(token->line, token->column,
token->length, file, "Syntax Error",
"expected identifier after dot"),
NULL};
}
parsedAccess->line = token->line;
parsedAccess->column = token->column;
parsedAccess->length = token->length;
ParsedValueReturn parsedString = parse_string(token, false);
if (parsedString.err.exists) {
free_parsed(parsedValue);
free(parsedValue);
return parsedString;
}
parsedAccess->access = parsedString.value;
(*index)++; (*index)++;
return (ParsedValueReturn){no_err, parsedValue}; return (ParsedValueReturn){no_err, parsedValue};
} }

View File

@@ -0,0 +1,80 @@
/*
* SPDX-FileCopyrightText: 2025 William Bell
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "item.h"
#include "../../../lexer/token.h"
#include "../../../memory.h"
#include "../../parser.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
ParsedValueReturn parse_item_access(char *file, DArray *tokens, size_t *index,
ParsedValue *to_access) {
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
ParsedItemAccess *parsedItemAccess = checked_malloc(sizeof(ParsedItemAccess));
parsedItemAccess->to_access = to_access;
size_t capacity = 4;
parsedItemAccess->items = checked_malloc(capacity * sizeof(ParsedValue *));
parsedItemAccess->itemc = 0;
parsedValue->type = AST_ITEM_ACCESS;
parsedValue->data = parsedItemAccess;
Token *token = darray_get(tokens, *index);
parsedItemAccess->line = token->line;
parsedItemAccess->column = token->column;
parsedItemAccess->length = token->length;
(*index)++;
while (true) {
ArErr err = error_if_finished(file, tokens, index);
if (err.exists) {
free_parsed(parsedValue);
free(parsedValue);
return (ParsedValueReturn){err, NULL};
}
ParsedValueReturn parsedKey = parse_token(file, tokens, index, true);
if (parsedKey.err.exists) {
free_parsed(parsedValue);
free(parsedValue);
return parsedKey;
}
parsedItemAccess->items[parsedItemAccess->itemc++] = parsedKey.value;
if (parsedItemAccess->itemc > capacity) {
capacity *= 2;
parsedItemAccess->items = checked_realloc(
parsedItemAccess->items, capacity * sizeof(ParsedValue *));
}
Token *token = darray_get(tokens, *index);
(*index)++;
if (token->type == TOKEN_COMMA) {
continue;
} else if (token->type == TOKEN_RBRACKET) {
break;
} else {
free_parsed(parsedValue);
free(parsedValue);
return (ParsedValueReturn){
create_err(token->line, token->column, token->length, file,
"Syntax Error",
"expected either a comma or a closing bracket"),
NULL};
}
}
return (ParsedValueReturn){no_err, parsedValue};
}
void free_parse_item_access(void *ptr) {
ParsedValue *parsedValue = ptr;
ParsedItemAccess *parsedItemAccess = parsedValue->data;
free_parsed(parsedItemAccess->to_access);
free(parsedItemAccess->to_access);
for (size_t i = 0; i < parsedItemAccess->itemc; i++) {
free_parsed(parsedItemAccess->items[i]);
free(parsedItemAccess->items[i]);
}
free(parsedItemAccess->items);
free(parsedItemAccess);
}

View File

@@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2025 William Bell
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef ITEM_ACCESS_H
#define ITEM_ACCESS_H
#include "../../parser.h"
#include "../../../lexer/token.h" // for Token
typedef struct {
ParsedValue *to_access;
ParsedValue **items;
size_t itemc;
size_t line;
size_t column;
size_t length;
} ParsedItemAccess;
ParsedValueReturn parse_item_access(char *file, DArray *tokens, size_t *index,
ParsedValue *to_access);
void free_parse_item_access(void *ptr);
#endif // ACCESS_H

View File

@@ -11,6 +11,7 @@
#include "assignable/assign/assign.h" #include "assignable/assign/assign.h"
#include "assignable/call/call.h" #include "assignable/call/call.h"
#include "assignable/identifier/identifier.h" #include "assignable/identifier/identifier.h"
#include "assignable/item/item.h"
#include "declaration/declaration.h" #include "declaration/declaration.h"
#include "dictionary/dictionary.h" #include "dictionary/dictionary.h"
#include "dowrap/dowrap.h" #include "dowrap/dowrap.h"
@@ -164,9 +165,11 @@ ParsedValueReturn parse_token_full(char *file, DArray *tokens, size_t *index,
output = parse_call(file, tokens, index, output.value); output = parse_call(file, tokens, index, output.value);
break; break;
case TOKEN_DOT: case TOKEN_DOT:
case TOKEN_LBRACKET:
output = parse_access(file, tokens, index, output.value); output = parse_access(file, tokens, index, output.value);
break; break;
case TOKEN_LBRACKET:
output = parse_item_access(file, tokens, index, output.value);
break;
SWITCH_OPERATIONS SWITCH_OPERATIONS
if (process_operations) { if (process_operations) {
output = parse_operations(file, tokens, index, output.value); output = parse_operations(file, tokens, index, output.value);
@@ -241,6 +244,9 @@ void free_parsed(void *ptr) {
case AST_ACCESS: case AST_ACCESS:
free_parse_access(parsed); free_parse_access(parsed);
break; break;
case AST_ITEM_ACCESS:
free_parse_item_access(parsed);
break;
case AST_NULL: case AST_NULL:
case AST_BOOLEAN: case AST_BOOLEAN:
break; break;

View File

@@ -40,6 +40,7 @@ typedef enum {
AST_NUMBER, AST_NUMBER,
AST_IF, AST_IF,
AST_ACCESS, AST_ACCESS,
AST_ITEM_ACCESS,
AST_CALL, AST_CALL,
AST_DECLARATION, AST_DECLARATION,
AST_NULL, AST_NULL,

View File

@@ -6,7 +6,7 @@
#include "darray_armem.h" #include "darray_armem.h"
#include "../../../memory.h" #include "../../../memory.h"
#include <gc/gc.h> #include <gc.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

View File

@@ -7,7 +7,7 @@
#include "hashmap.h" #include "hashmap.h"
#include "../../../memory.h" #include "../../../memory.h"
#include <gc/gc.h> #include <gc.h>
#include <inttypes.h> #include <inttypes.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>

View File

@@ -122,14 +122,14 @@ ArgonObject *create_ARGON_DICTIONARY_TYPE___string__(size_t argc,
return result; return result;
} }
ArgonObject *create_ARGON_DICTIONARY_TYPE___get_attr__(size_t argc, ArgonObject *create_ARGON_DICTIONARY_TYPE___getattr__(size_t argc,
ArgonObject **argv, ArgonObject **argv,
ArErr *err, ArErr *err,
RuntimeState *state) { RuntimeState *state) {
(void)state; (void)state;
if (argc != 2) { if (argc != 2) {
*err = create_err(0, 0, 0, "", "Runtime Error", *err = create_err(0, 0, 0, "", "Runtime Error",
"__get_attr__ expects 2 argument, got %" PRIu64, argc); "__getattr__ expects 2 argument, got %" PRIu64, argc);
return ARGON_NULL; return ARGON_NULL;
} }
ArgonObject *object = argv[0]; ArgonObject *object = argv[0];
@@ -169,6 +169,32 @@ ArgonObject *create_ARGON_DICTIONARY_TYPE___setattr__(size_t argc,
return value; 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 *create_ARGON_DICTIONARY_TYPE___setitem__(size_t argc,
ArgonObject **argv, ArgonObject **argv,
@@ -199,9 +225,9 @@ void create_ARGON_DICTIONARY_TYPE() {
create_argon_native_function( create_argon_native_function(
"__init__", create_ARGON_DICTIONARY_TYPE___init__)); "__init__", create_ARGON_DICTIONARY_TYPE___init__));
add_builtin_field( add_builtin_field(
ARGON_DICTIONARY_TYPE, __get_attr__, ARGON_DICTIONARY_TYPE, __getattr__,
create_argon_native_function("__get_attr__", create_argon_native_function("__getattr__",
create_ARGON_DICTIONARY_TYPE___get_attr__)); create_ARGON_DICTIONARY_TYPE___getattr__));
add_builtin_field( add_builtin_field(
ARGON_DICTIONARY_TYPE, __setattr__, ARGON_DICTIONARY_TYPE, __setattr__,
create_argon_native_function("__setattr__", create_argon_native_function("__setattr__",
@@ -210,6 +236,10 @@ void create_ARGON_DICTIONARY_TYPE() {
ARGON_DICTIONARY_TYPE, __setitem__, ARGON_DICTIONARY_TYPE, __setitem__,
create_argon_native_function("__setitem__", create_argon_native_function("__setitem__",
create_ARGON_DICTIONARY_TYPE___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__, add_builtin_field(ARGON_DICTIONARY_TYPE, __string__,
create_argon_native_function( create_argon_native_function(
"__string__", create_ARGON_DICTIONARY_TYPE___string__)); "__string__", create_ARGON_DICTIONARY_TYPE___string__));

View File

@@ -45,7 +45,8 @@ const char *built_in_field_names[BUILT_IN_FIELDS_COUNT] = {
"__new__", "__new__",
"__init__", "__init__",
"__boolean__", "__boolean__",
"__get_attr__", "__getattr__",
"__getitem__",
"address", "address",
"__call__", "__call__",
"__number__", "__number__",

View File

@@ -5,6 +5,7 @@
*/ */
#include "string.h" #include "string.h"
#include "../../call/call.h"
#include "../number/number.h" #include "../number/number.h"
#include "../object.h" #include "../object.h"
#include <ctype.h> #include <ctype.h>
@@ -14,51 +15,58 @@
ArgonObject *ARGON_STRING_TYPE = NULL; ArgonObject *ARGON_STRING_TYPE = NULL;
char *c_quote_string(const char *input, size_t len) { char *c_quote_string(const char *input, size_t len) {
// Worst case: every byte becomes "\uXXXX" (6 chars) + quotes + NUL // Worst case: every byte becomes "\uXXXX" (6 chars) + quotes + NUL
size_t max_out = 2 + (len * 6) + 1; size_t max_out = 2 + (len * 6) + 1;
char *out = malloc(max_out); char *out = malloc(max_out);
if (!out) return NULL; if (!out)
return NULL;
size_t j = 0; size_t j = 0;
out[j++] = '"'; out[j++] = '"';
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
unsigned char c = (unsigned char)input[i]; unsigned char c = (unsigned char)input[i];
switch (c) { switch (c) {
case '\n': case '\n':
out[j++] = '\\'; out[j++] = 'n'; break; out[j++] = '\\';
case '\t': out[j++] = 'n';
out[j++] = '\\'; out[j++] = 't'; break; break;
case '\r': case '\t':
out[j++] = '\\'; out[j++] = 'r'; break; out[j++] = '\\';
case '\\': out[j++] = 't';
out[j++] = '\\'; out[j++] = '\\'; break; break;
case '\"': case '\r':
out[j++] = '\\'; out[j++] = '\"'; break; out[j++] = '\\';
default: out[j++] = 'r';
if (isprint(c)) { break;
out[j++] = c; case '\\':
} else { out[j++] = '\\';
// write \uXXXX out[j++] = '\\';
j += sprintf(&out[j], "\\u%04X", c); break;
} case '\"':
} out[j++] = '\\';
out[j++] = '\"';
break;
default:
if (isprint(c)) {
out[j++] = c;
} else {
// write \uXXXX
j += sprintf(&out[j], "\\u%04X", c);
}
} }
}
out[j++] = '"'; out[j++] = '"';
out[j] = '\0'; out[j] = '\0';
return out; return out;
} }
void init_string(ArgonObject*object,char *data, size_t length, uint64_t prehash, void init_string(ArgonObject *object, char *data, size_t length,
uint64_t hash) { uint64_t prehash, uint64_t hash) {
add_builtin_field(object, field_length, add_builtin_field(object, field_length, new_number_object_from_int64(length));
new_number_object_from_int64(length));
object->type = TYPE_STRING; object->type = TYPE_STRING;
object->value.as_str = ar_alloc(sizeof(struct string_struct)); object->value.as_str = ar_alloc(sizeof(struct string_struct));
object->value.as_str->data = data; object->value.as_str->data = data;
@@ -69,18 +77,40 @@ void init_string(ArgonObject*object,char *data, size_t length, uint64_t prehash,
object->as_bool = length; object->as_bool = length;
} }
ArgonObject *new_string_object_without_memcpy(char *data, size_t length, uint64_t prehash, ArgonObject *new_string_object_without_memcpy(char *data, size_t length,
uint64_t hash) { uint64_t prehash, uint64_t hash) {
ArgonObject *object = new_instance(ARGON_STRING_TYPE); ArgonObject *object = new_instance(ARGON_STRING_TYPE);
init_string(object,data,length,prehash,hash); init_string(object, data, length, prehash, hash);
return object; return object;
} }
ArgonObject *new_string_object(char *data, size_t length, uint64_t prehash, ArgonObject *new_string_object(char *data, size_t length, uint64_t prehash,
uint64_t hash) { uint64_t hash) {
char*data_copy = ar_alloc_atomic(length); char *data_copy = ar_alloc_atomic(length);
memcpy(data_copy, data, length); memcpy(data_copy, data, length);
return new_string_object_without_memcpy(data_copy,length, prehash, hash); return new_string_object_without_memcpy(data_copy, length, prehash, hash);
}
char *argon_object_to_null_terminated_string(ArgonObject *object, ArErr *err,
RuntimeState *state) {
ArgonObject *string_convert_method = get_builtin_field_for_class(
get_builtin_field(object, __class__), __repr__, object);
if (!string_convert_method)
return "<object>";
ArgonObject *string_object =
argon_call(string_convert_method, 0, NULL, err, state);
if (err->exists)
return NULL;
if (string_object->type != TYPE_STRING) return "<object>";
char *string = ar_alloc(string_object->value.as_str->length+1);
string[string_object->value.as_str->length] = '\0';
memcpy(string, string_object->value.as_str->data, string_object->value.as_str->length);
return string;
} }
ArgonObject *new_string_object_null_terminated(char *data) { ArgonObject *new_string_object_null_terminated(char *data) {

View File

@@ -12,13 +12,17 @@ extern ArgonObject *ARGON_STRING_TYPE;
char *c_quote_string(const char *input, size_t len); char *c_quote_string(const char *input, size_t len);
void init_string(ArgonObject*object,char *data, size_t length, uint64_t prehash, void init_string(ArgonObject *object, char *data, size_t length,
uint64_t prehash, uint64_t hash);
char *argon_object_to_null_terminated_string(ArgonObject *object, ArErr *err,
RuntimeState *state);
ArgonObject *new_string_object_without_memcpy(char *data, size_t length,
uint64_t prehash, uint64_t hash);
ArgonObject *new_string_object(char *data, size_t length, uint64_t prehash,
uint64_t hash); uint64_t hash);
ArgonObject *new_string_object_without_memcpy(char *data, size_t length, uint64_t prehash, ArgonObject *new_string_object_null_terminated(char *data);
uint64_t hash);
ArgonObject *new_string_object(char *data, size_t length, uint64_t prehash, uint64_t hash);
ArgonObject *new_string_object_null_terminated(char*data);
#endif // STRING_OBJ_H #endif // STRING_OBJ_H

View File

@@ -22,7 +22,7 @@
#include "objects/term/term.h" #include "objects/term/term.h"
#include "objects/type/type.h" #include "objects/type/type.h"
#include <fcntl.h> #include <fcntl.h>
#include <gc/gc.h> #include <gc.h>
#include <gmp.h> #include <gmp.h>
#include <inttypes.h> #include <inttypes.h>
#include <stddef.h> #include <stddef.h>
@@ -72,11 +72,11 @@ ArgonObject *BASE_CLASS___getattribute__(size_t argc, ArgonObject **argv,
access->value.as_str->length, true, false); access->value.as_str->length, true, false);
if (value) if (value)
return value; return value;
ArgonObject *cls__get_attr__ = get_builtin_field_for_class( ArgonObject *cls__getattr__ = get_builtin_field_for_class(
get_builtin_field(to_access, __class__), __get_attr__, to_access); get_builtin_field(to_access, __class__), __getattr__, to_access);
if (cls__get_attr__) { if (cls__getattr__) {
value = value =
argon_call(cls__get_attr__, 1, (ArgonObject *[]){access}, err, state); argon_call(cls__getattr__, 1, (ArgonObject *[]){access}, err, state);
if (err->exists) { if (err->exists) {
return ARGON_NULL; return ARGON_NULL;
} }
@@ -890,7 +890,8 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack,
[OP_NOT] = &&DO_NOT, [OP_NOT] = &&DO_NOT,
[OP_LOAD_SETATTR_METHOD] = &&DO_LOAD_SETATTR_METHOD, [OP_LOAD_SETATTR_METHOD] = &&DO_LOAD_SETATTR_METHOD,
[OP_CREATE_DICTIONARY] = &&DO_CREATE_DICTIONARY, [OP_CREATE_DICTIONARY] = &&DO_CREATE_DICTIONARY,
[OP_LOAD_SETITEM_METHOD] = &&DO_LOAD_SETITEM_METHOD}; [OP_LOAD_SETITEM_METHOD] = &&DO_LOAD_SETITEM_METHOD,
[OP_LOAD_GETITEM_METHOD] = &&DO_LOAD_GETITEM_METHOD};
_state.head = 0; _state.head = 0;
StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame)); StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame));
@@ -1288,6 +1289,18 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack,
} }
continue; continue;
} }
DO_LOAD_GETITEM_METHOD: {
state->registers[0] = get_builtin_field_for_class(
get_builtin_field(state->registers[0], __class__), __getitem__,
state->registers[0]);
if (!state->registers[0]) {
*err = create_err(
state->source_location.line, state->source_location.column,
state->source_location.length, state->path, "Runtime Error",
"unable to get __getitem__ from objects class");
}
continue;
}
} }
ArgonObject *result = currentStackFrame->state.registers[0]; ArgonObject *result = currentStackFrame->state.registers[0];

View File

@@ -193,6 +193,10 @@ loads the \_\_setattr\_\_ method from the objects class in register 0 and put it
create a dictionary object into register 0. create a dictionary object into register 0.
## OP_LOAD_GETITEM_METHOD
loads the \_\_getitem\_\_ method from the objects class in register 0 and put it into register 0
## OP_LOAD_SETITEM_METHOD ## OP_LOAD_SETITEM_METHOD
loads the \_\_setitem\_\_ method from the objects class in register 0 and put it into register 0 loads the \_\_setitem\_\_ method from the objects class in register 0 and put it into register 0

View File

@@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2025 William Bell
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "item_access.h"
#include <stddef.h>
size_t translate_item_access(Translated *translated, ParsedItemAccess *access,
ArErr *err) {
set_registers(translated, 1);
uint64_t first = translate_parsed(translated, access->to_access, err);
if (err->exists)
return 0;
push_instruction_byte(translated, OP_LOAD_GETITEM_METHOD);
push_instruction_byte(translated, OP_INIT_CALL);
push_instruction_code(translated, access->itemc);
for (size_t i = 0; i < access->itemc; i++) {
translate_parsed(translated, access->items[i], err);
if (err->exists)
return 0;
push_instruction_byte(translated, OP_INSERT_ARG);
push_instruction_code(translated, i);
}
push_instruction_byte(translated, OP_SOURCE_LOCATION);
push_instruction_code(translated, access->line);
push_instruction_code(translated, access->column);
push_instruction_code(translated, access->length);
push_instruction_byte(translated, OP_CALL);
return first;
}

View File

@@ -0,0 +1,15 @@
/*
* SPDX-FileCopyrightText: 2025 William Bell
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef translator_item_access_H
#define translator_item_access_H
#include "../../parser/assignable/item/item.h"
#include "../translator.h"
size_t translate_item_access(Translated *translated, ParsedItemAccess *access,
ArErr *err);
#endif // translator_item_access_H

View File

@@ -9,6 +9,8 @@
#include "../parser/dictionary/dictionary.h" #include "../parser/dictionary/dictionary.h"
#include "../parser/not/not.h" #include "../parser/not/not.h"
#include "access/access.h" #include "access/access.h"
#include "../parser/assignable/item/item.h"
#include "item_access/item_access.h"
#include "assignment/assignment.h" #include "assignment/assignment.h"
#include "call/call.h" #include "call/call.h"
#include "declaration/declaration.h" #include "declaration/declaration.h"
@@ -163,6 +165,8 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue,
err); err);
case AST_ACCESS: case AST_ACCESS:
return translate_access(translated, (ParsedAccess *)parsedValue->data, err); return translate_access(translated, (ParsedAccess *)parsedValue->data, err);
case AST_ITEM_ACCESS:
return translate_item_access(translated, (ParsedItemAccess *)parsedValue->data, err);
case AST_OPERATION: case AST_OPERATION:
return translate_operation(translated, (ParsedOperation *)parsedValue->data, return translate_operation(translated, (ParsedOperation *)parsedValue->data,
err); err);

View File

@@ -42,6 +42,7 @@ typedef enum {
OP_NOT, OP_NOT,
OP_LOAD_SETATTR_METHOD, OP_LOAD_SETATTR_METHOD,
OP_CREATE_DICTIONARY, OP_CREATE_DICTIONARY,
OP_LOAD_GETITEM_METHOD,
OP_LOAD_SETITEM_METHOD OP_LOAD_SETITEM_METHOD
} OperationType; } OperationType;

View File

@@ -1,3 +0,0 @@
let i = 1e7
while (i) do
i=i-1