diff --git a/functions.c b/functions.c index 37252d7..5efd088 100644 --- a/functions.c +++ b/functions.c @@ -5,6 +5,7 @@ #include "lang.h" #include "main.h" +#include "util.h" void lenv_add_builtin(lenv* env, char* sym, lbuiltin func) { lval* symval = lval_sym(sym); @@ -392,10 +393,38 @@ lval* builtin_lambda(lenv* env, lval* val) { return lambda; } lval* builtin_load(lenv* env, lval* val) { - LASSERT_ARG_COUNT("load", val, val, 1); + LASSERT_MIN_ARG_COUNT("load", val, val, 1); LASSERT_TYPE("load", val, val->cell_list[0], LVAL_STR); - char* filename = val->cell_list[0]->data.str; + lval* fileval = NULL; + lval* option = NULL; + + if (val->cell_count == 1) { + fileval = val->cell_list[0]; + } else if (val->cell_count > 1) { + LASSERT_TYPE("load", val, val->cell_list[1], LVAL_STR); + option = val->cell_list[0]; + fileval = val->cell_list[1]; + } + + lenv* rootenv = lenv_get_root(env); + + char* filename = fileval->data.str; + + BOOL file_loaded = FALSE; + for(int i =0 ; i < rootenv->loaded_files_count; i++) { + if (strcmp(filename, rootenv->loaded_files[i]) == 0) { + file_loaded = TRUE; + break; + } + } + + if (option != NULL && strcmp(option->data.str, "once") == 0) { + if (file_loaded == TRUE) { + lval_delete(val); + return lval_s_expr(); + } + } mpc_result_t result; if (mpc_parse_contents(filename, gLispy, &result)) { @@ -412,19 +441,21 @@ lval* builtin_load(lenv* env, lval* val) { lval_delete(x); } + if (file_loaded == FALSE) { + rootenv->loaded_files = realloc(rootenv->loaded_files, sizeof(char*) * rootenv->loaded_files_count+1); + rootenv->loaded_files[rootenv->loaded_files_count] = strdup(filename); + rootenv->loaded_files_count++; + } + lval_delete(resultLval); lval_delete(val); - + return lval_s_expr(); } else { //Parse error char* errorMessage = mpc_err_string(result.error); mpc_err_delete(result.error); - char cwd[1024]; - getcwd(cwd, sizeof(cwd)-1); - printf("dir: %s\n", cwd); - lval* err = lval_err_detail(LERR_OTHER,"Load: %s", errorMessage); free(errorMessage); lval_delete(val); diff --git a/lenv.c b/lenv.c index 73c0af2..6e25ded 100644 --- a/lenv.c +++ b/lenv.c @@ -8,15 +8,24 @@ lenv* lenv_new() { env->count = 0; env->parent = NULL; env->syms = NULL; + env->loaded_files_count = 0; + env->loaded_files = NULL; return env; } void lenv_delete(lenv* env) { for(int i = 0; i < env->count; i++) { - lval_delete(env->syms[i]->lval); - free(env->syms[i]->sym); - free(env->syms[i]); + symtab_delete(env->syms[i]); } - free(env->syms); + for(int i = 0; i < env->loaded_files_count; i++) { + free(env->loaded_files[i]); + } + if (env->loaded_files_count > 0) { + free(env->loaded_files); + } + if (env->syms != NULL) { + free(env->syms); + } + env->parent = NULL; free(env); } lenv* lenv_copy(lenv* env) { @@ -59,6 +68,13 @@ symtab* lenv_search(lenv* env, char* sym) { } return *result; } +lenv* lenv_get_root(lenv* env) { + if (env->parent == NULL) { + return env; + } else { + return lenv_get_root(env->parent); + } +} lval* lenv_get(lenv* env, lval* sym) { LASSERT(sym, sym->type == LVAL_SYM, LERR_BAD_OP, "Expected symbol"); diff --git a/lenv.h b/lenv.h index 2b91cc5..b1624bc 100644 --- a/lenv.h +++ b/lenv.h @@ -26,6 +26,8 @@ extern "C" { struct lenv { size_t count; struct lenv* parent; + char** loaded_files; + size_t loaded_files_count; struct symtab** syms; }; @@ -36,6 +38,7 @@ extern "C" { int lenv_compare_symtabs(const void *a, const void *b); void lenv_sort(lenv* env); symtab* lenv_search(lenv* env, char* sym); + lenv* lenv_get_root(lenv* env); lval* lenv_get(lenv* env, lval* sym); void lenv_put(lenv* env, lval* key, lval* val);