Chapter 9 Key Section 9.1 4. Define a denotational semantics for the language of octal (base 8) numerals. Use the definition to find the value of “752”. Syntactic Domains: N : Numeral -- nonnegative numerals D : Digit -- decimal digits Abstract Production Rules: Numeral ::= Digit | Numeral Digit Digit ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 Semantic Domain: Number = { 0, 1, 2, 3, 4, … } -- natural numbers Semantic Functions: value : Numeral → Number digit : Digit → Number Semantic Equations: value [N D] = plus(times(8, value [N]), digit [D]) value [D] = digit [D] digit [0] = 0 digit [4] = 4 digit [1] = 1 digit [5] = 5 digit [2] = 2 digit [6] = 6 digit [3] = 3 digit [7] = 7 value [752]

= plus(times(8, value [75]), digit [2]) = plus(times(8, plus(times(8, value [7]), digit [5])), 2) = plus(times(8, plus(times(8, digit [7]), 5)), 2) = plus(times(8, plus(times(8, 7), 5)), 2) = plus(times(8, 61), 2) = 490

5. This is a BNF specification (and abstract syntax) of the language of Roman numerals less than five hundred. Roman ::= Hundreds Tens Units Hundreds ::= ε | C | CC| CCC | CD Tens ::= LowTens | XL | L LowTens | XC LowTens ::= ε | LowTens X

Chapter 9, Section 1

1

Units ::= LowUnits | IV | V LowUnits | IX LowUnits ::= ε | LowUnits I The language of Roman numerals is subject to the context constraint that the number of X’s in LowTens and I’s in LowUnits can be no more than three. Remember ε represents the empty string. Provide semantic functions and semantic equations for a denotational definition of Roman numerals that furnishes the numeric value of each string in the language. Assume that the context constraint has been verified by other means. Semantic Functions: r o m a n : Roman → Number hundreds : Hundreds → Number tens : Tens → Number lowtens : LowTens → Number units : Units → Number lowunits : LowUnits → Number Semantic Equations: r o m a n [H T U] = hundreds [H] + tens [T] + units [U] hundreds [ε] = 0 hundreds [C] = 100 hundreds [CC] = 200 hundreds [CCC] = 300 hundreds [CD] = 400 tens [Lt] = lowtens [LT] tens [XL] = 40 tens [L Lt] = 50 + lowtens [LT] tens [XC] = 90 lowtens [ε] = 0 lowtens [Lt X] = lowtens [LT] + 10 units [Lu] = lowunits [LU] units [IV] = 4 units [V Lu] = 5 + lowunits [LU] units [IX] = 9 lowunits [ε] = 0 lowunits [Lu I] = lowunits [LU] + 1

Section 9.2 1. Draw the abstract syntax tree that results from parsing the series of keystrokes 12 + 5 + / - M+ M+ - 55 =. Do not bother to parse the numerals. Remember, keystrokes are entered and evaluated from left to right.

2

Chapter 9, Section 1

Expression Expression Expression

55

M+

Expression M+

Expression 12



=

+

Expression 5

+/–

2. Evaluate the semantics of these combinations of keystrokes using the denotational definition in this section: b) 7 x 2 M+ M+ M+ - 15 + M R = meaning [7 x 2 M+ M+ M+ - 15 + M R =] = d where (a,op,d,m) = perform [7 x 2 M+ M+ M+ - 15 + M R =](0,n o p ,0,0). perform [7 x 2 M+ M+ M+ - 15 + M R =] = evaluate [7 x 2 M+ M+ M+ - 15 + M R =] = calculate [=] ° evaluate [7 x 2 M+ M+ M+ - 15 + M R] = calculate [=] ° evaluate [MR] ° compute [+] ° evaluate [7 x 2 M+ M+ M+ - 15] = calculate [=] ° evaluate [MR] ° compute [+] ° evaluate [15] ° compute [–] ° evaluate [7 x 2 M+ M+ M+ ] = calculate [=] ° evaluate [MR] ° compute [+] ° evaluate [15] ° compute [–] ° calculate [M+ ] ° calculate [M+ ] ° calculate [M+ ] ° evaluate [7 x 2] = calculate [=] ° evaluate [MR] ° compute [+] ° evaluate [15] ° compute [–] ° calculate [M+ ] ° calculate [M+ ] ° calculate [M+ ] ° evaluate [2] ° compute [x] ° evaluate [7] perform [7 x 2 M+ M+ M+ - 15 + M R =](0,n o p ,0,0) = calculate [=] (evaluate [MR] (compute [+] (evaluate [15] (compute [–] (calculate [M+ ] (calculate [M+ ] (calculate [M+ ] (evaluate [2] (compute [x] (evaluate [7] (0,n o p ,0,0)))))))))))

