make objects initialisation through type.__call__
This commit is contained in:
@@ -13,10 +13,12 @@
|
|||||||
#include <gmp.h>
|
#include <gmp.h>
|
||||||
|
|
||||||
typedef struct ArErr ArErr;
|
typedef struct ArErr ArErr;
|
||||||
|
typedef struct RuntimeState RuntimeState;
|
||||||
|
|
||||||
typedef struct ArgonObject ArgonObject; // forward declaration
|
typedef struct ArgonObject ArgonObject; // forward declaration
|
||||||
|
|
||||||
typedef ArgonObject* (*native_fn)(size_t argc, ArgonObject**argv, ArErr*err);
|
typedef ArgonObject *(*native_fn)(size_t argc, ArgonObject **argv, ArErr *err,
|
||||||
|
RuntimeState *state);
|
||||||
|
|
||||||
typedef enum ArgonType {
|
typedef enum ArgonType {
|
||||||
TYPE_NULL,
|
TYPE_NULL,
|
||||||
@@ -29,12 +31,11 @@ typedef enum ArgonType {
|
|||||||
TYPE_OBJECT,
|
TYPE_OBJECT,
|
||||||
} ArgonType;
|
} ArgonType;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *data;
|
void *data;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
size_t size;
|
size_t size;
|
||||||
struct hashmap_GC * hashmap;
|
struct hashmap_GC *hashmap;
|
||||||
} ConstantArena;
|
} ConstantArena;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -42,7 +43,7 @@ typedef struct {
|
|||||||
DArray *return_jumps;
|
DArray *return_jumps;
|
||||||
darray_armem bytecode;
|
darray_armem bytecode;
|
||||||
ConstantArena constants;
|
ConstantArena constants;
|
||||||
char* path;
|
char *path;
|
||||||
} Translated;
|
} Translated;
|
||||||
|
|
||||||
struct string_struct {
|
struct string_struct {
|
||||||
@@ -57,7 +58,7 @@ typedef struct Stack {
|
|||||||
|
|
||||||
struct argon_function_struct {
|
struct argon_function_struct {
|
||||||
Translated translated;
|
Translated translated;
|
||||||
uint8_t* bytecode;
|
uint8_t *bytecode;
|
||||||
size_t bytecode_length;
|
size_t bytecode_length;
|
||||||
Stack *stack;
|
Stack *stack;
|
||||||
size_t number_of_parameters;
|
size_t number_of_parameters;
|
||||||
@@ -66,11 +67,10 @@ struct argon_function_struct {
|
|||||||
uint64_t column;
|
uint64_t column;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// full definition of ArgonObject (no typedef again!)
|
// full definition of ArgonObject (no typedef again!)
|
||||||
struct ArgonObject {
|
struct ArgonObject {
|
||||||
ArgonType type;
|
ArgonType type;
|
||||||
|
ArgonType child_type;
|
||||||
struct hashmap_GC *dict;
|
struct hashmap_GC *dict;
|
||||||
union {
|
union {
|
||||||
mpq_t as_number;
|
mpq_t as_number;
|
||||||
|
|||||||
@@ -70,41 +70,50 @@ double get_memory_usage_mb() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ArErr run_call(Translated *translated, RuntimeState *state) {
|
ArgonObject *argon_call(ArgonObject *original_object, size_t argc,
|
||||||
ArgonObject *original_object = state->call_instance->to_call;
|
ArgonObject **argv, ArErr *err, RuntimeState *state) {
|
||||||
|
*err = run_call(original_object, argc, argv, state);
|
||||||
|
return state->registers[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
ArErr run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv,
|
||||||
|
RuntimeState *state) {
|
||||||
ArgonObject *object = original_object;
|
ArgonObject *object = original_object;
|
||||||
if (object->type != TYPE_FUNCTION && object->type != TYPE_NATIVE_FUNCTION &&
|
if (object->type != TYPE_FUNCTION && object->type != TYPE_NATIVE_FUNCTION &&
|
||||||
object->type != TYPE_METHOD) {
|
object->type != TYPE_METHOD) {
|
||||||
ArgonObject *call_method = get_field_for_class(
|
ArgonObject *call_method =
|
||||||
get_field(object, "__class__", false), "__call__", original_object);
|
get_field_for_class(get_field(object, "__class__", false, false),
|
||||||
|
"__call__", original_object);
|
||||||
if (call_method) {
|
if (call_method) {
|
||||||
object = call_method;
|
object = call_method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool to_free_args = false;
|
||||||
if (object->type == TYPE_METHOD) {
|
if (object->type == TYPE_METHOD) {
|
||||||
ArgonObject *binding_object = get_field(object, "__binding__", false);
|
ArgonObject *binding_object =
|
||||||
|
get_field(object, "__binding__", false, false);
|
||||||
if (binding_object) {
|
if (binding_object) {
|
||||||
ArgonObject **new_call_args = malloc(
|
ArgonObject **new_call_args = malloc(sizeof(ArgonObject *) * (argc + 1));
|
||||||
sizeof(ArgonObject *) * (state->call_instance->args_length + 1));
|
|
||||||
new_call_args[0] = binding_object;
|
new_call_args[0] = binding_object;
|
||||||
if (state->call_instance->args_length > 0) {
|
if (argc > 0) {
|
||||||
memcpy(new_call_args + 1, state->call_instance->args,
|
memcpy(new_call_args + 1, argv, argc * sizeof(ArgonObject *));
|
||||||
state->call_instance->args_length);
|
|
||||||
}
|
}
|
||||||
free(state->call_instance->args);
|
argv = new_call_args;
|
||||||
state->call_instance->args = new_call_args;
|
argc++;
|
||||||
state->call_instance->args_length++;
|
to_free_args = true;
|
||||||
}
|
}
|
||||||
ArgonObject *function_object = get_field(object, "__function__", false);
|
ArgonObject *function_object =
|
||||||
|
get_field(object, "__function__", false, false);
|
||||||
if (function_object)
|
if (function_object)
|
||||||
object = function_object;
|
object = function_object;
|
||||||
}
|
}
|
||||||
if (object->type == TYPE_FUNCTION) {
|
if (object->type == TYPE_FUNCTION) {
|
||||||
if (state->call_instance->args_length !=
|
if (argc != object->value.argon_fn.number_of_parameters) {
|
||||||
object->value.argon_fn.number_of_parameters) {
|
ArgonObject *type_object_name =
|
||||||
ArgonObject *type_object_name = get_field_for_class(
|
get_field_for_class(get_field(object, "__class__", false, false),
|
||||||
get_field(object, "__class__", false), "__name__", original_object);
|
"__name__", original_object);
|
||||||
ArgonObject *object_name = get_field_for_class(object, "__name__", original_object);
|
ArgonObject *object_name =
|
||||||
|
get_field_for_class(object, "__name__", original_object);
|
||||||
return create_err(
|
return create_err(
|
||||||
state->source_location.line, state->source_location.column,
|
state->source_location.line, state->source_location.column,
|
||||||
state->source_location.length, state->path, "Type Error",
|
state->source_location.length, state->path, "Type Error",
|
||||||
@@ -112,19 +121,20 @@ ArErr run_call(Translated *translated, RuntimeState *state) {
|
|||||||
(int)type_object_name->value.as_str.length,
|
(int)type_object_name->value.as_str.length,
|
||||||
type_object_name->value.as_str.data,
|
type_object_name->value.as_str.data,
|
||||||
(int)object_name->value.as_str.length, 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,
|
object->value.argon_fn.number_of_parameters, argc);
|
||||||
state->call_instance->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_instance->args_length; i++) {
|
for (size_t i = 0; i < argc; i++) {
|
||||||
struct string_struct key = object->value.argon_fn.parameters[i];
|
struct string_struct key = object->value.argon_fn.parameters[i];
|
||||||
ArgonObject *value = (state->call_instance->args)[i];
|
ArgonObject *value = argv[i];
|
||||||
uint64_t hash = siphash64_bytes(key.data, key.length, siphash_key);
|
uint64_t hash = siphash64_bytes(key.data, key.length, siphash_key);
|
||||||
hashmap_insert_GC(scope->scope, hash,
|
hashmap_insert_GC(scope->scope, hash,
|
||||||
new_string_object(key.data, key.length), value, 0);
|
new_string_object(key.data, key.length), value, 0);
|
||||||
}
|
}
|
||||||
|
if (to_free_args)
|
||||||
|
free(argv);
|
||||||
StackFrame new_stackFrame = {
|
StackFrame new_stackFrame = {
|
||||||
{translated->registerCount,
|
{object->value.argon_fn.translated.registerCount,
|
||||||
NULL,
|
NULL,
|
||||||
{object->value.argon_fn.bytecode, sizeof(uint8_t),
|
{object->value.argon_fn.bytecode, sizeof(uint8_t),
|
||||||
object->value.argon_fn.bytecode_length,
|
object->value.argon_fn.bytecode_length,
|
||||||
@@ -169,8 +179,9 @@ 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) {
|
||||||
ArErr err = no_err;
|
ArErr err = no_err;
|
||||||
state->registers[0] = object->value.native_fn(
|
state->registers[0] = object->value.native_fn(argc, argv, &err, state);
|
||||||
state->call_instance->args_length, state->call_instance->args, &err);
|
if (to_free_args)
|
||||||
|
free(argv);
|
||||||
if (err.exists) {
|
if (err.exists) {
|
||||||
err.line = state->source_location.line;
|
err.line = state->source_location.line;
|
||||||
err.column = state->source_location.column;
|
err.column = state->source_location.column;
|
||||||
@@ -179,8 +190,11 @@ ArErr run_call(Translated *translated, RuntimeState *state) {
|
|||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
ArgonObject *type_object_name = get_field_for_class(
|
if (to_free_args)
|
||||||
get_field(original_object, "__class__", false), "__name__", original_object);
|
free(argv);
|
||||||
|
ArgonObject *type_object_name =
|
||||||
|
get_field_for_class(get_field(original_object, "__class__", false, false),
|
||||||
|
"__name__", original_object);
|
||||||
return create_err(state->source_location.line, state->source_location.column,
|
return create_err(state->source_location.line, state->source_location.column,
|
||||||
state->source_location.length, state->path, "Type Error",
|
state->source_location.length, state->path, "Type Error",
|
||||||
"'%.*s' object is not callable",
|
"'%.*s' object is not callable",
|
||||||
|
|||||||
@@ -8,6 +8,10 @@
|
|||||||
#define runtime_call_H
|
#define runtime_call_H
|
||||||
#include "../runtime.h"
|
#include "../runtime.h"
|
||||||
|
|
||||||
ArErr run_call(Translated *translated, RuntimeState *state);
|
ArgonObject *argon_call(ArgonObject *original_object, size_t argc,
|
||||||
|
ArgonObject **argv, ArErr *err, RuntimeState *state);
|
||||||
|
|
||||||
|
ArErr run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv,
|
||||||
|
RuntimeState *state);
|
||||||
|
|
||||||
#endif // runtime_call_H
|
#endif // runtime_call_H
|
||||||
@@ -34,21 +34,22 @@ ArgonObject *bind_object_to_function(ArgonObject *object,
|
|||||||
add_field(bound_method_wrapper, "__class__", ARGON_METHOD_TYPE);
|
add_field(bound_method_wrapper, "__class__", ARGON_METHOD_TYPE);
|
||||||
add_field(bound_method_wrapper, "__binding__", object);
|
add_field(bound_method_wrapper, "__binding__", object);
|
||||||
add_field(bound_method_wrapper, "__function__", function);
|
add_field(bound_method_wrapper, "__function__", function);
|
||||||
ArgonObject *function_name = get_field(function, "__name__", false);
|
ArgonObject *function_name = get_field(function, "__name__", false, false);
|
||||||
if (function_name)
|
if (function_name)
|
||||||
add_field(bound_method_wrapper, "__name__", function_name);
|
add_field(bound_method_wrapper, "__name__", function_name);
|
||||||
return bound_method_wrapper;
|
return bound_method_wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgonObject *get_field_for_class(ArgonObject *target, char *name, ArgonObject *binding_object) {
|
ArgonObject *get_field_for_class(ArgonObject *target, char *name,
|
||||||
|
ArgonObject *binding_object) {
|
||||||
char *field = "__base__";
|
char *field = "__base__";
|
||||||
while (target) {
|
while (target) {
|
||||||
uint64_t hash = siphash64_bytes(name, strlen(name), siphash_key);
|
uint64_t hash = siphash64_bytes(name, strlen(name), siphash_key);
|
||||||
ArgonObject *object = hashmap_lookup_GC(target->dict, hash);
|
ArgonObject *object = hashmap_lookup_GC(target->dict, hash);
|
||||||
|
|
||||||
if (object) {
|
if (object) {
|
||||||
if (object->type == TYPE_FUNCTION ||
|
if ((object->type == TYPE_FUNCTION ||
|
||||||
object->type == TYPE_NATIVE_FUNCTION) {
|
object->type == TYPE_NATIVE_FUNCTION) && binding_object) {
|
||||||
object = bind_object_to_function(binding_object, object);
|
object = bind_object_to_function(binding_object, object);
|
||||||
}
|
}
|
||||||
return object;
|
return object;
|
||||||
@@ -59,10 +60,18 @@ ArgonObject *get_field_for_class(ArgonObject *target, char *name, ArgonObject *b
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgonObject *get_field(ArgonObject *target, char *name, bool recursive) {
|
ArgonObject *get_field(ArgonObject *target, char *name, bool recursive,
|
||||||
|
bool disable_method_wrapper) {
|
||||||
char *field = "__class__";
|
char *field = "__class__";
|
||||||
ArgonObject *object = hashmap_lookup_GC(target->dict, siphash64_bytes(name, strlen(name), siphash_key));
|
ArgonObject *object = hashmap_lookup_GC(
|
||||||
|
target->dict, siphash64_bytes(name, strlen(name), siphash_key));
|
||||||
if (!recursive || object)
|
if (!recursive || object)
|
||||||
return object;
|
return object;
|
||||||
return get_field_for_class(hashmap_lookup_GC(target->dict, siphash64_bytes(field, strlen(field), siphash_key)), name, target);
|
ArgonObject *binding = target;
|
||||||
|
if (disable_method_wrapper)
|
||||||
|
binding = NULL;
|
||||||
|
return get_field_for_class(
|
||||||
|
hashmap_lookup_GC(target->dict,
|
||||||
|
siphash64_bytes(field, strlen(field), siphash_key)),
|
||||||
|
name, binding);
|
||||||
}
|
}
|
||||||
@@ -17,8 +17,10 @@ ArgonObject *new_object();
|
|||||||
|
|
||||||
void add_field(ArgonObject *target, char *name, ArgonObject *object);
|
void add_field(ArgonObject *target, char *name, ArgonObject *object);
|
||||||
|
|
||||||
ArgonObject *get_field_for_class(ArgonObject *target, char *name, ArgonObject *binding_object);
|
ArgonObject *get_field_for_class(ArgonObject *target, char *name,
|
||||||
|
ArgonObject *binding_object);
|
||||||
|
|
||||||
ArgonObject *get_field(ArgonObject *target, char *name, bool recursive);
|
ArgonObject *get_field(ArgonObject *target, char *name, bool recursive,
|
||||||
|
bool disable_method_wrapper);
|
||||||
|
|
||||||
#endif // OBJECT_H
|
#endif // OBJECT_H
|
||||||
@@ -29,16 +29,52 @@ ArgonObject *ARGON_METHOD_TYPE;
|
|||||||
Stack *Global_Scope = NULL;
|
Stack *Global_Scope = NULL;
|
||||||
|
|
||||||
ArgonObject *ARGON_TYPE_TYPE___call__(size_t argc, ArgonObject **argv,
|
ArgonObject *ARGON_TYPE_TYPE___call__(size_t argc, ArgonObject **argv,
|
||||||
ArErr *err) {
|
ArErr *err, RuntimeState *state) {
|
||||||
if (argc<1) {
|
if (argc < 1) {
|
||||||
*err = create_err(0, 0, 0, "", "Runtime Error", "call missing self object.");
|
*err = create_err(0, 0, 0, "", "Runtime Error",
|
||||||
|
"__call__ expects at least 1 argument, got 0");
|
||||||
return ARGON_NULL;
|
return ARGON_NULL;
|
||||||
}
|
}
|
||||||
ArgonObject *self = argv[0];
|
ArgonObject *cls = argv[0];
|
||||||
ArgonObject *self_name = get_field(argv[0], "__name__", true);
|
if (cls == ARGON_TYPE_TYPE && argc == 2) {
|
||||||
|
ArgonObject *cls_class = get_field(argv[1], "__class__", true, false);
|
||||||
printf("type: %.*s\n", (int)self_name->value.as_str.length, self_name->value.as_str.data);
|
if (cls_class)
|
||||||
|
return cls_class;
|
||||||
return ARGON_NULL;
|
return ARGON_NULL;
|
||||||
|
}
|
||||||
|
ArgonObject *cls___new__ = get_field_for_class(argv[0], "__new__", NULL);
|
||||||
|
if (!cls___new__) {
|
||||||
|
ArgonObject *cls___name__ = get_field(argv[0], "__name__", true, false);
|
||||||
|
*err = create_err(
|
||||||
|
0, 0, 0, "", "Runtime Error",
|
||||||
|
"Object '%.*s' is missing __new__ method, so cannot be initialised",
|
||||||
|
(int)cls___name__->value.as_str.length,
|
||||||
|
cls___name__->value.as_str.data);
|
||||||
|
return ARGON_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArgonObject *new_object = argon_call(cls___new__, argc, argv, err, state);
|
||||||
|
if (err->exists)
|
||||||
|
return ARGON_NULL;
|
||||||
|
ArgonObject *args[] = {ARGON_TYPE_TYPE, new_object};
|
||||||
|
ArgonObject *new_object_class = ARGON_TYPE_TYPE___call__(2, args, err, state);
|
||||||
|
if (new_object_class != ARGON_NULL && new_object_class == cls) {
|
||||||
|
ArgonObject *cls___init__ =
|
||||||
|
get_field_for_class(argv[0], "__init__", new_object);
|
||||||
|
if (!cls___init__) {
|
||||||
|
ArgonObject *cls___name__ = get_field(argv[0], "__name__", true, false);
|
||||||
|
*err = create_err(
|
||||||
|
0, 0, 0, "", "Runtime Error",
|
||||||
|
"Object '%.*s' is missing __init__ method, so cannot be initialised",
|
||||||
|
(int)cls___name__->value.as_str.length,
|
||||||
|
cls___name__->value.as_str.data);
|
||||||
|
}
|
||||||
|
argon_call(cls___init__, argc - 1, argv + 1, err, state);
|
||||||
|
if (err->exists)
|
||||||
|
return ARGON_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bootstrap_types() {
|
void bootstrap_types() {
|
||||||
@@ -47,8 +83,7 @@ void bootstrap_types() {
|
|||||||
add_field(ARGON_TYPE_TYPE, "__base__", BASE_CLASS);
|
add_field(ARGON_TYPE_TYPE, "__base__", BASE_CLASS);
|
||||||
add_field(ARGON_TYPE_TYPE, "__class__", ARGON_TYPE_TYPE);
|
add_field(ARGON_TYPE_TYPE, "__class__", ARGON_TYPE_TYPE);
|
||||||
add_field(ARGON_TYPE_TYPE, "__call__",
|
add_field(ARGON_TYPE_TYPE, "__call__",
|
||||||
create_argon_native_function(
|
create_argon_native_function("__call__", ARGON_TYPE_TYPE___call__));
|
||||||
"__call__", ARGON_TYPE_TYPE___call__));
|
|
||||||
|
|
||||||
ARGON_NULL_TYPE = new_object();
|
ARGON_NULL_TYPE = new_object();
|
||||||
add_field(ARGON_NULL_TYPE, "__base__", BASE_CLASS);
|
add_field(ARGON_NULL_TYPE, "__base__", BASE_CLASS);
|
||||||
@@ -91,8 +126,7 @@ void bootstrap_types() {
|
|||||||
|
|
||||||
void add_to_scope(Stack *stack, char *name, ArgonObject *value) {
|
void add_to_scope(Stack *stack, char *name, ArgonObject *value) {
|
||||||
size_t length = strlen(name);
|
size_t length = strlen(name);
|
||||||
uint64_t hash =
|
uint64_t hash = siphash64_bytes(name, length, siphash_key);
|
||||||
siphash64_bytes(name, length, siphash_key);
|
|
||||||
ArgonObject *key = new_string_object(name, length);
|
ArgonObject *key = new_string_object(name, length);
|
||||||
hashmap_insert_GC(stack->scope, hash, key, value, 0);
|
hashmap_insert_GC(stack->scope, hash, key, value, 0);
|
||||||
}
|
}
|
||||||
@@ -249,7 +283,9 @@ ArErr run_instruction(Translated *translated, RuntimeState *state,
|
|||||||
(state->call_instance->args)[index] = state->registers[0];
|
(state->call_instance->args)[index] = state->registers[0];
|
||||||
break;
|
break;
|
||||||
case OP_CALL:;
|
case OP_CALL:;
|
||||||
ArErr err = run_call(translated, state);
|
ArErr err = run_call(state->call_instance->to_call,
|
||||||
|
state->call_instance->args_length,
|
||||||
|
state->call_instance->args, state);
|
||||||
free(state->call_instance->args);
|
free(state->call_instance->args);
|
||||||
call_instance = *state->call_instance;
|
call_instance = *state->call_instance;
|
||||||
free(state->call_instance);
|
free(state->call_instance);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# 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
|
||||||
type()
|
type.__call__()
|
||||||
Reference in New Issue
Block a user