work on method wrapper and native function support

This commit is contained in:
William Bell
2025-08-09 06:40:16 +01:00
parent 38e2cad507
commit 0635ba8517
23 changed files with 404 additions and 324 deletions

6
app.py
View File

@@ -1,6 +1,4 @@
def f(): def f():
return g() return f()
def g():
return f
f()() f()

View File

@@ -16,6 +16,8 @@ typedef struct ArErr ArErr;
typedef struct ArgonObject ArgonObject; // forward declaration typedef struct ArgonObject ArgonObject; // forward declaration
typedef ArgonObject* (*native_fn)(size_t argc, ArgonObject**argv, ArErr*err);
typedef enum ArgonType { typedef enum ArgonType {
TYPE_NULL, TYPE_NULL,
TYPE_BOOL, TYPE_BOOL,
@@ -24,10 +26,25 @@ typedef enum ArgonType {
TYPE_FUNCTION, TYPE_FUNCTION,
TYPE_NATIVE_FUNCTION, TYPE_NATIVE_FUNCTION,
TYPE_METHOD, TYPE_METHOD,
TYPE_NATIVE_METHOD,
TYPE_OBJECT, TYPE_OBJECT,
} ArgonType; } ArgonType;
typedef struct {
void *data;
size_t capacity;
size_t size;
struct hashmap_GC * hashmap;
} ConstantArena;
typedef struct {
uint8_t registerCount;
DArray *return_jumps;
darray_armem bytecode;
ConstantArena constants;
char* path;
} Translated;
struct string_struct { struct string_struct {
char *data; char *data;
size_t length; size_t length;
@@ -39,13 +56,12 @@ typedef struct Stack {
} Stack; } Stack;
struct argon_function_struct { struct argon_function_struct {
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;
struct string_struct *parameters; struct string_struct *parameters;
char* path;
DArray source_locations;
uint64_t line; uint64_t line;
uint64_t column; uint64_t column;
}; };
@@ -60,7 +76,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;
ArgonObject* (*native_fn)(size_t argc, ArgonObject**argv, ArErr*err); native_fn native_fn;
struct argon_function_struct argon_fn; struct argon_function_struct argon_fn;
} value; } value;
}; };

View File

