# Class 11: Introduction to Formal Semantics

Held Wednesday, February 17

Summary

Contents

Handouts

Notes

• I hadn't intended to talk more about continuation-passing style (CPS), but I've received enough questions that it clearly warrants at least a little bit more discussion.
• Cool Statistics Talk tomorrow at 4:15/4:30. Be there, or never quite understand the meaning of truth (since everything that's not Bayesian statistics is wrong, at least according to the presenter).
• Next Monday at noon, there's a CS brown bag lunch discussing summer opportunities for research in CS at Grinnell. (The seniors may not care, but the rest of you should.)
• Any final questions on the exam?

## CPS, Revisited

• In CPS, functions take a continuation as an argument. The continuation specifies what to do with the result.
• How do you convert a function to CPS?
• First, build a new version of the function that takes a continuation as an argument and applies that continuation to your results.
```;;; Compute the stripes value.
(function (zebra alpha beta)
...
stripes)
;;; Compute the stripes value and then apply a continuation to it.
(function (zebra-cps alpha beta cont)
...
(cont stripes))
```
• Next, identify any recursive calls to the original function.
```(function (zebra-cps alpha beta cont)
(begin
(stuff)
(morestuff (zebra antelope bear))
(evenmorestuff)
(cont stripes)))
```
• For each recursive call, determine the context of that call (the continuation)
```(lambda (recursive-result)
(begin
(morestuff recursive-result)
(evenmorestuff)
(cont stripes)))
```
• Convert the recursive call to the original function into a recursive call to the CPS version.
```(function (zebra-cps alpha beta cont)
(begin
(stuff)
(zebra-cps antelope bear (lambda (recursive-result)
(begin
(morestuff recursive-result)
(evenmorestuff)
(cont stripes))))))
```
• Note that CPS makes more sense if you write and read it in a particular way.
```(foo-cps stuff (lambda (x)
(computation)))
```
• ``Do foo using stuff. Call the result x. Then do the computation.''
• We'll try this with the Fibonacci function, defined as
```(define (fib n)
(if (< n 0) 1
(+ (fib (- n 1)) (fib (- n 2)))))
```

## Introduction to Formal Semantics

• When describing a programming language it is necessary to specify not only the syntax (what programs look like) but also the semantics (what programs mean).
• Traditionally, semantics have been specified informally. However, this leads to many ambiguities when the designers don't consider all the alternatives:
• In many informal definitions, it is unclear in what order the various function calls are done in `f1()+f2()+f3()` (the order of addition is clear, but it's not always specified which argument is fully evaluated first).
• In many informal definitions, no effort is made to handle error cases other than to say that they're in error.
• In many informal definitions, it is unclear how the various parts of the language interact (can I have a const ref? What does it mean?)
• ...
• Often, it is up to the implementers of languages to make these decisions. Different implementers make different decisions, which leads to incompatible implementations.
• Clearly, implementers should be able to make some decisions (e.g., where in memory to put values). However, most informal definitions don't make it clear what belongs in the hands of the implementer, and what belongs in the hands of the language designer.
• What is the solution? Currently, the trend is to define a formal semantics for the language based on rules of logic.
• Of course, a bad formal specification is no better than a casual specification.
• The use of logics and formal systems can help us ensure that we don't make mistakes.
• But it may be hard to read formal notation.
• What are typical informal and formal semantics?
• ``Casual'' semantics: English text describing what each part does. Likely to lead to misinterpretation, particularly as we concern ourselves with the interaction of different parts of the language.
• ``Implementational'' semantics: meaning is based on a particular implementation.
• Translational semantics: meaning is based on a formal translation of the language to another language. Often, these translations are done via an attribute grammar. [In some sense, the transitional semantics is a more formalized implementational semantics based on compilation.]
• Operational semantics: meaning is given by specifying the effects of any program on any input. Typically, this is done via an interpreter. [Similarly, the translational semantics is an implementational semantics based on interpretation.]
• Denotational semantics: Every program has an associated meaning (a denotation), given by a Meaning function (the semantics). For some, this seems similar to translational semantics with the destination language being something very similar to the lambda calculus (generic functional programs). The translation is described more with function definitions than with attributes (although there is again some similarity). The advantage here is that the destination is well understood.

History

• Created Tuesday, January 19, 1999 as a blank outline.
• Added details on Wednesday, February 17, 1999. Some parts were based on outline 37 of CS302 98S.
• Removed uncovered materials on Thursday, February 18, 1999.

Disclaimer Often, these pages were created ``on the fly'' with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.