Chapter 9, Section 2

3

= calculate [=] (evaluate [MR] (compute [+] (evaluate [15] (compute [–] (calculate [M+ ] (calculate [M+ ] (calculate [M+ ] (evaluate [2] (compute [x] (0,n o p ,7,0)))))))))) = calculate [=] (evaluate [MR] (compute [+] (evaluate [15] (compute [–] (calculate [M+ ] (calculate [M+ ] (calculate [M+ ] (evaluate [2] (7,times,7,0))))))))) = calculate [=] (evaluate [MR] (compute [+] (evaluate [15] (compute [–] (calculate [M+ ] (calculate [M+ ] (calculate [M+ ] (7,times,2,0)))))))) = calculate [=] (evaluate [MR] (compute [+] (evaluate [15] (compute [–] (calculate [M+ ] (calculate [M+ ] (7,n o p ,14,14))))))) = calculate [=] (evaluate [MR] (compute [+] (evaluate [15] (compute [–] (calculate [M+ ] (7,n o p ,14,28)))))) = calculate [=] (evaluate [MR] (compute [+] (evaluate [15] (compute [–] (7,n o p ,14,42))))) = calculate [=] (evaluate [MR] (compute [+] (evaluate [15] (14,m i n u s ,14,42)))) = calculate [=] (evaluate [MR] (compute [+] (14,m i n u s ,15,42))) = calculate [=] (evaluate [MR] (-1,plus,-1,42)) = calculate [=] (-1,plus,42,42) = (-1,n o p ,41,42) Therefore meaning [7 x 2 M+ M+ M+ - 15 + M R =] = 41 6. Add to the calculator a key sqr that computes the square of the value in the display. Alter the semantics to model the action of this key. Its syntax should be similar to that of the + / - key. Syntax: ::= | MR | Clear | +/ - | sqr Semantics: calculate [sqr] (a, op, d, m) = (a, op, times(d,d), m)

Section 9.3 1. Add these language constructs to Wren and provide their denotational semantics. Note that we provide the abstract syntax for these constructs, and that the concrete syntax may have to be slightly more complicated to avoid ambiguity.

4

Chapter 9, Section 2

a) repeat-until command Command ::= ... | repeat Command until Expression execute [repeat C until E] = loop ° execute [C] where loop sto = if not(p) then loop(execute [C] sto) else sto where bool(p) = evaluate [E] sto b) conditional expression Expression ::= ... | if Expression then Expression else Expression evaluate [if E1 then E2 else E3] sto = if p then (evaluate [E2] sto) else (evaluate [E3] sto) where bool(p) = evaluate [E1] sto Use your definition to prove the semantic equivalence of m := if E1 then E2 else E3 and if E1 then m:=E 2 else m:=E 3. c) expression with side effects Expression ::= ... | begin Command return Expression end. Specifying the denotational semantics of this command requires changing the syntax and semantic equations for evaluate as suggested below. evaluate : Expression → Store → (EV x Store) evaluate [begin C return E end] sto = (val, sto2) where sto1 = execute [C] sto and (val, sto2) = evaluate [E] sto 1 evaluate [E1 + E2] sto = (int(plus(m,n)),sto2) where (int(m),sto1) = evaluate [E1] sto and (int(n),sto2) = evaluate [E2] sto 1 evaluate [I] sto = if val=undefined then error else (val,sto) where val = applySto(sto, I) evaluate [N] sto = (int(value [N]),sto) evaluate [true] sto = (bool(true),sto) evaluate [- E] sto = (int(m i n u s (0,m)),sto1) where (int(m),sto1) = evaluate [E] sto Similar semantic equations are needed for the other binary operations. Also, each semantic equation that involves expressions will have to be altered to reflect the changing store. d) case command

