From fba074a5a4d7d4c3947a59e8658c280ecbb0a29b Mon Sep 17 00:00:00 2001 From: Ugric Date: Tue, 8 Jul 2025 04:31:01 +0100 Subject: [PATCH] limit arguments to not support duplicate names --- .gitignore | 2 -- gentest.py | 10 +++---- src/parser/declaration/declaration.c | 15 +++++++++-- src/runtime/internals/hashmap/hashmap.c | 2 +- src/runtime/runtime.c | 23 +++++++++++++--- src/runtime/runtime.h | 15 ++++++++--- test.py | 35 +++++++++++++++++++++++++ 7 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 test.py diff --git a/.gitignore b/.gitignore index 24cad0e..ec28779 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,4 @@ build *.yy.c *.yy.h -out.arbin -rand_test.ar __arcache__ \ No newline at end of file diff --git a/gentest.py b/gentest.py index 0f227cb..b02acc0 100644 --- a/gentest.py +++ b/gentest.py @@ -1,7 +1,7 @@ import random -myfile = open("rand_test.ar","w") +import sys -for i in range(10000000): - myfile.write("\"") - myfile.write(str(random.random())[2::]) - myfile.write("\"\n") +for i in range(100000000): + sys.stdout.write("\"") + sys.stdout.write(str(random.random())) + sys.stdout.write("\"\n") diff --git a/src/parser/declaration/declaration.c b/src/parser/declaration/declaration.c index 890917e..27431ba 100644 --- a/src/parser/declaration/declaration.c +++ b/src/parser/declaration/declaration.c @@ -1,4 +1,6 @@ #include "declaration.h" +#include "../../hashmap/hashmap.h" +#include "../../hash_data/hash_data.h" #include "../../lexer/token.h" #include "../../memory.h" #include "../function/function.h" @@ -23,7 +25,7 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) { darray_push(declarations, &_declaration); ParsedSingleDeclaration *declaration = darray_get(declarations, declarations->size - 1); - bool isFunction=false; + bool isFunction = false; DArray parameters; declaration->from = parse_null(); @@ -41,6 +43,7 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) { token = darray_get(tokens, *index); if (token->type == TOKEN_LPAREN) { isFunction = true; + struct hashmap *parameters_hashmap = createHashmap(); darray_init(¶meters, sizeof(char *)); (*index)++; error_if_finished(file, tokens, index); @@ -63,8 +66,16 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) { file, token->line, token->column); exit(EXIT_FAILURE); } - char *parameter_name = checked_malloc(strlen(token->value) + 1); + uint64_t hash = siphash64_bytes(token->value, token->length, siphash_key); + if (hashmap_lookup(parameters_hashmap, hash) != NULL) { + fprintf(stderr, + "%s:%zu:%zu error: duplicate argument '%.*s' in function definition\n", + file, token->line, token->column, (int)token->length, token->value); + exit(EXIT_FAILURE); + } + char *parameter_name = checked_malloc(token->length + 1); strcpy(parameter_name, token->value); + hashmap_insert(parameters_hashmap, hash, parameter_name, (void*)1, 0); darray_push(¶meters, ¶meter_name); (*index)++; error_if_finished(file, tokens, index); diff --git a/src/runtime/internals/hashmap/hashmap.c b/src/runtime/internals/hashmap/hashmap.c index c758bd3..4ed9a84 100644 --- a/src/runtime/internals/hashmap/hashmap.c +++ b/src/runtime/internals/hashmap/hashmap.c @@ -41,7 +41,7 @@ void resize_hashmap_GC(struct hashmap_GC *t) { } } -int hashCode_GC(struct hashmap_GC *t, uint64_t hash) { return hash % t->size; } +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); diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index b6dbec2..526ce0d 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -33,7 +33,6 @@ void init_types() { init_base_field(); } - uint8_t pop_byte(Translated *translated, RuntimeState *state) { return *((uint8_t *)darray_get(&translated->bytecode, state->head++)); } @@ -63,8 +62,20 @@ void load_const(Translated *translated, RuntimeState *state) { state->registers[to_register] = object; } -void run_instruction(Translated *translated, RuntimeState *state, - struct Stack stack) { +const ArErr no_err = (ArErr){false}; + +ArErr create_err(char *path, int64_t line, char *type, char *message) { + return (ArErr){ + false, + path, + line, + type, + message + }; +} + + ArErr run_instruction(Translated *translated, RuntimeState *state, + struct Stack stack) { OperationType opcode = pop_byte(translated, state); switch (opcode) { case OP_LOAD_NULL: @@ -76,7 +87,11 @@ void run_instruction(Translated *translated, RuntimeState *state, case OP_LOAD_FUNCTION: load_argon_function(translated, state, stack); break; + default: + fprintf(stderr, "bytecode invalid\n"); + exit(EXIT_FAILURE); } + return no_err; } RuntimeState init_runtime_state(Translated translated) { @@ -86,7 +101,7 @@ RuntimeState init_runtime_state(Translated translated) { } ArgonObject *runtime(Translated translated, RuntimeState state) { - struct Stack stack = {NULL,NULL}; + struct Stack stack = {NULL, NULL}; state.head = 0; while (state.head < translated.bytecode.size) { run_instruction(&translated, &state, stack); diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 87af9c4..4f4367d 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -8,16 +8,25 @@ typedef struct { size_t head; } RuntimeState; +typedef struct { + bool exists; + char *path; + int64_t line; + char *type; + char *message; +} ArErr; + typedef struct Stack { - ArgonObject *scope; - struct Stack *prev; + ArgonObject *scope; + struct Stack *prev; } Stack; void init_types(); uint64_t pop_bytecode(Translated *translated, RuntimeState *state); -void run_instruction(Translated *translated, RuntimeState *state, struct Stack stack); +ArErr run_instruction(Translated *translated, RuntimeState *state, + struct Stack stack); RuntimeState init_runtime_state(Translated translated); diff --git a/test.py b/test.py new file mode 100644 index 0000000..43743ee --- /dev/null +++ b/test.py @@ -0,0 +1,35 @@ +import string +from itertools import product +import sys + +def generate_names(max_width, skip_keywords=None): + if skip_keywords is None: + skip_keywords = {"if", "else", "while", "forever", "for", "break", "continue", + "return", "let", "import", "from", "do", "true", "false", "null", + "delete", "not", "try", "catch", "in"} + else: + skip_keywords = set(skip_keywords) + + chars = string.ascii_lowercase + first = True + write = sys.stdout.write + + for length in range(1, max_width + 1): + print(length, file=sys.stderr) + i = 0 + for p in product(chars, repeat=length): + name = ''.join(p) + if name in skip_keywords: + continue + if not first: + write('\n') + write(name) + first = False + if i>10000000: + break + i+=1 + +# Example usage: +max_width = 15 +# sys.stdout.write("let ") +generate_names(max_width)