# 自省 自省系列是运行中的 Deft 程序描述自身及其运行时的方式。`deft/` 在值与源码字面量之间往返转换、把任意源码解析为形式树,并对源码文本做高亮;`info/` 查询注册表中的模块、定义、类型、协议、元数据、签名和源码;`capture/` 为测试和工具拦截 `echo` 输出;`capabilities` 报告二进制在编译时内置了哪些能力。它们都是原生标准库,无需导入即可使用。 ## 函数 | 函数 | 用途 | |---|---| | `deft/stringify $value` | 将任意值序列化为可解析的 Deft 字面量字符串 | | `deft/parse "source"` | 把字面量字符串解析回值;仅处理数据,不求值 | | `deft/parse-forms "source"` | 把任意源码解析为 `%Sexpr{}` 形式树;不求值 | | `deft/syntax-highlight $source` | 将 Deft 源码分词为 `%__HtmlSafe{:value "<html>"}` | | `info/modules` | 已加载的命名空间名称 | | `info/defs ?ns` | 当前命名空间或指定命名空间中的定义 | | `info/vars` | 当前作用域中可见的变量 | | `info/types` | 用户定义的类型名称 | | `info/protocols` | 已注册的协议名称 | | `info/props value` | 值、命名空间或类型的元数据映射 | | `info/sig value` | 函数的格式化签名字符串 | | `info/source value` | 符号的源文件与命名空间 | | `info/resolve name` | 沿命名空间链解析名称;返回值或 `nil` | | `capture/start` | 安装(或清除)echo 捕获缓冲区;幂等 | | `capture/flush` | 排空并卸载缓冲区;返回捕获行的列表 | | `capture/clear` | 丢弃缓冲区而不读取 | | `capture/with $thunk` | 围绕 0 元可调用对象的作用域捕获 | | `capabilities` | 编译时内置的能力映射,用于可移植性检查 | 说明: - 字面量往返。 `deft/stringify` 处理 nil、布尔值、数字、字符串、关键字、向量、映射、带标签的映射和集合;`deft/parse` 把结果读回来。解析仅处理数据 —— 函数调用、中缀表达式、变量和语句关键字都会被拒绝,因此可以安全地用于不受信任的输入。裸标识符会被读作关键字,没有任何字面量值的源码则得到 `nil`。 - 形式解析。 与 `deft/parse` 不同,`deft/parse-forms` 对任意源码运行完整的解析器,并返回 `%{ :forms @{%Sexpr{} ...} :errors @{...} }`。每个形式都带有 `:tag`、`:line`/`:col` 以及一个负载(`:value`、`:items` 或 `:pairs`);畸形源码会在 `:errors` 中给出诊断信息后恢复,而不是抛出异常。用它来构建检查代码的工具 —— 导入器、图构建器、linter。 - 语法高亮。 `deft/syntax-highlight` 返回经过 HTML 转义的 `%__HtmlSafe{ :value "..." }`,其中每个具有已知类型的词元都被包裹在带 Tailwind 类的 `<span>` 中(关键字为 `text-cyan-400`,字符串和关键字为 `text-green-400`,数字为 `text-amber-400`,等等)。词法分析失败时回退为纯转义文本,因此结果总能作为源码渲染。 - 注册表查询。 `info/modules`、`info/types` 和 `info/protocols` 返回关键字列表;`info/defs` 接受一个可选的命名空间名称,否则列出当前命名空间;`info/vars` 列出作用域中可见的内容。`info/props` 返回元数据映射(文档文本、声明的返回类型以及其他 `@` 标签),`info/sig` 返回格式化的 `name(args) -> type | doc` 字符串,`info/source` 返回源文件和命名空间 —— 原生函数报告 `%{ :ns core }`。`info/resolve` 沿命名空间链查找并返回绑定的值或 `nil`。 - 输出捕获。 `capture/start` 把随后的 `echo`/`println` 调用重定向到缓冲区;`capture/flush` 为每次调用返回一个条目并卸载缓冲区,`capture/clear` 则在不读取的情况下丢弃它。`capture/with` 将相同行为限定在零元可调用对象的作用域内,并返回 `%{ :result $r :output $lines }`;它可以安全嵌套,退出时恢复之前的缓冲区。测试框架就建立在这些动词之上。 - 能力。 该映射报告 `:pixels`(栅格输出确实会栅格化)、`:svg`、`:textures`、`:ffi` 和 `:backend`(脚本二进制和精简文本构建中为 `:ansi`,完整 TUI 构建中为 `:gl`)。请根据这些字段分支,而不要依赖缺少某特性的构建中的静默空操作。 ## 示例
# 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
## 另见 - 实用工具 —— `eval`、`pretty` 以及其余杂项 - 测试 —— `deftest` 中的 `capture/*` - 调试服务器 —— 检查运行中的运行时