Block quasiquote and #block: layout expansion

A block backtick reads raw #block: conses and wraps them in a synthetic (#block: (quasiquote) INNER) form. The layout/quasiquote handler lowers that to (quasiquote INNER) for compilation. The quasiquote fills the unquote sites and leaves the #block: structure alone, so a filled block is still reader form, not source the compiler accepts.

Module reading expands blocks as it goes. Macro expansion applies the layout handlers to a transformer’s output before the captured material is unboxed, so a macro whose template is a block quasiquote needs no extra step. Code that builds a #block: cons at run time and wants source out of it calls apply-layout or apply-layouts.

apply-layout

(apply-layout BLOCK TARGET) expands one form. TARGET is a LayoutReader, or a namespace whose module owns one – (globals) at module level. A #block: cons is expanded through the layout/HEAD handler for its head; any other form is returned unchanged. Expansion is depth-first, and peer blocks that a handler declares are consumed from the block’s entries.

>>> var forms '(1 2 3)
>>> var tmpl:
...   `begin:
...     ,@forms
>>> tmpl
(#block: (begin) (#splice: 1 2 3))
>>> (apply-layout tmpl (globals))
(begin 1 2 3)
>>> (evaluate (apply-layout tmpl (globals)) (globals))
3

apply-layouts

(apply-layouts FORMS TARGET) walks a proper cons list of forms and expands each one, returning the list of results. Forms that are not blocks pass through. A declared peer block is consumed from the spine following its primary block, so if and its else peer collapse into one form:

>>> var b1:
...   `if (> 2 1):
...     "yes"
>>> var b2:
...   `begin:
...     (+ 1 2)
>>> (apply-layouts (cons b1 b2 '(x) nil) (globals))
((cond ((> 2 1) "yes")) (begin (+ 1 2)) (x))

if lowers to cond, which is the special the layout reads to.

See also: Block quote, Block quasiquote, Layout forms.