make native function support and start working on support for error catching
This commit is contained in:
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
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 = new_call_args;
|
||||||
(*state->call_args_length)++;
|
(*state->call_args_length)++;
|
||||||
object = call_object;
|
object = call_method;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
to_call = get_field(to_call,"__base__");
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
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,18 +106,19 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
@@ -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));
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
char *field = "__base__";
|
||||||
|
while (target) {
|
||||||
uint64_t hash = siphash64_bytes(name, strlen(name), siphash_key);
|
uint64_t hash = siphash64_bytes(name, strlen(name), siphash_key);
|
||||||
return hashmap_lookup_GC(target->dict, hash);
|
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;
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
@@ -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 = ¤tStackFrame;
|
currentStackFrame->state.currentStackFramePointer = ¤tStackFrame;
|
||||||
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(¤tStackFrame->translated,
|
run_instruction(¤tStackFrame->translated,
|
||||||
¤tStackFrame->state, ¤tStackFrame->stack);
|
¤tStackFrame->state, ¤tStackFrame->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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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")()
|
||||||
Reference in New Issue
Block a user