Presentation is loading. Please wait.

Presentation is loading. Please wait.

CS 476 – Programming Language Design

Similar presentations


Presentation on theme: "CS 476 – Programming Language Design"— Presentation transcript:

1 CS 476 – Programming Language Design
William Mansky

2 Adding Variables Next target language: expressions + variables

3 Adding Variables: Syntax
E ::= <#> | E + E | E – E | E * E | <bool> | E and E | E or E | not E | E = E | if E then E else E

4 Adding Variables: Syntax
E ::= <#> | <ident> | E + E | E – E | E * E | <bool> | E and E | E or E | not E | E = E | if E then E else E Example terms: x + 5 if y then 3 else z

5 Adding Variables How do variables get their values?
Option 1: local binding fun x -> x + 5 let x = in if x = 5 then true else false Option 2: assignment x = 3; y = x + 5; x = 4; z = x + 5; // y != z

6 Adding Variables Option 2: assignment
x = 3; y = x + 5; x = 4; z = x + 5; // y != z Some terms now don’t just compute values: they have side effects that change the meaning of later terms We call terms that compute values expressions, and terms with side effects commands

7 Adding Variables: Syntax
E ::= <#> | <ident> | E + E | E – E | E * E | <bool> | E and E | E or E | not E | E = E | if E then E else E C ::= <ident> := E | C; C | skip Example terms: x := 3; y := x = 2; z := true && y x := 0; x := x + 1; y := x; x := x + 1

8 Adding Variables: Types
How do we type variables? (𝑛 is a number) 𝑛 :int 𝑒 1 :int 𝑒 2 :int 𝑒 1 + 𝑒 2 :int (𝑥 is an identifier) 𝑥 : ?

9 Typing Variables, Approach #1
How do we type variables? (𝑛 is a number) 𝑛 :int 𝑒 1 :int 𝑒 2 :int 𝑒 1 + 𝑒 2 :int (𝑥 is an identifier) 𝑥 :int (𝑥 is an identifier) 𝑥 :bool

10 Typing Variables, Approach #1
How do we type variables? (𝑛 is a number) 𝑛 :int 𝑒 1 :int 𝑒 2 :int 𝑒 1 + 𝑒 2 :int (𝑥 is an identifier) 𝑥 :𝜏

11 Typing Variables, Approach #2
How do we type variables? E ::= <#> | (<ident> : T) | E + E | E – E | E * E | <bool> | E and E | E or E | not E | E = E | if E then E else E T ::= INT | BOOL Each tag has its own namespace add INT/BOOL tags in preprocessing 𝑥 :INT :int 𝑥 :BOOL :bool

12

13 Adding Variables: Syntax
E ::= <#> | <ident> | E + E | E – E | E * E | <bool> | E and E | E or E | not E | E = E | if E then E else E C ::= <ident> := E | C; C | skip Example terms: x := 3; y := x = 2; z := true && y x := 0; x := x + 1; y := x; x := x + 1

14 Typing Variables, Approach #3
How do we type variables? Instead of putting tags in the syntax, we could store them separately, in a type context New typing judgment: Γ⊢𝑒 :𝜏, “𝑒 has type 𝜏 in context Γ” Γ is a partial function from identifiers to types Γ 𝑥 =𝜏 Γ⊢𝑥 :𝜏 (𝑛 is a number) Γ⊢𝑛 :int Γ⊢ 𝑒 1 :int Γ⊢ 𝑒 2 :int Γ⊢ 𝑒 1 + 𝑒 2 :int

15 Adding Variables: Types for Commands
What types can a command have? Only one: “correct”, or “ok” Γ⊢𝑒 :𝜏 Γ 𝑥 =𝜏 Γ⊢𝑥≔𝑒 :ok Γ⊢ 𝑐 1 :ok Γ⊢ 𝑐 2 :ok Γ⊢ 𝑐 1 ; 𝑐 2 :ok Γ⊢skip :ok

16

17 Adding Variables: Semantics
Our programs now have state! x := 3 + 4; y := x + 5; b := if y = 12 then true else false; x := 2; z := x + 5; c := b && true; What are the values of the variables at this point? {b = true, x = 2, y = 12}

18 Adding Variables: Semantics
Our programs now have state! Small-step relation is 𝑡, 𝜎 → 𝑡 ′ , 𝜎 ′ , where state 𝜎 is a map from variables to values 𝜎 𝑥 =𝑣 𝑥 ,𝜎 →(𝑣, 𝜎) 𝑒 1 , 𝜎 →( 𝑒 1 ′ , 𝜎 ′ ) 𝑒 1 + 𝑒 2 ,𝜎 →( 𝑒 1 ′ + 𝑒 2 , 𝜎 ′ ) ( 𝑣 1 + 𝑣 2 =𝑣) 𝑣 1 + 𝑣 2 ,𝜎 →(𝑣,𝜎)

