From 5b0950cabbaa791b55daf4e2fac30877ba387da8 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 26 Apr 2025 11:04:21 -0400 Subject: [PATCH] Finished linked env scope on user functions. Doesn't work for builtin functions yet, so doesn't compile. TODO. --- src/ast.c | 10 ++++++ src/exec.c | 83 ++++++++++++++++++--------------------------- src/include/ast.h | 4 ++- src/include/exec.h | 16 ++++----- src/include/scope.h | 6 ++-- src/scope.c | 8 +++-- 6 files changed, 64 insertions(+), 63 deletions(-) diff --git a/src/ast.c b/src/ast.c index 32f78de..d8c0fb7 100644 --- a/src/ast.c +++ b/src/ast.c @@ -276,3 +276,13 @@ void ast_arg_print(ASTArgData* arg, int i) { INDENT_FIELD("name", "%s", arg->name); INDENT_END; } + +AST* ast_find(Scope* scope, char* name) { + while (scope) { + AST* gotten = htab_get(scope->here, name); + if (gotten) return gotten; + else scope = scope->inherit; + } + + return NULL; +} diff --git a/src/exec.c b/src/exec.c index 276c662..4b1934b 100644 --- a/src/exec.c +++ b/src/exec.c @@ -6,66 +6,58 @@ #include "include/builtin.h" #include "include/exec.h" #include "include/htab.h" -#include "include/stack.h" +#include "include/scope.h" #include "include/util.h" -AST* exec_find(char* name); - AST* exec_start(AST* ast) { log_dbg("Started execution."); - Stack* scope = stack_init(); - - HTab* global = htab_init(); + Scope* builtin = scope_init(NULL); for (int i = 0; i < BUILTIN_FNS_LN; i++) htab_ins( - global, BUILTIN_FNS[i].name, + builtin->here, BUILTIN_FNS[i].name, ast_init(AST_TYPE_BIF, ast_bif_data_init(BUILTIN_FNS[i].fn)) ); - // Push global namespace to `scope`. - stack_push(scope, global); - - return exec_exp(ast); + return exec_exp(ast, builtin); } -AST* exec_exp(AST* ast) { +AST* exec_exp(AST* ast, Scope* parent) { switch (ast->type) { - case AST_TYPE_BLOCK: return exec_block(ast); - case AST_TYPE_CALL: return exec_call(ast); + case AST_TYPE_BLOCK: return exec_block(ast, parent); + case AST_TYPE_CALL: return exec_call(ast, parent); case AST_TYPE_NUM: return ast; - case AST_TYPE_VREF: return exec_vref(ast); - case AST_TYPE_VDEF: return exec_vdef(ast); - case AST_TYPE_FDEF: return exec_fdef(ast); + case AST_TYPE_VREF: return exec_vref(ast, parent); + case AST_TYPE_VDEF: return exec_vdef(ast, parent); + case AST_TYPE_FDEF: return exec_fdef(ast, parent); default: printf("what\n"); exit(1); } } -AST* exec_block(AST* ast) { +AST* exec_block(AST* ast, Scope* parent) { ASTBlockData* block = (ASTBlockData*)ast->data; - HTab* local = htab_init(); - // stack_push(scope, local); + ast->scope = scope_init(parent); // Loop through all but last ast. - for (int i = 0; i < block->ln - 1; i++) exec_exp(block->inside[i]); - AST* last = exec_exp(block->inside[block->ln - 1]); - - // stack_pop(scope); - htab_destroy(local); + for (int i = 0; i < block->ln - 1; i++) + exec_exp(block->inside[i], ast->scope); + AST* last = exec_exp(block->inside[block->ln - 1], ast->scope); return last; } -AST* exec_call(AST* ast) { +AST* exec_call(AST* ast, Scope* parent) { log_dbg("Started call execution."); ASTCallData* data = (ASTCallData*)ast->data; size_t argc = data->argc; AST** argv = data->argv; char* fname = data->to; - AST* fdef = exec_find(fname); + ast->scope = parent; + + AST* fdef = ast_find(ast->scope, fname); if (fdef == NULL) return ast_init( @@ -83,42 +75,32 @@ AST* exec_call(AST* ast) { } AST* exec_cf(AST* ast, size_t argc, AST** argv) { + Scope* callscope = scope_init(ast->scope); ASTFDefData* fdef = (ASTFDefData*)ast->data; for (int i = 0; i < argc; i++) { char* key = ((ASTArgData*)fdef->argv[i]->data)->name; AST* val = argv[i]; - // htab_ins(scope->buf[scope->ln - 1], key, val); + scope_add(callscope, key, val); } - return exec_exp(fdef->body); + return exec_exp(fdef->body, callscope); } -AST* exec_find(char* name) { - AST* val = NULL; - - /* - for (int i = scope->ln - 1; i >= 0; i--) { - HTab* lvl = scope->buf[i]; - val = htab_get(lvl, name); - if (val != NULL) return val; - }*/ - - return NULL; -} - -AST* exec_vdef(AST* ast) { +AST* exec_vdef(AST* ast, Scope* parent) { + ast->scope = scope_init(parent); ASTVDefData* data = (ASTVDefData*)ast->data; AST* val = data->val; char* key = data->name; - // htab_ins(scope->buf[scope->ln - 1], key, val); - return exec_exp(val); + scope_add(parent, key, val); + return exec_exp(val, ast->scope); } -AST* exec_vref(AST* ast) { +AST* exec_vref(AST* ast, Scope* parent) { + ast->scope = parent; log_dbg("attempting to reference var"); ASTVrefData* vref = (ASTVrefData*)ast->data; - AST* found = exec_find(vref->to); + AST* found = ast_find(parent, vref->to); if (found == NULL) { // TODO: Better memory management here. @@ -130,14 +112,15 @@ AST* exec_vref(AST* ast) { return ast_init(AST_TYPE_EXC, ast_exc_data_init(msg, NULL)); } - return exec_exp(found); + return exec_exp(found, ast->scope); } -AST* exec_fdef(AST* ast) { +AST* exec_fdef(AST* ast, Scope* parent) { + ast->scope = scope_init(parent); ASTFDefData* fdef = (ASTFDefData*)ast->data; AST* val = fdef->body; char* key = fdef->name; - // htab_ins(scope->buf[scope->ln - 1], key, val); + scope_add(parent, key, val); return val; // Function definitions return function body. } diff --git a/src/include/ast.h b/src/include/ast.h index e384673..366e6a3 100644 --- a/src/include/ast.h +++ b/src/include/ast.h @@ -1,7 +1,6 @@ #ifndef AST_H #define AST_H -#include "htab.h" #include "scope.h" #include @@ -154,4 +153,7 @@ void ast_arg_data_destroy(ASTArgData* arg); // Print an `ASTArgData`. void ast_arg_print(ASTArgData* arg, int i); +// Find a name in the scope. +AST* ast_find(Scope* scope, char* name); + #endif diff --git a/src/include/exec.h b/src/include/exec.h index 72476e0..abfd6df 100644 --- a/src/include/exec.h +++ b/src/include/exec.h @@ -2,24 +2,24 @@ #define EXEC_H #include "ast.h" -#include "stack.h" +#include "scope.h" // Start executing at the root of the AST. Initialize the `scope`. AST* exec_start(AST* ast); // Execute an expression. Delegates to the other executor functions. -AST* exec_exp(AST* ast); +AST* exec_exp(AST* ast, Scope* parent); // Execute the expressions of a block. -AST* exec_block(AST* ast); +AST* exec_block(AST* ast, Scope* parent); // Execute a call. -AST* exec_call(AST* ast); +AST* exec_call(AST* ast, Scope* parent); // Execute a custom function call. AST* exec_cf(AST* ast, size_t argc, AST** argv); -// Execute a variable reference. -AST* exec_vref(AST* ast); // Execute a variable definition. -AST* exec_vdef(AST* ast); +AST* exec_vdef(AST* ast, Scope* parent); +// Execute a variable reference. +AST* exec_vref(AST* ast, Scope* parent); // Execute a function definition. -AST* exec_fdef(AST* ast); +AST* exec_fdef(AST* ast, Scope* parent); // Print the result of an execution. void exec_print(double n); diff --git a/src/include/scope.h b/src/include/scope.h index 3531584..467735e 100644 --- a/src/include/scope.h +++ b/src/include/scope.h @@ -9,11 +9,13 @@ typedef struct SCOPE_T { struct SCOPE_T* inherit; } Scope; -// Create a new `Scope`. -Scope* scope_init(HTab* here, Scope* inherit); +// Create a new `Scope`. Creates new empty `HTab` for current scope. +Scope* scope_init(Scope* inherit); // Destroy all linked `Scope`s this inherits from. void scope_destroy(Scope* scope); // Destroy the current `Scope` only. void scope_destroy_psv(Scope *scope); +// Insert a key/val pair into the `HTab` of a `Scope`. +inline void scope_add(Scope* scope, char* key, void* val); #endif diff --git a/src/scope.c b/src/scope.c index 30ed71c..a433bd2 100644 --- a/src/scope.c +++ b/src/scope.c @@ -2,10 +2,10 @@ #include "include/htab.h" #include -Scope* scope_init(HTab* here, Scope* inherit) { +Scope* scope_init(Scope* inherit) { Scope* scope = malloc(sizeof(Scope)); - scope->here = here; + scope->here = htab_init(); scope->inherit = inherit; return scope; @@ -22,3 +22,7 @@ void scope_destroy_psv(Scope* scope) { scope->inherit = NULL; free(scope); } + +inline void scope_add(Scope* scope, char* key, void* val) { + htab_ins(scope->here, key, val); +}