@@ -24,13 +24,13 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <direct.h> // for _mkdir
#include <direct.h> // for _mkdir #include <sys/stat.h> // for _stat
#include <sys/stat.h> // for _stat #include <windows.h>
#else #else
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
#include "../external/cwalk/include/cwalk.h" #include "../external/cwalk/include/cwalk.h"
#include <string.h> #include <string.h>
@@ -48,30 +48,22 @@
// Windows / MinGW usually uses little-endian, so these can be no-ops // Windows / MinGW usually uses little-endian, so these can be no-ops
// But define them explicitly to avoid implicit declaration warnings // But define them explicitly to avoid implicit declaration warnings
static inline uint32_t le32toh(uint32_t x) { static inline uint32_t le32toh(uint32_t x) { return x; }
return x; static inline uint64_t le64toh(uint64_t x) { return x; }
} static inline uint32_t htole32(uint32_t x) { return x; }
static inline uint64_t le64toh(uint64_t x) { static inline uint64_t htole64(uint64_t x) { return x; }
return x;
}
static inline uint32_t htole32(uint32_t x) {
return x;
}
static inline uint64_t htole64(uint64_t x) {
return x;
}
#elif defined(__linux__) #elif defined(__linux__)
#include <endian.h> #include <endian.h>
#elif defined(__APPLE__) #elif defined(__APPLE__)
#include <libkern/OSByteOrder.h> #include <libkern/OSByteOrder.h>
#define htole32(x) OSSwapHostToLittleInt32(x) #define htole32(x) OSSwapHostToLittleInt32(x)
#define le32toh(x) OSSwapLittleToHostInt32(x) #define le32toh(x) OSSwapLittleToHostInt32(x)
#define htole64(x) OSSwapHostToLittleInt64(x) #define htole64(x) OSSwapHostToLittleInt64(x)
#define le64toh(x) OSSwapLittleToHostInt64(x) #define le64toh(x) OSSwapLittleToHostInt64(x)
// Add others as needed // Add others as needed
#else #else
#error "Unsupported platform" #error "Unsupported platform"
#endif #endif
char *get_current_directory() { char *get_current_directory() {
@@ -131,18 +123,79 @@ int ensure_dir_exists(const char *path) {
return 0; return 0;
} }
static inline void write_and_hash(FILE *file, XXH64_state_t *state,
const void *ptr, size_t size, size_t count) {
fwrite(ptr, size, count, file);
XXH64_update(state, ptr, size * count);
}
static inline void update_hash_from_file(FILE *file, XXH64_state_t *state,
size_t size) {
char buffer[4096];
size_t bytes_read;
size_t remaining = size;
while (remaining > 0 &&
(bytes_read =
fread(buffer, 1,
remaining > sizeof(buffer) ? sizeof(buffer) : remaining,
file)) > 0) {
XXH64_update(state, buffer, bytes_read);
remaining -= bytes_read;
}
}
const char CACHE_FOLDER[] = "__arcache__"; const char CACHE_FOLDER[] = "__arcache__";
const char FILE_IDENTIFIER[5] = "ARBI"; const char FILE_IDENTIFIER[5] = "ARBI";
const char BYTECODE_EXTENTION[] = "arbin"; const char BYTECODE_EXTENTION[] = "arbin";
const uint32_t version_number = 0; const uint32_t version_number = 0;
int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash) { int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash, char*source_path) {
bool translated_inited = false;
FILE *bytecode_file = fopen(joined_paths, "rb"); FILE *bytecode_file = fopen(joined_paths, "rb");
if (!bytecode_file) { if (!bytecode_file) {
printf("cache doesnt exist... compiling from source.\n"); printf("cache doesnt exist... compiling from source.\n");
return 1; return 1;
} }
// Find file size
fseek(bytecode_file, 0, SEEK_END);
long file_size = ftell(bytecode_file);
if (file_size < (long)sizeof(uint64_t)) {
goto FAILED;
}
fseek(bytecode_file, 0, SEEK_SET);
// Footer is the last 8 bytes
long data_size = file_size - sizeof(uint64_t);
// Set up hash state
XXH64_state_t *state = XXH64_createState();
XXH64_reset(state, 0);
// Hash everything except last 8 bytes
update_hash_from_file(bytecode_file, state, data_size);
// Read stored footer hash
uint64_t stored_hash_le;
if (fread(&stored_hash_le, 1, sizeof(stored_hash_le), bytecode_file) !=
sizeof(stored_hash_le)) {
XXH64_freeState(state);
goto FAILED;
}
uint64_t stored_hash = le64toh(stored_hash_le);
// Compare
uint64_t calc_hash = XXH64_digest(state);
XXH64_freeState(state);
if (calc_hash != stored_hash) {
printf("cache hash mismatch (corrupted?)\n");
goto FAILED;
}
// Now actually parse the file contents
fseek(bytecode_file, 0, SEEK_SET); // rewind to start
char file_identifier_from_cache[sizeof(FILE_IDENTIFIER)] = {0}; char file_identifier_from_cache[sizeof(FILE_IDENTIFIER)] = {0};
if (fread(&file_identifier_from_cache, 1, if (fread(&file_identifier_from_cache, 1,
sizeof(file_identifier_from_cache) - 1, sizeof(file_identifier_from_cache) - 1,
@@ -194,15 +247,7 @@ int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash) {
} }
bytecodeSize = le64toh(bytecodeSize); bytecodeSize = le64toh(bytecodeSize);
uint64_t sourceLocationSize; *translated_dest = init_translator(source_path);
if (fread(&sourceLocationSize, 1, sizeof(sourceLocationSize),
bytecode_file) != sizeof(sourceLocationSize)) {
goto FAILED;
}
sourceLocationSize = le64toh(sourceLocationSize);
*translated_dest = init_translator("");
translated_inited = true;
arena_resize(&translated_dest->constants, constantsSize); arena_resize(&translated_dest->constants, constantsSize);
@@ -211,29 +256,18 @@ int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash) {
goto FAILED; goto FAILED;
} }
darray_resize(&translated_dest->bytecode, bytecodeSize); darray_armem_resize(&translated_dest->bytecode, bytecodeSize);
if (fread(translated_dest->bytecode.data, 1, bytecodeSize, bytecode_file) != if (fread(translated_dest->bytecode.data, 1, bytecodeSize, bytecode_file) !=
bytecodeSize) { bytecodeSize) {
goto FAILED; goto FAILED;
} }
darray_resize(&translated_dest->source_locations, sourceLocationSize);
if (fread(translated_dest->source_locations.data, sizeof(SourceLocation),
sourceLocationSize, bytecode_file) != sourceLocationSize) {
goto FAILED;
}
translated_dest->registerCount = register_count;
printf("cache exists and is valid, so will be used.\n"); printf("cache exists and is valid, so will be used.\n");
fclose(bytecode_file); fclose(bytecode_file);
return 0; return 0;
FAILED: FAILED:
printf("cache is invalid... compiling from source.\n"); printf("cache is invalid... compiling from source.\n");
if (translated_inited)
free_translator(translated_dest);
fclose(bytecode_file); fclose(bytecode_file);
return 1; return 1;
} }
@@ -292,7 +326,7 @@ Execution execute(char *path, Stack *stack) {
Translated translated; Translated translated;
if (load_cache(&translated, cache_file_path, hash) != 0) { if (load_cache(&translated, cache_file_path, hash, path) != 0) {
translated = init_translator(path); translated = init_translator(path);
DArray tokens; DArray tokens;
@@ -302,7 +336,6 @@ Execution execute(char *path, Stack *stack) {
start = clock(); start = clock();
ArErr err = lexer(state); ArErr err = lexer(state);
if (err.exists) { if (err.exists) {
free_translator(&translated);
darray_free(&tokens, free_token); darray_free(&tokens, free_token);
return (Execution){err, (Stack){NULL, NULL}}; return (Execution){err, (Stack){NULL, NULL}};
} }
@@ -319,7 +352,6 @@ Execution execute(char *path, Stack *stack) {
start = clock(); start = clock();
err = parser(path, &ast, &tokens, false); err = parser(path, &ast, &tokens, false);
if (err.exists) { if (err.exists) {
free_translator(&translated);
darray_free(&tokens, free_token); darray_free(&tokens, free_token);
darray_free(&ast, free_parsed); darray_free(&ast, free_parsed);
return (Execution){err, (Stack){NULL, NULL}}; return (Execution){err, (Stack){NULL, NULL}};
@@ -333,7 +365,6 @@ Execution execute(char *path, Stack *stack) {
start = clock(); start = clock();
err = translate(&translated, &ast); err = translate(&translated, &ast);
if (err.exists) { if (err.exists) {
free_translator(&translated);
darray_free(&ast, free_parsed); darray_free(&ast, free_parsed);
return (Execution){err, (Stack){NULL, NULL}}; return (Execution){err, (Stack){NULL, NULL}};
} }
@@ -349,27 +380,36 @@ Execution execute(char *path, Stack *stack) {
uint64_t constantsSize = translated.constants.size; uint64_t constantsSize = translated.constants.size;
uint64_t bytecodeSize = translated.bytecode.size; uint64_t bytecodeSize = translated.bytecode.size;
uint64_t sourceLocationSize = translated.source_locations.size;
uint32_t version_number_htole32ed = htole32(version_number); uint32_t version_number_htole32ed = htole32(version_number);
uint64_t net_hash = htole64(hash); uint64_t net_hash = htole64(hash);
constantsSize = htole64(constantsSize); constantsSize = htole64(constantsSize);
bytecodeSize = htole64(bytecodeSize); bytecodeSize = htole64(bytecodeSize);
sourceLocationSize = htole64(sourceLocationSize);
fwrite(&FILE_IDENTIFIER, sizeof(char), strlen(FILE_IDENTIFIER), file); XXH64_state_t *hash_state = XXH64_createState();
fwrite(&version_number_htole32ed, sizeof(uint32_t), 1, file); XXH64_reset(hash_state, 0);
fwrite(&net_hash, sizeof(net_hash), 1, file);
fwrite(&translated.registerCount, sizeof(uint8_t), 1, file); write_and_hash(file, hash_state, &FILE_IDENTIFIER, sizeof(char),
fwrite(&constantsSize, sizeof(uint64_t), 1, file); strlen(FILE_IDENTIFIER));
fwrite(&bytecodeSize, sizeof(uint64_t), 1, file); write_and_hash(file, hash_state, &version_number_htole32ed,
fwrite(&sourceLocationSize, sizeof(uint64_t), 1, file); sizeof(uint32_t), 1);
fwrite(translated.constants.data, 1, translated.constants.size, file); write_and_hash(file, hash_state, &net_hash, sizeof(net_hash), 1);
fwrite(translated.bytecode.data, translated.bytecode.element_size, write_and_hash(file, hash_state, &translated.registerCount, sizeof(uint8_t),
translated.bytecode.size, file); 1);
fwrite(translated.source_locations.data, write_and_hash(file, hash_state, &constantsSize, sizeof(uint64_t), 1);
translated.source_locations.element_size, write_and_hash(file, hash_state, &bytecodeSize, sizeof(uint64_t), 1);
translated.source_locations.size, file); write_and_hash(file, hash_state, translated.constants.data, 1,
translated.constants.size);
write_and_hash(file, hash_state, translated.bytecode.data,
translated.bytecode.element_size, translated.bytecode.size);
// Finalize the hash
uint64_t file_hash = XXH64_digest(hash_state);
XXH64_freeState(hash_state);
// Convert to little-endian before writing if needed
uint64_t file_hash_le = htole64(file_hash);
fwrite(&file_hash_le, sizeof(file_hash_le), 1, file);
fclose(file); fclose(file);
} }
@@ -385,7 +425,6 @@ Execution execute(char *path, Stack *stack) {
printf("Execution time taken: %f seconds\n", time_spent); printf("Execution time taken: %f seconds\n", time_spent);
printf("total time taken: %f seconds\n", total_time_spent); printf("total time taken: %f seconds\n", total_time_spent);
free_translator(&translated);
return (Execution){err, *main_scope}; return (Execution){err, *main_scope};
} }
@@ -394,6 +433,7 @@ int main(int argc, char *argv[]) {
ar_memory_init(); ar_memory_init();
generate_siphash_key(siphash_key); generate_siphash_key(siphash_key);
bootstrap_types(); bootstrap_types();
bootstrap_globals();
char *CWD = get_current_directory(); char *CWD = get_current_directory();
if (argc <= 1) if (argc <= 1)
return -1; return -1;
@@ -401,7 +441,7 @@ int main(int argc, char *argv[]) {
char path[FILENAME_MAX]; char path[FILENAME_MAX];
cwk_path_get_absolute(CWD, path_non_absolute, path, sizeof(path)); cwk_path_get_absolute(CWD, path_non_absolute, path, sizeof(path));
free(CWD); free(CWD);
Execution resp = execute(path, NULL); Execution resp = execute(path, Global_Scope);
if (runtime_hash_table) if (runtime_hash_table)
hashmap_free(runtime_hash_table, NULL); hashmap_free(runtime_hash_table, NULL);
if (resp.err.exists) { if (resp.err.exists) {

View File

@@ -26,8 +26,6 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index,
(*index)++; (*index)++;
ArErr err = error_if_finished(file, tokens, index); ArErr err = error_if_finished(file, tokens, index);
if (err.exists) { if (err.exists) {
free_parsed(to_call);
free(to_call);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
return (ParsedValueReturn){err, NULL}; return (ParsedValueReturn){err, NULL};
@@ -38,22 +36,16 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index,
skip_newlines_and_indents(tokens, index); skip_newlines_and_indents(tokens, index);
ArErr err = error_if_finished(file, tokens, index); ArErr err = error_if_finished(file, tokens, index);
if (err.exists) { if (err.exists) {
free_parsed(to_call);
free(to_call);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
return (ParsedValueReturn){err, NULL}; return (ParsedValueReturn){err, NULL};
} }
ParsedValueReturn parsedArg = parse_token(file, tokens, index, true); ParsedValueReturn parsedArg = parse_token(file, tokens, index, true);
if (parsedArg.err.exists) { if (parsedArg.err.exists) {
free_parsed(to_call);
free(to_call);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
return parsedArg; return parsedArg;
} else if (!parsedArg.value) { } else if (!parsedArg.value) {
free_parsed(to_call);
free(to_call);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
@@ -66,8 +58,6 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index,
free(parsedArg.value); free(parsedArg.value);
err = error_if_finished(file, tokens, index); err = error_if_finished(file, tokens, index);
if (err.exists) { if (err.exists) {
free_parsed(to_call);
free(to_call);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
return (ParsedValueReturn){err, NULL}; return (ParsedValueReturn){err, NULL};
@@ -75,8 +65,6 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index,
skip_newlines_and_indents(tokens, index); skip_newlines_and_indents(tokens, index);
err = error_if_finished(file, tokens, index); err = error_if_finished(file, tokens, index);
if (err.exists) { if (err.exists) {
free_parsed(to_call);
free(to_call);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
return (ParsedValueReturn){err, NULL}; return (ParsedValueReturn){err, NULL};
@@ -85,8 +73,6 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index,
if (token->type == TOKEN_RPAREN) { if (token->type == TOKEN_RPAREN) {
break; break;
} else if (token->type != TOKEN_COMMA) { } else if (token->type != TOKEN_COMMA) {
free_parsed(to_call);
free(to_call);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
@@ -98,8 +84,6 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index,
(*index)++; (*index)++;
err = error_if_finished(file, tokens, index); err = error_if_finished(file, tokens, index);
if (err.exists) { if (err.exists) {
free_parsed(to_call);
free(to_call);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
return (ParsedValueReturn){err, NULL}; return (ParsedValueReturn){err, NULL};

View File

@@ -61,6 +61,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) {
(*index)++; (*index)++;
ArErr err = error_if_finished(file, tokens, index); ArErr err = error_if_finished(file, tokens, index);
if (err.exists) { if (err.exists) {
hashmap_free(parameters_hashmap, NULL);
darray_free(&parameters, free_parameter); darray_free(&parameters, free_parameter);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
@@ -70,6 +71,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) {
if (token->type == TOKEN_RPAREN) { if (token->type == TOKEN_RPAREN) {
(*index)++; (*index)++;
if ((*index) >= tokens->size) { if ((*index) >= tokens->size) {
hashmap_free(parameters_hashmap, NULL);
declaration->from = create_parsed_function( declaration->from = create_parsed_function(
declaration->name, parameters, declaration->from); declaration->name, parameters, declaration->from);
return (ParsedValueReturn){no_err, parsedValue}; return (ParsedValueReturn){no_err, parsedValue};
@@ -118,6 +120,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) {
(*index)++; (*index)++;
err = error_if_finished(file, tokens, index); err = error_if_finished(file, tokens, index);
if (err.exists) { if (err.exists) {
hashmap_free(parameters_hashmap, NULL);
darray_free(&parameters, free_parameter); darray_free(&parameters, free_parameter);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
@@ -126,6 +129,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) {
skip_newlines_and_indents(tokens, index); skip_newlines_and_indents(tokens, index);
err = error_if_finished(file, tokens, index); err = error_if_finished(file, tokens, index);
if (err.exists) { if (err.exists) {
hashmap_free(parameters_hashmap, NULL);
darray_free(&parameters, free_parameter); darray_free(&parameters, free_parameter);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);
@@ -150,6 +154,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) {
(*index)++; (*index)++;
err = error_if_finished(file, tokens, index); err = error_if_finished(file, tokens, index);
if (err.exists) { if (err.exists) {
hashmap_free(parameters_hashmap, NULL);
darray_free(&parameters, free_parameter); darray_free(&parameters, free_parameter);
free_parsed(parsedValue); free_parsed(parsedValue);
free(parsedValue); free(parsedValue);

View File

@@ -71,73 +71,72 @@ double get_memory_usage_mb() {
#endif #endif
ArErr run_call(Translated *translated, RuntimeState *state) { ArErr run_call(Translated *translated, RuntimeState *state) {
uint8_t from_register = pop_byte(translated, state); ArgonObject *original_object = state->call_instance->to_call;
uint8_t source_location_index = pop_bytecode(translated, state);
ArgonObject *original_object = state->registers[from_register];
ArgonObject *object = original_object; ArgonObject *object = original_object;
int is_method = if (object->type != TYPE_FUNCTION && object->type != TYPE_NATIVE_FUNCTION &&
object->type == TYPE_METHOD || object->type == TYPE_NATIVE_METHOD; object->type != TYPE_METHOD) {
if (object->type != TYPE_FUNCTION && object->type != TYPE_NATIVE_FUNCTION && !is_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), "__call__");
if (call_method) { if (call_method) {
object = call_method; object = call_method;
is_method =
object->type == TYPE_METHOD && object->type == TYPE_NATIVE_METHOD;
} }
} }
if (is_method) { if (object->type == TYPE_METHOD) {
ArgonObject **new_call_args = ArgonObject *binding_object = get_field(object, "__binding__", false);
malloc(sizeof(ArgonObject *) * (*state->call_args_length + 1)); if (binding_object) {
new_call_args[0] = original_object; ArgonObject **new_call_args = malloc(
if (*state->call_args_length > 0) { sizeof(ArgonObject *) * (state->call_instance->args_length + 1));
memcpy(new_call_args + 1, *state->call_args, *state->call_args_length); new_call_args[0] = binding_object;
if (state->call_instance->args_length > 0) {
memcpy(new_call_args + 1, state->call_instance->args,
state->call_instance->args_length);
} }
if (*state->call_args) { free(state->call_instance->args);
free(*state->call_args); state->call_instance->args = new_call_args;
state->call_instance->args_length++;
} }
*state->call_args = new_call_args; ArgonObject *function_object = get_field(object, "__function__", false);
(*state->call_args_length)++; if (function_object)
object = function_object;
} }
if (object->type == TYPE_FUNCTION || object->type == TYPE_METHOD) { if (object->type == TYPE_FUNCTION) {
SourceLocation *source_location = if (state->call_instance->args_length !=
darray_get(&translated->source_locations, source_location_index);
if (*state->call_args_length !=
object->value.argon_fn.number_of_parameters) { object->value.argon_fn.number_of_parameters) {
ArgonObject *type_object_name = get_field_for_class( ArgonObject *type_object_name = get_field_for_class(
get_field(object, "__class__", false), "__name__"); get_field(object, "__class__", false), "__name__", original_object);
ArgonObject *object_name = get_field_for_class(object, "__name__"); ArgonObject *object_name = get_field_for_class(object, "__name__", original_object);
return create_err( return create_err(
source_location->line, source_location->column, state->source_location.line, state->source_location.column,
source_location->length, state->path, "Type Error", state->source_location.length, state->path, "Type Error",
"%.*s %.*s takes %" PRIu64 " argument(s) but %" PRIu64 " was given", "%.*s %.*s takes %" PRIu64 " argument(s) but %" PRIu64 " was given",
(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,
*state->call_args_length); 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_args_length; i++) { for (size_t i = 0; i < state->call_instance->args_length; 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_args)[i]; ArgonObject *value = (state->call_instance->args)[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);
} }
DArray bytecode_darray = {object->value.argon_fn.bytecode, sizeof(uint8_t),
object->value.argon_fn.bytecode_length,
object->value.argon_fn.bytecode_length, false};
StackFrame new_stackFrame = { StackFrame new_stackFrame = {
{translated->registerCount, NULL, bytecode_darray, {translated->registerCount,
object->value.argon_fn.source_locations, translated->constants, NULL,
object->value.argon_fn.path}, {object->value.argon_fn.bytecode, sizeof(uint8_t),
object->value.argon_fn.bytecode_length,
object->value.argon_fn.bytecode_length, false},
object->value.argon_fn.translated.constants,
object->value.argon_fn.translated.path},
{state->registers, {state->registers,
0, 0,
state->path, object->value.argon_fn.translated.path,
NULL,
state->currentStackFramePointer, state->currentStackFramePointer,
state->call_args, {},
state->call_args_length,
{}}, {}},
scope, scope,
*state->currentStackFramePointer, *state->currentStackFramePointer,
@@ -153,13 +152,12 @@ ArErr run_call(Translated *translated, RuntimeState *state) {
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) {
SourceLocation *source_location =
darray_get(&translated->source_locations, source_location_index);
double memoryUsage = get_memory_usage_mb(); double memoryUsage = get_memory_usage_mb();
fprintf(stderr, fprintf(stderr,
"Warning: %s:%" PRIu64 ":%" PRIu64 "Warning: %s:%" PRIu64 ":%" PRIu64
" the call stack depth has exceeded %" PRIu64, " the call stack depth has exceeded %" PRIu64,
state->path, source_location->line, source_location->column, state->path, state->source_location.line,
state->source_location.column,
(*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);
@@ -169,18 +167,22 @@ ArErr run_call(Translated *translated, RuntimeState *state) {
} }
}; };
return no_err; return no_err;
} else if (object->type == TYPE_NATIVE_FUNCTION || object->type == TYPE_NATIVE_METHOD) { } else if (object->type == TYPE_NATIVE_FUNCTION) {
ArErr err = no_err; ArErr err = no_err;
state->registers[0] = object->value.native_fn(*state->call_args_length, state->registers[0] = object->value.native_fn(
*state->call_args, &err); state->call_instance->args_length, state->call_instance->args, &err);
if (err.exists) {
err.line = state->source_location.line;
err.column = state->source_location.column;
err.length = state->source_location.length;
err.path = state->path;
}
return err; return err;
} }
SourceLocation *source_location =
darray_get(&translated->source_locations, source_location_index);
ArgonObject *type_object_name = get_field_for_class( ArgonObject *type_object_name = get_field_for_class(
get_field(original_object, "__class__", false), "__name__"); get_field(original_object, "__class__", false), "__name__", original_object);
return create_err(source_location->line, source_location->column, return create_err(state->source_location.line, state->source_location.column,
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",
(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);

View File

@@ -12,12 +12,10 @@ ArErr runtime_declaration(Translated *translated, RuntimeState *state,
int64_t offset = pop_bytecode(translated, state); int64_t offset = pop_bytecode(translated, state);
int64_t prehash = pop_bytecode(translated, state); int64_t prehash = pop_bytecode(translated, state);
int64_t from_register = pop_byte(translated, state); int64_t from_register = pop_byte(translated, state);
int64_t source_location_index = pop_bytecode(translated, state);
uint64_t hash = runtime_hash(arena_get(&translated->constants, offset), length, prehash); uint64_t hash = runtime_hash(arena_get(&translated->constants, offset), length, prehash);
ArgonObject * exists = hashmap_lookup_GC(stack->scope, hash); ArgonObject * exists = hashmap_lookup_GC(stack->scope, hash);
if (exists) { if (exists) {
SourceLocation *source_location = darray_get(&translated->source_locations, source_location_index); return create_err(state->source_location.line, state->source_location.column, state->source_location.length, state->path, "Runtime Error", "Identifier '%.*s' has already been declared in the current scope", length, arena_get(&translated->constants, offset));
return create_err(source_location->line, source_location->column, source_location->length, state->path, "Runtime Error", "Identifier '%.*s' has already been declared in the current scope", length, arena_get(&translated->constants, offset));
} }
ArgonObject * key = new_string_object(arena_get(&translated->constants, offset), length); ArgonObject * key = new_string_object(arena_get(&translated->constants, offset), length);
hashmap_insert_GC(stack->scope, hash, key, state->registers[from_register], 0); hashmap_insert_GC(stack->scope, hash, key, state->registers[from_register], 0);

View File

@@ -45,7 +45,6 @@ void darray_armem_resize(darray_armem *arr, size_t new_size) {
} }
if (new_capacity != arr->capacity) { if (new_capacity != arr->capacity) {
printf("%zu\n", new_capacity_bytes);
arr->data = ar_realloc(arr->data, new_capacity_bytes); arr->data = ar_realloc(arr->data, new_capacity_bytes);
if (!arr->data) { if (!arr->data) {
fprintf(stderr, "darray_armem_resize: reallocation failed\n"); fprintf(stderr, "darray_armem_resize: reallocation failed\n");

View File

@@ -14,6 +14,15 @@
ArgonObject *ARGON_FUNCTION_TYPE = NULL; ArgonObject *ARGON_FUNCTION_TYPE = NULL;
ArgonObject *create_argon_native_function(char*name, native_fn native_fn) {
ArgonObject *object = new_object();
add_field(object, "__class__", ARGON_FUNCTION_TYPE);
object->type = TYPE_NATIVE_FUNCTION;
add_field(object, "__name__", new_string_object(name, strlen(name)));
object->value.native_fn = native_fn;
return object;
}
void load_argon_function(Translated *translated, RuntimeState *state, void load_argon_function(Translated *translated, RuntimeState *state,
struct Stack *stack) { struct Stack *stack) {
ArgonObject *object = new_object(); ArgonObject *object = new_object();
@@ -22,8 +31,7 @@ void load_argon_function(Translated *translated, RuntimeState *state,
uint64_t offset = pop_bytecode(translated, state); uint64_t offset = pop_bytecode(translated, 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.translated = *translated;
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

@@ -10,6 +10,8 @@
extern ArgonObject *ARGON_FUNCTION_TYPE; extern ArgonObject *ARGON_FUNCTION_TYPE;
ArgonObject *create_argon_native_function(char*name, native_fn native_fn);
ArgonObject *load_argon_function(Translated *translated, RuntimeState *state, struct Stack *stack); ArgonObject *load_argon_function(Translated *translated, RuntimeState *state, struct Stack *stack);
#endif // FUNCTION_H #endif // FUNCTION_H

View File

@@ -9,6 +9,7 @@
#include "../../memory.h" #include "../../memory.h"
#include "type/type.h" #include "type/type.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
#include <string.h> #include <string.h>
ArgonObject *BASE_CLASS = NULL; ArgonObject *BASE_CLASS = NULL;
@@ -26,13 +27,32 @@ void add_field(ArgonObject *target, char *name, ArgonObject *object) {
object, 0); object, 0);
} }
ArgonObject *get_field_for_class(ArgonObject *target, char *name) { ArgonObject *bind_object_to_function(ArgonObject *object,
ArgonObject *function) {
ArgonObject *bound_method_wrapper = new_object();
bound_method_wrapper->type = TYPE_METHOD;
add_field(bound_method_wrapper, "__class__", ARGON_METHOD_TYPE);
add_field(bound_method_wrapper, "__binding__", object);
add_field(bound_method_wrapper, "__function__", function);
ArgonObject *function_name = get_field(function, "__name__", false);
if (function_name)
add_field(bound_method_wrapper, "__name__", function_name);
return bound_method_wrapper;
}
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 ||
object->type == TYPE_NATIVE_FUNCTION) {
object = bind_object_to_function(binding_object, object);
}
return object; return object;
}
hash = siphash64_bytes(field, strlen(field), siphash_key); hash = siphash64_bytes(field, strlen(field), siphash_key);
target = hashmap_lookup_GC(target->dict, hash); target = hashmap_lookup_GC(target->dict, hash);
} }
@@ -41,14 +61,8 @@ ArgonObject *get_field_for_class(ArgonObject *target, char *name) {
ArgonObject *get_field(ArgonObject *target, char *name, bool recursive) { ArgonObject *get_field(ArgonObject *target, char *name, bool recursive) {
char *field = "__class__"; char *field = "__class__";
while (target) { ArgonObject *object = hashmap_lookup_GC(target->dict, 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);
if (!recursive || object) if (!recursive || object)
return object; return object;
hash = siphash64_bytes(field, strlen(field), siphash_key); return get_field_for_class(hashmap_lookup_GC(target->dict, siphash64_bytes(field, strlen(field), siphash_key)), name, target);
target = hashmap_lookup_GC(target->dict, hash);
field = "__base__";
}
return NULL;
} }

View File

@@ -17,7 +17,7 @@ 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 *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);

View File

@@ -25,11 +25,30 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
ArgonObject *ARGON_METHOD_TYPE;
Stack *Global_Scope = NULL;
ArgonObject *ARGON_TYPE_TYPE___call__(size_t argc, ArgonObject **argv,
ArErr *err) {
if (argc<1) {
*err = create_err(0, 0, 0, "", "Runtime Error", "call missing self object.");
return ARGON_NULL;
}
ArgonObject *self = argv[0];
ArgonObject *self_name = get_field(argv[0], "__name__", true);
printf("type: %.*s\n", (int)self_name->value.as_str.length, self_name->value.as_str.data);
return ARGON_NULL;
}
void bootstrap_types() { void bootstrap_types() {
BASE_CLASS = new_object(); BASE_CLASS = new_object();
ARGON_TYPE_TYPE = new_object(); ARGON_TYPE_TYPE = new_object();
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__",
create_argon_native_function(
"__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);
@@ -63,6 +82,25 @@ void bootstrap_types() {
add_field(ARGON_FUNCTION_TYPE, "__base__", BASE_CLASS); add_field(ARGON_FUNCTION_TYPE, "__base__", BASE_CLASS);
add_field(ARGON_FUNCTION_TYPE, "__name__", add_field(ARGON_FUNCTION_TYPE, "__name__",
new_string_object_null_terminated("function")); new_string_object_null_terminated("function"));
ARGON_METHOD_TYPE = new_object();
add_field(ARGON_METHOD_TYPE, "__base__", BASE_CLASS);
add_field(ARGON_METHOD_TYPE, "__name__",
new_string_object_null_terminated("method"));
}
void add_to_scope(Stack *stack, char *name, ArgonObject *value) {
size_t length = strlen(name);
uint64_t hash =
siphash64_bytes(name, length, siphash_key);
ArgonObject *key = new_string_object(name, length);
hashmap_insert_GC(stack->scope, hash, key, value, 0);
}
void bootstrap_globals() {
Global_Scope = create_scope(NULL);
add_to_scope(Global_Scope, "string", ARGON_STRING_TYPE);
add_to_scope(Global_Scope, "type", ARGON_TYPE_TYPE);
} }
int compare_by_order(const void *a, const void *b) { int compare_by_order(const void *a, const void *b) {
@@ -72,7 +110,7 @@ int compare_by_order(const void *a, const void *b) {
} }
uint8_t pop_byte(Translated *translated, RuntimeState *state) { uint8_t pop_byte(Translated *translated, RuntimeState *state) {
return *((uint8_t *)darray_get(&translated->bytecode, state->head++)); return *((uint8_t *)darray_armem_get(&translated->bytecode, state->head++));
} }
uint64_t pop_bytecode(Translated *translated, RuntimeState *state) { uint64_t pop_bytecode(Translated *translated, RuntimeState *state) {
@@ -120,8 +158,7 @@ ArErr load_variable(Translated *translated, RuntimeState *state,
struct Stack *stack) { struct Stack *stack) {
int64_t length = pop_bytecode(translated, state); int64_t length = pop_bytecode(translated, state);
int64_t offset = pop_bytecode(translated, state); int64_t offset = pop_bytecode(translated, state);
int64_t prehash = pop_bytecode(translated, state); uint64_t prehash = pop_bytecode(translated, state);
int64_t source_location_index = pop_bytecode(translated, state);
uint64_t hash = uint64_t hash =
runtime_hash(arena_get(&translated->constants, offset), length, prehash); runtime_hash(arena_get(&translated->constants, offset), length, prehash);
struct Stack *current_stack = stack; struct Stack *current_stack = stack;
@@ -133,10 +170,9 @@ ArErr load_variable(Translated *translated, RuntimeState *state,
} }
current_stack = current_stack->prev; current_stack = current_stack->prev;
} }
SourceLocation *source_location = ArErr err =
darray_get(&translated->source_locations, source_location_index); create_err(state->source_location.line, state->source_location.column,
ArErr err = create_err(source_location->line, source_location->column, state->source_location.length, state->path, "Name Error",
source_location->length, state->path, "Name Error",
"name '%.*s' is not defined", (int)length, "name '%.*s' is not defined", (int)length,
arena_get(&translated->constants, offset)); arena_get(&translated->constants, offset));
return err; return err;
@@ -200,22 +236,25 @@ ArErr run_instruction(Translated *translated, RuntimeState *state,
// free(array); // free(array);
*stack = (*stack)->prev; *stack = (*stack)->prev;
break; break;
case OP_INIT_ARGS:; case OP_INIT_CALL:;
*state->call_args_length = pop_bytecode(translated, state); size_t length = pop_bytecode(translated, state);
size_t size = *state->call_args_length * sizeof(ArgonObject *); call_instance call_instance = {
if (*state->call_args) { state->call_instance, state->registers[0],
*state->call_args = realloc(*state->call_args, size); checked_malloc(length * sizeof(ArgonObject *)), length};
} else { state->call_instance = checked_malloc(sizeof(call_instance));
*state->call_args = checked_malloc(size); *state->call_instance = call_instance;
}
break; break;
case OP_INSERT_ARG:; case OP_INSERT_ARG:;
to_register = pop_byte(translated, state); size_t index = pop_bytecode(translated, state);
(*state->call_args)[pop_bytecode(translated, state)] = (state->call_instance->args)[index] = state->registers[0];
state->registers[to_register];
break; break;
case OP_CALL: case OP_CALL:;
return run_call(translated, state); ArErr err = run_call(translated, state);
free(state->call_instance->args);
call_instance = *state->call_instance;
free(state->call_instance);
state->call_instance = call_instance.previous;
return err;
// 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);
@@ -235,6 +274,11 @@ 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);
// } // }
case OP_SOURCE_LOCATION:
state->source_location = (SourceLocation){pop_bytecode(translated, state),
pop_bytecode(translated, state),
pop_bytecode(translated, state)};
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);
@@ -243,13 +287,13 @@ ArErr run_instruction(Translated *translated, RuntimeState *state,
} }
RuntimeState init_runtime_state(Translated translated, char *path) { RuntimeState init_runtime_state(Translated translated, char *path) {
RuntimeState runtime = (RuntimeState){ RuntimeState runtime = {
checked_malloc(translated.registerCount * sizeof(ArgonObject *)), checked_malloc(translated.registerCount * sizeof(ArgonObject *)),
0, 0,
path, path,
NULL, NULL,
NULL, NULL,
0, {0, 0, 0},
{}}; {}};
return runtime; return runtime;
} }
@@ -268,12 +312,6 @@ Stack *create_scope(Stack *prev) {
ArErr runtime(Translated translated, RuntimeState state, Stack *stack) { ArErr runtime(Translated translated, RuntimeState state, Stack *stack) {
state.head = 0; state.head = 0;
ArgonObject **call_args = NULL;
size_t call_args_length = 0;
state.call_args = &call_args;
state.call_args_length = &call_args_length;
StackFrame *currentStackFrame = StackFrame *currentStackFrame =
checked_malloc(sizeof(StackFrame) * STACKFRAME_CHUNKS); checked_malloc(sizeof(StackFrame) * STACKFRAME_CHUNKS);
*currentStackFrame = (StackFrame){translated, state, stack, NULL, 0}; *currentStackFrame = (StackFrame){translated, state, stack, NULL, 0};
@@ -288,19 +326,18 @@ ArErr runtime(Translated translated, RuntimeState state, Stack *stack) {
&currentStackFrame->state, &currentStackFrame->stack); &currentStackFrame->state, &currentStackFrame->stack);
} }
StackFrame *tempStackFrame = currentStackFrame; StackFrame *tempStackFrame = currentStackFrame;
while (currentStackFrame->state.call_instance) {
free(currentStackFrame->state.call_instance->args);
call_instance call_instance = *currentStackFrame->state.call_instance;
free(currentStackFrame->state.call_instance);
currentStackFrame->state.call_instance = call_instance.previous;
}
currentStackFrame = currentStackFrame->previousStackFrame; currentStackFrame = currentStackFrame->previousStackFrame;
if (tempStackFrame->depth % STACKFRAME_CHUNKS == 0) { if (tempStackFrame->depth % STACKFRAME_CHUNKS == 0) {
free(tempStackFrame); free(tempStackFrame);
} }
} }
if (call_args)
free(call_args);
call_args = NULL;
call_args_length = 0;
state.call_args = NULL;
state.call_args_length = NULL;
return err; return err;
} }

View File

@@ -11,9 +11,25 @@
#include "internals/dynamic_array_armem/darray_armem.h" #include "internals/dynamic_array_armem/darray_armem.h"
#include "internals/hashmap/hashmap.h" #include "internals/hashmap/hashmap.h"
extern ArgonObject *ARGON_METHOD_TYPE;
extern Stack *Global_Scope;
typedef struct StackFrame StackFrame; typedef struct StackFrame StackFrame;
typedef struct RuntimeState RuntimeState; typedef struct RuntimeState RuntimeState;
typedef struct SourceLocation {
uint64_t line;
uint64_t column;
uint64_t length;
} SourceLocation;
typedef struct call_instance {
struct call_instance *previous;
ArgonObject *to_call;
ArgonObject **args;
size_t args_length;
} call_instance;
typedef struct ErrorCatch { typedef struct ErrorCatch {
size_t jump_to; size_t jump_to;
Stack *stack; Stack *stack;
@@ -24,9 +40,9 @@ typedef struct RuntimeState {
ArgonObject **registers; ArgonObject **registers;
size_t head; size_t head;
char *path; char *path;
call_instance *call_instance;
StackFrame **currentStackFramePointer; StackFrame **currentStackFramePointer;
ArgonObject*** call_args; SourceLocation source_location;
size_t* call_args_length;
DArray catch_errors; // ErrorCatch[] DArray catch_errors; // ErrorCatch[]
} RuntimeState; } RuntimeState;
@@ -46,6 +62,8 @@ extern struct hashmap *runtime_hash_table;
uint64_t runtime_hash(const void *data, size_t len, uint64_t prehash); uint64_t runtime_hash(const void *data, size_t len, uint64_t prehash);
void bootstrap_globals();
uint8_t pop_byte(Translated *translated, RuntimeState *state); uint8_t pop_byte(Translated *translated, RuntimeState *state);
uint64_t pop_bytecode(Translated *translated, RuntimeState *state); uint64_t pop_bytecode(Translated *translated, RuntimeState *state);

View File

@@ -29,7 +29,6 @@ this operation takes 3 operands.
2. the offset in the constant buffer of the variable name. 2. the offset in the constant buffer of the variable name.
3. the fixed hash of the variable name. 3. the fixed hash of the variable name.
4. the register of the given value (*) 4. the register of the given value (*)
5. the index of the source location.
## OP_LOAD_NULL ## OP_LOAD_NULL
@@ -59,7 +58,6 @@ initilises a function to a given register.
1. the length of the identifer. 1. the length of the identifer.
2. the offset of the identifier. 2. the offset of the identifier.
3. the fixed hash of the variable name. 3. the fixed hash of the variable name.
4. the index of the source location.
## OP_BOOL ## OP_BOOL
@@ -89,27 +87,27 @@ creates a new stack
pops the top scope off the current pops the top scope off the current
## OP_INIT_ARGS ## OP_INIT_CALL
initialises the arguments buffer with a fixed number of objects on the current state initialises a call instance struct and arguments buffer.
1. the number of objects for the arguments buffer 1. the number of objects for the arguments buffer
## OP_INSERT_ARG ## OP_INSERT_ARG
1. the register to take the object from. (*)
1. index of the argument in the arguments buffer to write the object from the register into. 1. index of the argument in the arguments buffer to write the object from the register into.
## OP_RESET_ARGS
resets the arguments buffer to NULL
## OP_CALL ## OP_CALL
call a function with args call a function with args
1. the register containing the function to call. (*) ## OP_SOURCE_LOCATION
4. the index of the source location.
sets the source location onto the runtime
3. the line
4. the column
5. the length
## OP_SWAP_REGISTERS ## OP_SWAP_REGISTERS

View File

@@ -5,29 +5,27 @@
*/ */
#include "call.h" #include "call.h"
size_t translate_parsed_call(Translated *translated, ParsedCall* call, ArErr *err) { size_t translate_parsed_call(Translated *translated, ParsedCall *call,
ArErr *err) {
set_registers(translated, 1); set_registers(translated, 1);
size_t first = push_instruction_byte(translated, OP_INIT_ARGS); translate_parsed(translated, call->to_call, err);
size_t first = push_instruction_byte(translated, OP_INIT_CALL);
push_instruction_code(translated, call->args.size); push_instruction_code(translated, call->args.size);
for (size_t i = 0; i < call->args.size; i++) { for (size_t i = 0; i < call->args.size; i++) {
translate_parsed(translated, darray_get(&call->args, i), err); translate_parsed(translated, darray_get(&call->args, i), err);
if (err->exists) if (err->exists)
return first; return first;
push_instruction_byte(translated, OP_INSERT_ARG); push_instruction_byte(translated, OP_INSERT_ARG);
push_instruction_byte(translated, 0);
push_instruction_code(translated, i); push_instruction_code(translated, i);
} }
translate_parsed(translated, call->to_call, err);
if (err->exists) if (err->exists)
return first; return first;
push_instruction_byte(translated, OP_SOURCE_LOCATION);
push_instruction_code(translated, call->line);
push_instruction_code(translated, call->column);
push_instruction_code(translated, 1);
push_instruction_byte(translated, OP_CALL); push_instruction_byte(translated, OP_CALL);
push_instruction_byte(translated, 0);
SourceLocation source_locations = {
call->line,
call->column,
1
};
push_instruction_code(translated, translated->source_locations.size);
darray_push(&translated->source_locations, &source_locations);
return first; return first;
} }

View File

@@ -28,15 +28,16 @@ size_t translate_parsed_declaration(Translated *translated,
size_t offset = size_t offset =
arena_push(&translated->constants, singleDeclaration->name, length); arena_push(&translated->constants, singleDeclaration->name, length);
push_instruction_byte(translated, OP_SOURCE_LOCATION);
push_instruction_code(translated, singleDeclaration->line);
push_instruction_code(translated, singleDeclaration->column);
push_instruction_code(translated, length);
push_instruction_byte(translated, OP_DECLARE); push_instruction_byte(translated, OP_DECLARE);
push_instruction_code(translated, length); push_instruction_code(translated, length);
push_instruction_code(translated, offset); push_instruction_code(translated, offset);
push_instruction_code(translated, siphash64_bytes(singleDeclaration->name, length, siphash_key_fixed_for_translator)); push_instruction_code(translated, siphash64_bytes(singleDeclaration->name, length, siphash_key_fixed_for_translator));
push_instruction_byte(translated, 0); push_instruction_byte(translated, 0);
SourceLocation source_locations = {singleDeclaration->line,
singleDeclaration->column, length};
push_instruction_code(translated, translated->source_locations.size);
darray_push(&translated->source_locations, &source_locations);
translated->return_jumps = old_return_jumps; translated->return_jumps = old_return_jumps;
} }
return first; return first;

View File

@@ -13,9 +13,9 @@
#include <string.h> #include <string.h>
size_t translate_parsed_function(Translated *translated, size_t translate_parsed_function(Translated *translated,
ParsedFunction *parsedFunction, ArErr *err) { ParsedFunction *parsedFunction, ArErr *err) {
DArray main_bytecode = translated->bytecode; darray_armem main_bytecode = translated->bytecode;
DArray _temp_bytecode; darray_armem _temp_bytecode;
darray_init(&_temp_bytecode, sizeof(uint8_t)); darray_armem_init(&_temp_bytecode, sizeof(uint8_t));
set_registers(translated, 1); set_registers(translated, 1);
translated->bytecode = _temp_bytecode; translated->bytecode = _temp_bytecode;
translate_parsed(translated, parsedFunction->body, err); translate_parsed(translated, parsedFunction->body, err);
@@ -23,7 +23,6 @@ size_t translate_parsed_function(Translated *translated,
arena_push(&translated->constants, translated->bytecode.data, arena_push(&translated->constants, translated->bytecode.data,
translated->bytecode.size*translated->bytecode.element_size); translated->bytecode.size*translated->bytecode.element_size);
size_t function_bytecode_length = translated->bytecode.size; size_t function_bytecode_length = translated->bytecode.size;
darray_free(&translated->bytecode, NULL);
translated->bytecode = main_bytecode; translated->bytecode = main_bytecode;
size_t start = push_instruction_byte(translated, OP_LOAD_FUNCTION); size_t start = push_instruction_byte(translated, OP_LOAD_FUNCTION);
size_t offset = arena_push(&translated->constants, parsedFunction->name, size_t offset = arena_push(&translated->constants, parsedFunction->name,

View File

@@ -4,27 +4,30 @@
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
*/ */
#include "../translator.h"
#include "identifier.h" #include "identifier.h"
#include "../../hash_data/hash_data.h"
#include "../translator.h"
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "../../hash_data/hash_data.h"
size_t translate_parsed_identifier(Translated *translated, ParsedIdentifier *parsedIdentifier) { size_t translate_parsed_identifier(Translated *translated,
ParsedIdentifier *parsedIdentifier) {
size_t length = strlen(parsedIdentifier->name); size_t length = strlen(parsedIdentifier->name);
size_t identifier_pos = arena_push(&translated->constants, parsedIdentifier->name, length); size_t identifier_pos =
arena_push(&translated->constants, parsedIdentifier->name, length);
set_registers(translated, 1); set_registers(translated, 1);
size_t start = push_instruction_byte(translated, OP_IDENTIFIER);
push_instruction_code(translated,length); size_t start = push_instruction_byte(translated, OP_SOURCE_LOCATION);
push_instruction_code(translated, parsedIdentifier->line);
push_instruction_code(translated, parsedIdentifier->column);
push_instruction_code(translated, length);
push_instruction_byte(translated, OP_IDENTIFIER);
push_instruction_code(translated, length);
push_instruction_code(translated, identifier_pos); push_instruction_code(translated, identifier_pos);
push_instruction_code(translated, siphash64_bytes(parsedIdentifier->name, length, siphash_key_fixed_for_translator)); push_instruction_code(translated,
SourceLocation source_locations = { siphash64_bytes(parsedIdentifier->name, length,
parsedIdentifier->line, siphash_key_fixed_for_translator));
parsedIdentifier->column,
length
};
push_instruction_code(translated, translated->source_locations.size);
darray_push(&translated->source_locations, &source_locations);
return start; return start;
} }

View File

@@ -6,7 +6,6 @@
#include "translator.h" #include "translator.h"
#include "../hash_data/hash_data.h" #include "../hash_data/hash_data.h"
#include "../hashmap/hashmap.h"
#include "declaration/declaration.h" #include "declaration/declaration.h"
#include "call/call.h" #include "call/call.h"
#include "dowrap/dowrap.h" #include "dowrap/dowrap.h"
@@ -29,10 +28,10 @@ void uint64_to_bytes(uint64_t value, uint8_t bytes[8]) {
} }
void arena_init(ConstantArena *arena) { void arena_init(ConstantArena *arena) {
arena->data = checked_malloc(CHUNK_SIZE); arena->data = ar_alloc(CHUNK_SIZE);
arena->capacity = CHUNK_SIZE; arena->capacity = CHUNK_SIZE;
arena->size = 0; arena->size = 0;
arena->hashmap = createHashmap(); arena->hashmap = createHashmap_GC();
} }
void arena_resize(ConstantArena *arena, size_t new_size) { void arena_resize(ConstantArena *arena, size_t new_size) {
@@ -48,13 +47,6 @@ void arena_resize(ConstantArena *arena, size_t new_size) {
arena->capacity = new_capacity; arena->capacity = new_capacity;
} }
void arena_free(ConstantArena *arena) {
free(arena->data);
arena->capacity = 0;
arena->size = 0;
hashmap_free(arena->hashmap, NULL);
}
void *arena_get(ConstantArena *arena, size_t offset) { void *arena_get(ConstantArena *arena, size_t offset) {
return arena->data + offset; return arena->data + offset;
} }
@@ -63,7 +55,7 @@ size_t arena_push(ConstantArena *arena, const void *data, size_t length) {
uint64_t hash = siphash64_bytes(data, length, siphash_key); uint64_t hash = siphash64_bytes(data, length, siphash_key);
// Look up offset in hashmap // Look up offset in hashmap
void *val = hashmap_lookup(arena->hashmap, hash); void *val = hashmap_lookup_GC(arena->hashmap, hash);
if (val != NULL) { if (val != NULL) {
size_t offset = size_t offset =
(size_t)(uintptr_t)val - 1; // stored as pointer but really offset (size_t)(uintptr_t)val - 1; // stored as pointer but really offset
@@ -80,7 +72,7 @@ size_t arena_push(ConstantArena *arena, const void *data, size_t length) {
arena->size += length; arena->size += length;
// Insert into hashmap: store offset as pointer-sized integer // Insert into hashmap: store offset as pointer-sized integer
hashmap_insert(arena->hashmap, hash, (void *)data, hashmap_insert_GC(arena->hashmap, hash, (void *)data,
(void *)(uintptr_t)offset + 1, 0); (void *)(uintptr_t)offset + 1, 0);
return offset; return offset;
@@ -91,15 +83,14 @@ Translated init_translator(char* path) {
translated.path = path; translated.path = path;
translated.registerCount = 1; translated.registerCount = 1;
translated.return_jumps=NULL; translated.return_jumps=NULL;
darray_init(&translated.bytecode, sizeof(uint8_t)); darray_armem_init(&translated.bytecode, sizeof(uint8_t));
darray_init(&translated.source_locations, sizeof(SourceLocation));
arena_init(&translated.constants); arena_init(&translated.constants);
return translated; return translated;
} }
size_t push_instruction_byte(Translated *translator, uint8_t byte) { size_t push_instruction_byte(Translated *translator, uint8_t byte) {
size_t offset = translator->bytecode.size; size_t offset = translator->bytecode.size;
darray_push(&translator->bytecode, &byte); darray_armem_push(&translator->bytecode, &byte);
return offset; return offset;
} }
@@ -112,7 +103,7 @@ size_t push_instruction_code(Translated *translator, uint64_t code) {
uint8_t bytes[8]; uint8_t bytes[8];
uint64_to_bytes(code, bytes); uint64_to_bytes(code, bytes);
for (size_t i = 0; i < sizeof(bytes); i++) { for (size_t i = 0; i < sizeof(bytes); i++) {
darray_push(&translator->bytecode, &(bytes[i])); darray_armem_push(&translator->bytecode, &(bytes[i]));
} }
return offset; return offset;
} }
@@ -170,9 +161,3 @@ ArErr translate(Translated *translated, DArray *ast) {
} }
return err; return err;
} }
void free_translator(Translated *translated) {
darray_free(&translated->bytecode, NULL);
darray_free(&translated->source_locations, NULL);
arena_free(&translated->constants);
}

View File

@@ -14,31 +14,9 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
typedef enum { OP_LOAD_CONST, OP_DECLARE, OP_LOAD_NULL, OP_LOAD_FUNCTION, OP_IDENTIFIER, OP_BOOL, OP_JUMP_IF_FALSE, OP_JUMP, OP_NEW_SCOPE, OP_POP_SCOPE, OP_INIT_ARGS, OP_INSERT_ARG, OP_RESET_ARGS, OP_CALL } OperationType; typedef enum { OP_LOAD_CONST, OP_DECLARE, OP_LOAD_NULL, OP_LOAD_FUNCTION, OP_IDENTIFIER, OP_BOOL, OP_JUMP_IF_FALSE, OP_JUMP, OP_NEW_SCOPE, OP_POP_SCOPE, OP_INIT_CALL, OP_INSERT_ARG, OP_CALL, OP_SOURCE_LOCATION } OperationType;
typedef enum { TYPE_OP_STRING, TYPE_OP_NUMBER } types; typedef enum { TYPE_OP_STRING, TYPE_OP_NUMBER } types;
typedef struct {
void *data;
size_t capacity;
size_t size;
struct hashmap * hashmap;
} ConstantArena;
typedef struct {
uint8_t registerCount;
DArray *return_jumps;
DArray bytecode;
DArray source_locations;
ConstantArena constants;
char* path;
} Translated;
typedef struct {
uint64_t line;
uint64_t column;
uint64_t length;
} SourceLocation;
void arena_resize(ConstantArena *arena, size_t new_size); void arena_resize(ConstantArena *arena, size_t new_size);
void *arena_get(ConstantArena *arena, size_t offset); void *arena_get(ConstantArena *arena, size_t offset);
@@ -61,6 +39,4 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue, ArErr*
ArErr translate(Translated *translated, DArray *ast); ArErr translate(Translated *translated, DArray *ast);
void free_translator(Translated *translated);
#endif #endif

View File

@@ -1,5 +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
let x(hello, x, y) = "hello world" type()
x(10,10,10)