Denotational Semantics The meaning of a program is

  • Slides: 7
Download presentation
Denotational Semantics • The meaning of a program is given by specifying the function

Denotational Semantics • The meaning of a program is given by specifying the function (from input to output) that corresponds to the program. • The denotational semantic definition, thus maps syntactical things into functions: P: Program→Input→Output • We need to specify each of these: – Syntactic domains (describing program syntax elements that are assigned common valuation functions) – Semantic domains (that are used to express meanings of programs and their components). – Semantic functions (that map syntax into semantics)

Elements for The Expression Language • • • Syntactic Domains E: Expression N: Number

Elements for The Expression Language • • • Syntactic Domains E: Expression N: Number D: Digit Semantic Domains v: Integer = {. . . , -2, -1, 0, 1, 2, . . . } Operations +: Integer Χ Integer → Integer -: Integer Χ Integer → Integer *: Integer Χ Integer → Integer Semantic Functions E : Expression → Integer E[[E 1 ‘+’ E 2]] = E[[E 1]] + E[[E 2]] E[[E 1 ‘*’ E 2]] = E[[E 1]] * E[[E 2]] E[[E 1 ‘-’ E 2]] = E[[E 1]] - E[[E 2]] E[[‘(‘ E ‘)’]] = E[[E]] E[[N]] = N[[N]] N: Number → Integer N[[ND]] = 10*N[[N]] + N[[D]] N[[ND]] = D[[D]] D: Digit → Integer D[[‘ 0’]] = 0, D[[‘ 1’]] = 1, . . . D[[‘ 9’]] = 9

Adding an Environment to the Expression Language • • • Need to create a

Adding an Environment to the Expression Language • • • Need to create a lifted domain from the Integers. A lifted domain has all the elements of some partially ordered domain together with a unique bottom element ( ), that is less than any other element in the original domain. We call the lifted integers Integer. New Semantic Domains: Environment = Identifier → Integer Modified Semantic Functions E : Expression → Environment → Integer E[[E 1 ‘+’ E 2]](Env) = E[[E 1]](Env) + E[[E 2]] (Env) E[[E 1 ‘*’ E 2]](Env)= E[[E 1]](Env) * E[[E 2]](Env) E[[E 1 ‘-’ E 2]](Env) = E[[E 1]](Env) - E[[E 2]](Env) E[[‘(‘ E ‘)’]](Env) = E[[E]](Env) E[[I]](Env) = Env(I) E[[N]](Env) = N[[N]] Note that E is now a higher-order function (when given an Expression, it yields a function mapping an Environment to an Integer). Such functions can be constructed from normal functions by Currying. This is useful in this context, because it lets us explain what the meaning of an expression is, no matter what the environment in which we evaluate that expression.

Adding Statements • • New Syntactic Domains L: Statement-list S: Statement I: Identifier L:

Adding Statements • • New Syntactic Domains L: Statement-list S: Statement I: Identifier L: Letter New Semantic Functions P: Program → Environment P[[L]] = L[[L]](Env 0)) L: Statement-list→Environment L[[L 1 ‘; ’ L 2]] = L[[L 2]] L[[L 1]] L[[S]] = S[[S]] S: Statement → Environment S[[I ‘: =‘ E]](Env) = Env{I = E[[E]](Env)}

Mathematics of Functional Programming • We can define a function by extension (by providing

Mathematics of Functional Programming • We can define a function by extension (by providing the graph of the function, namely, the set of ordered pairs that represent the function’s mapping) or by comprehension (by providing a rule that tells us how to calculate the value of the function at any point). • Consider the normal definition of the factorial function: f(n) = if n = 0 then 1 else n*g(n-1) • Think of a recursive definition of a function as really naming two functions, the function used in the body, and the function being defined: f(n) = if n = 0 then 1 else n*f(n-1) • Now f has two arguments, n, and g. Think of defining a higher order function H H(g)(n) = if n = 0 then 1 else n*g(n-1) • The factorial function f is a fixed-point of H, that is, a value of H such that H(g) = g. Why? H(f)(n) = if n = 0 then 1 else n*f(n-1) ≡ f(n)

Least-Fixed-Points • If we think of a function being represented by extension, then we

Least-Fixed-Points • If we think of a function being represented by extension, then we can talk about a partial ordering of all functions, with the bottom element being the empty set . • Think of the function that just maps 0 to 1, {(0, 1)}, and the function that in addition maps 1 to 1, {(0, 1), (1, 1)}, and the function that further maps 2 to 2, {(0, 1), (1, 1), (2, 2)}, and the function that further maps 3 to 6, {(0, 1), (1, 1), (2, 2), (3, 6)}. We are constructing a sequence of functions, f 0, f 1, f 2, f 3, that begin a sequence of functions that represent the factorial function. • If we defined a function f* that was just like f, but in addition mapped negative values to -1, f* would still satisfy the definition of the factorial function, however, f* would be a larger function in the natural lattice order of the function definitions because it contains every pair in f, but it also contains many other pairs. That’s why we say the factorial function is the least-fixed-point of the definition of H(f).

Adding Control Flow • Defining if statements is relatively straightforward S[[‘if’ E ‘then’ L

Adding Control Flow • Defining if statements is relatively straightforward S[[‘if’ E ‘then’ L 1 ‘else’ L 2]](Env) = if E[[E]](Env) > 0 then L[[L 1]](Env) else L[[L 1]](Env) • While and other repetitive statements, however present somewhat of a problem: S[[‘while’ E ‘do’ L ‘od’]](Env) = if E[[E]](Env) 0 then Env else S[[L ‘; ’ ‘while’ E ‘do’ L ‘od’]](Env) The recursive nature of the while is typically handled by defining the meaning as the least-fixed-point of the specified semantic function.