summaryrefslogtreecommitdiff
path: root/pit/src/native.c
diff options
context:
space:
mode:
Diffstat (limited to 'pit/src/native.c')
-rw-r--r--pit/src/native.c60
1 files changed, 53 insertions, 7 deletions
diff --git a/pit/src/native.c b/pit/src/native.c
index d0989a5..4dab09d 100644
--- a/pit/src/native.c
+++ b/pit/src/native.c
@@ -2,6 +2,8 @@
#include <stdio.h>
#include <string.h>
+#include <sys/stat.h>
+
#include <lcq/pit/lexer.h>
#include <lcq/pit/parser.h>
#include <lcq/pit/runtime.h>
@@ -101,7 +103,7 @@ pit_value pit_value_bytes_new_file(pit_runtime *rt, char *path) {
/* check invariants - these should always hold between top-level evaluations! */
static void check_invariants(pit_runtime *rt) {
if (rt->saved_bindings->next != 0) {
- pit_error(rt, "leaked saved_bindings memory! %ld", rt->result_stack->next);
+ pit_error(rt, "leaked saved_bindings memory! %ld", rt->saved_bindings->next);
}
if (rt->expr_stack->next != 0) {
pit_error(rt, "leaked expr_stack memory! %ld", rt->expr_stack->next);
@@ -110,7 +112,7 @@ static void check_invariants(pit_runtime *rt) {
pit_error(rt, "leaked result_stack memory! %ld", rt->result_stack->next);
}
if (rt->compilation_stack->next != 0) {
- pit_error(rt, "leaked compilation_stack memory! %ld", rt->result_stack->next);
+ pit_error(rt, "leaked compilation_stack memory! %ld", rt->compilation_stack->next);
}
if (rt->traversal->next != 0) {
pit_error(rt, "leaked traversal memory! %ld", rt->traversal->next);
@@ -146,7 +148,6 @@ void pit_repl(pit_runtime *rt) {
size_t bufcap = 8;
char *buf = malloc(bufcap);
i64 len = 0;
- pit_runtime_freeze(rt);
check_invariants(rt); if (pit_runtime_print_error(rt)) exit(1);
setbuf(stdout, NULL);
printf("> ");
@@ -223,13 +224,58 @@ static pit_value impl_princ(pit_runtime *rt, pit_value args, void *data) {
static pit_value impl_load(pit_runtime *rt, pit_value args, void *data) {
(void) data;
pit_value path = pit_value_cons_car(rt, args);
- char pathbuf[1024] = {0};
- i64 len = pit_value_bytes_copy(rt, path, (u8 *) pathbuf, sizeof(pathbuf) - 1);
+ char relbuf[1024] = {0};
+ i64 len = pit_value_bytes_copy(rt, path, (u8 *) relbuf, sizeof(relbuf) - 1);
if (len < 0) { pit_error(rt, "path was not a string"); return PIT_NIL; }
- pathbuf[len] = 0;
- return pit_load_file(rt, pathbuf);
+ relbuf[len] = 0;
+ if (relbuf[0] != '/') {
+ /* if this is a relative path... */
+ char absbuf[1024] = {0};
+ struct stat sb;
+ pit_value lp = pit_symtab_get(rt, pit_symtab_intern_cstr(rt, "*load-path*"));
+ /* ...first search against the current directory... */
+ if (stat(relbuf, &sb) == 0) {
+ return pit_load_file(rt, relbuf);
+ }
+ while (lp != PIT_NIL) {
+ /* ...and then the *load-path* variable */
+ pit_value ent = pit_value_cons_car(rt, lp);
+ i64 elen = pit_value_bytes_copy(rt, ent, (u8 *) absbuf, sizeof(absbuf) - 1);
+ if (elen > 0 && absbuf[elen - 1] != '/') absbuf[elen++] = '/';
+ i64 remaining = (i64) sizeof(absbuf) - elen - 1;
+ if (len > remaining) {
+ pit_error(rt, "not enough space in buffer to construct file load path");
+ return PIT_NIL;
+ }
+ pit_libc_string_memcpy((u8 *) &absbuf[elen], (u8 *) relbuf, (size_t) len);
+ absbuf[elen + len] = 0;
+ if (stat(absbuf, &sb) == 0) {
+ /* the file exists, this is the one we load! */
+ return pit_load_file(rt, absbuf);
+ }
+ lp = pit_value_cons_cdr(rt, lp);
+ }
+ /* we didn't find the file anywhere :( */
+ pit_error(rt, "failed to load file: %s", relbuf);
+ return PIT_NIL;
+ } else {
+ /* this is an absolute path, so simply load it */
+ return pit_load_file(rt, relbuf);
+ }
}
void pit_install_library_io(pit_runtime *rt) {
+ pit_value load_path = PIT_NIL;
+ char *lp = getenv("PIT_LOAD_PATH");
+ if (lp != NULL) {
+ char *section = strtok(lp, ":");
+ while (section) {
+ load_path = pit_value_cons(rt, pit_value_bytes_new_cstr(rt, section), load_path);
+ section = strtok(NULL, ":");
+ }
+ load_path = pit_value_list_reverse(rt, load_path);
+ }
+ /* variables */
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "*load-path*"), load_path);
/* diagnostics */
pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "diagnostics!"), pit_value_nativefunc_new(rt, impl_diagnostics));
/* stream IO */