19 Textbook Notation Warning
The Formal Semantics of Programming Languages, Winskel Where we write 𝑒⇓𝑣, Winskel writes 𝑒→𝑣 Where we write 𝑒→ 𝑒 ′ , Winskel writes 𝑒 → 1 𝑒 ′

20 Adding Variables: Semantics
Our programs now have state! Small-step relation is 𝑡, 𝜎 → 𝑡 ′ , 𝜎 ′ , where state 𝜎 is a map from variables to values 𝜎 𝑥 =𝑣 𝑥 ,𝜎 →(𝑣, 𝜎) 𝑒 1 , 𝜎 →( 𝑒 1 ′ ,𝜎) 𝑒 1 + 𝑒 2 ,𝜎 →( 𝑒 1 ′ + 𝑒 2 ,𝜎) ( 𝑣 1 + 𝑣 2 =𝑣) 𝑣 1 + 𝑣 2 ,𝜎 →(𝑣,𝜎)

21 Adding Variables: Semantics
Our programs now have state! Small-step relation is 𝑡, 𝜎 → 𝑡 ′ , 𝜎 ′ , where state 𝜎 is a map from variables to values 𝑒,𝜎 →( 𝑒 ′ ,𝜎) 𝑥≔𝑒,𝜎 →(𝑥≔𝑒′, 𝜎) 𝑐 1 ,𝜎 →( 𝑐 1 ′ , 𝜎 ′ ) 𝑐 1 ; 𝑐 2 ,𝜎 →( 𝑐 1 ′ ; 𝑐 2 , 𝜎 ′ ) 𝑥≔𝑣,𝜎 →(skip,𝜎 𝑥↦𝑣 ) skip; 𝑐 2 ,𝜎 →( 𝑐 2 ,𝜎)

22 Structural Rule for Sequencing
What if we had x := 3; x := x + 1; x := 4 → x := x + 1; x := 4, {x = 3} (by rule 1) → x := x + 1, {x = 4} (by rule 2) → skip, {x = 5} 𝑐 2 ,𝜎 →( 𝑐 2 ′ , 𝜎 ′ ) 𝑐 1 ; 𝑐 2 ,𝜎 →( 𝑐 1 ; 𝑐 2 ′ , 𝜎 ′ )

23 Adding Variables: Big-Step Semantics
𝑒, 𝜎 ⇓𝑣 What does an expression evaluate to? What does a command evaluate to? 𝑐, 𝜎 ⇓ 𝜎 ′ 𝜎 𝑥 =𝑣 𝑥,𝜎 ⇓𝑣 𝑒 1 , 𝜎 ⇓ 𝑣 𝑒 2 ,𝜎 ⇓ 𝑣 ( 𝑣 1 + 𝑣 2 =𝑣) 𝑒 1 + 𝑒 2 ,𝜎 ⇓𝑣 𝑒,𝜎 ⇓𝑣 𝑥≔𝑒,𝜎 ⇓𝜎[𝑥↦𝑣] 𝑐 1 ,𝜎 ⇓ 𝜎 ′ 𝑐 2 , 𝜎 ′ ⇓𝜎′′ 𝑐 1 ; 𝑐 2 ,𝜎 ⇓𝜎′′ skip,𝜎 ⇓𝜎

24 Adding Variables: Hybrid Semantics
Expressions don’t change the state, commands do So we might only care about intermediate steps for commands 𝜎 𝑥 =𝑣 𝑥,𝜎 ⇓𝑣 𝑒 1 , 𝜎 ⇓ 𝑣 𝑒 2 ,𝜎 ⇓ 𝑣 ( 𝑣 1 + 𝑣 2 =𝑣) 𝑒 1 + 𝑒 2 ,𝜎 ⇓𝑣 𝑒,𝜎 ⇓𝑣 𝑥≔𝑒,𝜎 →(skip, 𝜎 𝑥↦𝑣 ) 𝑐 1 ,𝜎 →( 𝑐 1 ′ , 𝜎 ′ ) 𝑐 1 ; 𝑐 2 ,𝜎 →( 𝑐 1 ′ ; 𝑐 2 , 𝜎 ′ ) skip; 𝑐 2 ,𝜎 →( 𝑐 2 , 𝜎 ′ )

25 Adding Variables: Interpreter
Follow the big-step semantics let rec eval_exp (e : exp) : value option = match e with | Id x -> | Add (e1, e2) -> | …

26 Adding Variables: Interpreter
Follow the big-step semantics type state = string -> value option let rec eval_exp (e : exp) (s : state) : value option = match e with | Id x -> | Add (e1, e2) -> | … 𝜎 𝑥 =𝑣 𝑥,𝜎 ⇓𝑣

27 Adding Variables: Interpreter
Follow the big-step semantics type state = string -> value option let rec eval_exp (e : exp) (s : state) : value option = match e with | Id x -> s x | Add (e1, e2) -> | … 𝜎 𝑥 =𝑣 𝑥,𝜎 ⇓𝑣

28 Adding Variables: Interpreter
Follow the big-step semantics type state = string -> value option let rec eval_exp (e : exp) (s : state) : value option = match e with | Add (e1, e2) -> (match eval_exp e1 s, eval_exp e2 s with | Some (IntV i1), Some (IntV i2) -> Some (IntV (i1 + i2)) | _, _ -> None) 𝑒 1 , 𝜎 ⇓ 𝑣 𝑒 2 ,𝜎 ⇓ 𝑣 ( 𝑣 1 + 𝑣 2 =𝑣) 𝑒 1 + 𝑒 2 ,𝜎 ⇓𝑣

29 Adding Variables: Interpreter
let update (s : state) (x : string) (v : value) : state = fun y -> if y = x then Some v else s y let rec eval_cmd (c : cmd) (s : state) : state option = match c with | Assign (x, e) -> | Seq (c1, c2) -> | Skip -> 𝑒,𝜎 ⇓𝑣 𝑥≔𝑒,𝜎 ⇓𝜎[𝑥↦𝑣]

30 Adding Variables: Interpreter
let rec eval_cmd (c : cmd) (s : state) : state option = match c with | Assign (x, e) -> (match eval_exp e s with | Some v -> Some (update s x v) | None -> None) | Seq (c1, c2) -> | Skip -> 𝑒,𝜎 ⇓𝑣 𝑥≔𝑒,𝜎 ⇓𝜎[𝑥↦𝑣]

31 Adding Variables: Interpreter
let rec eval_cmd (c : cmd) (s : state) : state option = match c with | … | Seq (c1, c2) -> | Skip -> 𝑐 1 ,𝜎 ⇓ 𝜎 ′ 𝑐 2 , 𝜎 ′ ⇓𝜎′′ 𝑐 1 ; 𝑐 2 ,𝜎 ⇓𝜎′′

32 Adding Variables: Interpreter
let rec eval_cmd (c : cmd) (s : state) : state option = match c with | … | Seq (c1, c2) -> (match eval_cmd c1 s with | Some s’ -> eval_cmd c2 s’ | None -> None) | Skip -> 𝑐 1 ,𝜎 ⇓ 𝜎 ′ 𝑐 2 , 𝜎 ′ ⇓𝜎′′ 𝑐 1 ; 𝑐 2 ,𝜎 ⇓𝜎′′

33 Adding Variables: Interpreter
let rec eval_cmd (c : cmd) (s : state) : state option = match c with | … | Seq (c1, c2) -> (match eval_cmd c1 s with | Some s’ -> eval_cmd c2 s’ | None -> None) | Skip -> Some s skip,𝜎 ⇓𝜎

34 Adding Variables: Interpreter
let empty_state = fun x -> None;; eval_cmd (Seq (Assign (“x”, Int 2), Assign (“y”, Add (Ident “x”, Int 3)))) empty_state;;

35 Adding Variables: Interpreter
eval_cmd (Seq (Assign (“x”, Int 2), Assign (“y”, Add (Ident “x”, Int 3)))) empty_state;; let rec eval_cmd (c : cmd) (s : state) : state option = match c with | Seq (c1, c2) -> (match eval_cmd c1 s with | Some s’ -> eval_cmd c2 s’ | None -> None)

36 Adding Variables: Interpreter
eval_cmd (Seq (Assign (“x”, Int 2), Assign (“y”, Add (Ident “x”, Int 3)))) empty_state;; let rec eval_cmd (c : cmd) (s : state) : state option = match c with | Seq (c1, c2) -> (match eval_cmd (Assign (“x”, 2)) empty_state with | Some s’ -> eval_cmd (Assign (“y”, Add (Ident “x”, Int 3))) s’ | None -> None)

