diff options
| author | LLLL Colonq <llll@colonq> | 2025-12-19 21:01:18 -0500 |
|---|---|---|
| committer | LLLL Colonq <llll@colonq> | 2025-12-19 21:01:18 -0500 |
| commit | 2dfa52e475fbc5614f92cfbc42d5b25fc5b8eff2 (patch) | |
| tree | 01109ae3e8748aeb784bdd97925af3e942fde316 | |
| parent | 8612ca228aacb3e770c485d851c809ddc4a5a7b2 (diff) | |
Add support for keywords and variadic arguments
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | include/lcq/pit/library.h | 1 | ||||
| -rw-r--r-- | include/lcq/pit/runtime.h | 5 | ||||
| -rw-r--r-- | src/library.c | 23 | ||||
| -rw-r--r-- | src/main.c | 5 | ||||
| -rw-r--r-- | src/runtime.c | 41 |
6 files changed, 61 insertions, 16 deletions
@@ -1,4 +1,4 @@ -/build/ +/build_gcc/ /.direnv/ /pit /*.a diff --git a/include/lcq/pit/library.h b/include/lcq/pit/library.h index ff325dc..6bca3a6 100644 --- a/include/lcq/pit/library.h +++ b/include/lcq/pit/library.h @@ -5,6 +5,7 @@ void pit_install_library_essential(pit_runtime *rt); void pit_install_library_io(pit_runtime *rt); +void pit_install_library_plist(pit_runtime *rt); void pit_install_library_bytestring(pit_runtime *rt); #endif diff --git a/include/lcq/pit/runtime.h b/include/lcq/pit/runtime.h index a8b6593..32bf198 100644 --- a/include/lcq/pit/runtime.h +++ b/include/lcq/pit/runtime.h @@ -60,7 +60,7 @@ typedef struct { /* "heavy" values, the targets of refs */ struct { pit_value car, cdr; } cons; struct { pit_value *data; i64 len; } array; struct { u8 *data; i64 len; } bytes; - struct { pit_value env; pit_value args; pit_value body; } func; + struct { pit_value env; pit_value args; pit_value arg_rest_nm; pit_value body; } func; pit_nativefunc nativefunc; struct { pit_value tag; void *data; } nativedata; } in; @@ -70,7 +70,7 @@ typedef struct { pit_value name; /* ref to bytestring */ pit_value value; /* ref to cell */ pit_value function; /* ref to cell */ - bool is_macro, is_special_form; + bool is_macro, is_special_form, is_keyword; } pit_symtab_entry; /* "programs"; vectors of "instructions" for a very simple VM used by the evaluator */ @@ -206,7 +206,6 @@ pit_value pit_apply(pit_runtime *rt, pit_value f, pit_value args); /* working with native data */ pit_value pit_nativedata_new(pit_runtime *rt, pit_value tag, void *d); - /* evaluation! */ pit_value pit_expand_macros(pit_runtime *rt, pit_value top); pit_value pit_eval(pit_runtime *rt, pit_value e); diff --git a/src/library.c b/src/library.c index 3175e27..9a40646 100644 --- a/src/library.c +++ b/src/library.c @@ -322,6 +322,22 @@ void pit_install_library_io(pit_runtime *rt) { pit_fset(rt, pit_intern_cstr(rt, "load!"), pit_nativefunc_new(rt, impl_load)); } +static pit_value impl_plist_get(pit_runtime *rt, pit_value args) { + pit_value k = pit_car(rt, args); + pit_value vs = pit_car(rt, pit_cdr(rt, args)); + while (vs != PIT_NIL) { + if (pit_eq(k, pit_car(rt, vs))) { + return pit_car(rt, pit_cdr(rt, vs)); + } + vs = pit_cdr(rt, vs); + } + return PIT_NIL; +} +void pit_install_library_plist(pit_runtime *rt) { + /* property lists / keyword arguments */ + pit_fset(rt, pit_intern_cstr(rt, "plist/get"), pit_nativefunc_new(rt, impl_plist_get)); +} + struct bytestring { i64 len, cap; u8 *data; @@ -373,8 +389,10 @@ static pit_value impl_bs_delete(pit_runtime *rt, pit_value args) { return PIT_NIL; } struct bytestring *bs = h->in.nativedata.data; - if (bs->data) free(bs->data); bs->data = NULL; - free(bs); h->in.nativedata.data = NULL; + if (bs->data) free(bs->data); + bs->data = NULL; + free(bs); + h->in.nativedata.data = NULL; return PIT_T; } static pit_value impl_bs_grow(pit_runtime *rt, pit_value args) { @@ -390,6 +408,7 @@ static pit_value impl_bs_grow(pit_runtime *rt, pit_value args) { } bs->len = sz; } + return v; } static pit_value impl_bs_spit(pit_runtime *rt, pit_value args) { pit_value path = pit_car(rt, args); @@ -5,9 +5,14 @@ #include <lcq/pit/lexer.h> #include <lcq/pit/parser.h> #include <lcq/pit/runtime.h> +#include <lcq/pit/library.h> int main(int argc, char **argv) { pit_runtime *rt = pit_runtime_new(); + pit_install_library_essential(rt); + pit_install_library_io(rt); + pit_install_library_plist(rt); + pit_install_library_bytestring(rt); if (argc < 2) { /* run repl */ char buf[1024] = {0}; i64 len = 0; diff --git a/src/runtime.c b/src/runtime.c index d0386ef..fcfe81a 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -87,9 +87,6 @@ pit_runtime *pit_runtime_new() { pit_set(ret, nil, PIT_NIL); pit_value truth = pit_intern_cstr(ret, "t"); pit_set(ret, truth, truth); - pit_install_library_essential(ret); - pit_install_library_io(ret); - pit_install_library_bytestring(ret); pit_runtime_freeze(ret); return ret; } @@ -489,6 +486,7 @@ pit_value pit_intern(pit_runtime *rt, u8 *nm, i64 len) { ent->function = PIT_NIL; ent->is_macro = false; ent->is_special_form = false; + ent->is_keyword = len >= 1 && nm[0] == ':'; rt->symtab_len += 1; return pit_symbol_new(rt, idx); } @@ -708,7 +706,7 @@ pit_value pit_free_vars(pit_runtime *rt, pit_value bound, pit_value body) { i64 expr_stack_reset = rt->expr_stack->top; pit_value ret = PIT_NIL; pit_values_push(rt, rt->expr_stack, body); - while (rt->expr_stack->top > 0) { + while (rt->expr_stack->top > expr_stack_reset) { pit_value cur = pit_values_pop(rt, rt->expr_stack); if (pit_is_cons(rt, cur)) { pit_value fsym = pit_car(rt, cur); @@ -752,14 +750,26 @@ pit_value pit_lambda(pit_runtime *rt, pit_value args, pit_value body) { } h->hsort = PIT_VALUE_HEAVY_SORT_FUNC; pit_value arg_cells = PIT_NIL; + pit_value arg_rest_nm = PIT_NIL; + pit_value separator = pit_intern_cstr(rt, "&"); while (args != PIT_NIL) { pit_value nm = pit_car(rt, args); - pit_value ent = pit_cons(rt, nm, pit_cell_new(rt, PIT_NIL)); - arg_cells = pit_cons(rt, ent, arg_cells); - args = pit_cdr(rt, args); + if (pit_eq(nm, separator)) { + pit_value next_nm = pit_car(rt, pit_cdr(rt, args)); + if (next_nm == PIT_NIL) { pit_error(rt, "invalid & in lambda list"); return PIT_NIL; } + arg_rest_nm = next_nm; + pit_value ent = pit_cons(rt, next_nm, pit_cell_new(rt, PIT_NIL)); + arg_cells = pit_cons(rt, ent, arg_cells); + break; + } else { + pit_value ent = pit_cons(rt, nm, pit_cell_new(rt, PIT_NIL)); + arg_cells = pit_cons(rt, ent, arg_cells); + args = pit_cdr(rt, args); + } } arg_cells = pit_reverse(rt, arg_cells); h->in.func.args = arg_cells; + h->in.func.arg_rest_nm = arg_rest_nm; h->in.func.env = env; h->in.func.body = expanded; return ret; @@ -793,8 +803,14 @@ pit_value pit_apply(pit_runtime *rt, pit_value f, pit_value args) { pit_value aform = pit_car(rt, anames); pit_value nm = pit_car(rt, aform); pit_value cell = pit_cdr(rt, aform); - pit_cell_set(rt, cell, pit_car(rt, args)); - pit_bind(rt, nm, cell); + if (h->in.func.arg_rest_nm != PIT_NIL && pit_eq(nm, h->in.func.arg_rest_nm)) { + pit_cell_set(rt, cell, args); + pit_bind(rt, nm, cell); + break; + } else { + pit_cell_set(rt, cell, pit_car(rt, args)); + pit_bind(rt, nm, cell); + } bound = pit_cons(rt, nm, bound); args = pit_cdr(rt, args); anames = pit_cdr(rt, anames); @@ -998,7 +1014,12 @@ pit_value pit_eval(pit_runtime *rt, pit_value top) { } } } else if (pit_is_symbol(rt, cur)) { /* unquoted symbols: variable lookup */ - pit_runtime_eval_program_push_literal(rt, rt->program, pit_get(rt, cur)); + pit_symtab_entry *ent = pit_symtab_lookup(rt, cur); + if (ent->is_keyword) { + pit_runtime_eval_program_push_literal(rt, rt->program, cur); + } else { + pit_runtime_eval_program_push_literal(rt, rt->program, pit_get(rt, cur)); + } } else { /* other expressions evaluate to themselves! */ pit_runtime_eval_program_push_literal(rt, rt->program, cur); } |
