University of Arizonacollberg/Teaching/520/... · 520—Spring 2005—54 Abstract Syntax data...
Transcript of University of Arizonacollberg/Teaching/520/... · 520—Spring 2005—54 Abstract Syntax data...
520—Spring 2005—54
CSc 520
Principles of ProgrammingLanguages
54: Semantics — Denotational Semantics —Static Semantics
Christian Collberg
Department of Computer Science
University of Arizona
Copyright c© 2005 Christian Collberg[1] 520—Spring 2005—54
Context-Sensitive Syntax
We can use a denotational-semantic style to define thecontext-sensitive syntax (the context conditions, thestatic semantic rules) of the language.
These are the rules that a compiler will typically checkduring the semantic analysis phase of compilation.
[2]
520—Spring 2005—54
Pelican Context Conditions
1. The program name identifier lies in a scope outside themain block.
2. All identifiers that appear in a block must be declared inthat block or in an enclosing block.
3. No identifier may be declared more than once at the toplevel of a block.
4. The identifier on the left side of an assignmentcommand must be declared as a variable, and theexpression on the right side must be of the same type.
5. An identifier occurring as an (integer) element must bean integer variable or an integer constant.
6. An identifier occurring as a Boolean element must be aBoolean variable or a Boolean constant.
[3] 520—Spring 2005—54
Pelican Context Conditions. . .
7. An identifier occurring in a read command must be aninteger variable.
8. An identifier used in a procedure call must be defined ina procedure declaration with the same (zero or one)number of parameters.
9. The identifier defined as the formal parameter in aprocedure declaration is considered to belong to the toplevel declarations of the block that forms the body of theprocedure.
10. The expression in a procedure call must match the typeof the formal parameter in the procedure s declaration.
[4]
520—Spring 2005—54
The Static Semantics of Pelican
[5] 520—Spring 2005—54
Abstract Syntactic Domains
These are the abstract syntactic domains of Pelican:
P : Program
B: Block
C: Command
D: Declaration
T : Type
E: Expression
O: Operator
N : Numeral
I: Identifier
[6]
520—Spring 2005—54
Abstract Syntax of Pelican
Program ::= program identifieris Block end
Block ::= Declaration* begin Command end
Declaration ::= var Identifier: Type | const Identifier=Expression | procedure Identifieris Block | procedureIdentifier( identifier: Type ) is Block |
Type ::= integer | boolean
Command ::= . . . |declare BlockIdentifier |Identifier( Expression )
Expression ::= . . .
[7] 520—Spring 2005—54
Semantic Domains of Pelican
Environments map identifiers to types.
Sort represents all the different types an expression cantake on.
We distinguish between variables (IntVar,BoolVar) andconstants (Integer,Boolean).
Sort = {Integer, Boolean, IntVar, BoolVar, Program, unbound}
Boolean = {true, false}
Env = Identifier → Sort
[8]
520—Spring 2005—54
Semantic Functions of Pelican
We return true if a program satisfies all it staticsemantic constraints:
validate : Program → Boolean
To check a block we need access to an environmentcontaining declared identifiers:
examine : Block → Env → Boolean
The result of checking an expression is its type:
typify : Expression → Env → Sort
[9] 520—Spring 2005—54
Semantic Functions of Pelican. . .
To elaborate a declaration we need two environments:
elaborate : Declaration → (Env, Env) → (Env, Env)
1. The first environment lenv holds the identifiers localto the block. It is used to check for multiply declaredidentifiers.
2. The second environment env holds accumulateddeclarations.
Commands (statements) are checked given anenvironment of identifiers and their types:
check : Command → Env → Boolean
[10]
520—Spring 2005—54
Environment ADT
The environment is a structure that maps identifiers totheir types:
Example:
env = {c 7→ Integer, a 7→ IntVar}
emptyEnv : Env
extendEnv : Env × Identifier × Sort → Env
applyEnv : Env × Identifier → Sort
[11] 520—Spring 2005—54
Semantic Equations
[12]
520—Spring 2005—54
Programs
We validate the program (check its context conditions)by checking the main block B:
validate [[program I is B]] = examine [[B]] env
where env = extendEnv(e, I, Program)
where e = emptyEnv
lenv1 will contain all the identifiers declared in D. envcontains the identifiers inherited from enclosing blocks:
examine [[D begin C end]] env = check [[C]] env1
where (lenv1, env1) = elaborate [[D]] (e, env)
where e = emptyEnv
[13] 520—Spring 2005—54
Declarations
Sequences of declarations build up the environment:
elaborate [[ε]] (lenv, env) = (lenv, env)
elaborate [[D1 D2]] env = elaborate [[D2]] ◦ elaborate [[D1]]
Constant declarations add an entry id 7→ type to theenvironment, first checking for multiple declarations:
elaborate [[const I = E]](lenv, env) =
if applyEnv(lenv, I) == unbound then(l, e) else error
where t = typify [[E]] env
l = extendEnv(lenv, I, t)
e = extendEnv(env, I, t)
[14]
520—Spring 2005—54
Declarations. . .
Variable declarations add an entry id 7→ type to theenvironment, first checking for multiple declarations:
elaborate [[var I : T ]] (lenv, env) =
if applyEnv(lenv, I) == unbound then(l, e) else error
where t = type(T )
l = extendEnv(lenv, I, t)
e = extendEnv(env, I, t)
[15] 520—Spring 2005—54
Commands
A sequence of commands is OK, if each individualcommand is:
check [[C1; C2]] env = (check [[C1]] env) & (check [[C2]] env)
Note that both commands get the same environment.
The skip command is always OK:
check [[skip]] env = true
[16]
520—Spring 2005—54
Commands. . .
The assignment statement looks up the identifier in theenvironment and compares it to the type of the righthand side:
check [[I:= E]] env = (l = IntVar & r = Integer) |
(l = BoolVar & r = Boolean)
where l = applyEnv(env, I)
r = typify [[E]] env
Note that I cannot be an identifier declared to be aconstant.
[17] 520—Spring 2005—54
Commands. . .
If-statements:
check [[if E then C]] env = p &check [[C]]
where p = typify [[E]] env
If-then-else-statements:
check [[if E then C1 else C2]] env = p &check [[C1]] &check [[C2]]
where p = typify [[E]] env
Loops:
check [[while E do C]] env = p &check [[C]]
where p = typify [[E]] env[18]
520—Spring 2005—54
Commands. . .
Local scope:
check [[declare B]] env = examine [[B]] env
Input and Output:
check [[read I ]] env = applyEnv(I, env) = IntVar
check [[write E]] env = typify [[E]] env = Integer
[19] 520—Spring 2005—54
Expressions
typify [[I ]] env = if v ∈ {IntVar, Integer} then Integer
else if v ∈ {BoolVar, Boolean} then Boolean
else if v = unbound then error
where v = applyEnv(env, I)
We look up the identifier I in the current environment.
Integer variables and constants generate an Integersort, Boolean variables and constants generate aBoolean sort.
Undeclared identifiers generate an error.
[20]
520—Spring 2005—54
Expressions. . .
typify [[N ]] env = Integer
typify [[true]] env = Boolean
typify [[false]] env = Boolean
typify [[E1 + E2]] env = if m = n = Integer
then Integer
else error
where m = typify [[E1]] env
n = typify [[E2]] env
[21] 520—Spring 2005—54
Example
program p is
const m = 34; -- Point A
begin
declare -- Point B
var c : boolean; -- Point C
const c = m+21; -- Error
begin
write m+c;
end
end
At point A: env = {m 7→ Integer, p 7→ Program}, lenv = {m 7→ Integer}
At point B: env = {m 7→ Integer, p 7→ Program}, lenv = { }
At point C: env = {c 7→ BoolVar, m 7→ Integer, p 7→ Program},lenv = {c 7→ BoolVar}
[22]
520—Spring 2005—54
A Haskell Prototype
[23] 520—Spring 2005—54
Abstract Syntax
-- Abstract Syntax for storeable values:
type Num = Int
data Sort = IntType | BoolType | IntVar |
BoolVar | Routine | Unbound
type Identifier = String
type Env = [(Identifier,Sort)]
[24]
520—Spring 2005—54
Abstract Syntax
data Operator = Add | Sub | Mul | Minus | Div ...
data Expression = Id Identifier |
LitInt Num |
TrueVal |
FalseVal |
Unary Operator Expression |
Binary Expression Operator Expression
[25] 520—Spring 2005—54
Abstract Syntax
data Program = Program Identifier Block
data Block = Block Declaration Command
data Declaration =
VarDecl Identifier Sort |
DeclSeq Declaration Declaration |
NullDecl |
ConstDecl Identifier Expression |
ProcDecl0 Identifier Block |
ProcDecl1 Identifier Identifier Sort Block
[26]
520—Spring 2005—54
Abstract Syntax
data Command = Skip |
Assign Identifier Expression |
Read Identifier |
Write Expression |
IfThen Expression Command |
IfThenElse Expression Command Command |
While Expression Command |
Seq Command Command |
Declare Block |
Call0 Identifier |
Call1 Identifier Expression
[27] 520—Spring 2005—54
Environment
emptyEnv:: Env
emptyEnv = []
extendEnv:: Env -> Identifier -> Sort -> Env
extendEnv env id val = (id,val) : env
applyEnv:: Env -> Identifier -> Sort
applyEnv [] _ = Unbound
applyEnv ((s,sort):r) id
| s==id = sort
| otherwise = applyEnv r id
[28]
520—Spring 2005—54
Declarations
elaborate :: Declaration -> (Env,Env) -> (Env,Env)
elaborate NullDecl (lenv,env) = (lenv,env)
elaborate (DeclSeq d1 d2) (lenv,env) = (lenv2,env2)
where (lenv1,env1) = elaborate d1 (lenv,env)
(lenv2,env2) = elaborate d2 (lenv1,env1)
[29] 520—Spring 2005—54
Declarations
elaborate (VarDecl id typeid) (lenv,env) =
if (applyEnv lenv id) == Unbound then
(lenv1,env1)
else
error ("ERROR: Multiple declaration")
where lenv1 = extendEnv lenv id typev
env1 = extendEnv env id typev
typev = case typeid of
IntType -> IntVar
BoolType -> BoolVar
[30]
520—Spring 2005—54
Declarations
elaborate (ConstDecl id e) (lenv,env) =
if (applyEnv lenv id) == Unbound then
(lenv1,env1)
else
error ("ERROR: Multiple declaration")
where lenv1 = extendEnv lenv id (typify e env)
env1 = extendEnv env id (typify e env)
[31] 520—Spring 2005—54
Expressions
btype :: Sort -> Operator -> Sort -> Sort
btype IntType Add IntType = IntType
btype IntType Mul IntType = IntType
btype IntType Div IntType = IntType
btype IntType Sub IntType = IntType
btype BoolType And BoolType = BoolType
btype BoolType Or BoolType = BoolType
btype IntType Lt IntType = BoolType
btype IntType Gt IntType = BoolType
btype IntType Le IntType = BoolType
btype IntType Ge IntType = BoolType
btype IntType Eq IntType = BoolType
btype IntType Ne IntType = BoolType
btype a op b =
error ("ERROR: Type mismatch")
[32]
520—Spring 2005—54
Expressions
typify :: Expression -> Env -> Sort
typify (Id id) env = case (applyEnv env id) of
IntVar -> IntType
IntType -> IntType
BoolVar -> BoolType
BoolType -> BoolType
Routine -> Routine
Unbound -> error ("ERROR: Ident not declared")
[33] 520—Spring 2005—54
Expressions
typify (LitInt n) env = IntType
typify (TrueVal) env = BoolType
typify (FalseVal) env = BoolType
typify (Unary op r) env = utype op n
where n = typify r env
typify (Binary l op r) env = btype m op n
where m = typify l env
n = typify r env
[34]
520—Spring 2005—54
Commands
check :: Command -> Env -> Bool
check (Skip) env = True
check (Seq c1 c2) env = (check c1 env) && (check c2 env)
[35] 520—Spring 2005—54
Commands. . .
check (Assign id e) env =
if not v then
error ("ERROR: Variable expected")
else
if b then b
else error "ERROR: Assignment type error"
where l = applyEnv env id
r = typify e env
b = ((l==IntVar) && (r==IntType) ||
(l==BoolVar) && (r==BoolType))
v = (l==IntVar) || (l==BoolVar)
[36]
520—Spring 2005—54
Commands. . .
check (Read id) env =
if not v then
error ("ERROR: Variable expected")
else
if l==IntVar then True
else error "ERROR: Read type error"
where l = applyEnv env id
v = (l==IntVar) || (l==BoolVar)
check (Write e) env =
if r==IntType then True
else error "ERROR: Write type error"
where r = typify e env
[37] 520—Spring 2005—54
Commands. . .
check (IfThen b c) env = if p then check c env
else error "ERROR: Boolean type expected."
where p = (typify b env)==BoolType
check (IfThenElse b c1 c2) env = if p
then (check c1 env) && (check c2 env)
else error "ERROR: Boolean type expected"
where p = (typify b env)==BoolType
check (While b c) env = if p then check c env
else error "ERROR: Boolean type expected."
where p = (typify b env)==BoolType
[38]
520—Spring 2005—54
Programs
validate :: Program -> Bool
validate (Program id b) = examine b (env)
where env = extendEnv emptyEnv id Routine
-- Note: "seq" is necessary to force elaboration
-- (avoid laziness) even when the new environment
-- is not needed.
examine :: Block -> Env -> Bool
examine (Block decl cmd) env = seq env1 (check cmd env1)
where env1 = snd (elaborate decl (emptyEnv,env))
[39] 520—Spring 2005—54
Examples
> validate (Program "h"
(Block
(VarDecl "s" IntType)
(Assign "s" (LitInt 5))))
True
> validate (Program "h"
(Block
(VarDecl "s" IntType)
(Assign "s" (TrueVal))))
Program error: ERROR: Assignment type error
[40]
520—Spring 2005—54
Examples. . .
> validate (Program "h"
(Block
NullDecl
(Assign "s" (LitInt 5))))
Program error: ERROR: Variable expected
[41] 520—Spring 2005—54
Examples. . .
> validate (Program "h"
(Block
(VarDecl "x" BoolType)
(Declare
(Block
(VarDecl "y" BoolType)
(Declare
(Block
(VarDecl "x" IntType)
(Assign "s" (LitInt 99))
) ) ) ) )
)
Program error: ERROR: Variable expected
[42]
520—Spring 2005—54
Examples. . .
> validate (Program "h"
(Block (
DeclSeq
(VarDecl "s" BoolType)
(VarDecl "s" IntType))
Skip))
Program error: ERROR: Multiple declaration
[43] 520—Spring 2005—54
Readings and References
Read pp. 323–328, in Chapter 9 of Syntax andSemantics of Programming Languages, by KenSlonneger and Barry Kurtz,http://www.cs.uiowa.edu/˜slonnegr/plf/Book.
[44]
520—Spring 2005—54
Acknowledgments
Much of the material in this lecture on DenotationalSemantics is taken from the book Syntax andSemantics of Programming Languages, by KenSlonneger and Barry Kurtz,http://www.cs.uiowa.edu/˜slonnegr/plf/Book.
[45]