summaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2025-09-23 04:30:25 -0400
committerLLLL Colonq <llll@colonq>2025-09-23 04:30:25 -0400
commitf5dd8de68e70d6948005aa8bdcde1a9c80a6c0ea (patch)
tree733509c05edf221bb375abba592107019cfa21cc /src/parser.c
parent5c1404b6fd35a5eef9724dd197cdc645b7673e4c (diff)
Add let
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/src/parser.c b/src/parser.c
index 34472d2..cb75817 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -57,17 +57,22 @@ pit_value pit_parse(pit_runtime *rt, pit_parser *st) {
pit_error(rt, "end-of-file while parsing");
return PIT_NIL;
case PIT_LEX_TOKEN_LPAREN: {
- i64 arg = 0; i64 args_cap = 32;
- pit_value *args = calloc(args_cap, sizeof(pit_value));
+ // to construct a cons-list, we need the arguments "backwards"
+ // we could reverse or build up a temporary list
+ // (or use non-tail recursion, which is basically the temporary list on the stack)
+ // we choose to build a temporary list on the scratch arena
+ i64 scratch_reset = rt->scratch->next;
while (!match(st, PIT_LEX_TOKEN_RPAREN)) {
- args[arg++] = pit_parse(rt, st);
+ pit_value *cell = pit_arena_alloc_bulk(rt->scratch, sizeof(pit_value));
+ *cell = pit_parse(rt, st);
if (rt->error != PIT_NIL) return PIT_NIL; // if we hit an error, stop!
- if (arg >= args_cap) args = realloc(args, (args_cap <<= 1) * sizeof(pit_value));
}
pit_value ret = PIT_NIL;
- for (int i = 0; i < arg; ++i) {
- ret = pit_cons(rt, args[arg - i - 1], ret);
+ for (i64 i = rt->scratch->next - sizeof(pit_value); i >= scratch_reset; i -= sizeof(pit_value)) {
+ pit_value *v = pit_arena_idx(rt->scratch, i);
+ ret = pit_cons(rt, *v, ret);
}
+ rt->scratch->next = scratch_reset;
return ret;
}
case PIT_LEX_TOKEN_QUOTE: