summaryrefslogtreecommitdiff
path: root/src/runtime.c
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2025-09-27 04:21:06 -0400
committerLLLL Colonq <llll@colonq>2025-09-27 04:21:06 -0400
commitab57bc2a6d6ea9c24aa119df6efbd8a38b54c312 (patch)
treebfc7fe32f40804e7808016038a3f2f15ef9e643e /src/runtime.c
parent811f11463851a0f35835ac72ef09b65b1072de20 (diff)
Source location tracking
Diffstat (limited to 'src/runtime.c')
-rw-r--r--src/runtime.c103
1 files changed, 82 insertions, 21 deletions
diff --git a/src/runtime.c b/src/runtime.c
index 3bfd1d4..6825bbe 100644
--- a/src/runtime.c
+++ b/src/runtime.c
@@ -6,6 +6,8 @@
#include <math.h>
#include "utils.h"
+#include "lexer.h"
+#include "parser.h"
#include "runtime.h"
#include "library.h"
@@ -76,6 +78,8 @@ pit_runtime *pit_runtime_new() {
ret->frozen_bytes = 0;
ret->frozen_symtab = 0;
ret->error = PIT_NIL;
+ ret->source_line = ret->source_column = -1;
+ ret->error_line = ret->error_column = -1;
pit_value nil = pit_intern_cstr(ret, "nil"); // nil must be the 0th symbol for PIT_NIL to work
pit_set(ret, nil, PIT_NIL);
pit_value truth = pit_intern_cstr(ret, "t");
@@ -95,8 +99,17 @@ void pit_runtime_reset(pit_runtime *rt) {
rt->bytes->next = rt->frozen_bytes;
rt->symtab->next = rt->frozen_symtab;
}
+bool pit_runtime_print_error(pit_runtime *rt) {
+ if (!pit_eq(rt->error, PIT_NIL)) {
+ char buf[1024] = {0};
+ pit_dump(rt, buf, sizeof(buf), rt->error, false);
+ fprintf(stderr, "error at line %ld, column %ld: %s\n", rt->error_line, rt->error_column, buf);
+ return true;
+ }
+ return false;
+}
-i64 pit_dump(pit_runtime *rt, char *buf, i64 len, pit_value v) {
+i64 pit_dump(pit_runtime *rt, char *buf, i64 len, pit_value v, bool readable) {
pit_value_heavy *h = NULL;
if (len <= 0) return 0;
switch (pit_value_sort(v)) {
@@ -128,7 +141,7 @@ i64 pit_dump(pit_runtime *rt, char *buf, i64 len, pit_value v) {
char *end = buf + len;
char *start = buf;
*(buf++) = '{';
- buf += pit_dump(rt, buf, end - buf, pit_car(rt, h->cell));
+ buf += pit_dump(rt, buf, end - buf, pit_car(rt, h->cell), readable);
*(buf++) = '}';
return buf - start;
}
@@ -139,12 +152,12 @@ i64 pit_dump(pit_runtime *rt, char *buf, i64 len, pit_value v) {
do {
if (pit_is_cons(rt, cur)) {
*(buf++) = ' '; if (buf >= end) return end - buf;
- buf += pit_dump(rt, buf, end - buf, pit_car(rt, cur));
+ buf += pit_dump(rt, buf, end - buf, pit_car(rt, cur), readable);
if (buf >= end) return end - buf;
} else {
buf += snprintf(buf, end - buf, " . ");
if (buf >= end) return end - buf;
- buf += pit_dump(rt, buf, end - buf, cur);
+ buf += pit_dump(rt, buf, end - buf, cur, readable);
if (buf >= end) return end - buf;
}
} while (!pit_eq((cur = pit_cdr(rt, cur)), PIT_NIL));
@@ -153,14 +166,15 @@ i64 pit_dump(pit_runtime *rt, char *buf, i64 len, pit_value v) {
return buf - start;
}
case PIT_VALUE_HEAVY_SORT_BYTES:
- buf[0] = '"';
- i64 i = 1;
- for (i64 j = 0; i < len - 1 && j < h->bytes.len;) {
+ i64 i = 0;
+ if (readable) buf[i++] = '"';
+ i64 maxlen = len - i;
+ for (i64 j = 0; i < maxlen && j < h->bytes.len;) {
if (buf[i - 1] != '\\' && (h->bytes.data[j] == '\\' || h->bytes.data[j] == '"'))
buf[i++] = '\\';
else buf[i++] = h->bytes.data[j++];
}
- if (i < len - 1) buf[i++] = '"';
+ if (readable && i < len - 1) buf[i++] = '"';
return i;
default:
return snprintf(buf, len, "<ref %d>", r);
@@ -173,7 +187,7 @@ i64 pit_dump(pit_runtime *rt, char *buf, i64 len, pit_value v) {
void pit_trace_(pit_runtime *rt, const char *format, pit_value v) {
char buf[1024] = {0};
- pit_dump(rt, buf, sizeof(buf), v);
+ pit_dump(rt, buf, sizeof(buf), v, true);
fprintf(stderr, format, buf);
}
@@ -185,14 +199,8 @@ void pit_error(pit_runtime *rt, const char *format, ...) {
vsnprintf(buf, sizeof(buf), format, vargs);
va_end(vargs);
rt->error = pit_bytes_new_cstr(rt, buf);
- }
-}
-
-void pit_check_error_maybe_panic(pit_runtime *rt) {
- if (!pit_eq(rt->error, PIT_NIL)) {
- char buf[1024] = {0};
- pit_dump(rt, buf, sizeof(buf), rt->error);
- pit_panic("runtime error: %s", buf);
+ rt->error_line = rt->source_line;
+ rt->error_column = rt->source_column;
}
}
@@ -349,12 +357,10 @@ bool pit_equal(pit_runtime *rt, pit_value a, pit_value b) {
}
return false;
}
-
pit_value pit_bytes_new(pit_runtime *rt, u8 *buf, i64 len) {
u8 *dest = pit_arena_alloc_bulk(rt->bytes, len);
if (!dest) { pit_error(rt, "failed to allocate bytes"); return PIT_NIL; }
memcpy(dest, buf, len);
- if (!dest) return PIT_NIL;
pit_value ret = pit_heavy_new(rt);
pit_value_heavy *h = pit_deref(rt, ret);
if (!h) { pit_error(rt, "failed to create new heavy value for bytes"); return PIT_NIL; }
@@ -363,11 +369,30 @@ pit_value pit_bytes_new(pit_runtime *rt, u8 *buf, i64 len) {
h->bytes.len = len;
return ret;
}
-
pit_value pit_bytes_new_cstr(pit_runtime *rt, char *s) {
return pit_bytes_new(rt, (u8 *) s, strlen(s));
}
-
+pit_value pit_bytes_new_file(pit_runtime *rt, char *path) {
+ FILE *f = fopen(path, "r");
+ if (f == NULL) {
+ pit_error(rt, "failed to open file: %s", path);
+ return PIT_NIL;
+ }
+ fseek(f, 0, SEEK_END);
+ i64 len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ u8 *dest = pit_arena_alloc_bulk(rt->bytes, len);
+ if (!dest) { pit_error(rt, "failed to allocate bytes"); fclose(f); return PIT_NIL; }
+ fread(dest, sizeof(char), len, f);
+ fclose(f);
+ pit_value ret = pit_heavy_new(rt);
+ pit_value_heavy *h = pit_deref(rt, ret);
+ if (!h) { pit_error(rt, "failed to create new heavy value for bytes"); return PIT_NIL; }
+ h->hsort = PIT_VALUE_HEAVY_SORT_BYTES;
+ h->bytes.data = dest;
+ h->bytes.len = len;
+ return ret;
+}
// return true if v is a reference to bytes that are the same as those in buf
bool pit_bytes_match(pit_runtime *rt, pit_value v, u8 *buf, i64 len) {
if (pit_value_sort(v) != PIT_VALUE_SORT_REF) return false;
@@ -381,6 +406,42 @@ bool pit_bytes_match(pit_runtime *rt, pit_value v, u8 *buf, i64 len) {
}
return true;
}
+i64 pit_as_bytes(pit_runtime *rt, pit_value v, u8 *buf, i64 maxlen) {
+ if (pit_value_sort(v) != PIT_VALUE_SORT_REF) return -1;
+ pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, v));
+ if (!h) { pit_error(rt, "bad ref"); return -1; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_BYTES) {
+ pit_error(rt, "invalid use of value as bytes");
+ return -1;
+ }
+ i64 len = maxlen < h->bytes.len ? maxlen : h->bytes.len;
+ for (i64 i = 0; i < len; ++i) {
+ buf[i] = h->bytes.data[i];
+ }
+ return len;
+}
+bool pit_lexer_from_bytes(pit_runtime *rt, pit_lexer *ret, pit_value v) {
+ if (pit_value_sort(v) != PIT_VALUE_SORT_REF) return false;
+ pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, v));
+ if (!h) { pit_error(rt, "bad ref"); return false; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_BYTES) {
+ pit_error(rt, "invalid use of value as bytes");
+ return -1;
+ }
+ pit_lex_bytes(ret, (char *) h->bytes.data, h->bytes.len);
+ return true;
+}
+pit_value pit_read_bytes(pit_runtime *rt, pit_value v) { // read a single lisp form from a bytestring
+ pit_lexer lex;
+ if (!pit_lexer_from_bytes(rt, &lex, v)) {
+ pit_error(rt, "failed to initialize lexer");
+ return PIT_NIL;
+ }
+ pit_parser parse;
+ pit_parser_from_lexer(&parse, &lex);
+ pit_value program = pit_parse(rt, &parse, NULL);
+ return pit_eval(rt, program);
+}
pit_value pit_intern(pit_runtime *rt, u8 *nm, i64 len) {
for (i64 i = 0; i < rt->symtab_len; ++i) {