“这些约束属于静态语义。借用检查算法可以用词法作用域、数据流或非词法生命周期推断 $\rho$,并保守拒绝无法证明安全的程序。运行语义仍由堆、位置和更新组成的可变状态语义给出;类型系统的可靠性…”
形式陈述 ​
操作语义把存储
变量环境与存储必须分开:前者把源语言变量映到值或位置,后者把位置映到当前内容。是否可观察位置身份、何时回收不可达位置,以及分配失败如何处理,都属于具体语言语义的一部分。
若还要证明类型安全,静态语义通常加入存储类型
直觉
纯 λ 演算中,变量可由值替换;一旦引入可变引用,同一个位置的内容会随时间改变,程序含义便依赖“现在的存储是什么”。最有效的图像是两层映射:变量名找到一个抽屉编号,存储记录每个抽屉此刻装什么。别名使两个不同表达式指向同一抽屉,因此局部赋值可能被远处代码观察到。闭包捕获可变变量时也通常保存这个位置,而非复制某一时刻的内容。
例子与边界
程序 let r = ref 0 in r := 1; !r 先分配新位置 s = r,则 s := 2 后 !r 也为 r 与 s 是同一位置的别名。
边界是把赋值误作普通代换。表达式 f(r); !r 的结果取决于 f 是否能写入该位置,不能把 r 在源码中简单替换为初始值。垃圾回收通常不改变可观察语义,但若语言暴露地址、终结器或弱引用,就需要更细致的等价条件。
推论与应用
可变状态语义为命令式语言、对象、数组和函数共享可变位置提供基础。分离逻辑以堆的可分资源结构支持局部推理,所有权与借用则用静态 owner、loan 和生命周期限制别名访问;两者都建立在位置与存储之上,却不是运行配置本身。
在并发环境中,多个线程共享
参考资料
- Robert Harper, Practical Foundations for Programming Languages, 2nd ed., Cambridge University Press, 2016,Chs. 34–36, state, references, and store typing。
- Glynn Winskel, The Formal Semantics of Programming Languages, MIT Press, 1993,Chs. 2–5, transition semantics with stores。