Software Open Access
Arjen Rouvoet; Hendrik van Antwerpen; Casper Bach Poulsen; Robbert Krebbers; Eelco Visser
There is a large gap between the specification of type systems and the
implementation of their type checkers, which impedes reasoning about the
soundness of the type checker with respect to the specification. A vision to
close this gap is to automatically obtain type checkers from declarative
programming language specifications. This moves the burden of proving
correctness from a case-by-case basis for concrete languages, to a single
correctness proof for the specification language.
This vision is obstructed by an aspect common to all programming languages: name
resolution. Naming and scoping are pervasive and complex aspects of the static
semantics of programming languages. Implementations of type checkers for
languages with name binding features such as modules, imports, classes, and
inheritance interleave collection of binding information (i.e., declarations,
scoping structure, and imports) and querying that information. This requires
scheduling those two aspects in such a way that query answers are stable---i.e.,
they are computed only after all relevant binding structure has been collected.
Type checkers for concrete languages accomplish stability using
language-specific knowledge about the type system.
In this paper we give a language-independent characterization of necessary and
sufficient conditions to guarantee stability of name and type queries during
type checking in terms of _critical edges in an incomplete scope graph_.
We use critical edges to give a formal small-step operational semantics to a
declarative specification language for type systems, that achieves soundness by
delaying queries that may depend on missing information. This yields type
checkers for the specified languages that are sound by construction---i.e., they
schedule queries so that the answers are stable, and only accept programs that
are name- and type-correct according to the declarative language specification.
We implement this approach, and evaluate it against specifications of a small
module and record language, as well as subsets of Java and Scala.