# Introspection The introspection family is how a running Deft program describes itself and its runtime. `deft/` round-trips values as source literals, parses arbitrary source into form trees, and highlights source text; `info/` queries the registry for modules, definitions, types, protocols, metadata, signatures, and source; `capture/` intercepts `echo` output for tests and tooling; and `capabilities` reports what the binary was compiled with. All are native stdlib, available without an import. ## Functions | Function | Purpose | |---|---| | `deft/stringify $value` | Serialize any value to a parseable Deft-literal string | | `deft/parse "source"` | Parse a literal string back to a value; data-only, no evaluation | | `deft/parse-forms "source"` | Parse arbitrary source into `%Sexpr{}` form trees; no evaluation | | `deft/syntax-highlight $source` | Tokenize Deft source into `%__HtmlSafe{:value "<html>"}` | | `info/modules` | Loaded namespace names | | `info/defs ?ns` | Defs in the current namespace, or in a named namespace | | `info/vars` | Vars visible in the current scope | | `info/types` | User-defined type names | | `info/protocols` | Registered protocol names | | `info/props value` | Metadata map for a value, namespace, or type | | `info/sig value` | Formatted signature string for a function | | `info/source value` | Source file and namespace for a symbol | | `info/resolve name` | Resolve a name through the namespace chain; value or `nil` | | `capture/start` | Install (or clear) the echo capture buffer; idempotent | | `capture/flush` | Drain the buffer and uninstall it; list of captured lines | | `capture/clear` | Discard the buffer without reading it | | `capture/with $thunk` | Scoped capture around a 0-arity callable | | `capabilities` | Compiled-in feature map for portability checks | Notes: - Literal round-trip. `deft/stringify` handles nil, booleans, numbers, strings, keywords, vectors, maps, tagged maps, and sets; `deft/parse` reads the result back. Parsing is data-only — function calls, infix expressions, variables, and statement keywords are rejected, which makes it safe to run on untrusted input. Bare identifiers are read as keywords, and a source with no literal value yields `nil`. - Form parsing. Unlike `deft/parse`, `deft/parse-forms` runs the full parser over any source and returns `%{ :forms @{%Sexpr{} ...}` :errors @{...} }`. Each form carries `:tag`, `:line`/`:col`, and a` payload (`:value`, `:items`, or `:pairs`); malformed source recovers with diagnostics in `:errors` rather than throwing. Use it for tooling that inspects code — importers, graph builders, linters. - Syntax highlighting. `deft/syntax-highlight` returns an HTML-escaped `%__HtmlSafe{ :value "..." }` where each token with a known type is wrapped in a Tailwind-classed `<span>` (keywords `text-cyan-400`, strings and keywords `text-green-400`, numbers `text-amber-400`, and so on). Lex failures fall back to plain escaped text, so the result always renders as source. - Registry queries. `info/modules`, `info/types`, and `info/protocols` return keyword lists; `info/defs` takes an optional namespace name and otherwise lists the current one; `info/vars` lists what is visible in scope. `info/props` returns a metadata map (doc text, declared return type, and other `@` tags), `info/sig` a formatted `name(args) -> type | doc` string, and `info/source` the source file and namespace — native functions report `%{ :ns core }`. `info/resolve` walks the namespace chain and returns the bound value or `nil`. - Output capture. `capture/start` redirects subsequent `echo`/`println` calls into a buffer; `capture/flush` returns one entry per call and uninstalls the buffer, and `capture/clear` drops it without reading. `capture/with` scopes the same behaviour around a zero-arity callable and returns `%{ :result $r :output $lines }`; it is safe to nest, restoring the previous buffer on exit. The test framework builds on these verbs. - Capabilities. The map reports `:pixels` (raster output really rasterizes), `:svg`, `:textures`, `:ffi`, and `:backend` (`:ansi` in the scripting binary and lean text build, `:gl` in the full TUI build). Branch on these instead of relying on silent no-ops in builds that lack a feature. ## Examples
# Literal round-trip
[deft/stringify %Point{ :x 1 :y 2 }]      # => "%Point{:y 2 :x 1}"
[deft/parse "%{:a 1 :b @{1 2 3}}"]        # => %{ :a 1 :b @{1 2 3} }

# Parse arbitrary source into positioned form trees (no evaluation)
set p [deft/parse-forms "set x [len \$xs]"]
[first $p~forms]                           # => %Sexpr{ :tag :list :line 1 :col 1 ... }
[get [first $p~errors] :message]           # diagnostics, not exceptions

# Inspect the registry
[info/modules]                             # => @{ :core :user }
[info/defs "core"]                         # defs exported from :core
[info/types]                               # user-defined type names
[info/protocols]                           # registered protocol names
[info/sig "str"]                           # => "str(...) -> string | ..."
[info/props "str"]                         # => metadata map (doc, returns, ...)
[info/source "str"]                        # => %{ :ns core }
[info/resolve "map"]                       # => <native-fn>

# Highlight a snippet the way the docs renderer does
[get [deft/syntax-highlight "set x 42"] :value]
# => "<span class=\"text-cyan-400\">set</span> x <span ...>42</span>"

# Assert on printed output without touching stdout
[capture/with { echo "hi" }]
# => %{ :output @{ "hi" } :result nil }

# Discover what this binary actually exposes
[capabilities]
# => %{ :textures false :svg false :ffi false :backend :ansi :pixels false }
[info/defs]                                # defs in the current namespace
## See Also - Utility — `eval`, `pretty`, and the rest of the grab-bag - Testing — `capture/*` inside `deftest` - Debug Server — inspecting a live runtime