programming language principles lecture 26 prepared by manuel e. bermúdez, ph.d. associate...

26
Programming Language Principles Lecture 26 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Denotational Semantics

Upload: nathaniel-reeves

Post on 31-Dec-2015

220 views

Category:

Documents


0 download

TRANSCRIPT

Programming Language PrinciplesLecture 26

Prepared byManuel E. Bermúdez, Ph.D.

Associate ProfessorUniversity of Florida

Denotational Semantics

Semantic Descriptions

• In general, three approaches to describing semantics of a programming language:

1. Axiomatic approach:• Good formalizing type systems. Skipped.

2. Operational approach:• Describe semantics by giving a process.• The “meaning” of a program is the result of

the process.• Program behavior gleaned from process.• RPAL: scan, parse, standardize, evaluate.

Denotational Semantics

3. Denotational approach:

• Describe semantics by “denoting” constructs, usually with functions.

• The “meaning” of a program is given by a collection of semantic functions, on a construct-by-construct basis.

• Program behavior gleaned from behavior of semantic functions.

• We will specify Tiny.

Denotation Descriptions

• A denotational semantic description has three parts:

1. A set of syntactic domains (usually AST’s).2. A set of semantic domains.

• Usually, objects and/or states.3. A set of semantic functions.

• Functions describe how PL constructs manipulate/change values in the semantic domains.

We will use RPAL notation to describe functions

Sample Denotational Description

Let’s describe the behavior of an ‘add’ instruction in a fictitious machine.

1. Syntactic domain: ASTs of the form

<Opcode Operand1 Operand2>

2. Semantic domains:Register: {0,1,2,3,4,5,6,7}Value: {16-bit number}Address: {16-bit number}Memory: Address → ValueRegValues: Address → Value

Sample Denotational Description

3. Semantic function: EE (for EEvaluate).

EE: AST → (RegValues x Memory) → (RegValues x Memory)

EE takes an AST, and returns a function that• takes a (registers,memory) pair, and

returns a new (registers,memory) pair.• EE shows how the “state” is changed by

the construct in the AST.• “state”: current register contents, and

current memory contents.

Sample Denotational Description

Description of the ‘add’ operation:

EE[<+ r m>] = λ(R,M). let Result = R r + M m

in (R, (λa. a eq m → Result | M a))

1. Get contents of register r, add to contents of memory location m (yielding Result).

2. Build new “state”:• Registers (mapping) R unchanged.• New memory, maps m to Result, otherwise

maps as M does.

Sample Denotational Description

A different ‘add’ operation:

EE[<+ r m>] = λ(R,M). let Result = R r + M m

in ((λp. p eq r → Result | R p), M)

1. Get contents of register r, add to contents of memory location m (yielding Result).

2. Build new “state”:• New registers: register r contains Result.• Memory M unchanged.

Sample Denotational Description

Clearly, the denotational description specifies the semantics of the <+ r m> instruction.

– Behavior depends on (is function of) R and M.– Add contents of register r and memory m.– We specified two versions:

1. Store result in memory location m.2. Store result in register r.

Functions as “Storage”

Where do R and M come from ?

Consider

R0 = (λ().0) all registers contain zero.

R1= (λp. p eq 2 → 3 | R0 p) register 2 contains 3, others zero.

R2= (λp. p eq 4 → 7 | R1 p) register 2 contains 3, 4 contains 7, others zero.

R3= (λp. p eq 2 → 5 | R2 p) register 2 contains 5 ! (3 forgotten) register 4 contains 7, others zero.

Some Useful Notation

The “pipeline” operator (=>):

x => f denotes

x eq error → error | f(x)

Before applying a function f to an argument:• Check whether it’s error.• If it is, cancel application of f, return error.

x f

Some Useful Notation (cont’d)

The “o” (composition) operator is defined as

o = λf. λg. λx. f x eq error → error | g(f x)

• The “o” function takes two functions, f and g, and an argument x.

– Evaluate f(x):

• If f(x) is error, return error (cancel application of g)

• Otherwise, return g(f(x)).

Some Useful Notation (cont’d)

We will use “o” as an infix operator, writing f o g instead of o f g.

