0% found this document useful (1 vote)
76 views3 pages

Week 12 Practical Class Exercises Denotational Semantics Solutions

This document contains 4 solutions to exercises on denotational semantics. Solution 1 provides the denotational semantics for a "repeat until" construct. Solution 2 analyzes the denotational semantics for a "while true" loop. Solution 3 proves the semantic equivalence of two loop constructs. Solution 4 modifies the semantic functions to account for side effects from expressions and commands.

Uploaded by

vhiep1988
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (1 vote)
76 views3 pages

Week 12 Practical Class Exercises Denotational Semantics Solutions

This document contains 4 solutions to exercises on denotational semantics. Solution 1 provides the denotational semantics for a "repeat until" construct. Solution 2 analyzes the denotational semantics for a "while true" loop. Solution 3 proves the semantic equivalence of two loop constructs. Solution 4 modifies the semantic functions to account for side effects from expressions and commands.

Uploaded by

vhiep1988
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 3

Department of Computer Science, Australian National University COMP3610 Principles of Programming Languages Semester 2, 2007

Week 12 Practical Class Exercises Denotational Semantics Solutions


Solution 1 Following the same idea as the while loop clause: C [[repeat c until b]] = x(..B [[b]](C [[c]] ) C [[c]] ; (C [[c]] )) Solution 2 We know that B [[b]] is either tt, or . (In fact, we can show that it cant be but that looks like more work.) We have: C [[while b do skip]] = x(..B [[b]] ; ) Now consider the 3 cases: x(..tt ; ) x(.. ; ) x(.. ; ) and calculate. The rst and third are . and the second is the identity, . . Solution 3 Two commands c and c are semantically equivalent iff C [[c]] = C [[c ]]. That is, semantic equivalence in denotational semantics is simple equality, so we need to show: C [[c; if not b then repeat c until b else skip]] = C [[repeat c until b]] We can prove this by using simple equational reasoning: C [[c; if not b then repeat c until b else skip]] = C [[if not b then repeat c until b else skip]](C [[c]] ) = B [[not b]] C [[repeat c until b]] ; C [[skip]] (where = C [[c]] ) = B[[b]] (xR) ; (where R = ..B [[b]](C [[c]] ) C [[c]] ; (C [[c]] )) = B [[b]] ; (xR) = B [[b]](C [[c]] ) C [[c]] ; (xR)(C [[c]] ) Denotational Semantics Solutions 1

Also, by a single unfolding of the clause for repeat loops, we get: C [[repeat c until b]] = x(..B [[b]](C [[c]] ) C [[c]] ; (C [[c]] )) = B [[b]](C [[c]] ) C [[c]] ; (xR)(C [[c]] ) Solution 4 Since arithmetic expressions may now have side-effects (function calls are expressions which may change the store), the semantic function A needs modication. A simple approach is to return both a value and a modied store: A : Aexp Env Store (Z Store) With side-effects, the order of evaluation of sub-expressions becomes important: A[[n]] = (N [[n]], ) A[[x]] = ( [[x]], ) A[[a0 + a1 ]] = (n0 + n1 , ) where A[[a0 ]] = (n0 , ) and A[[a1 ]] = (n1 , ) Similarly, boolean expressions can affect the store: B : Bexp Env Store (B Store) The clauses for boolean expressions are straightforward and are left as a exercise. They follow the style of the arithmetic expression clauses above. The clauses for commands must also be rewritten, for example: C [[x := a]] = [[[x]] n] where A[[a]] = (n, ) C [[if b then c0 else c1 ]] = t C [[c0 ]] ; C [[c1 ]] where B [[b]] = (t, ) Again, the other semantic clauses for commands are straightforward and are left as an exercise. Now for the details regarding function declarations and calls. First the syntax extensions: f : Fdecl (function declarations)

f ::= func x is c return a | f0 ; f1 a ::= . . . | eval x c ::= . . . | begin d; p; f ; c end As with procedures, the environment binds function meanings to their names. The meaning of arithmetic expressions (above) together with the choice of static scope leads to the observation Denotational Semantics Solutions 2

that function denotations are functions Store (Z Store). The domain of environments is thus: : Env = Ide (Loc + (Store Store) + (Store (Z Store))) The new semantic function for function declarations is : F : Fdecl Env Env F [[f0 ; f1 ]] = (F [[f0 ]]) (F [[f1 ]]) F [[func x is c return a]] = [x .A[[a]](C [[c]] )] To admit recursive functions the following clause is appropriate: F [[func x is c return a]] = x( .[x .A[[a]] (C [[c]] )]) Function calls are now straightforward: A[[eval x]] = [[x]] Finally blocks: C [[begin d; p; f ; c end]] = C [[c]](F [[f ]](P [[p]] )) where D[[d]](, ) = ( , ) Solution 5 The denotation of a function is similar to above but now the argument must be taken into account. Therefore it will be: Z Store (Z Store) That is, a function takes an integer (the value of the argument) and a store and returns an integer (the result) and a store (possibly modied through side-effects). The semantic domain of environments must accordingly be: : Env = Ide (Loc + (Store Store) + (Z Store (Z Store))) the argument is passed by value, so allocate a new location and initialise it to the argument value before executing the function body: F [[func x(y ) is c return a]] = [x n..A[[a]] (C [[c]] )] where l = new and = [y l] and = [l n]. Function calls proceed by evaluating the argument to produce its value n and a side-effected store then passing them onto the denotation of the function retrieved from the environment. The clause is thus: A[[eval x(a)]] = [[x]]n whereA[[a]] = (n, ) To admit (direct) recursion, modify the clause for function declarations: F [[func x(y ) is c return a]] = x( .[x n..A[[a]] (C [[c]] )]) where l = new and = [y l] and [l n].

Denotational Semantics Solutions

You might also like