diff --git a/sx/sx/essays.sx b/sx/sx/essays.sx index 9d0bbdf..aaa0ca3 100644 --- a/sx/sx/essays.sx +++ b/sx/sx/essays.sx @@ -259,3 +259,97 @@ "If you add a new host function and forget to declare it, the service will not start. If you return a disallowed type, the validation will catch it. The spec files are not documentation — they are the mechanism. The bootstrappers read them. The validators parse them. The contract is enforced by the same files that describe it.") (p :class "text-stone-600" "This closes the loop on self-hosting. The SX spec defines the language. The boundary spec defines the edge. The bootstrappers generate implementations from both. And the generated code validates itself against the spec at startup. The spec is the implementation is the contract is the spec.")))) + +(defcomp ~essay-sx-and-ai () + (~doc-page :title "SX and AI" + (p :class "text-stone-500 text-sm italic mb-8" + "Why s-expressions are the most AI-friendly representation for web interfaces — and what that means for how software gets built.") + + (~doc-section :title "The syntax tax" :id "syntax-tax" + (p :class "text-stone-600" + "Every programming language imposes a syntax tax on AI code generation. The model must produce output that satisfies a grammar — matching braces, semicolons in the right places, operator precedence, indentation rules, closing tags that match opening tags. The more complex the grammar, the more tokens the model wastes on syntactic bookkeeping instead of semantic intent.") + (p :class "text-stone-600" + "Consider what an AI must get right to produce a valid React component: JSX tags that open and close correctly, curly braces for JavaScript expressions inside markup, import statements with correct paths, semicolons or ASI rules, TypeScript type annotations, CSS-in-JS string literals with different quoting rules than the surrounding code. Each syntactic concern is a potential failure point. Each failure produces something that does not parse, let alone run.") + (p :class "text-stone-600" + "S-expressions have one syntactic form: " (code "(head args...)") ". Parentheses open and close. Strings are quoted. That is the entire grammar. There is no operator precedence because there are no operators. There is no indentation sensitivity because whitespace is not significant. There are no closing tags because there are no tags — just lists.") + (p :class "text-stone-600" + "The syntax tax for SX is essentially zero. An AI that can count parentheses can produce syntactically valid SX. This is not a small advantage — it is a categorical one. The model spends its capacity on " (em "what") " to generate, not " (em "how") " to format it.")) + + (~doc-section :title "One representation for everything" :id "one-representation" + (p :class "text-stone-600" + "A typical web project requires the AI to context-switch between HTML (angle brackets, void elements, boolean attributes), CSS (selectors, properties, at-rules, a completely different syntax from HTML), JavaScript (statements, expressions, classes, closures, async/await), and whatever templating language glues them together (Jinja delimiters, ERB tags, JSX interpolation). Each is a separate grammar. Each has edge cases. Each interacts with the others in ways that are hard to predict.") + (p :class "text-stone-600" + "In SX, structure, style, logic, and data are all s-expressions:") + (~doc-code :code (highlight ";; Structure\n(div :class \"card\" (h2 title) (p body))\n\n;; Style\n(cssx card-style\n :bg white :rounded-lg :shadow-md :p 6)\n\n;; Logic\n(if (> (length items) 0)\n (map render-item items)\n (p \"No items found.\"))\n\n;; Data\n{:name \"Alice\" :role \"admin\" :active true}\n\n;; Component definition\n(defcomp ~user-card (&key user)\n (div :class \"card\"\n (h2 (get user \"name\"))\n (span :class \"badge\" (get user \"role\"))))" "lisp")) + (p :class "text-stone-600" + "The AI learns one syntax and applies it everywhere. The mental model does not fragment across subsystems. A " (code "div") " and an " (code "if") " and a " (code "defcomp") " are all lists. The model that generates one can generate all three, because they are the same thing.")) + + (~doc-section :title "The spec fits in a context window" :id "spec-fits" + (p :class "text-stone-600" + "The complete SX language specification — evaluator, parser, renderer, primitives — lives in four files totalling roughly 3,000 lines. An AI model with a 200k token context window can hold the " (em "entire language definition") " alongside the user's codebase and still have room to work. Compare this to JavaScript (the " (a :href "https://ecma-international.org/publications-and-standards/standards/ecma-262/" :class "text-violet-600 hover:underline" "ECMAScript specification") " is 900+ pages), or the combined specifications for HTML, CSS, and the DOM.") + (p :class "text-stone-600" + "This is not just a convenience — it changes what kind of code the AI produces. When the model has the full spec in context, it does not hallucinate nonexistent features. It does not confuse one version's semantics with another's. It knows exactly which primitives exist, which special forms are available, and how evaluation works — because it is reading the authoritative definition, not interpolating from training data.") + (p :class "text-stone-600" + "The spec is also written in SX. " (code "eval.sx") " defines the evaluator as s-expressions. " (code "parser.sx") " defines the parser as s-expressions. The language the AI is generating is the same language the spec is written in. There is no translation gap between \"understanding the language\" and \"using the language\" — they are the same act of reading s-expressions.")) + + (~doc-section :title "Structural validation is trivial" :id "structural-validation" + (p :class "text-stone-600" + "Validating AI output before executing it is a critical safety concern. With conventional languages, validation means running a full parser, type checker, and linter — each with their own error recovery modes and edge cases. With SX, structural validation is: " (em "do the parentheses balance?") " That is it. If they balance, the expression parses. If it parses, it can be evaluated.") + (p :class "text-stone-600" + "This makes it trivial to build AI pipelines that generate SX. Parse the output. If it parses, evaluate it in a sandbox. If it does not parse, the error is always the same kind — unmatched parentheses — and the fix is always mechanical. There is no \"your JSX is invalid because you used " (code "class") " instead of " (code "className") "\" or \"you forgot the semicolon after the type annotation but before the generic constraint.\"") + (p :class "text-stone-600" + "Beyond parsing, the SX " (a :href "/specs/primitives" :class "text-violet-600 hover:underline" "boundary system") " provides semantic validation. A pure component cannot call IO primitives — not by convention, but by the evaluator refusing to resolve them. An AI generating a component can produce whatever expressions it wants; the sandbox ensures only permitted operations execute. Validation is not a separate step bolted onto the pipeline. It is the language.")) + + (~doc-section :title "Components are self-documenting" :id "self-documenting" + (p :class "text-stone-600" + "A React component's interface is spread across prop types (or TypeScript interfaces), JSDoc comments, Storybook stories, and whatever documentation someone wrote. An AI reading a component must synthesize information from multiple sources to understand what it accepts and what it produces.") + (p :class "text-stone-600" + "An SX component declares everything in one expression:") + (~doc-code :code (highlight "(defcomp ~product-card (&key title price image &rest children)\n (div :class \"rounded border p-4\"\n (img :src image :alt title)\n (h3 :class \"font-bold\" title)\n (span :class \"text-lg\" (format-price price))\n children))" "lisp")) + (p :class "text-stone-600" + "The AI reads this and knows: it takes " (code "title") ", " (code "price") ", and " (code "image") " as keyword arguments, and " (code "children") " as rest arguments. It knows the output structure — a " (code "div") " with an image, heading, price, and slot for children. It knows this because the definition " (em "is") " the documentation. There is no separate spec to consult, no type file to find, no ambiguity about which props are required.") + (p :class "text-stone-600" + "This self-describing property scales across the entire component environment. An AI can " (code "(map ...)") " over every component in the registry, extract all parameter signatures, build a complete map of the UI vocabulary — and generate compositions that use it correctly, because the interface is declared in the same language the AI is generating.")) + + (~doc-section :title "Token efficiency" :id "token-efficiency" + (p :class "text-stone-600" + "LLMs operate on tokens. Every token costs compute, latency, and money. The information density of a representation — how much semantics per token — directly affects how much an AI can see, generate, and reason about within its context window and output budget.") + (p :class "text-stone-600" + "Compare equivalent UI definitions:") + (~doc-code :code (highlight ";; SX: 42 tokens\n(div :class \"card p-4\"\n (h2 :class \"font-bold\" title)\n (p body)\n (when footer\n (div :class \"mt-4 border-t pt-2\" footer)))" "lisp")) + (~doc-code :code (highlight "// React/JSX: ~75 tokens\n
{body}
\n {footer && (\n