add function calling
This commit is contained in:
4
app.py
Normal file
4
app.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
def factorial(x):
|
||||||
|
if x==1: return 1
|
||||||
|
return factorial(x-1) + x
|
||||||
|
factorial(10000)
|
||||||
@@ -36,9 +36,12 @@ typedef struct Stack {
|
|||||||
struct argon_function_struct {
|
struct argon_function_struct {
|
||||||
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;
|
||||||
|
uint64_t line;
|
||||||
|
uint64_t column;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index,
|
|||||||
ParsedValue *to_call) {
|
ParsedValue *to_call) {
|
||||||
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
|
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
|
||||||
ParsedCall *call = checked_malloc(sizeof(ParsedCall));
|
ParsedCall *call = checked_malloc(sizeof(ParsedCall));
|
||||||
|
Token *token = darray_get(tokens, *index);
|
||||||
|
call->line = token->line;
|
||||||
|
call->column = token->column;
|
||||||
call->to_call = to_call;
|
call->to_call = to_call;
|
||||||
parsedValue->data = call;
|
parsedValue->data = call;
|
||||||
parsedValue->type = AST_CALL;
|
parsedValue->type = AST_CALL;
|
||||||
@@ -29,7 +32,7 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index,
|
|||||||
free(parsedValue);
|
free(parsedValue);
|
||||||
return (ParsedValueReturn){err, NULL};
|
return (ParsedValueReturn){err, NULL};
|
||||||
}
|
}
|
||||||
Token *token = darray_get(tokens, *index);
|
token = darray_get(tokens, *index);
|
||||||
if (token->type != TOKEN_RPAREN) {
|
if (token->type != TOKEN_RPAREN) {
|
||||||
while ((*index) < tokens->size) {
|
while ((*index) < tokens->size) {
|
||||||
skip_newlines_and_indents(tokens, index);
|
skip_newlines_and_indents(tokens, index);
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
ParsedValue * to_call;
|
ParsedValue * to_call;
|
||||||
DArray args;
|
DArray args;
|
||||||
|
uint64_t line;
|
||||||
|
uint64_t column;
|
||||||
} ParsedCall;
|
} ParsedCall;
|
||||||
|
|
||||||
// Function declaration for parsing an identifier
|
// Function declaration for parsing an identifier
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 William Bell
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "call.h"
|
||||||
|
#include "../../hash_data/hash_data.h"
|
||||||
|
#include "../objects/string/string.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <psapi.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
double get_memory_usage_mb() {
|
||||||
|
PROCESS_MEMORY_COUNTERS pmc;
|
||||||
|
if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
|
||||||
|
return pmc.WorkingSetSize / (1024.0 * 1024.0); // in MB
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include <mach/mach.h>
|
||||||
|
|
||||||
|
double get_memory_usage_mb() {
|
||||||
|
struct task_basic_info info;
|
||||||
|
mach_msg_type_number_t size = TASK_BASIC_INFO_COUNT;
|
||||||
|
if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size) ==
|
||||||
|
KERN_SUCCESS) {
|
||||||
|
return info.resident_size / (1024.0 * 1024.0); // in MB
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__linux__)
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
double get_memory_usage_mb() {
|
||||||
|
FILE *fp = fopen("/proc/self/status", "r");
|
||||||
|
if (!fp)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
char line[256];
|
||||||
|
size_t memory_kb = 0;
|
||||||
|
|
||||||
|
while (fgets(line, sizeof(line), fp)) {
|
||||||
|
if (strncmp(line, "VmRSS:", 6) == 0) {
|
||||||
|
sscanf(line + 6, "%zu", &memory_kb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return memory_kb / 1024.0; // Convert KB to MB
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
double get_memory_usage_mb() {
|
||||||
|
// Unsupported platform
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void 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) {
|
||||||
|
Stack *scope = create_scope(object->value.argon_fn.stack);
|
||||||
|
for (size_t i = 0; i < state->call_args_length; i++) {
|
||||||
|
struct string_struct key = object->value.argon_fn.parameters[i];
|
||||||
|
ArgonObject *value = state->call_args[i];
|
||||||
|
uint64_t hash = siphash64_bytes(key.data, key.length, siphash_key);
|
||||||
|
hashmap_insert_GC(scope->scope, hash,
|
||||||
|
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 = {
|
||||||
|
(Translated){translated->registerCount, NULL, bytecode_darray,
|
||||||
|
translated->source_locations, translated->constants,
|
||||||
|
object->value.argon_fn.path},
|
||||||
|
(RuntimeState){state->registers, 0, state->path,
|
||||||
|
state->currentStackFramePointer, state->call_args,
|
||||||
|
state->call_args_length},
|
||||||
|
scope,
|
||||||
|
*state->currentStackFramePointer,
|
||||||
|
no_err,
|
||||||
|
(*state->currentStackFramePointer)->depth + 1};
|
||||||
|
if ((*state->currentStackFramePointer)->depth >= 10000) {
|
||||||
|
double logval = log10((double)(*state->currentStackFramePointer)->depth);
|
||||||
|
if (floor(logval) == logval) {
|
||||||
|
SourceLocation *source_location =
|
||||||
|
darray_get(&translated->source_locations, source_location_index);
|
||||||
|
fprintf(stderr,
|
||||||
|
"Warning: %s:%zu:%zu the call stack depth has exceeded %zu\n",
|
||||||
|
state->path, source_location->line, source_location->column,
|
||||||
|
(*state->currentStackFramePointer)->depth);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
*state->currentStackFramePointer = checked_malloc(sizeof(StackFrame));
|
||||||
|
**state->currentStackFramePointer = new_stackFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 William Bell
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef runtime_call_H
|
||||||
|
#define runtime_call_H
|
||||||
|
#include "../runtime.h"
|
||||||
|
|
||||||
|
void run_call(Translated *translated, RuntimeState *state);
|
||||||
|
|
||||||
|
#endif // runtime_call_H
|
||||||
@@ -22,6 +22,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.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));
|
||||||
@@ -35,6 +36,6 @@ void load_argon_function(Translated *translated, RuntimeState *state,
|
|||||||
length = pop_bytecode(translated, state);
|
length = pop_bytecode(translated, state);
|
||||||
object->value.argon_fn.bytecode = arena_get(&translated->constants, offset);
|
object->value.argon_fn.bytecode = arena_get(&translated->constants, offset);
|
||||||
object->value.argon_fn.bytecode_length = length;
|
object->value.argon_fn.bytecode_length = length;
|
||||||
object->value.argon_fn.stack = *stack;
|
object->value.argon_fn.stack = stack;
|
||||||
state->registers[0]=object;
|
state->registers[0]=object;
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "../hash_data/hash_data.h"
|
#include "../hash_data/hash_data.h"
|
||||||
#include "../translator/translator.h"
|
#include "../translator/translator.h"
|
||||||
#include "declaration/declaration.h"
|
#include "declaration/declaration.h"
|
||||||
|
#include "call/call.h"
|
||||||
#include "internals/hashmap/hashmap.h"
|
#include "internals/hashmap/hashmap.h"
|
||||||
#include "objects/functions/functions.h"
|
#include "objects/functions/functions.h"
|
||||||
#include "objects/literals/literals.h"
|
#include "objects/literals/literals.h"
|
||||||
@@ -212,26 +213,27 @@ ArErr run_instruction(Translated *translated, RuntimeState *state,
|
|||||||
state->call_args[pop_bytecode(translated, state)] =
|
state->call_args[pop_bytecode(translated, state)] =
|
||||||
state->registers[to_register];
|
state->registers[to_register];
|
||||||
break;
|
break;
|
||||||
case OP_RESET_ARGS:;
|
|
||||||
free(state->call_args);
|
|
||||||
state->call_args = NULL;
|
|
||||||
break;
|
|
||||||
case OP_CALL:
|
case OP_CALL:
|
||||||
from_register = pop_byte(translated, state);
|
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);
|
||||||
ArgonObject *class = hashmap_lookup_GC(object->dict, hash);
|
// ArgonObject *class = hashmap_lookup_GC(object->dict, hash);
|
||||||
field = "__name__";
|
// field = "__name__";
|
||||||
hash = siphash64_bytes(field, strlen(field), siphash_key);
|
// hash = siphash64_bytes(field, strlen(field), siphash_key);
|
||||||
ArgonObject *class_name = hashmap_lookup_GC(class->dict, hash);
|
// ArgonObject *class_name = hashmap_lookup_GC(class->dict, hash);
|
||||||
hash = siphash64_bytes(field, strlen(field), siphash_key);
|
// hash = siphash64_bytes(field, strlen(field), siphash_key);
|
||||||
ArgonObject *object_name = hashmap_lookup_GC(object->dict, hash);
|
// ArgonObject *object_name = hashmap_lookup_GC(object->dict, hash);
|
||||||
if (object_name) {
|
// if (object_name) {
|
||||||
printf("call <%.*s %.*s at %p>\n", (int)class_name->value.as_str.length, class_name->value.as_str.data,(int)object_name->value.as_str.length, object_name->value.as_str.data, object);
|
// printf("call <%.*s %.*s at %p>\n",
|
||||||
} else {
|
// (int)class_name->value.as_str.length,
|
||||||
printf("call <%.*s object at %p>\n", (int)class_name->value.as_str.length, class_name->value.as_str.data, object);
|
// class_name->value.as_str.data,(int)object_name->value.as_str.length,
|
||||||
}
|
// object_name->value.as_str.data, object);
|
||||||
|
// } else {
|
||||||
|
// printf("call <%.*s object at %p>\n",
|
||||||
|
// (int)class_name->value.as_str.length, class_name->value.as_str.data,
|
||||||
|
// object);
|
||||||
|
// }
|
||||||
break;
|
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",
|
||||||
@@ -245,10 +247,9 @@ RuntimeState init_runtime_state(Translated translated, char *path) {
|
|||||||
checked_malloc(translated.registerCount * sizeof(ArgonObject *)),
|
checked_malloc(translated.registerCount * sizeof(ArgonObject *)),
|
||||||
0,
|
0,
|
||||||
path,
|
path,
|
||||||
ARGON_NULL,
|
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL};
|
0};
|
||||||
return runtime;
|
return runtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,9 +268,10 @@ 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;
|
||||||
|
|
||||||
StackFrame *currentStackFrame = checked_malloc(sizeof(StackFrame));
|
StackFrame *currentStackFrame = checked_malloc(sizeof(StackFrame));
|
||||||
*currentStackFrame = (StackFrame){translated, state, stack, NULL, no_err};
|
*currentStackFrame = (StackFrame){translated, state, stack, NULL, no_err};
|
||||||
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 <
|
||||||
@@ -282,9 +284,8 @@ ArErr runtime(Translated translated, RuntimeState state, Stack *stack) {
|
|||||||
StackFrame *tempStackFrame = currentStackFrame;
|
StackFrame *tempStackFrame = currentStackFrame;
|
||||||
err = currentStackFrame->err;
|
err = currentStackFrame->err;
|
||||||
currentStackFrame = currentStackFrame->previousStackFrame;
|
currentStackFrame = currentStackFrame->previousStackFrame;
|
||||||
if (currentStackFrame)
|
|
||||||
free_runtime_state(tempStackFrame->state);
|
|
||||||
free(tempStackFrame);
|
free(tempStackFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -14,17 +14,13 @@
|
|||||||
typedef struct StackFrame StackFrame;
|
typedef struct StackFrame StackFrame;
|
||||||
typedef struct RuntimeState RuntimeState;
|
typedef struct RuntimeState RuntimeState;
|
||||||
|
|
||||||
typedef ArErr (*error_result)(ArErr, Translated *translated,
|
|
||||||
RuntimeState *state, struct Stack **stack);
|
|
||||||
|
|
||||||
typedef struct RuntimeState {
|
typedef struct RuntimeState {
|
||||||
ArgonObject **registers;
|
ArgonObject **registers;
|
||||||
size_t head;
|
size_t head;
|
||||||
char *path;
|
char *path;
|
||||||
ArgonObject *return_value;
|
|
||||||
StackFrame **currentStackFramePointer;
|
StackFrame **currentStackFramePointer;
|
||||||
error_result result;
|
|
||||||
ArgonObject** call_args;
|
ArgonObject** call_args;
|
||||||
|
size_t call_args_length;
|
||||||
} RuntimeState;
|
} RuntimeState;
|
||||||
|
|
||||||
typedef struct StackFrame {
|
typedef struct StackFrame {
|
||||||
@@ -33,6 +29,7 @@ typedef struct StackFrame {
|
|||||||
Stack *stack;
|
Stack *stack;
|
||||||
StackFrame *previousStackFrame;
|
StackFrame *previousStackFrame;
|
||||||
ArErr err;
|
ArErr err;
|
||||||
|
uint64_t depth;
|
||||||
} StackFrame;
|
} StackFrame;
|
||||||
|
|
||||||
void bootstrap_types();
|
void bootstrap_types();
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ resets the arguments buffer to NULL
|
|||||||
call a function with args
|
call a function with args
|
||||||
|
|
||||||
1. the register containing the function to call. (*)
|
1. the register containing the function to call. (*)
|
||||||
|
4. the index of the source location.
|
||||||
|
|
||||||
## OP_SWAP_REGISTERS
|
## OP_SWAP_REGISTERS
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ size_t translate_parsed_call(Translated *translated, ParsedCall* call, ArErr *er
|
|||||||
return first;
|
return first;
|
||||||
push_instruction_byte(translated, OP_CALL);
|
push_instruction_byte(translated, OP_CALL);
|
||||||
push_instruction_byte(translated, 0);
|
push_instruction_byte(translated, 0);
|
||||||
push_instruction_byte(translated, OP_RESET_ARGS);
|
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;
|
||||||
}
|
}
|
||||||
1092503
testing.ar
1092503
testing.ar
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user