make native function support and start working on support for error catching
This commit is contained in:
@@ -7,10 +7,13 @@
|
||||
#ifndef AROBJECT_H
|
||||
#define AROBJECT_H
|
||||
|
||||
#include "dynamic_array/darray.h"
|
||||
#include "runtime/internals/dynamic_array_armem/darray_armem.h"
|
||||
#include "runtime/internals/hashmap/hashmap.h"
|
||||
#include <gmp.h>
|
||||
|
||||
typedef struct ArErr ArErr;
|
||||
|
||||
typedef struct ArgonObject ArgonObject; // forward declaration
|
||||
|
||||
typedef enum ArgonType {
|
||||
@@ -40,6 +43,7 @@ struct argon_function_struct {
|
||||
size_t number_of_parameters;
|
||||
struct string_struct *parameters;
|
||||
char* path;
|
||||
DArray source_locations;
|
||||
uint64_t line;
|
||||
uint64_t column;
|
||||
};
|
||||
@@ -54,7 +58,7 @@ struct ArgonObject {
|
||||
mpq_t as_number;
|
||||
bool as_bool;
|
||||
struct string_struct as_str;
|
||||
void *native_fn;
|
||||
ArgonObject* (*native_fn)(size_t argc, ArgonObject**argv, ArErr*err);
|
||||
struct argon_function_struct argon_fn;
|
||||
} value;
|
||||
};
|
||||
|
||||
@@ -11,9 +11,8 @@
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <psapi.h>
|
||||
@@ -70,26 +69,29 @@ double get_memory_usage_mb() {
|
||||
}
|
||||
#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 source_location_index = pop_bytecode(translated, state);
|
||||
ArgonObject *object = state->registers[from_register];
|
||||
if (object->type != TYPE_FUNCTION) {
|
||||
ArgonObject *to_call = get_field(object,"__class__");
|
||||
while (to_call) {
|
||||
ArgonObject *call_object = get_field(to_call,"__call__");
|
||||
if (call_object) {
|
||||
ArgonObject** new_call_args = malloc(sizeof(ArgonObject*)*(*state->call_args_length+1));
|
||||
memcpy(new_call_args+1, *state->call_args, *state->call_args_length);
|
||||
free(*state->call_args);
|
||||
new_call_args[0] = object;
|
||||
*state->call_args = new_call_args;
|
||||
(*state->call_args_length)++;
|
||||
object = call_object;
|
||||
break;
|
||||
ArgonObject *original_object = state->registers[from_register];
|
||||
ArgonObject *object = original_object;
|
||||
if (object->type != TYPE_FUNCTION && object->type != TYPE_NATIVE_FUNCTION) {
|
||||
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);
|
||||
}
|
||||
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) {
|
||||
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, false};
|
||||
StackFrame new_stackFrame = {
|
||||
(Translated){translated->registerCount, NULL, bytecode_darray,
|
||||
translated->source_locations, translated->constants,
|
||||
{translated->registerCount, NULL, bytecode_darray,
|
||||
object->value.argon_fn.source_locations, translated->constants,
|
||||
object->value.argon_fn.path},
|
||||
(RuntimeState){state->registers, 0, state->path,
|
||||
{state->registers, 0, state->path,
|
||||
state->currentStackFramePointer, state->call_args,
|
||||
state->call_args_length},
|
||||
state->call_args_length, {}},
|
||||
scope,
|
||||
*state->currentStackFramePointer,
|
||||
no_err,
|
||||
(*state->currentStackFramePointer)->depth + 1};
|
||||
if (((*state->currentStackFramePointer)->depth+1) % STACKFRAME_CHUNKS == 0) {
|
||||
*state->currentStackFramePointer = checked_malloc(sizeof(StackFrame) * STACKFRAME_CHUNKS);
|
||||
if (((*state->currentStackFramePointer)->depth + 1) % STACKFRAME_CHUNKS ==
|
||||
0) {
|
||||
*state->currentStackFramePointer =
|
||||
checked_malloc(sizeof(StackFrame) * STACKFRAME_CHUNKS);
|
||||
} else {
|
||||
*state->currentStackFramePointer = *state->currentStackFramePointer + 1;
|
||||
}
|
||||
**state->currentStackFramePointer = new_stackFrame;
|
||||
**state->currentStackFramePointer = new_stackFrame;
|
||||
if ((*state->currentStackFramePointer)->depth >= 10000) {
|
||||
double logval = log10((double)(*state->currentStackFramePointer)->depth);
|
||||
if (floor(logval) == logval) {
|
||||
@@ -133,11 +136,21 @@ void run_call(Translated *translated, RuntimeState *state) {
|
||||
(*state->currentStackFramePointer)->depth);
|
||||
if (memoryUsage) {
|
||||
fprintf(stderr, ", memory usage at %f MB\n", memoryUsage);
|
||||
|
||||
} else {
|
||||
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
|
||||
#include "../runtime.h"
|
||||
|
||||
void run_call(Translated *translated, RuntimeState *state);
|
||||
ArErr run_call(Translated *translated, RuntimeState *state);
|
||||
|
||||
#endif // runtime_call_H
|
||||
@@ -23,6 +23,7 @@ void load_argon_function(Translated *translated, RuntimeState *state,
|
||||
uint64_t length = pop_bytecode(translated, state);
|
||||
add_field(object, "__name__", new_string_object(arena_get(&translated->constants, offset), length));
|
||||
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.parameters =
|
||||
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);
|
||||
}
|
||||
|
||||
ArgonObject *get_field(ArgonObject *target, char *name) {
|
||||
uint64_t hash = siphash64_bytes(name, strlen(name), siphash_key);
|
||||
return hashmap_lookup_GC(target->dict, hash);
|
||||
ArgonObject *get_field_for_class(ArgonObject *target, char *name) {
|
||||
char *field = "__base__";
|
||||
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;
|
||||
}
|
||||
@@ -17,6 +17,8 @@ ArgonObject *new_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
|
||||
@@ -214,7 +214,7 @@ ArErr run_instruction(Translated *translated, RuntimeState *state,
|
||||
state->registers[to_register];
|
||||
break;
|
||||
case OP_CALL:
|
||||
run_call(translated, state);
|
||||
return run_call(translated, state);
|
||||
// ArgonObject *object = state->registers[from_register];
|
||||
// char *field = "__class__";
|
||||
// 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,
|
||||
// object);
|
||||
// }
|
||||
break;
|
||||
default:
|
||||
return create_err(0, 0, 0, NULL, "Runtime Error", "Invalid Opcode %#x",
|
||||
opcode);
|
||||
@@ -249,7 +248,8 @@ RuntimeState init_runtime_state(Translated translated, char *path) {
|
||||
path,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL};
|
||||
0,
|
||||
{}};
|
||||
return runtime;
|
||||
}
|
||||
|
||||
@@ -275,19 +275,18 @@ ArErr runtime(Translated translated, RuntimeState state, Stack *stack) {
|
||||
|
||||
StackFrame *currentStackFrame =
|
||||
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;
|
||||
ArErr err = no_err;
|
||||
while (currentStackFrame) {
|
||||
while (currentStackFrame->state.head <
|
||||
currentStackFrame->translated.bytecode.size &&
|
||||
!currentStackFrame->err.exists) {
|
||||
currentStackFrame->err =
|
||||
!err.exists) {
|
||||
err =
|
||||
run_instruction(¤tStackFrame->translated,
|
||||
¤tStackFrame->state, ¤tStackFrame->stack);
|
||||
}
|
||||
StackFrame *tempStackFrame = currentStackFrame;
|
||||
err = currentStackFrame->err;
|
||||
currentStackFrame = currentStackFrame->previousStackFrame;
|
||||
if (tempStackFrame->depth % STACKFRAME_CHUNKS == 0) {
|
||||
free(tempStackFrame);
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
typedef struct StackFrame StackFrame;
|
||||
typedef struct RuntimeState RuntimeState;
|
||||
|
||||
typedef struct ErrorCatch {
|
||||
size_t jump_to;
|
||||
Stack *stack;
|
||||
StackFrame *stackFrame;
|
||||
} ErrorCatch;
|
||||
|
||||
typedef struct RuntimeState {
|
||||
ArgonObject **registers;
|
||||
size_t head;
|
||||
@@ -21,6 +27,7 @@ typedef struct RuntimeState {
|
||||
StackFrame **currentStackFramePointer;
|
||||
ArgonObject*** call_args;
|
||||
size_t* call_args_length;
|
||||
DArray catch_errors; // ErrorCatch[]
|
||||
} RuntimeState;
|
||||
|
||||
typedef struct StackFrame {
|
||||
@@ -28,7 +35,6 @@ typedef struct StackFrame {
|
||||
RuntimeState state;
|
||||
Stack *stack;
|
||||
StackFrame *previousStackFrame;
|
||||
ArErr err;
|
||||
uint64_t depth;
|
||||
} StackFrame;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user