summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/library.c23
-rw-r--r--src/main.c5
-rw-r--r--src/runtime.c41
3 files changed, 57 insertions, 12 deletions
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);
diff --git a/src/main.c b/src/main.c
index 2ea5ef8..bc697de 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);
}