In a naive big-step semantics, one can't tell the difference between the following two programs, even though their behavior is quite different according to single-step reduction rules. fix(λf.λy.fy)3
The naive big-step semantics that I'm referring to is the following. The ρ maps variables to values (parameters to their arguments), and is called the environment. ρ⊢x⇓ρ(x)ρ⊢λx.e⇓⟨λx.e,ρ⟩ρ⊢e1⇓⟨λx.e′,ρ′⟩ρ⊢e2⇓v′ρ′[x↦v′]⊢e′⇓vρ⊢e1e2⇓vρ⊢e⇓⟨λf.e′,ρ′⟩ρ′[f↦⟨λf.e′,ρ′⟩]⊢e′⇓vρ⊢fixe⇓v
Trouble formulating type safety
This inability to distinguish between divergence and stuck makes it difficult to formulate type safety using a naive big-step semantics. The following statement is true but not very strong. If ∅⊢e:T and ∅⊢e⇓v then ∅⊢v:T.
Several textbooks stop at this point and just say that the above is a problem with big-step semantics. Not true! There are several solutions to this problem in the literature. I've included papers that address the divergence/stuck issue at the bottom of this blog. If you know of others, please let me know! The solutions I've seen fall into three categories:
- Introduce a separate co-inductive definition of divergence for the language in question.
- Develop a notion of partial derivations.
- Add a time counter that causes a time-out error when it gets to zero. That is, make the semantics step-indexed.
Big-step Semantics with Counters
The first part of the solution is to augment the big-step semantics with a counter k, making sure to decrement the counter in the premises of each rule. ρ;k⊢x⇓ρ(x)ρ;k⊢λx.e⇓⟨λx.e,ρ⟩ρ;k−1⊢e1⇓⟨λx.e′,ρ′⟩ρ;k−1⊢e2⇓v′ρ′[x↦v′];k−1⊢e′⇓vρ;k⊢e1e2⇓vρ;k−1⊢e⇓⟨λf.e′,ρ′⟩ρ′[f↦⟨λf.e′,ρ′⟩];k−1⊢e′⇓vρ;k⊢fixe⇓v
With the addition of the counter, we can always build a derivation for a diverging program, with the result being a time out, no matter how high you set the counter to begin with. However, for a program that gets stuck, there will be some starting counter that is high enough so that you can't build a derivation anymore (you might have been able to get time outs with lower values).
The type safety theorem can now be stated in a way that is both strong enough and true! Let r range over both values and the time out. For any k, if ∅⊢e:T then ∅;k⊢e⇓r and ∅⊢r:T for some r.
One parting comment. The addition of propagation rules was rather annoying. I'll discuss how to avoid propagation rules in big-step semantics in an upcoming blog post, summarizing a talk I gave at Scottish Programming Languages Seminar in 2010.
References
- C. A. Gunter and D. Rémy. A Proof-Theoretic Assesment of Runtime Type Errors. AT&T Bell Laboratories Technical Memo 11261-921230-43TM, 1993.
- A. Stoughton. An operational semantics framework supporting the incremental construction of derivation trees. Electr. Notes Theor. Comput. Sci., 10, 1997.
- H. Ibraheem and D. A. Schmidt. Adapting big-step semantics to small-step style: Coinductive interpretations and “higher-order” derivations. In Second Workshop on Higher-Order Techniques in Operational Semantics (HOOTS2). Elsevier, 1997.
- Kathleen Fisher and John Reppy. Statically typed traits. University of Chicago, technical report TR-2003-13, December 2003.
- Erik Ernst, Klaus Ostermann, and William R. Cook. A Virtual Class Calculus. In POPL 2006.
- Xavier Leroy and Herve Grall. Coinductive big-step operational semantics. Journal of Information and Computation. Vol. 207, Issue 2, February 2009.
- Big-step Operational Semantics Revisited, by Jarosław Dominik, Mateusz Kuśmierek, and Viviana Bono. In Fundamenta Informaticae Volume 103, Issue 1-4, January 2010.
I did a double take on the statement 42 3 because it looked to me like 423. You might want to increase the space to \: or even \;.
ReplyDeleteTypo: JarosłAw should be Jarosław.
Thanks, fixed!
Delete