make native function support and start working on support for error catching

This commit is contained in:
William Bell
2025-08-06 22:31:31 +01:00
parent c567b59459
commit 4b6d15336a
9 changed files with 91 additions and 44 deletions

View File

@@ -7,10 +7,13 @@
#ifndef AROBJECT_H #ifndef AROBJECT_H
#define AROBJECT_H #define AROBJECT_H
#include "dynamic_array/darray.h"
#include "runtime/internals/dynamic_array_armem/darray_armem.h" #include "runtime/internals/dynamic_array_armem/darray_armem.h"
#include "runtime/internals/hashmap/hashmap.h" #include "runtime/internals/hashmap/hashmap.h"
#include <gmp.h> #include <gmp.h>
typedef struct ArErr ArErr;
typedef struct ArgonObject ArgonObject; // forward declaration typedef struct ArgonObject ArgonObject; // forward declaration
typedef enum ArgonType { typedef enum ArgonType {
@@ -40,6 +43,7 @@ struct argon_function_struct {
size_t number_of_parameters; size_t number_of_parameters;
struct string_struct *parameters; struct string_struct *parameters;
char* path; char* path;
DArray source_locations;
uint64_t line; uint64_t line;
uint64_t column; uint64_t column;
}; };
@@ -54,7 +58,7 @@ struct ArgonObject {
mpq_t as_number; mpq_t as_number;
bool as_bool; bool as_bool;
struct string_struct as_str; struct string_struct as_str;
void *native_fn; ArgonObject* (*native_fn)(size_t argc, ArgonObject**argv, ArErr*err);
struct argon_function_struct argon_fn; struct argon_function_struct argon_fn;
} value; } value;
}; };

View File

