From 38e2cad50786d2ca35b8fdac82fd0a82c6fbb037 Mon Sep 17 00:00:00 2001 From: William Bell <62452284+Ugric@users.noreply.github.com> Date: Thu, 7 Aug 2025 05:16:51 +0100 Subject: [PATCH] pass object into call if object is a method --- src/arobject.h | 2 + src/parser/declaration/declaration.c | 5 +- src/runtime/call/call.c | 81 +++++++++++++++++++--------- src/runtime/runtime.c | 3 +- testing.ar | 4 +- 5 files changed, 64 insertions(+), 31 deletions(-) diff --git a/src/arobject.h b/src/arobject.h index 367db70..ae4be2e 100644 --- a/src/arobject.h +++ b/src/arobject.h @@ -23,6 +23,8 @@ typedef enum ArgonType { TYPE_STRING, TYPE_FUNCTION, TYPE_NATIVE_FUNCTION, + TYPE_METHOD, + TYPE_NATIVE_METHOD, TYPE_OBJECT, } ArgonType; diff --git a/src/parser/declaration/declaration.c b/src/parser/declaration/declaration.c index a786acc..2e53121 100644 --- a/src/parser/declaration/declaration.c +++ b/src/parser/declaration/declaration.c @@ -23,7 +23,6 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { return (ParsedValueReturn){err, NULL}; } Token *token = darray_get(tokens, *index); - ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); parsedValue->type = AST_DECLARATION; DArray *declarations = checked_malloc(sizeof(DArray)); @@ -171,7 +170,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { ParsedValueReturn from = parse_token(file, tokens, index, true); if (from.err.exists) { - darray_free(¶meters, free_parameter); + if (isFunction) darray_free(¶meters, free_parameter); free_parsed(parsedValue); free(parsedValue); return from; @@ -179,7 +178,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { free(declaration->from); declaration->from = from.value; if (!declaration->from) { - darray_free(¶meters, free_parameter); + if (isFunction) darray_free(¶meters, free_parameter); free_parsed(parsedValue); free(parsedValue); return (ParsedValueReturn){create_err(token->line, token->column, diff --git a/src/runtime/call/call.c b/src/runtime/call/call.c index 1ac148b..6e66bed 100644 --- a/src/runtime/call/call.c +++ b/src/runtime/call/call.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -74,26 +75,48 @@ ArErr run_call(Translated *translated, RuntimeState *state) { uint8_t source_location_index = pop_bytecode(translated, state); ArgonObject *original_object = state->registers[from_register]; ArgonObject *object = original_object; - if (object->type != TYPE_FUNCTION && object->type != TYPE_NATIVE_FUNCTION) { + int is_method = + object->type == TYPE_METHOD || object->type == TYPE_NATIVE_METHOD; + if (object->type != TYPE_FUNCTION && object->type != TYPE_NATIVE_FUNCTION && !is_method) { ArgonObject *call_method = get_field_for_class(get_field(object, "__class__", false), "__call__"); if (call_method) { - // Prepend the original object as first argument (self) - ArgonObject **new_call_args = - malloc(sizeof(ArgonObject *) * (*state->call_args_length + 1)); - new_call_args[0] = object; - if (*state->call_args_length > 0) { - memcpy(new_call_args + 1, *state->call_args, *state->call_args_length); - } - if (*state->call_args) { - free(*state->call_args); - } - *state->call_args = new_call_args; - (*state->call_args_length)++; object = call_method; + is_method = + object->type == TYPE_METHOD && object->type == TYPE_NATIVE_METHOD; } } - if (object->type == TYPE_FUNCTION) { + if (is_method) { + ArgonObject **new_call_args = + malloc(sizeof(ArgonObject *) * (*state->call_args_length + 1)); + new_call_args[0] = original_object; + if (*state->call_args_length > 0) { + memcpy(new_call_args + 1, *state->call_args, *state->call_args_length); + } + if (*state->call_args) { + free(*state->call_args); + } + *state->call_args = new_call_args; + (*state->call_args_length)++; + } + if (object->type == TYPE_FUNCTION || object->type == TYPE_METHOD) { + SourceLocation *source_location = + darray_get(&translated->source_locations, source_location_index); + if (*state->call_args_length != + object->value.argon_fn.number_of_parameters) { + ArgonObject *type_object_name = get_field_for_class( + get_field(object, "__class__", false), "__name__"); + ArgonObject *object_name = get_field_for_class(object, "__name__"); + return create_err( + source_location->line, source_location->column, + 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, + *state->call_args_length); + } Stack *scope = create_scope(object->value.argon_fn.stack); for (size_t i = 0; i < *state->call_args_length; i++) { struct string_struct key = object->value.argon_fn.parameters[i]; @@ -107,11 +130,15 @@ ArErr run_call(Translated *translated, RuntimeState *state) { object->value.argon_fn.bytecode_length, false}; StackFrame new_stackFrame = { {translated->registerCount, NULL, bytecode_darray, - object->value.argon_fn.source_locations, translated->constants, - object->value.argon_fn.path}, - {state->registers, 0, state->path, - state->currentStackFramePointer, state->call_args, - state->call_args_length, {}}, + object->value.argon_fn.source_locations, translated->constants, + object->value.argon_fn.path}, + {state->registers, + 0, + state->path, + state->currentStackFramePointer, + state->call_args, + state->call_args_length, + {}}, scope, *state->currentStackFramePointer, (*state->currentStackFramePointer)->depth + 1}; @@ -142,15 +169,19 @@ ArErr run_call(Translated *translated, RuntimeState *state) { } }; return no_err; - } else if (object->type == TYPE_NATIVE_FUNCTION) { + } else if (object->type == TYPE_NATIVE_FUNCTION || object->type == TYPE_NATIVE_METHOD) { ArErr err = no_err; - state->registers[0] = - object->value.native_fn(*state->call_args_length, *state->call_args, - &err); + state->registers[0] = object->value.native_fn(*state->call_args_length, + *state->call_args, &err); return err; } SourceLocation *source_location = darray_get(&translated->source_locations, source_location_index); - ArgonObject *type_object_name = get_field_for_class(get_field(object, "__class__", false), "__name__"); - return create_err(source_location->line, source_location->column, 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); + ArgonObject *type_object_name = get_field_for_class( + get_field(original_object, "__class__", false), "__name__"); + return create_err(source_location->line, source_location->column, + 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); } \ No newline at end of file diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index efb0bf4..22e2569 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -201,7 +201,8 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, *stack = (*stack)->prev; break; case OP_INIT_ARGS:; - size_t size = pop_bytecode(translated, state) * sizeof(ArgonObject *); + *state->call_args_length = pop_bytecode(translated, state); + size_t size = *state->call_args_length * sizeof(ArgonObject *); if (*state->call_args) { *state->call_args = realloc(*state->call_args, size); } else { diff --git a/testing.ar b/testing.ar index 7c12052..e808716 100644 --- a/testing.ar +++ b/testing.ar @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2025 William Bell # SPDX-License-Identifier: GPL-3.0-or-later -let f(name)="" -f("bruh")() \ No newline at end of file +let x(hello, x, y) = "hello world" +x(10,10,10) \ No newline at end of file