pass object into call if object is a method

This commit is contained in:
William Bell
2025-08-07 05:16:51 +01:00
parent 4b6d15336a
commit 38e2cad507
5 changed files with 64 additions and 31 deletions

View File

@@ -23,6 +23,8 @@ typedef enum ArgonType {
TYPE_STRING, TYPE_STRING,
TYPE_FUNCTION, TYPE_FUNCTION,
TYPE_NATIVE_FUNCTION, TYPE_NATIVE_FUNCTION,
TYPE_METHOD,
TYPE_NATIVE_METHOD,
TYPE_OBJECT, TYPE_OBJECT,
} ArgonType; } ArgonType;

View File

@@ -23,7 +23,6 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) {
return (ParsedValueReturn){err, NULL}; return (ParsedValueReturn){err, NULL};
} }
Token *token = darray_get(tokens, *index); Token *token = darray_get(tokens, *index);
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
parsedValue->type = AST_DECLARATION; parsedValue->type = AST_DECLARATION;
DArray *declarations = checked_malloc(sizeof(DArray)); 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); ParsedValueReturn from = parse_token(file, tokens, index, true);
if (from.err.exists) { if (from.err.exists) {
darray_free(&parameters, free_parameter); if (isFunction) darray_free(&parameters, free_parameter);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
return from; return from;
@@ -179,7 +178,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) {
free(declaration->from); free(declaration->from);
declaration->from = from.value; declaration->from = from.value;
if (!declaration->from) { if (!declaration->from) {
darray_free(&parameters, free_parameter); if (isFunction) darray_free(&parameters, free_parameter);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
return (ParsedValueReturn){create_err(token->line, token->column, return (ParsedValueReturn){create_err(token->line, token->column,

View File

@@ -10,6 +10,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <math.h> #include <math.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -74,26 +75,48 @@ ArErr run_call(Translated *translated, RuntimeState *state) {
uint8_t source_location_index = pop_bytecode(translated, state); uint8_t source_location_index = pop_bytecode(translated, state);
ArgonObject *original_object = state->registers[from_register]; ArgonObject *original_object = state->registers[from_register];
ArgonObject *object = original_object; 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 = ArgonObject *call_method =
get_field_for_class(get_field(object, "__class__", false), "__call__"); get_field_for_class(get_field(object, "__class__", false), "__call__");
if (call_method) { 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; 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); Stack *scope = create_scope(object->value.argon_fn.stack);
for (size_t i = 0; i < *state->call_args_length; i++) { for (size_t i = 0; i < *state->call_args_length; i++) {
struct string_struct key = object->value.argon_fn.parameters[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}; object->value.argon_fn.bytecode_length, false};
StackFrame new_stackFrame = { StackFrame new_stackFrame = {
{translated->registerCount, NULL, bytecode_darray, {translated->registerCount, NULL, bytecode_darray,
object->value.argon_fn.source_locations, translated->constants, object->value.argon_fn.source_locations, translated->constants,
object->value.argon_fn.path}, object->value.argon_fn.path},
{state->registers, 0, state->path, {state->registers,
state->currentStackFramePointer, state->call_args, 0,
state->call_args_length, {}}, state->path,
state->currentStackFramePointer,
state->call_args,
state->call_args_length,
{}},
scope, scope,
*state->currentStackFramePointer, *state->currentStackFramePointer,
(*state->currentStackFramePointer)->depth + 1}; (*state->currentStackFramePointer)->depth + 1};
@@ -142,15 +169,19 @@ ArErr run_call(Translated *translated, RuntimeState *state) {
} }
}; };
return no_err; 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; ArErr err = no_err;
state->registers[0] = state->registers[0] = object->value.native_fn(*state->call_args_length,
object->value.native_fn(*state->call_args_length, *state->call_args, *state->call_args, &err);
&err);
return err; return err;
} }
SourceLocation *source_location = SourceLocation *source_location =
darray_get(&translated->source_locations, source_location_index); darray_get(&translated->source_locations, source_location_index);
ArgonObject *type_object_name = get_field_for_class(get_field(object, "__class__", false), "__name__"); ArgonObject *type_object_name = get_field_for_class(
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); 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);
} }

View File

@@ -201,7 +201,8 @@ ArErr run_instruction(Translated *translated, RuntimeState *state,
*stack = (*stack)->prev; *stack = (*stack)->prev;
break; break;
case OP_INIT_ARGS:; 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) { if (*state->call_args) {
*state->call_args = realloc(*state->call_args, size); *state->call_args = realloc(*state->call_args, size);
} else { } else {

View File

@@ -1,5 +1,5 @@
# SPDX-FileCopyrightText: 2025 William Bell # SPDX-FileCopyrightText: 2025 William Bell
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
let f(name)="" let x(hello, x, y) = "hello world"
f("bruh")() x(10,10,10)