@@ -11,9 +11,8 @@
#include <math.h> #include <math.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#if defined(_WIN32) #if defined(_WIN32)
#include <psapi.h> #include <psapi.h>
@@ -70,26 +69,29 @@ double get_memory_usage_mb() {
} }
#endif #endif
void run_call(Translated *translated, RuntimeState *state) { ArErr run_call(Translated *translated, RuntimeState *state) {
uint8_t from_register = pop_byte(translated, state); uint8_t from_register = pop_byte(translated, state);
uint8_t source_location_index = pop_bytecode(translated, state); uint8_t source_location_index = pop_bytecode(translated, state);
ArgonObject *object = state->registers[from_register]; ArgonObject *original_object = state->registers[from_register];
if (object->type != TYPE_FUNCTION) { ArgonObject *object = original_object;
ArgonObject *to_call = get_field(object,"__class__"); if (object->type != TYPE_FUNCTION && object->type != TYPE_NATIVE_FUNCTION) {
while (to_call) { ArgonObject *call_method =
ArgonObject *call_object = get_field(to_call,"__call__"); get_field_for_class(get_field(object, "__class__", false), "__call__");
if (call_object) { if (call_method) {
ArgonObject** new_call_args = malloc(sizeof(ArgonObject*)*(*state->call_args_length+1)); // Prepend the original object as first argument (self)
memcpy(new_call_args+1, *state->call_args, *state->call_args_length); ArgonObject **new_call_args =
free(*state->call_args); malloc(sizeof(ArgonObject *) * (*state->call_args_length + 1));
new_call_args[0] = object; new_call_args[0] = object;
*state->call_args = new_call_args; if (*state->call_args_length > 0) {
(*state->call_args_length)++; memcpy(new_call_args + 1, *state->call_args, *state->call_args_length);
object = call_object;
break;
} }
to_call = get_field(to_call,"__base__"); if (*state->call_args) {
}; free(*state->call_args);
}
*state->call_args = new_call_args;
(*state->call_args_length)++;
object = call_method;
}
} }
if (object->type == TYPE_FUNCTION) { if (object->type == TYPE_FUNCTION) {
Stack *scope = create_scope(object->value.argon_fn.stack); Stack *scope = create_scope(object->value.argon_fn.stack);
@@ -104,22 +106,23 @@ void run_call(Translated *translated, RuntimeState *state) {
object->value.argon_fn.bytecode_length, object->value.argon_fn.bytecode_length,
object->value.argon_fn.bytecode_length, false}; object->value.argon_fn.bytecode_length, false};
StackFrame new_stackFrame = { StackFrame new_stackFrame = {
(Translated){translated->registerCount, NULL, bytecode_darray, {translated->registerCount, NULL, bytecode_darray,
translated->source_locations, translated->constants, object->value.argon_fn.source_locations, translated->constants,
object->value.argon_fn.path}, object->value.argon_fn.path},
(RuntimeState){state->registers, 0, state->path, {state->registers, 0, state->path,
state->currentStackFramePointer, state->call_args, state->currentStackFramePointer, state->call_args,
state->call_args_length}, state->call_args_length, {}},
scope, scope,
*state->currentStackFramePointer, *state->currentStackFramePointer,
no_err,
(*state->currentStackFramePointer)->depth + 1}; (*state->currentStackFramePointer)->depth + 1};
if (((*state->currentStackFramePointer)->depth+1) % STACKFRAME_CHUNKS == 0) { if (((*state->currentStackFramePointer)->depth + 1) % STACKFRAME_CHUNKS ==
*state->currentStackFramePointer = checked_malloc(sizeof(StackFrame) * STACKFRAME_CHUNKS); 0) {
*state->currentStackFramePointer =
checked_malloc(sizeof(StackFrame) * STACKFRAME_CHUNKS);
} else { } else {
*state->currentStackFramePointer = *state->currentStackFramePointer + 1; *state->currentStackFramePointer = *state->currentStackFramePointer + 1;
} }
**state->currentStackFramePointer = new_stackFrame; **state->currentStackFramePointer = new_stackFrame;
if ((*state->currentStackFramePointer)->depth >= 10000) { if ((*state->currentStackFramePointer)->depth >= 10000) {
double logval = log10((double)(*state->currentStackFramePointer)->depth); double logval = log10((double)(*state->currentStackFramePointer)->depth);
if (floor(logval) == logval) { if (floor(logval) == logval) {
@@ -133,11 +136,21 @@ void run_call(Translated *translated, RuntimeState *state) {
(*state->currentStackFramePointer)->depth); (*state->currentStackFramePointer)->depth);
if (memoryUsage) { if (memoryUsage) {
fprintf(stderr, ", memory usage at %f MB\n", memoryUsage); fprintf(stderr, ", memory usage at %f MB\n", memoryUsage);
} else { } else {
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
} }
}; };
return no_err;
} else if (object->type == TYPE_NATIVE_FUNCTION) {
ArErr err = no_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);
} }

View File

@@ -8,6 +8,6 @@
#define runtime_call_H #define runtime_call_H
#include "../runtime.h" #include "../runtime.h"
void run_call(Translated *translated, RuntimeState *state); ArErr run_call(Translated *translated, RuntimeState *state);
#endif // runtime_call_H #endif // runtime_call_H

View File

@@ -23,6 +23,7 @@ void load_argon_function(Translated *translated, RuntimeState *state,
uint64_t length = pop_bytecode(translated, state); uint64_t length = pop_bytecode(translated, state);
add_field(object, "__name__", new_string_object(arena_get(&translated->constants, offset), length)); add_field(object, "__name__", new_string_object(arena_get(&translated->constants, offset), length));
object->value.argon_fn.path = translated->path; object->value.argon_fn.path = translated->path;
object->value.argon_fn.source_locations = translated->source_locations;
object->value.argon_fn.number_of_parameters = pop_bytecode(translated, state); object->value.argon_fn.number_of_parameters = pop_bytecode(translated, state);
object->value.argon_fn.parameters = object->value.argon_fn.parameters =
ar_alloc(object->value.argon_fn.number_of_parameters * sizeof(struct string_struct)); ar_alloc(object->value.argon_fn.number_of_parameters * sizeof(struct string_struct));

View File

@@ -26,7 +26,29 @@ void add_field(ArgonObject *target, char *name, ArgonObject *object) {
object, 0); object, 0);
} }
ArgonObject *get_field(ArgonObject *target, char *name) { ArgonObject *get_field_for_class(ArgonObject *target, char *name) {
uint64_t hash = siphash64_bytes(name, strlen(name), siphash_key); char *field = "__base__";
return hashmap_lookup_GC(target->dict, hash); while (target) {
uint64_t hash = siphash64_bytes(name, strlen(name), siphash_key);
ArgonObject *object = hashmap_lookup_GC(target->dict, hash);
if (object)
return object;
hash = siphash64_bytes(field, strlen(field), siphash_key);
target = hashmap_lookup_GC(target->dict, hash);
}
return NULL;
}
ArgonObject *get_field(ArgonObject *target, char *name, bool recursive) {
char *field = "__class__";
while (target) {
uint64_t hash = siphash64_bytes(name, strlen(name), siphash_key);
ArgonObject *object = hashmap_lookup_GC(target->dict, hash);
if (!recursive || object)
return object;
hash = siphash64_bytes(field, strlen(field), siphash_key);
target = hashmap_lookup_GC(target->dict, hash);
field = "__base__";
}
return NULL;
} }

View File