Chapter 9, Section 3

5

Command ::= case IntegerExpr of (when Numeral + => Command)+ Auxiliary Function: m e m b e r : Integer x Integer* → Boolean m e m b e r (m, [ ]) = false m e m b e r (m, L) = if m=h e a d L then true else m e m b e r (m, tail L) New Semantic Function: val : Numeral + → Integer+ val [ [ ] ] = [ ] val [ L ] = cons (val [ h e a d L ], val [ tail L ]) execute [case E of when L => C] sto = if m e m b e r (m, val [ L ]) then execute [C] sto else sto where int(m) = evaluate [E] sto execute [case E of (when L1 => C1) (when L => C)+] sto = if m e m b e r (m, val [ L1 ]) then execute [C1] sto else execute [case E of (when L => C)+] sto where int(m) = evaluate [E] sto 5. Prove the semantic equivalence of these language phrases: c) x := 5; y := 2* x and y := 10; x := y/2 execute [x := 5; y := 2*x] sto = execute [y := 2*x] {x|→int(5)}sto = {x|→int(5), y|→int(10)]sto, since 10 = times(2, 5). execute [y := 10; x := y/2] sto = execute [x := y/2] {y|→int(10)} sto = {x|→int(5), y|→int(10)}sto, since 5 = divides(10, 2). Therefore, "x := 5; y := 2*x" and "y := 10; x := y/2" are semantically equivalent.

6

Chapter 9, Section 3

8. A vending machine takes nickels, dimes, and quarters and has buttons to select gum (30¢), a candy bar (50¢), or a brownie (65¢), or to return the coins entered. After entering a sequence of coins and pressing a button, the user receives the selected item (or nothing) and the change from the purchase. When the value of the coins is insufficient for the button pressed, the outcome is the same as from return. The following two examples show how the vending machine might be used: “dime, dime, dime, quarter, candy bar button” produces a candy bar and 5 cents in change. “quarter, nickel, return” or “quarter, nickel, candy” produce nothing and 30 cents in change. The language of the vending machine has the following abstract syntax: Program ::= CoinSeq Button CoinSeq ::= ε | Coin CoinSeq -- ε represents the empty string Coin ::= Nickel | Dime | Quarter Button ::= Gum | Candy | Brownie | Return Using the semantic domains Result = { gum, candy, brownie, naught } and Number = { 0, 1, 2, 3, 4, … }, provide a denotational semantics for the language of the vending machine. Abstract Syntactic Domains: P : Program

C : Coin

S : CoinSeq

B : Button

Abstract Production Rules: Program ::= CoinSeq Button CoinSeq ::= ε | Coin CoinSeq Coin ::= Nickel | Dime | Quarter Button ::= Gum | Candy | Brownie | Return Semantic Domains: Result = { gum, candy, brownie, naught } Number = { 0, 1, 2, 3, ... } Semantic Functions: meaning : Program → Result x Number total : CoinSeq → Number

Chapter 9, Section 3

7

m o n e y : Coin → Number select : Button → Number → Result x Number Semantic Equations: meaning [Cs B] = select [B] (total [Cs]) total [C Cs] = plus(total [Cs],m o n e y [C]) total [ε] = 0 m o n e y [Nickel] = 5 m o n e y [Dime] = 10 m o n e y [Quarter] = 25 select [Gum] num = if (num >= 30) then (gum,m i n u s (num,30)) else (naught, num) select [Candy] num = if (num >= 50) then (candy,m i n u s (num,50)) else (naught, num) select [Brownie] num = if (num >= 65) then (brownie,m i n u s (num,65)) else (naught,num) select [Return] num = (naught, num)

Section 9.5 1. Although we defined an auxiliary function deallocate, we made no use of it in the denotational semantics of Pelican. Extend the denotational definition to provide for the deallocation of store locations at block exit. Hint: Use perform [D begin C end] env sto = release [D] env 1 (execute [C] env 1 sto 1) where (env 1,sto 1) = elaborate [D] env sto and define the semantic function release. release : Declaration → Environment → Store → Store perform [D begin C end] env sto = release [D] env 1 (execute [C] env 1 sto 1) where (env 1,sto 1) = elaborate [D] env sto release [D1 D2] env sto = release [D2] env (release [D1] env sto) release [ε] env sto = sto 8

