solnDS

Embed Size (px)

Citation preview

  • 7/29/2019 solnDS

    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]] = fix(..B[[b]](C[[c]]) C[[c]] ; (C[[c]]))

    Solution 2

    We know that B[[b]] is either tt, ff or . (In fact, we can show that it cant be but that lookslike more work.)

    We have:

    C[[while b do skip]] = fix(..B[[b]] ; )

    Now consider the 3 cases:

    fix(..tt ; )

    fix(..ff ; )

    fix(.. ; )

    and calculate. The first and third are. and the second is the identity,..

    Solution 3

    Two commands c and c are semantically equivalent iffC[[c]] = C[[c]]. That is, semantic equiva-lence 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]] (fixR) ;

    (where R = ..B[[b]](C[[c]]) C[[c]] ; (C[[c]]))

    = B[[b]] ; (fixR)

    = B[[b]](C[[c]]) C[[c]] ; (fixR)(C[[c]])

    Denotational Semantics Solutions 1

  • 7/29/2019 solnDS

    2/3

    Also, by a single unfolding of the clause for repeat loops, we get:

    C[[repeat c until b]]

    = fix(..B[[b]](C[[c]]) C[[c]] ; (C[[c]]))

    = B[[b]](C[[c]]) C[[c]] ; (fixR)(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 modification. A simple approach is to returnboth a value and a modified 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

  • 7/29/2019 solnDS

    3/3

    that function denotations are functions Store (Z Store). The domain of environments isthus:

    : 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]] = fix(.[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 in-

    teger (the result) and a store (possibly modified 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 valuen and a side-effected store

    then passing them onto the denotation of the function retrieved from the environment. The clauseis 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]] = fix(.[x n..A[[a]](C[[c]])])

    where l = new and = [y l] and [l n].

    Denotational Semantics Solutions 3