@@ -17,6 +17,8 @@ ArgonObject *new_object();
void add_field(ArgonObject *target, char *name, ArgonObject *object); void add_field(ArgonObject *target, char *name, ArgonObject *object);
ArgonObject *get_field(ArgonObject *target, char *name); ArgonObject *get_field_for_class(ArgonObject *target, char *name);
ArgonObject *get_field(ArgonObject *target, char *name, bool recursive);
#endif // OBJECT_H #endif // OBJECT_H

View File

@@ -214,7 +214,7 @@ ArErr run_instruction(Translated *translated, RuntimeState *state,
state->registers[to_register]; state->registers[to_register];
break; break;
case OP_CALL: case OP_CALL:
run_call(translated, state); return run_call(translated, state);
// ArgonObject *object = state->registers[from_register]; // ArgonObject *object = state->registers[from_register];
// char *field = "__class__"; // char *field = "__class__";
// uint64_t hash = siphash64_bytes(field, strlen(field), siphash_key); // uint64_t hash = siphash64_bytes(field, strlen(field), siphash_key);
@@ -234,7 +234,6 @@ ArErr run_instruction(Translated *translated, RuntimeState *state,
// (int)class_name->value.as_str.length, class_name->value.as_str.data, // (int)class_name->value.as_str.length, class_name->value.as_str.data,
// object); // object);
// } // }
break;
default: default:
return create_err(0, 0, 0, NULL, "Runtime Error", "Invalid Opcode %#x", return create_err(0, 0, 0, NULL, "Runtime Error", "Invalid Opcode %#x",
opcode); opcode);
@@ -249,7 +248,8 @@ RuntimeState init_runtime_state(Translated translated, char *path) {
path, path,
NULL, NULL,
NULL, NULL,
NULL}; 0,
{}};
return runtime; return runtime;
} }
@@ -275,19 +275,18 @@ ArErr runtime(Translated translated, RuntimeState state, Stack *stack) {
StackFrame *currentStackFrame = StackFrame *currentStackFrame =
checked_malloc(sizeof(StackFrame) * STACKFRAME_CHUNKS); checked_malloc(sizeof(StackFrame) * STACKFRAME_CHUNKS);
*currentStackFrame = (StackFrame){translated, state, stack, NULL, no_err, 0}; *currentStackFrame = (StackFrame){translated, state, stack, NULL, 0};
currentStackFrame->state.currentStackFramePointer = &currentStackFrame; currentStackFrame->state.currentStackFramePointer = &currentStackFrame;
ArErr err = no_err; ArErr err = no_err;
while (currentStackFrame) { while (currentStackFrame) {
while (currentStackFrame->state.head < while (currentStackFrame->state.head <
currentStackFrame->translated.bytecode.size && currentStackFrame->translated.bytecode.size &&
!currentStackFrame->err.exists) { !err.exists) {
currentStackFrame->err = err =
run_instruction(&currentStackFrame->translated, run_instruction(&currentStackFrame->translated,
&currentStackFrame->state, &currentStackFrame->stack); &currentStackFrame->state, &currentStackFrame->stack);
} }
StackFrame *tempStackFrame = currentStackFrame; StackFrame *tempStackFrame = currentStackFrame;
err = currentStackFrame->err;
currentStackFrame = currentStackFrame->previousStackFrame; currentStackFrame = currentStackFrame->previousStackFrame;
if (tempStackFrame->depth % STACKFRAME_CHUNKS == 0) { if (tempStackFrame->depth % STACKFRAME_CHUNKS == 0) {
free(tempStackFrame); free(tempStackFrame);

View File

@@ -14,6 +14,12 @@
typedef struct StackFrame StackFrame; typedef struct StackFrame StackFrame;
typedef struct RuntimeState RuntimeState; typedef struct RuntimeState RuntimeState;
typedef struct ErrorCatch {
size_t jump_to;
Stack *stack;
StackFrame *stackFrame;
} ErrorCatch;
typedef struct RuntimeState { typedef struct RuntimeState {
ArgonObject **registers; ArgonObject **registers;
size_t head; size_t head;
@@ -21,6 +27,7 @@ typedef struct RuntimeState {
StackFrame **currentStackFramePointer; StackFrame **currentStackFramePointer;
ArgonObject*** call_args; ArgonObject*** call_args;
size_t* call_args_length; size_t* call_args_length;
DArray catch_errors; // ErrorCatch[]
} RuntimeState; } RuntimeState;
typedef struct StackFrame { typedef struct StackFrame {
@@ -28,7 +35,6 @@ typedef struct StackFrame {
RuntimeState state; RuntimeState state;
Stack *stack; Stack *stack;
StackFrame *previousStackFrame; StackFrame *previousStackFrame;
ArErr err;
uint64_t depth; uint64_t depth;
} StackFrame; } StackFrame;

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()=f() let f(name)=""
f() f("bruh")()