From 8909986b89eaac74bb4cd8dc7019f96e4f650470 Mon Sep 17 00:00:00 2001 From: LLLL Colonq Date: Mon, 29 Jun 2026 20:29:36 -0400 Subject: Initial annotations --- Makefile | 4 +++- emacs/pit.el | 36 ----------------------------------- include/lcq/pit/runtime.h | 16 ++++++++++++++++ src/library.c | 18 ------------------ src/main.c | 12 ++++++------ src/parser.c | 10 ++++++++++ src/runtime.c | 48 ++++++++++++++++++++++++++++++++++++++++++++--- test/error2.pit | 4 ++++ whereweleftoff.org | 8 ++++++++ 9 files changed, 92 insertions(+), 64 deletions(-) create mode 100644 test/error2.pit create mode 100644 whereweleftoff.org diff --git a/Makefile b/Makefile index baa81e8..0b5d02f 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,6 @@ EXE ?= pit CC ?= gcc AR ?= ar -CHK_SOURCES ?= src/main.c $(SRCS) override CPPFLAGS += -MMD -MP override CFLAGS += -Oz -fPIC --std=c99 -g -Ideps/ -Isrc/ -Iinclude/ -Wall -Wextra -Wpedantic -Wconversion -Wformat-security -Wshadow -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wnull-dereference -Wfloat-equal -Wundef -Wpointer-arith -Wbad-function-cast -Wlogical-op -Wmissing-braces -Wcast-align -Wstrict-overflow=5 -fwrapv # -ftrapv override LDFLAGS += -g -static @@ -16,6 +15,9 @@ SRCS_NATIVE := src/native.c OBJECTS_NATIVE := $(SRCS_NATIVE:src/%.c=$(BUILD)/%.o) LIB_NATIVE := libcolonq-pit-native.a +SRCS := src/main.c $(SRCS_CORE) $(SRCS_NATIVE) +CHK_SOURCES ?= $(SRCS) + prefix ?= /usr/local exec_prefix ?= $(prefix) bindir ?= $(exec_prefix)/bin diff --git a/emacs/pit.el b/emacs/pit.el index 9a357a3..3665d93 100644 --- a/emacs/pit.el +++ b/emacs/pit.el @@ -102,41 +102,5 @@ (cider--update-host-port) (cider--check-existing-session)))))) -(defun cider-repl-handler (buffer) - "Make an nREPL evaluation handler for the REPL BUFFER." - (message "running cider-repl-handler") - (let ((show-prompt t)) - (nrepl-make-response-handler - buffer - (lambda (buffer value) - (message "value-handler") - (cider-repl-emit-result buffer value t)) - (lambda (buffer out) - (dolist (f cider--repl-stdout-functions) - (funcall f buffer out)) - (cider-repl-emit-stdout buffer out)) - (lambda (buffer err) - (dolist (f cider--repl-stderr-functions) - (funcall f buffer err)) - (cider-repl-emit-stderr buffer err)) - (lambda (buffer) - (message "done-handler: %s" show-prompt) - (when show-prompt - (cider-repl-emit-prompt buffer)) - (when cider-repl-buffer-size-limit - (cider-repl-maybe-trim-buffer buffer)) - (dolist (f cider--repl-done-functions) - (funcall f buffer))) - nrepl-err-handler - (lambda (buffer value content-type) - (if-let* ((content-attrs (cadr content-type)) - (content-type* (car content-type)) - (handler (cdr (assoc content-type* - cider-repl-content-type-handler-alist)))) - (setq show-prompt (funcall handler content-type buffer value nil t)) - (cider-repl-emit-result buffer value t t))) - (lambda (buffer warning) - (cider-repl-emit-stderr buffer warning))))) - (provide 'pit) ;;; pit.el ends here diff --git a/include/lcq/pit/runtime.h b/include/lcq/pit/runtime.h index 48e2bcd..da93dda 100644 --- a/include/lcq/pit/runtime.h +++ b/include/lcq/pit/runtime.h @@ -81,12 +81,28 @@ pit_runtime_eval_program *pit_runtime_eval_program_new(u8 *buf, i64 buf_len); void pit_runtime_eval_program_push_literal(struct pit_runtime *rt, pit_runtime_eval_program *s, pit_value x); void pit_runtime_eval_program_push_apply(struct pit_runtime *rt, pit_runtime_eval_program *s, i64 arity); +/* annotation attached to (some) heavy values detaiking things like line numbers */ +typedef struct { + pit_ref ref; + i64 line; + i64 column; +} pit_expr_annotation; +typedef struct { + i64 capacity, next; + pit_expr_annotation data[]; +} pit_expr_annotations; +pit_expr_annotations *pit_expr_annotations_new(u8 *buf, i64 buf_len); +void pit_expr_annotations_push(pit_expr_annotations *s, pit_ref ref, i64 line, i64 column); +pit_expr_annotation *pit_expr_annotations_lookup(pit_expr_annotations *s, pit_ref ref); + typedef struct pit_runtime { /* interpreter state */ pit_arena *heap; /* all heavy values, bytestrings, and arrays. */ /* bytestrings and arrays are allocated at the end (descending), heavy values are allocated at the front */ /* this allows us to iterate over only heavy values at the front (useful in Cheney's algorithm for GC */ pit_arena *backbuffer; /* additional allocation, the same size as the heap (used by GC) */ + pit_expr_annotations *annotations; + pit_expr_annotations *annotations_backbuffer; pit_arena *symtab; i64 symtab_len; /* all symbols - effectively an array of pit_symtab_entry */ /* temporary/"scratch" memory */ pit_arena *scratch; /* temporary arena used during parsing and evaluation */ diff --git a/src/library.c b/src/library.c index 8e243b9..383105b 100644 --- a/src/library.c +++ b/src/library.c @@ -805,7 +805,6 @@ void pit_install_library_essential(pit_runtime *rt) { /* eval */ pit_fset(rt, pit_intern_cstr(rt, "eval!"), pit_nativefunc_new(rt, impl_eval)); /* predicates */ - /* pit_fset(rt, pit_intern_cstr(rt, "eq?"), pit_nativefunc_new(rt, impl_eq_p)); pit_fset(rt, pit_intern_cstr(rt, "equal?"), pit_nativefunc_new(rt, impl_equal_p)); pit_fset(rt, pit_intern_cstr(rt, "integer?"), pit_nativefunc_new(rt, impl_integer_p)); @@ -815,25 +814,19 @@ void pit_install_library_essential(pit_runtime *rt) { pit_fset(rt, pit_intern_cstr(rt, "array?"), pit_nativefunc_new(rt, impl_array_p)); pit_fset(rt, pit_intern_cstr(rt, "bytes?"), pit_nativefunc_new(rt, impl_bytes_p)); pit_fset(rt, pit_intern_cstr(rt, "function?"), pit_nativefunc_new(rt, impl_function_p)); - */ /* symbols */ - /* pit_fset(rt, pit_intern_cstr(rt, "set!"), pit_nativefunc_new(rt, impl_set)); pit_fset(rt, pit_intern_cstr(rt, "fset!"), pit_nativefunc_new(rt, impl_fset)); pit_fset(rt, pit_intern_cstr(rt, "symbol-is-macro!"), pit_nativefunc_new(rt, impl_symbol_is_macro)); pit_fset(rt, pit_intern_cstr(rt, "funcall"), pit_nativefunc_new(rt, impl_funcall)); pit_fset(rt, pit_intern_cstr(rt, "apply"), pit_nativefunc_new(rt, impl_apply)); - */ /* cons cells */ - /* pit_fset(rt, pit_intern_cstr(rt, "cons"), pit_nativefunc_new(rt, impl_cons)); pit_fset(rt, pit_intern_cstr(rt, "car"), pit_nativefunc_new(rt, impl_car)); pit_fset(rt, pit_intern_cstr(rt, "cdr"), pit_nativefunc_new(rt, impl_cdr)); pit_fset(rt, pit_intern_cstr(rt, "setcar!"), pit_nativefunc_new(rt, impl_setcar)); pit_fset(rt, pit_intern_cstr(rt, "setcdr!"), pit_nativefunc_new(rt, impl_setcdr)); - */ /* cons lists*/ - /* pit_fset(rt, pit_intern_cstr(rt, "list"), pit_nativefunc_new(rt, impl_list)); pit_fset(rt, pit_intern_cstr(rt, "list/nth"), pit_nativefunc_new(rt, impl_list_nth)); pit_fset(rt, pit_intern_cstr(rt, "list/iota"), pit_nativefunc_new(rt, impl_list_iota)); @@ -851,14 +844,10 @@ void pit_install_library_essential(pit_runtime *rt) { pit_fset(rt, pit_intern_cstr(rt, "list/contains?"), pit_nativefunc_new(rt, impl_list_contains_p)); pit_fset(rt, pit_intern_cstr(rt, "list/all?"), pit_nativefunc_new(rt, impl_list_all_p)); pit_fset(rt, pit_intern_cstr(rt, "list/zip-with"), pit_nativefunc_new(rt, impl_list_zip_with)); - */ /* bytestrings */ - /* pit_fset(rt, pit_intern_cstr(rt, "bytes/len"), pit_nativefunc_new(rt, impl_bytes_len)); pit_fset(rt, pit_intern_cstr(rt, "bytes/range"), pit_nativefunc_new(rt, impl_bytes_range)); - */ /* array */ - /* pit_fset(rt, pit_intern_cstr(rt, "array"), pit_nativefunc_new(rt, impl_array)); pit_fset(rt, pit_intern_cstr(rt, "array/to-list"), pit_nativefunc_new(rt, impl_array_to_list)); pit_fset(rt, pit_intern_cstr(rt, "array/from-list"), pit_nativefunc_new(rt, impl_array_from_list)); @@ -868,7 +857,6 @@ void pit_install_library_essential(pit_runtime *rt) { pit_fset(rt, pit_intern_cstr(rt, "array/set!"), pit_nativefunc_new(rt, impl_array_set)); pit_fset(rt, pit_intern_cstr(rt, "array/map"), pit_nativefunc_new(rt, impl_array_map)); pit_fset(rt, pit_intern_cstr(rt, "array/map!"), pit_nativefunc_new(rt, impl_array_map_mut)); - */ /* arithmetic */ pit_fset(rt, pit_intern_cstr(rt, "abs"), pit_nativefunc_new(rt, impl_abs)); pit_fset(rt, pit_intern_cstr(rt, "+"), pit_nativefunc_new(rt, impl_add)); @@ -876,25 +864,19 @@ void pit_install_library_essential(pit_runtime *rt) { pit_fset(rt, pit_intern_cstr(rt, "*"), pit_nativefunc_new(rt, impl_mul)); pit_fset(rt, pit_intern_cstr(rt, "/"), pit_nativefunc_new(rt, impl_div)); /* booleans */ - /* pit_fset(rt, pit_intern_cstr(rt, "not"), pit_nativefunc_new(rt, impl_not)); - */ /* comparisons */ - /* pit_fset(rt, pit_intern_cstr(rt, "<"), pit_nativefunc_new(rt, impl_lt)); pit_fset(rt, pit_intern_cstr(rt, ">"), pit_nativefunc_new(rt, impl_gt)); pit_fset(rt, pit_intern_cstr(rt, "<="), pit_nativefunc_new(rt, impl_le)); pit_fset(rt, pit_intern_cstr(rt, ">="), pit_nativefunc_new(rt, impl_ge)); - */ /* bitwise arithmetic */ - /* pit_fset(rt, pit_intern_cstr(rt, "bitwise/and"), pit_nativefunc_new(rt, impl_bitwise_and)); pit_fset(rt, pit_intern_cstr(rt, "bitwise/or"), pit_nativefunc_new(rt, impl_bitwise_or)); pit_fset(rt, pit_intern_cstr(rt, "bitwise/xor"), pit_nativefunc_new(rt, impl_bitwise_xor)); pit_fset(rt, pit_intern_cstr(rt, "bitwise/not"), pit_nativefunc_new(rt, impl_bitwise_not)); pit_fset(rt, pit_intern_cstr(rt, "bitwise/lshift"), pit_nativefunc_new(rt, impl_bitwise_lshift)); pit_fset(rt, pit_intern_cstr(rt, "bitwise/rshift"), pit_nativefunc_new(rt, impl_bitwise_rshift)); - */ } static pit_value impl_plist_get(pit_runtime *rt, pit_value args, void *data) { diff --git a/src/main.c b/src/main.c index f29245b..76da802 100644 --- a/src/main.c +++ b/src/main.c @@ -8,15 +8,15 @@ #include int main(int argc, char **argv) { - // i64 sz = 256 * 1024 * 1024; - i64 sz = 32 * 1024; + i64 sz = 256 * 1024 * 1024; + // i64 sz = 32 * 1024; u8 *buf = malloc((size_t) sz); pit_runtime *rt = pit_runtime_new(buf, sz); pit_install_library_essential(rt); - // pit_install_library_io(rt); - // pit_install_library_plist(rt); - // pit_install_library_alist(rt); - // pit_install_library_bytestring(rt); + pit_install_library_io(rt); + pit_install_library_plist(rt); + pit_install_library_alist(rt); + pit_install_library_bytestring(rt); if (argc < 2) { pit_repl(rt); } else { diff --git a/src/parser.c b/src/parser.c index 77b4172..002641e 100644 --- a/src/parser.c +++ b/src/parser.c @@ -3,6 +3,8 @@ #include #include +#include + static pit_lex_token peek(pit_parser *st) { if (!st) return PIT_LEX_TOKEN_ERROR; return st->next.token; @@ -106,6 +108,14 @@ pit_value pit_parse(pit_runtime *rt, pit_parser *st, bool *eof) { ret = pit_cons(rt, *v, ret); } rt->scratch->next = scratch_reset; + if (pit_value_sort(ret) == PIT_VALUE_SORT_REF) { + fprintf(stderr, "adding annotation (%ld): ", pit_as_ref(rt, ret)); + pit_trace_(rt, "%s\n", ret); + pit_expr_annotations_push(rt->annotations, + pit_as_ref(rt, ret), + rt->source_line, rt->source_column + ); + } return ret; } case PIT_LEX_TOKEN_LSQUARE: { diff --git a/src/runtime.c b/src/runtime.c index 2d5dede..007a62f 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -4,6 +4,8 @@ #include #include +#include + enum pit_value_sort pit_value_sort(pit_value v) { /* if this isn't a NaN, or it's a quiet NaN, this is a real double */ /* if (((v >> 52) & 0b011111111111) != 0b011111111111 || ((v >> 51) & 0b1) == 1) return PIT_VALUE_SORT_DOUBLE; */ @@ -26,11 +28,14 @@ pit_runtime *pit_runtime_new(u8 *buf, i64 len) { pit_arena *a = pit_arena_new(buf, len, sizeof(u8)); pit_runtime *ret = pit_arena_alloc_back(a, sizeof(*ret)); i64 heap_size = len / 4; - i64 symtab_size = len / 8; - i64 scratch_size = len / 16; - i64 stack_size = len / 16; + i64 annotations_size = len / 32; + i64 symtab_size = len / 16; + i64 scratch_size = len / 32; + i64 stack_size = len / 32; ret->heap = pit_arena_new(pit_arena_alloc_back(a, heap_size), heap_size, sizeof(pit_value_heavy)); ret->backbuffer = pit_arena_new(pit_arena_alloc_back(a, heap_size), heap_size, sizeof(pit_value_heavy)); + ret->annotations = pit_expr_annotations_new(pit_arena_alloc_back(a, annotations_size), annotations_size); + ret->annotations_backbuffer = pit_expr_annotations_new(pit_arena_alloc_back(a, annotations_size), annotations_size); ret->symtab = pit_arena_new(pit_arena_alloc_back(a, symtab_size), symtab_size, sizeof(pit_symtab_entry)); ret->symtab_len = 0; ret->scratch = pit_arena_new(pit_arena_alloc_back(a, scratch_size), scratch_size, sizeof(u8)); @@ -965,6 +970,32 @@ void pit_runtime_eval_program_push_apply(pit_runtime *rt, pit_runtime_eval_progr (void) rt; } +pit_expr_annotations *pit_expr_annotations_new(u8 *buf, i64 buf_len) { + uintptr_t base = (uintptr_t) buf; + uintptr_t aligned = pit_align_up(base, sizeof(void *)); + pit_expr_annotations *ret = (pit_expr_annotations *) aligned; + uintptr_t data = aligned + sizeof(pit_arena); + i64 offset = (i64) data - (i64) base; + i64 remaining = (i64) (buf_len - offset); + i64 cap = remaining / (i64) sizeof(pit_expr_annotation); + ret->next = 0; + ret->capacity = cap; + return ret; +} +void pit_expr_annotations_push(pit_expr_annotations *s, pit_ref ref, i64 line, i64 column) { + pit_expr_annotation *ent = &s->data[s->next++]; + ent->ref = ref; + ent->line = line; + ent->column = column; +} + +pit_expr_annotation *pit_expr_annotations_lookup(pit_expr_annotations *s, pit_ref ref) { + for (i64 i = 0; i < s->next; ++i) { + if (s->data[i].ref == ref) return &s->data[i]; + } + return NULL; +} + pit_value pit_expand_macros(pit_runtime *rt, pit_value top) { i64 expr_stack_reset = rt->expr_stack->next; i64 result_stack_reset = rt->result_stack->next; @@ -1066,6 +1097,16 @@ pit_value pit_eval(pit_runtime *rt, pit_value top) { if (pit_is_cons(rt, cur)) { /* compound expressions: function/macro application special forms */ pit_value fsym = pit_car(rt, cur); bool is_symbol = pit_is_symbol(rt, fsym); + pit_expr_annotation *ann = pit_expr_annotations_lookup(rt->annotations, pit_as_ref(rt, cur)); + fprintf(stderr, "looking up annotation (%ld): ", pit_as_ref(rt, cur)); + pit_trace_(rt, "%s\n", cur); + if (ann) { + fprintf(stderr, "%ld:%ld\n", ann->line, ann->column); + rt->source_line = ann->line; + rt->source_column = ann->column; + } else { + fprintf(stderr, "failed to find ann\n"); + } if (is_symbol && pit_is_symbol_special_form(rt, fsym)) { /* special forms */ pit_value f = pit_fget(rt, fsym); pit_value args = pit_cdr(rt, cur); @@ -1160,6 +1201,7 @@ static pit_value gc_copy_value(pit_runtime *rt, pit_arena *tospace, pit_value v) } } void pit_collect_garbage(pit_runtime *rt) { + return; // TODO rt->frozen_values = 0; rt->frozen_symtab = 0; pit_arena *fromspace = rt->heap; diff --git a/test/error2.pit b/test/error2.pit new file mode 100644 index 0000000..63ab173 --- /dev/null +++ b/test/error2.pit @@ -0,0 +1,4 @@ +(defun! foo () + (error! "yuck")) + +(foo) diff --git a/whereweleftoff.org b/whereweleftoff.org new file mode 100644 index 0000000..3b89918 --- /dev/null +++ b/whereweleftoff.org @@ -0,0 +1,8 @@ +[2026-06-26] + +- annotations do not work properly because macroexpansion creates an entirely new body for lambdas +- we realized that we are handling macro application in two separate places: pit_expand_macros expands lambda bodies, and pit_eval expands macros encountered while evaling. we ought to unify this so that only one is used (probably pit_expand_macros, because we need to expand macros eagerly to identify free variables to capture) +- we probably can make pit_expand_macros and pit_eval much nicer +- we can probably make pit_expand_macros operate in place +- if we want to be really smart, cool, happy, rich: + let's just make stuff translate to a little VM before it evaluates, and let's store VM programs as functions instead of sexps -- cgit v1.2.3