37 Adding Variables: Interpreter
eval_cmd (Seq (Assign (“x”, Int 2), Assign (“y”, Add (Ident “x”, Int 3)))) empty_state;; match eval_cmd (Assign (“x”, 2)) empty_state with | Some s’ -> eval_cmd (Assign (“y”, Add (Ident “x”, Int 3))) s’ | Assign (x, e) -> (match eval_exp e s with | Some v -> Some (update s x v)

38 Adding Variables: Interpreter
eval_cmd (Seq (Assign (“x”, Int 2), Assign (“y”, Add (Ident “x”, Int 3)))) empty_state;; match eval_cmd (Assign (“x”, 2)) empty_state with | Some s’ -> eval_cmd (Assign (“y”, Add (Ident “x”, Int 3))) s’ | Assign (x, e) -> (match eval_exp (Int 2) empty_state with | Some v -> Some (update empty_state “x” v)

39 Adding Variables: Interpreter
eval_cmd (Seq (Assign (“x”, Int 2), Assign (“y”, Add (Ident “x”, Int 3)))) empty_state;; match eval_cmd (Assign (“x”, 2)) empty_state with | Some s’ -> eval_cmd (Assign (“y”, Add (Ident “x”, Int 3))) s’ | Assign (x, e) -> (match Some (IntV 2) with | Some v -> Some (update empty_state “x” v)

40 Adding Variables: Interpreter
eval_cmd (Seq (Assign (“x”, Int 2), Assign (“y”, Add (Ident “x”, Int 3)))) empty_state;; match Some {“x” = IntV 2} with | Some s’ -> eval_cmd (Assign (“y”, Add (Ident “x”, Int 3))) s’ | Assign (x, e) -> (match Some (IntV 2) with | Some v -> Some (update empty_state “x” v)

41 Adding Variables: Interpreter
eval_cmd (Seq (Assign (“x”, Int 2), Assign (“y”, Add (Ident “x”, Int 3)))) empty_state;; eval_cmd (Assign (“y”, Add (Ident “x”, Int 3))) {“x” = IntV 2} | Assign (x, e) -> (match eval_exp (Add (Ident “x”, Int 3)) {“x” = IntV 2} with | Some v -> Some (update {“x” = IntV 2} “y” v)

42 Adding Variables: Interpreter
eval_cmd (Seq (Assign (“x”, Int 2), Assign (“y”, Add (Ident “x”, Int 3)))) empty_state;; eval_cmd (Assign (“y”, Add (Ident “x”, Int 3))) {“x” = IntV 2} | Assign (x, e) -> (match Some (IntV 5) with | Some v -> Some (update {“x” = IntV 2} “y” v)

43 Adding Variables: Interpreter
eval_cmd (Seq (Assign (“x”, Int 2), Assign (“y”, Add (Ident “x”, Int 3)))) empty_state;; Some {“x” = IntV 2, “y” = IntV 5} match eval_cmd (Seq (Assign (“x”, Int 2), Assign (“y”, Add (Ident “x”, Int 3)))) empty_state with | Some res -> res “y” | None -> None;; - : value option = Some (IntV 5)

44

45 Typing Variables, Approach #3
How do we type variables? Instead of putting tags in the syntax, we could store them separately, in a type context New typing judgment: Γ⊢𝑒 :𝜏, “𝑒 has type 𝜏 in context Γ” Γ is a partial function from identifiers to types Where does Γ come from? Γ 𝑥 =𝜏 Γ⊢𝑥 :𝜏 (𝑛 is a number) Γ⊢𝑛 :int Γ⊢ 𝑒 1 :int Γ⊢ 𝑒 2 :int Γ⊢ 𝑒 1 + 𝑒 2 :int

46 IMP with Declarations: Syntax
E ::= … C ::= … D ::= T <ident> | D; D T ::= int | bool P ::= D; C Example: int x; bool y; int z; x := 3; y := (x = 4); if y then z := 2 else x := 4

47 IMP with Declarations: Types
𝑑 :Γ means “𝑑 constructs type context Γ” int 𝑥 :{𝑥 :int} bool 𝑥 :{𝑥 :bool} 𝑑 1 : Γ 𝑑 2 : Γ 2 𝑑 1 ; 𝑑 2 : Γ 1 ⊎ Γ 2 𝑑 :Γ Γ⊢𝑐 :ok 𝑑;𝑐 :ok

48 IMP with Declarations: Semantics
eval_prog p = match p with Prog (d, c) -> eval_cmd c empty_state 𝑑;𝑐→(𝑐,∅) 𝑐,∅ ⇓𝜎 𝑑;𝑐⇓𝜎 And for an interpreter, same deal – we’d just call eval_cmd with empty_state.

49 IMP with Declarations: Type Checker
type typ = type decl = type prog = type tycon = let rec process_decls (d : decl) : tycon = let typecheck_prog p = match p with Prog (d, c) -> typecheck_cmd c (process_decls d) And for an interpreter, same deal – we’d just call eval_cmd with empty_state.

50


Download ppt "CS 476 – Programming Language Design"

Similar presentations


Ads by Google