C: add deep_copy_env, VM frame stack for continuations

asm: fix builtin dispatch, improve apply_proc_raw

C changes: deep_copy_env() for multi-shot continuations,
explicit frame stack in VM for compiled code call/cc support.

asm changes: improved builtin implementations, fixed dispatch paths.

All tests pass: asm 75, C 76+114 functional.
This commit is contained in:
russell@unturf.com 2026-04-15 19:57:17 -04:00
parent b038266173
commit 30d7279be2
5 changed files with 219 additions and 54 deletions

View file

@ -2164,7 +2164,8 @@ eval_list:
movq %rbx, %rax
shrq $3, %rax # index
# Jump table
# Jump table — shared entry point for apply_proc_raw dispatch
.app_builtin_dispatch:
cmpq $BI_ADD, %rax
je bi_add
cmpq $BI_SUB, %rax
@ -2762,28 +2763,27 @@ apply_proc_raw:
cmpq $VAL_NIL, %rsi
je .apr_eval_body
# Extract param name and rest params
movq %rcx, %rax
andq $-8, %rax
movq (%rax), %rdi # param name (symbol)
movq 8(%rax), %rcx # rest params
# Extract arg value and rest args
movq %rsi, %rax
andq $-8, %rax
movq (%rax), %rsi # arg value
pushq %rcx
pushq %rsi
pushq %rdx
movq %rsi, %rsi # value
movq 8(%rax), %r8 # rest args (cdr)
movq (%rax), %rsi # arg value (car)
pushq %r8 # save rest args
pushq %rcx # save rest params
pushq %rdx # save body
movq %rbp, %rdx # env
call env_define
movq %rax, %rbp
popq %rdx
popq %rsi
popq %rcx
# Advance arg list
# Need to re-fetch rest of args — we clobbered %rsi
# Actually we saved it wrong. Let me redo.
# This binding loop is getting complex. Use simpler approach.
popq %rdx # restore body
popq %rcx # restore rest params
popq %rsi # restore rest args
jmp .apr_bind
.apr_eval_body:
@ -2823,33 +2823,11 @@ apply_proc_raw:
ret
.apr_bi_dispatch:
# Dispatch builtin by index — reuse main dispatch table
# Dispatch builtin by index — jump to main dispatch table
# RET_VAL pops %r12,%rbp,%rbx — matching our pushes in apply_proc_raw
movq %rbx, %rax
shrq $3, %rax
# We need to jump into the builtin implementations
# But they use RET_VAL which pops %r12,%rbp,%rbx — which we pushed
# So it should work if we fall through to the existing dispatch
cmpq $BI_ADD, %rax
je bi_add
cmpq $BI_SUB, %rax
je bi_sub
cmpq $BI_MUL, %rax
je bi_mul
cmpq $BI_EQ, %rax
je bi_eq
cmpq $BI_LT, %rax
je bi_lt
cmpq $BI_GT, %rax
je bi_gt
cmpq $BI_CONS, %rax
je bi_cons
# ... for full dispatch, jump to the main dispatch
# Shortcut: just compute the address and jump
movq $VAL_VOID, %rax
popq %rbp
popq %r12
popq %rbx
ret
jmp .app_builtin_dispatch
# ── New builtins ─────────────────────────────────────────────
@ -2922,17 +2900,14 @@ bi_append:
jmp .bapp_copy
.bapp_link:
# set last cdr to lst2
popq %rbx
popq %rsi
movq %rcx, %rax # head
pushq %rax
movq %rbx, %rax # find actual tail - but we already have it
popq %rax
# We need to find the last pair of the copy and set its cdr
# Actually %rbx was the last pair before we popped it. Redo.
# Simpler: just use the Scheme approach — recurse
# For now: fall through to simple version
movq %rcx, %rax
# %rbx = last pair (tagged), %rcx = head (tagged)
# stack: [rbx_saved, rsi=lst2]
movq %rbx, %rax
andq $-8, %rax
popq %rbx # restore saved rbx
popq %rsi # lst2
movq %rsi, 8(%rax) # set last pair's cdr to lst2
movq %rcx, %rax # return head
RET_VAL
.bapp_done_rsi:
movq %rsi, %rax
@ -3457,8 +3432,10 @@ bi_integerp:
bi_expt:
GETARG %rax
sarq $3, %rax
pushq %rax # save untagged base
GETARG %rcx
sarq $3, %rcx
popq %rax # restore untagged base
# base^exp by repeated multiplication
movq $1, %rdx
.bexpt_loop: