Add canonical SX language spec reference to CLAUDE.md
Points AI and developers to shared/sx/ref/ as the authoritative source for SX semantics — eval rules, type system, rendering modes, component calling convention, and platform interface. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
67
CLAUDE.md
67
CLAUDE.md
@@ -52,6 +52,65 @@ artdag/
|
||||
test/ # Integration & e2e tests
|
||||
```
|
||||
|
||||
## SX Language — Canonical Reference
|
||||
|
||||
The SX language is defined by a self-hosting specification in `shared/sx/ref/`. **Read these files for authoritative SX semantics** — they supersede any implementation detail in `sx.js` or Python evaluators.
|
||||
|
||||
### Specification files
|
||||
|
||||
- **`shared/sx/ref/eval.sx`** — Core evaluator: types, trampoline (TCO), `eval-expr` dispatch, special forms (`if`, `when`, `cond`, `case`, `let`, `and`, `or`, `lambda`, `define`, `defcomp`, `defmacro`, `quasiquote`), higher-order forms (`map`, `filter`, `reduce`, `some`, `every?`, `for-each`), macro expansion, function/lambda/component calling.
|
||||
- **`shared/sx/ref/parser.sx`** — Tokenizer and parser: grammar, string escapes, dict literals `{:key val}`, quote sugar (`` ` ``, `,`, `,@`), serializer.
|
||||
- **`shared/sx/ref/primitives.sx`** — All ~80 built-in pure functions: arithmetic, comparison, predicates, string ops, collection ops, dict ops, format helpers, CSSX style primitives.
|
||||
- **`shared/sx/ref/render.sx`** — Three rendering modes: `render-to-html` (server HTML), `render-to-sx`/`aser` (SX wire format for client), `render-to-dom` (browser). HTML tag registry, void elements, boolean attrs.
|
||||
- **`shared/sx/ref/bootstrap_js.py`** — Transpiler: reads the `.sx` spec files and emits `sx-ref.js`.
|
||||
|
||||
### Type system
|
||||
|
||||
```
|
||||
number, string, boolean, nil, symbol, keyword, list, dict,
|
||||
lambda, component, macro, thunk (TCO deferred eval)
|
||||
```
|
||||
|
||||
### Evaluation rules (from eval.sx)
|
||||
|
||||
1. **Literals** (number, string, boolean, nil) — pass through
|
||||
2. **Symbols** — look up in env, then primitives, then `true`/`false`/`nil`, else error
|
||||
3. **Keywords** — evaluate to their string name
|
||||
4. **Dicts** — evaluate all values recursively
|
||||
5. **Lists** — dispatch on head:
|
||||
- Special forms (`if`, `when`, `cond`, `case`, `let`, `lambda`, `define`, `defcomp`, `defmacro`, `quote`, `quasiquote`, `begin`/`do`, `set!`, `->`)
|
||||
- Higher-order forms (`map`, `filter`, `reduce`, `some`, `every?`, `for-each`, `map-indexed`)
|
||||
- Macros — expand then re-evaluate
|
||||
- Function calls — evaluate head and args, then: native callable → `apply`, lambda → bind params + TCO thunk, component → parse keyword args + bind params + TCO thunk
|
||||
|
||||
### Component calling convention
|
||||
|
||||
```lisp
|
||||
(defcomp ~card (&key title subtitle &rest children)
|
||||
(div :class "card"
|
||||
(h2 title)
|
||||
(when subtitle (p subtitle))
|
||||
children))
|
||||
```
|
||||
|
||||
- `&key` params are keyword arguments: `(~card :title "Hi" :subtitle "Sub")`
|
||||
- `&rest children` captures positional args as `children`
|
||||
- Component body evaluated in merged env: `closure + caller-env + bound-params`
|
||||
|
||||
### Rendering modes (from render.sx)
|
||||
|
||||
| Mode | Function | Expands components? | Output |
|
||||
|------|----------|-------------------|--------|
|
||||
| HTML | `render-to-html` | Yes (recursive) | HTML string |
|
||||
| SX wire | `aser` | No — serializes `(~name ...)` | SX source text |
|
||||
| DOM | `render-to-dom` | Yes (recursive) | DOM nodes |
|
||||
|
||||
The `aser` (async-serialize) mode evaluates control flow and function calls but serializes HTML tags and component calls as SX source — the client renders them. This is the wire format for HTMX-like responses.
|
||||
|
||||
### Platform interface
|
||||
|
||||
Each target (JS, Python) must provide: type inspection (`type-of`), constructors (`make-lambda`, `make-component`, `make-macro`, `make-thunk`), accessors, environment operations (`env-has?`, `env-get`, `env-set!`, `env-extend`, `env-merge`), and DOM/HTML rendering primitives.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
**Web platform:** Python 3.11+, Quart (async Flask), SQLAlchemy (asyncpg), Jinja2, HTMX, PostgreSQL, Redis, Docker Swarm, Hypercorn.
|
||||
@@ -110,11 +169,11 @@ cd artdag/l1 && mypy app/types.py app/routers/recipes.py tests/
|
||||
|
||||
### SX Rendering Pipeline
|
||||
|
||||
The SX system renders component trees defined in s-expressions. The same AST can be evaluated in different modes depending on where the server/client rendering boundary is drawn:
|
||||
The SX system renders component trees defined in s-expressions. Canonical semantics are in `shared/sx/ref/` (see "SX Language" section above). The same AST can be evaluated in different modes depending on where the server/client rendering boundary is drawn:
|
||||
|
||||
- `render_to_html(name, **kw)` — server-side, produces HTML. Used by route handlers returning full HTML.
|
||||
- `render_to_sx(name, **kw)` — server-side, produces SX wire format. Component calls stay **unexpanded** (serialized for client-side rendering by sx.js).
|
||||
- `render_to_sx_with_env(name, env, **kw)` — server-side, **expands the top-level component** then serializes children as SX wire format. Used by layout components that need Python context (auth state, fragments, URLs) resolved server-side.
|
||||
- `render_to_html(name, **kw)` — server-side, produces HTML. Maps to `render-to-html` in the spec.
|
||||
- `render_to_sx(name, **kw)` — server-side, produces SX wire format. Maps to `aser` in the spec. Component calls stay **unexpanded**.
|
||||
- `render_to_sx_with_env(name, env, **kw)` — server-side, **expands known components** then serializes as SX wire format. Used by layout components that need Python context.
|
||||
- `sx_page(ctx, page_sx)` — produces the full HTML shell (`<!doctype html>...`) with component definitions, CSS, and page SX inlined for client-side boot.
|
||||
|
||||
See the docstring in `shared/sx/async_eval.py` for the full evaluation modes table.
|
||||
|
||||
Reference in New Issue
Block a user