Chapter 9, Section 3

release [const I = E] env sto = sto release [var I : T] env sto = deallocate(sto,loc) where var(loc) = applyEnv(env,I) release [var I,L : T] env sto = release [var L : T] env (release [var I : T] env sto) release [procedure I is D begin C end] env sto = sto release [procedure I1(I2 : T) is D begin C end] env sto = sto execute [I(E)] env sto = updateSto(sto 2,loc 1,unused) where proc1(proc) = applyEnv(env,I) and (sto1,loc 1) = allocate sto and sto2 = proc loc 1 updateSto(sto 1,loc 1,evaluate [E] env sto) 3. Modify Pelican so that the parameter is passed by a) reference elaborate [procedure I1(I2 : T) is B] env sto = (env1, sto) where env 1 = extendEnv(env,I 1,proc1(proc)) and proc loc = perform [B] extendEnv(env 1,I2,var(loc)) execute [I1(I2)] env sto = proc loc sto where proc1(proc) = applyEnv(env,I 1) and var(loc) = applyEnv(env,I 2) b)

value-result (an in-out parameter in Ada)

elaborate [procedure I1(I2 : T) is B] env sto = (env1, sto) where env 1 = extendEnv(env,I 1,proc1(proc)) and proc loc = perform [B] extendEnv(env 1,I2,var(loc)) execute [I1(I2)] env sto = updateSto(sto 2,loc 2,applySto(sto 2,loc 1)) where proc1(proc) = applyEnv(env,I 1) and (sto1,loc 1) = allocate sto and var(loc 2) = applyEnv(env,I 2) and sto2 = proc loc 1 updateSto(sto 1,loc 1,applySto(sto,loc2)) c)

constant (a read-only parameter known as an in parameter in Ada).

Procedure = proc0(Store → Store) + proc1(EV → Store → Store) elaborate [procedure I1(I2 : T) is B] env sto = (env1, sto) where env 1 = extendEnv(env,I 1,proc1(proc)) and proc val = perform [B] extendEnv(env 1,I2,val)

Chapter 9, Section 5

9

execute [I(E)] env sto = proc (evaluate [E] env sto) sto where proc1(proc) = applyEnv(env,I) 4. Modify Pelican so that it uses dynamic scoping to resolve nonlocal variable references. Procedure = proc0(Environment → Store → Store) + proc1(Environment → Location → Store → Store) elaborate [procedure I is B] env sto = (env1, sto) where env 1 = (extendEnv(env,I,proc0(proc)) and proc en = perform [B] en elaborate [procedure I1(I2 : T) is B] env sto = (env1, sto) where env 1 = (extendEnv(env,I 1,proc1(proc)) and proc en loc = perform [B] extendEnv(en,I2,var(loc)) execute [I] env sto = proc env sto where proc0(proc) = applyEnv(env,I) execute [I(E)] env sto = proc env loc updateSto(sto 1,loc,evaluate [E] env sto) where proc1(proc) = applyEnv(env,I) and (sto1,loc) = allocate sto following Pelican programs: a) program trace1 is var a : integer; procedure q1 is begin a := 5 end; procedure q2 is var a : integer; begin a := 3; q1 end;

Environment [a|→var(0)] [q1|→proc0(proc1), a|→var(0)] env 1 [q2|→proc0(proc2), q1|→proc0(proc1), a|→var(0)] [q2|→proc0(proc2), q1|→proc0(proc1), a|→var(1)] env 3

begin a := 0; q2; write a

env 2

end where env 1 = [q1|→proc0(proc1), a|→var(0)] proc1 = perform [begin a := 5 end] env 1 env 2 = [q2|→proc0(proc2), q1|→proc0(proc1), a|→var(0)]

10

Chapter 9, Section 5

proc2 = perform [var a : integer; begin a := 3; q1 end] env 2 env 3 = [q2|→proc0(proc2), q1|→proc0(proc1), a|→var(1)] program trace1 is var a : integer; begin a := 0 q2 var a : integer; begin a := 3 q1 begin a := 5 end { q1 } end { q2 } write a end

Store {0|→ud} {0|→int(0)} {0|→int(0), 1|→ud} {0|→int(0), 1|→int(3)} {0|→int(5), 1|→int(3)}

{0|→int(5), 1|→int(3)}

Section 9.6 1. Apply the validate semantic function to these Pelican programs and elaborate the definitions that check the context constraints for Pelican. c)

