Understanding Denotational Semantics in Simple Programming Languages
This tutorial explores the denotational semantics of a simple programming language by examining key components such as syntactic domains, abstract syntax, semantic domains, and meaning functions. Students will engage in exercises to deepen their understanding of how various syntactic structures correlate to denotations within defined semantic domains. The tutorial also discusses the store concept, commands, and the challenges posed by recursive functions in programming semantics. Relevant web notes and handouts will supplement the lectures to enhance learning.
Understanding Denotational Semantics in Simple Programming Languages
E N D
Presentation Transcript
CHA2545: WEEK 4 LECTURE: DENOTIONAL SEMANTICS OF A SIMPLE LANGUAGE TUTORIAL: Do exercises given out DURING THE WEEK: Go through ARJ’s supporting WEB notes (from main web page).
The Four Parts of a Semantic Definition: • Syntactic domains • Abstract Syntax • Semantic Domains • Meaning Functions Example syntax domains (see handout) Nml, Ide, Exp, Cmd
DENOTATIONS • The semantics of the various syntactic structures of a language is defined via meaning functions which take the syntactic structure as a parameter and returns its denotation. • A “denotation” is a mathematical representation of the meaning of a construct - its an object belonging to a SEMANTIC DOMAIN.
SEMANTIC DOMAINS - Examples Simple Semantic Domains - T - truth values N - natural numbers Z - integers Complex Domains are made up by combining Simple Domains with operators such as +, x, ->
COMPLEX DOMAINS - Examples • Disjoint Union Domain of all integers and truth values Z + T • Cross Product Domain of all pairs of integers Z x Z • Function Domain consisting of all functions from integers to truth values Z -> Z and pairs of integers to integers (Z x Z) -> Z
COMPLEX DOMAINS - Another Example All “expressible” values in a simple programming language with truth values and natural numbers: E = N + T + {error}
The STORE • The simplest way to represent the STATE of program execution is by a STORE - representing the values stored at any point in the execution of a program. • The store is represented by a function domain S = [ Ide -> E ] + {error} We usually let ‘s’ be a typical store or state.
Commands • Commands change the program state The domain of commands is therefore the functions between states, i.e. S -> S
Semantic Function: Emeans Emeans takes a syntactically well formed expression, and gives it a denotation in terms of a function between stores and expressible values so Emeans : Exp -> S -> E The definition of Emeans depends on the syntactic subclass to which it is applied.
Semantic Function: Cmeans Cmeans takes a syntactically well formed command, and gives it a denotation in terms of a function between stores and stores so Cmeans : Cmd -> S -> S The definition of Cmeans depends on the syntactic subclass to which it is applied
The Problem with Recursive Functions - what do they mean? Cmeans[[while B do C]] = ls.(Emeans[[B]]s -> Cmeans[[while B do C]](Cmeans[[C]]s), s) OR: Cmeans[[while B do C]] = f where f = ls.(Emeans[[B]]s -> f(Cmeans[[C]]s), s)
Recursive Functions - The Fixpoint Equation Given: f = ls.(Emeans[[B]]s -> f(Cmeans[[C]]s), s) Then: H = lf.ls.(Emeans[[B]]s -> f(Cmeans[[C]]s), s) Hf = (lf.ls.(Emeans[[B]]s -> f(Cmeans[[C]]s), s)) f = ls.(Emeans[[B]]s -> f(Cmeans[[C]]s), s) = f SO WE HAVE Hf = f - the fixpoint equation!!