Header

译自:What are denotations, exactly? 。除非特殊声明,文中「我」指原文作者 Oleg Kiselyov。

指称语义通常被描述为:利用数学对象解释表达式(语法对象)。那么,所谓『数学对象』究竟是什么?OCaml 代码可以是数学对象吗?花些时间去思考到底什么是指称语义是值得的。

在最早一批的诸多『指称语义』的定义中,Landin 指出(Landin 1966,第 8 节)

The commonplace expressions of arithmetic and algebra have a certain simplicity that most communications to computers lack. In particular, (a) each expression has a nesting subexpression structure, (b) each subexpression denotes something (usually a number, truth value or numerical function), (c) the thing an expression denotes, i.e., its `value’, depends only on the values of its subexpressions, not on other properties of them.
译文:算术和代数中常见的表达式有一种简洁性,绝大多数与计算机交流的工具(编程语言)都缺乏这种特性。即:(a)每个表达式都有嵌套的子表达式结构,(b)每个子表达式都有一个『指称』以指代某物(通常是数字,真值或者数值函数),(c)表达式所指称的,或者说它的『值』,仅基于其子表达式的值,而非子表达式的其他特性。

Landin 随后以字符串 'wine' 为例,分别用自然语言和 ISWIM 编程语言中的『等价类(equivalence class)』概念定义了其指称语义,

而在我们引用的文本中(Mosses 1990,第 3.1 节),Mosses 的定义本质上重复了 Landin 的定义,并补充道

It should be noted that the semantic analyst is free to choose the denotations of phrases – subject to compositionality’’.
译文:应当指出的是,语义分析家可以自由选择语句的『指称』--只要该指称满足组合性

他指出,让语句作为自身的指称技术上来说是可组合的,因此也可以作为一种指称语义--尽管这种做法的抽象性质是极其糟糕的。不过他又说道,在两种情况下把语句作为自身的指称是有必要的,例如标识符(identifier)。

由上可见,使用抽象的数学集合或者域之外的东西作为指称语义是有先例的。只要满足组合性原则,甚至语法对象也可作为指称语义。在 Eff direct in OCaml 中,我们使用具有外延性的 OCaml 值作为语义对象,因此检查函数之间是否相等的问题等价于到推理两个 OCaml 函数在相同参数的情况下是否会返回外延相等的值。具体的做法是:观察函数参数相等时 OCaml(字节码)解释器如何求值这些函数。字节码解释器的行为是明确定义的,我们用作例子的代码被 OCaml 编译生成的字节码片段也易于理解(包括 Obj.magic,其操作语义为 identity)。对于该文章中的核心思想 delimcc 的充分性的证明正是此类推理的一个很好的示例。

使用解释器来定义语言早有先例,Reynold 在 1972 年发表的文章正是如此。而 Schmidt 在 1996 年发布的调查中也提到了这种方法:

A pragmatist might view an operational or denotational semantics as merely an `interpreter’ for a programming language. Thus, to define a semantics for a general-purpose programming language, one writes an interpreter that manipulates data structures like symbol tables (environments) and storage vectors (stores). For example, a denotational semantics for an imperative language might use an environment, e, and a store, s, along with an environment lookup operation, find, and a storage update operation, update. Since data structures like symbol tables and storage vectors are explicit, a language’s subtleties are stated clearly and its flaws are exposed as awkward codings in the semantics.
译文:实用主义者可能会将编程语言的操作语义或指称语义看作一种『解释器』。当某人要为一个通用编程语言定义语义时,他只需写一个操纵符号表(绑定环境)和存储向量(存储)的解释器。以一种命令式语言为例,该语言的指称语义可能会用到一个环境 e,一个存储 s,以及环境查询操作 lookup 和存储更新操作 update。由于符号表和存储向量是明确的,所以我们可以清楚地看出语言中的微妙之处,并且语义解释器中笨拙的编码方式表示了语言的缺陷。

参考

上述对指称语义的介绍即是该论文的第 3.1.4 节

  • Peter J. Landin: The Next 700 Programming Languages

Comm. ACM, v9 N3, March 1966, pp. 157-166. doi:10.1145/365230.365257

  • Peter D. Mosses: Denotational Semantics

In:Handbook of Theoretical Computer Science B: Formal Models and Semantics, Ed. J. van Leewen, MIT Press, 1990. Chap 11, pp. 577-631.

  • David A. Schmidt: Programming Language Semantics

ACM Computing Surveys, v28 N1, March 1996, pp. 265-267. doi:10.1145/234313.234419

  • John C. Reynolds: Definitional Interpreters for Higher-Order Programming Languages

Proc. of the ACM National Conference 1972. Reprinted: Higher-Order and Symbolic Computation, v11 N4, 1998, pp. 363-397. doi:10.1023/A:1010027404223