D0006: Type System
Notist 最终需要完整的静态类型系统,同时保留运行时 Value。静态类型负责在执行前验证表达式和函数调用;Value 负责承载已经求值的数据,并交给 native、user 或 plugin function 执行。
Function API 使用结构化参数,避免每个函数自行解释字符串;类型能力可以逐步扩展,但不会改变 Type、Value 与 binding 的分工。
Functions Produce Content
heading、raw、quote 等“processor”本质上都是 callable function:
#heading(level=1)[Introduction]
#raw(text=`fn main() {}`, lang="rust")
#quote[quoted *content*]它们可以具有普通函数签名:
heading(level: Int = 1, body: Content) -> Content
raw(text: String, lang: String? = none) -> Content
quote(attribution: Content? = none, body: Content) -> Content因此不需要长期维护独立的 Processor type 和 ProcessorRegistry。统一系统包含 Function、FunctionRegistry、FunctionInput、FunctionOutput 和 FunctionContext。
Core Types
核心类型集合包括:
NoneBoolIntFloatStringContentArray<T>Dict<K, V>或结构化 recordFunction
Content 是可组合的语义 Element sequence,不是普通字符串。Raw source 由 host syntax 产生 String,并通过独立 source range 保留诊断映射;String 只有在显式插入 Content 时才转换为 Text。
类型还需要可选类型、联合类型或等价能力,以表达 String?、none 和未来更精确的参数约束。
Runtime Value
即使拥有静态类型,运行时仍需要 Value:
Value
├─ None
├─ Bool(bool)
├─ Int(i64)
├─ Float(f64)
├─ String(String)
├─ Content(Content)
├─ Array(Vec<Value>)
├─ Dict(...)
└─ Function(...)Type 描述表达式“可以产生什么”,Value 表示本次执行“实际产生了什么”。常量求值、默认参数、用户函数和控制流都需要 Value。
Expressions and Binding
函数参数的最终流程:
source arguments
-> Expression AST
-> name resolution
-> type inference/checking
-> evaluation to Value
-> signature binding
-> Function call例如:
#heading(level=1 + depth)[Title]parser 产生 Expression AST;analysis 解析 depth;type checker 确认表达式为 Int;eval 得到具体 Value;binder 将它绑定到 level。
Function Signature 至少描述:
参数名称与顺序。
positional/named 调用规则。
参数类型。
required/optional/default。
trailing body 类型。
返回类型。
完成 binding 后,native function 不再读取参数源码字符串。
User-Defined Functions
统一 Function 模型后,可以自然支持 Typst 风格的用户函数。建议先采用显式类型:
#let add(a: Int, b: Int) -> Int = a + b
#let warning(
title: String = "Warning",
body: Content,
) -> Content = #quote[
#heading(level=3)[#title]
#body
]Function 可以有三种实现来源:
Native Function:由 Notist 核心实现。
User Function:由 Notist 源码定义。
Plugin Function:由扩展提供。
三者共享名称解析、signature、参数 binding、Value 和返回类型检查。差异只在执行后端与权限边界。
Syntax Sugar
语法糖由 parser 直接识别,但其语义应归一到内置 Element 构造器:
= Title
-> builtin heading constructor
`raw`
-> builtin raw constructor语法糖不能通过动态名称查找改变含义。即使用户定义同名 heading,= Title 仍表示核心 Heading。显式 #heading[...] 是否允许局部遮蔽,则由名称解析规则决定。
插件可以注册函数并使用通用 Call 语法,但不能直接修改核心 grammar。未来的用户宏或声明式 sugar 应作为独立系统设计。
Analysis and Evaluation
静态 analysis 负责:
建立 module 和 lexical scope。
名称解析与 symbol identity。
推断或检查 Expression 类型。
解析 Function Signature。
校验参数、trailing Content 和返回类型。
产生不执行用户代码的 diagnostics。
Evaluation 负责:
求值 Expression AST 为 Value。
应用默认参数并完成运行时 binding。
执行 Native/User/Plugin Function。
产生 Content 和运行时 diagnostics。
Type checking 不执行 Function。这样 LSP 可以快速、确定地分析未保存或不完整的文档。