program c is var x,y,z : integer; begin read x; y := z; { C 1.2 } declare var x,z : integer; begin while x>0 do x := x-1 end while; declare var x,y : boolean; const y = false; begin skip end end end

Chapter 9, Section 5

{ D1 }

{ B1 }

{ C1.1 } { C1.3 } { D2 }

{ B2 }

{ C2.1 } { C2.2 } { D3.1 } { D3.2 }

{ B3 }

{ C3.1 }

11

validate [program c is B 1] = examine [B 1] extendEnv(emptyEnv,c,program) examine [D1 begin C1.1 ; C1.2 ; C1.3 end] [c|→program]) = check [C1.1 ; C1.2 ; C1.3 ] where (locenv, env) = elaborate [D1] (emptyEnv, [c|→program]) elaborate [var x,y,z : integer] (emptyEnv, [c|→program]) = elaborate [var y,z : integer] ( elaborate [var x : integer] (emptyEnv, [c|→program])) elaborate [var x : integer] (emptyEnv, [c|→program] = if applyEnv(emptyEnv, x) = unbound then (extendEnv(emptyEnv,x,type(integer)), extendEnv([c|→program],x,type(integer)) else error = (extendEnv(emptyEnv,x,intvar), extendEnv([c|→program],x,intvar) = ([x|→intvar], [x|→intvar, c|→program]) elaborate [var y,z : integer] ([x|→intvar], [x|→intvar, c|→program]) = elaborate [var z : integer] ( elaborate [var y : integer] ([x|→intvar], [x|→intvar, c|→program])) elaborate [var y : integer] ([x|→intvar], [x|→intvar, c|→program]) = if applyEnv([x|→intvar],y) = unbound then (extendEnv([x|→intvar],y,type(integer)), extendEnv([x|→intvar, c|→program],y,type(integer))) else error = (extendEnv([x|→intvar],y,intvar), extendEnv([x|→intvar, c|→program],y,intvar)) = ([y|→intvar, x|→intvar], [y|→intvar, x|→intvar, c|→program]) elaborate [var z : integer] ([y|→intvar,x|→intvar], [y|→intvar,x|→intvar, c|→program]) = if applyEnv([y|→intvar, x|→intvar],z) = unbound then (extendEnv([y|→intvar, x|→intvar],z,type(integer)), extendEnv([y|→intvar, x|→intvar],z,type(integer))) else error = (extendEnv([y|→intvar, x|→intvar],z,intvar), extendEnv([y|→intvar, x|→intvar],z,intvar)) = ([z|→intvar,y|→intvar,x|→intvar], [z|→intvar,y|→intvar,x|→intvar, c|→prog])

12

Chapter 9, Section 7

Let env1 = [z|→intvar, y|→intvar, x|→intvar, c|→program] check [C1.1 ] env 1 = check [read x] env 1 = (applyEnv(x, env 1) = intvar) = (intvar = intvar) = true check [C1.2 ] env 1 = check [y := z] env 1 = (applyEnv(env 1,y) = intvar and typify [z] env 1 = integer) or (applyEnv(env 1,y) = boolvar and typify [z] env 1 = boolean) = (intvar = intvar and integer = integer) or (intvar = boolvar and integer = boolean) = true check [C1.3 ] env 1 = check [declare B 2] env 1 = examine [D2] begin C2.1 ; C2.2 end] env 1 = check [C2.1 ; C2.2 ] env 2 where (locenv, env 2) = elaborate [D2] (emptyEnv, env 1) elaborate [var x,z : integer] (emptyEnv, env 1) = elaborate [var z : integer] (elaborate [var x : integer] (emptyEnv, env 1)) elaborate [var x : integer] (emptyEnv, env 1) = if applyEnv(emptyEnv, x) = unbound then (extendEnv(emptyEnv,m,type(integer)), extendEnv(env 1,m,type(integer))) else error = (extendEnv(emptyEnv,m,intvar), extendEnv(env 1,m,intvar)) = ([x|→intvar], [x|→intvar, z|→intvar, y|→intvar, c|→prog]) elaborate [var z : integer] ([x|→intvar], [x|→intvar, z|→intvar, y|→intvar, c|→prog]) = if applyEnv([x|→intvar],z) = unbound then (extendEnv([x|→intvar],z,type(integer)), extendEnv([x|→intvar, z|→intvar, y|→intvar, c|→prog,],z,type(integer))) else error = (extendEnv([x|→intvar],z,intvar), extendEnv([x|→intvar, z|→intvar, y|→intvar, c|→prog,],z,intvar)) = ([z|→intvar, x|→intvar], [z|→intvar, x|→intvar, y|→intvar, c|→prog,]

Chapter 9, Section 7

13

Let env2 = [z|→intvar, x|→intvar, y|→intvar, c|→program] typify [x>0] env 2 = if (typify [x] env 2 = integer) and (typify [0] env 2 = integer) then boolean else error = if (integer = integer) and (integer = integer) then boolean else error = boolean typify [x-1] env 2 = if (typify [x] env 2 = integer) and (typify [1] env 2 = integer) then integer else error = if (integer = integer) and (integer = integer) then integer else error = integer check [x := x-1] env 2 = (applyEnv(env 2,x) = intvar and typify [x-1] env 2 = integer) or (applyEnv(env 2,x) = boolvar and typify [x-1] env 2 = boolean) = (intvar = intvar and integer = integer) or (intvar = boolvar and integer = boolean) = true check [C2.1 ] env 2 = check [while x>0 do x := x-1] env 2 = (typify [x>0] env 2 = boolean) and (check [x := x-1] env 2) = (boolean = boolean) and true = true check [C2.2 ] env 2 = check [declare B 3] env 2 = examine [D3.1 ; D3.2 begin C3.1 end] env 2 = check [C3.1 ] env 3 where (locenv, env 3) = elaborate [D2] (emptyEnv, env 2) elaborate [var x,y : boolean] (emptyEnv, env 2) = elaborate [var y : boolean] (elaborate [var x : boolean] (emptyEnv, env 2)) elaborate [var x : boolean] (emptyEnv, env 2) = if applyEnv(emptyEnv, x) = unbound then (extendEnv(emptyEnv,x,type(boolean)) extendEnv(env 2,x,type(boolean))) else error = (extendEnv(emptyEnv,x,boolvar) extendEnv(env 2,x,boolvar)) = ([x|→boolvar], [x|→boolvar, z|→intvar, y|→intvar, c|→program]) 14

Chapter 9, Section 7

elaborate [var y : boolean] ([x|→boolvar], [x|→boolvar, z|→intvar, y|→intvar, c|→prog]) = if applyEnv([x|→boolvar],y) = unbound then (extendEnv([x|→boolvar],y,type(boolean)), extendEnv([x|→boolvar, z|→intvar, y|→intvar, c|→prog],y,type(boolean))) else error = (extendEnv([x|→boolvar],y,boolvar), extendEnv([x|→boolvar, z|→intvar, y|→intvar, c|→prog],y,boolvar)) = ([y|→boolvar, x|→boolvar], [y|→boolvar, x|→boolvar, z|→intvar, c|→prog]) elaborate [const y = false] ([y|→boolvar, x|→boolvar], [y|→boolvar, x|→boolvar, z|→intvar, c|→prog])) = if applyEnv([y|→boolvar, x|→boolvar],y) = unbound then (extendEnv([y|→boolvar, x|→boolvar],y,type(boolean)), extendEnv([y|→boolvar, x|→boolvar, z|→intvar, c|→prog],y,type(boolean))) else error = error elaborate [D3.1 ; D3.2 ] (emptyEnv, env 2) = error check [C3.1 ] error = error check [declare B 3] env 2 = error check [declare B 2] env 1 = check [C2.1 ; C2.2 ] env 2 = (check [while x>0 do x := x-1] env 2) and (check [declare B 3] env 2) = true and error = error check [C1.1 ; C1.2 ; C1.3 ] env 1 = (check [read x] env 1) and (check [y := z] env 1) and (check [declare B 2] env 1) = true and true and error = error

Chapter 9, Section 7

15