Allow aux stack operations inside quotations #393

Closed
opened 2026-04-10 23:29:10 +00:00 by navicore · 2 comments
navicore commented 2026-04-10 23:29:10 +00:00 (Migrated from github.com)

Summary

>aux and aux> are rejected inside quotations with:

Error: aux> is not supported inside quotations.
Quotations are compiled as separate functions without aux stack slots.
Extract the quotation body into a named word if you need aux.

The workaround (extract to a named word) works but creates friction for common patterns like list.fold callbacks that need temporary storage.

Motivation

When implementing algorithms that use list.fold with context beyond (acc, elem), the natural pattern is to stash a value on aux inside the fold quotation. For example, Horner's polynomial evaluation:

: eval-poly ( List Int -- Int )
  swap list.reverse swap
  >aux
  0 [ swap aux> dup >aux gf256-mul bxor ] list.fold
  aux> drop
;

Currently this requires extracting the fold body into a named word, which fragments the logic.

Proposed Change

Quotations are already compiled as separate LLVM functions with their own stack frames. The aux mechanism is compile-time alloca slots at function entry — the same approach used for named words.

Typechecker (typechecker.rs)

  • Remove the in_quotation_scope guards in infer_to_aux (line ~1354) and infer_from_aux (line ~1385)
  • Track aux depth per-quotation using the quotation ID, extending aux_max_depths (currently keyed by word name)
  • The existing balance enforcement (aux must be empty at scope exit) already works per-scope

Codegen (codegen/words.rs)

  • In codegen_quotation (line ~165), instead of clearing aux state defensively, look up the quotation's aux depth from aux_slot_counts and emit alloca %Value slots — the same pattern as word codegen (lines 81-89)
  • The quotation function gets its own %aux_slot_0, %aux_slot_1, etc., independent of the enclosing word

Runtime

No changes needed. Aux is purely compile-time allocas — zero overhead when not used.

Risk

Low. Quotation functions are already independent LLVM functions with their own frames. Adding allocas follows the established pattern. The typechecker already validates aux balance per-scope.


Context: discovered while implementing Shamir's Secret Sharing in Seq, where Lagrange interpolation requires fold callbacks with extra context.

## Summary `>aux` and `aux>` are rejected inside quotations with: ``` Error: aux> is not supported inside quotations. Quotations are compiled as separate functions without aux stack slots. Extract the quotation body into a named word if you need aux. ``` The workaround (extract to a named word) works but creates friction for common patterns like `list.fold` callbacks that need temporary storage. ## Motivation When implementing algorithms that use `list.fold` with context beyond `(acc, elem)`, the natural pattern is to stash a value on aux inside the fold quotation. For example, Horner's polynomial evaluation: ```seq : eval-poly ( List Int -- Int ) swap list.reverse swap >aux 0 [ swap aux> dup >aux gf256-mul bxor ] list.fold aux> drop ; ``` Currently this requires extracting the fold body into a named word, which fragments the logic. ## Proposed Change Quotations are already compiled as separate LLVM functions with their own stack frames. The aux mechanism is compile-time `alloca` slots at function entry — the same approach used for named words. ### Typechecker (`typechecker.rs`) - Remove the `in_quotation_scope` guards in `infer_to_aux` (line ~1354) and `infer_from_aux` (line ~1385) - Track aux depth per-quotation using the quotation ID, extending `aux_max_depths` (currently keyed by word name) - The existing balance enforcement (aux must be empty at scope exit) already works per-scope ### Codegen (`codegen/words.rs`) - In `codegen_quotation` (line ~165), instead of clearing aux state defensively, look up the quotation's aux depth from `aux_slot_counts` and emit `alloca %Value` slots — the same pattern as word codegen (lines 81-89) - The quotation function gets its own `%aux_slot_0`, `%aux_slot_1`, etc., independent of the enclosing word ### Runtime No changes needed. Aux is purely compile-time allocas — zero overhead when not used. ## Risk Low. Quotation functions are already independent LLVM functions with their own frames. Adding allocas follows the established pattern. The typechecker already validates aux balance per-scope. --- *Context: discovered while implementing [Shamir's Secret Sharing](https://en.wikipedia.org/wiki/Shamir%27s_secret_sharing) in Seq, where Lagrange interpolation requires fold callbacks with extra context.*
navicore commented 2026-04-11 12:21:18 +00:00 (Migrated from github.com)
implementation planed in https://github.com/navicore/patch-seq/blob/main/docs/design/AUX_IN_QUOTATIONS.md https://github.com/navicore/patch-seq/commit/166fea176a803e0d2adbc070004d8d53e5e51a07
navicore commented 2026-04-11 20:58:04 +00:00 (Migrated from github.com)
https://github.com/navicore/patch-seq/pull/398
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
navicore/patch-seq#393
No description provided.