• Advantage:(f o g o h) x means calculate

h(g(f(x))), but cancel all applications ifthe result is ‘error’ anywhere along the way.

x f g h

Some Useful Notation (cont’d)

• In our expressions, o has higher precedence than =>

• Example:x => f o g o h means

(f o g o h) x which is

h(g(f(x) unless any value (including x) is ‘error’ along the way.

Also, both => and o are left associative.

Tiny’s Denotational Semantics

Tiny’s syntactic domains:

AST = E + C + P, whereE = 0 | 1 | 2 ... | true | false | read | Id |

<not E> | < ≤ E E> | <+ E E>C = <:= I E> | <print E> | <if E C C> |

<while E C> | <; C C>P = <program C>

Tiny’s Denotational Semantics (cont’d)

Tiny’s Semantic Domains.

State: Mem x Input x Output

Mem: Id → Val

Input: Val* (zero or more values)Output: Val*Val: Num + Bool

Tiny’s Denotational Semantics (cont’d)

Tiny’s semantic functions.

EE: E → State → (Val x State)

CC: C → State → State

PP: P → Input → Output

Some Auxiliary FunctionsReturn: Val → State → (Val x State)

λv. λs. (v,s)

Check: Domain → (Val x State) → (Val x State) λD. λ(v,s). v D → (v,s) | error

Dummy: State → State λs. s

Cond: (State → State) λF1.

→ (State → State) λF2. → (Val x State) λ(v,s). → State s => (v → F1 | F2)

Replace: Mem → Id → Val → Mem λm. λi. λv. (λi'. i' eq i → v | m i')

Now, for EE, CC, and PP

EE[0] = Return 0; EE[1] = Return 1; EE[2] = Return 2; ... etc.

EE[true] = Return true; EE[false] = Return false

EE[read] = λ(m,i,o). Null i → error

| (Head i, (m, Tail i, o))

EE[I] = λ(m,i,o). m I eq → error | (m I, (m,i,o))

The EE Semantic Function (cont’d)

EE[<not E>] = EE[E]o (Check Bool)o (λ(v,s).((not v),s) )

EE[<≤ E1 E2>] = EE[E1]o (Check Num)o (λ(v1,s1). s1 => EE[E2]

=> (Check Num)=> (λ(v2,s2).(v1 ≤ v2,s2)

)

The EE Semantic Function (cont’d)

EE[<+ E1 E2>] = EE[E1]o (Check Num)o (λ(v1,s1). s1 => EE[E2]

=> (Check Num)=> (λ(v2,s2).(v1 + v2,s2)

)

The CC Semantic Function

CC[<:= I E>] = EE[E] o (λ(v,(m,i,o)). (Replace m I v, i, o))

CC[<print E>] = EE[E] o (λ(v,(m,i,o)). (m,i,o aug v))

CC[<if E C1 C2>] = EE[E] o (Check Bool) o (Cond CC[C1] CC[C2])

The CC and PP Semantic Functions

CC[<while E C>] = EE[E] o (Check Bool) o (Cond (CC[<; C <while E C>>]) Dummy)

CC[<; C1 C2>] = CC[C1] o CC[C2]

PP[<program C>] = (λi. CC[C] ((λ().), i, nil)) o (λ(m,i,o).o)

The meaning of a Tiny program <program C> is PP[<program C>]

Semantics of Tiny

• Issues enforced:– true, false, read not, if, while, print

treated as reserved words.– Can’t read from empty input.– Can’t use undefined variable values.– Argument of ‘not’ must be Bool.– ≤ comparison allowed only on Nums.– ‘+’ allowed only on Nums.– ‘If’ control expression must be Bool.– ‘while’ control expression must be Bool.

Semantics of Tiny (cont’d)

• Issues not enforced:

– Can store Bools ? Yes, even in a variable currently holding a Num !

– Legal values to print ? Anything.– No type checking on input values.– Typing issues difficult to enforce:

• Tiny has no declarations.

Programming Language PrinciplesLecture 26

Prepared byManuel E. Bermúdez, Ph.D.

Associate ProfessorUniversity of Florida

Denotational Semantics