Syntax Gabriele Keller Ron Vanderfeesten Overview So far - - PowerPoint PPT Presentation

syntax
SMART_READER_LITE
LIVE PREVIEW

Syntax Gabriele Keller Ron Vanderfeesten Overview So far - - PowerPoint PPT Presentation

Concepts of Program Design Syntax Gabriele Keller Ron Vanderfeesten Overview So far Revision of inference rules, natural (rule) induction Haskell Simple grammars specified using inference rules This week - first-order &


slide-1
SLIDE 1

Concepts of Program Design

Syntax

Gabriele Keller Ron Vanderfeesten

slide-2
SLIDE 2
  • So far
  • Revision of inference rules, natural (rule) induction
  • Haskell
  • Simple grammars specified using inference rules
  • This week
  • first-order & higher-order abstract syntax,
  • static and dynamic semantics
  • embedded languages
  • assignment 1 will be released early next week
  • let me know on Thu if you consider doing the project (no need for final decision

yet)

Overview

slide-3
SLIDE 3

Concrete Syntax

  • the inference rules for SExpr defined the concrete syntax of a simple language,

including precedence and associativity

  • the concrete syntax of a language is designed with the human user in mind
  • not adequate for internal representation during compilation

i FExpr e SExpr (e) FExpr e1 SExpr e2 PExpr e1 + e2 SExpr e1 PExpr e2 FExpr e1 * e2 PExpr e PExpr e SExpr e FExpr e PExpr i ∈ Int

slide-4
SLIDE 4

Concrete vs abstract syntax

  • Example:
  • 1 + 2 * 3
  • 1 + (2 * 3)
  • (1) + ((2) * (3))
  • what is the problem?
  • Concrete syntax contains too much information
  • these expressions all have different derivations, but semantically, they

represent the same arithmetic expression

  • After parsing, we’re just interested in three cases: an expression is either
  • an addition
  • a multiplication, or
  • a number
slide-5
SLIDE 5

Concrete vs abstract syntax

  • we use Haskell style terms of the form
  • perator arg1 arg2 ….

to represent parsed programs unambiguously; e.g., Plus (Num 1) (Times (Num 2) (Num 3))

  • we define the abstract grammar of arithmetic expressions as follows:

i∈Int (Num i) expr t1 expr t2 expr (Times t1 t2) expr t1 expr t2 expr (Plus t1 t2) expr

slide-6
SLIDE 6

Concrete vs abstract syntax

  • Parsers
  • check if the program (sequence of tokens) is derivable from the rules of the

concrete syntax

  • turn the derivation into an abstract syntax tree (AST)
  • Transformation rules
  • we formalise this with inference rules as a binary relation ↔:

We write e SExpr ↔ t expr iff the (concrete grammar) expression e corresponds to the (abstract grammar) expression t. Usually, many different concrete expressions correspond to a single abstract expression

slide-7
SLIDE 7

Concrete vs abstract syntax

  • Example:
  • 1 + 2 * 3 SExpr ↔ (Plus (Num 1) (Times (Num 2)(Num 3))) expr
  • 1 + (2 * 3) SExpr ↔ (Plus (Num 1) (Times (Num 2)(Num 3))) expr
  • (1) + ((2)*(3)) SExpr ↔ (Plus (Num 1) (Times (Num 2)(Num 3))) expr
slide-8
SLIDE 8

Concrete vs abstract syntax

  • Formal definition: we define a parsing relation ↔ formally as an extension of the

structural rules of the concrete syntax. i ∈ Int i FExpr e1 SExpr e2 PExpr e1 + e2 SExpr e PExpr e SExpr e1 PExpr e2 FExpr e1 * e2 PExpr e FExpr e PExpr e SExpr (e) FExpr ↔ e1’ expr ↔ e2’ expr ↔ (Plus e1’ e2’) expr ↔ e1’ expr ↔ e2’ expr ↔ (Times e1’ e2’) expr ↔ (Num i) expr ↔ e’ expr ↔ e’ expr ↔ e’ expr ↔ e’ expr ↔ e’ expr ↔ e’ expr

slide-9
SLIDE 9

The translation relation ↔

  • The binary syntax translation relation
  • e ↔ e’

can be viewed as translation function

  • input is e
  • output is e’
  • derivations are unambiguously determined by e
  • since the grammar of the concrete syntax was unambiguous
  • e’ is unambiguously determined by the derivation
  • for each concrete syntax term, there is only one rule we can apply at each

step

slide-10
SLIDE 10

The translation relation ↔

  • Derive the abstract syntax as follows:

(1) bottom up, decompose the concrete expression e according to the left hand side of ↔ (2) top down, synthesise the abstract expression e’ according to the right hand side of each ↔ from the rules used in the derivation.

  • Example: derivation for 1 + 2 * 3 (we abbreviate SExpr, PExpr, FExpr with S, P

, F respectively, and expr with e 1 + 2 * 3 S ↔

slide-11
SLIDE 11

The translation relation ↔

  • Derive the abstract syntax as follows:

(1) bottom up, decompose the concrete expression e according to the left hand side of ↔ (2) top down, synthesise the abstract expression e’ according to the right hand side of each ↔ from the rules used in the derivation.

  • Example: derivation for 1 + 2 * 3 (we abbreviate SExpr, PExpr, FExpr with S, P

, F respectively, and expr with e 1 + 2 * 3 S ↔ 1 S ↔ 1 P ↔ 1 F ↔ 1 Int (Num 1) e (Num 1) e (Num 1) e 2 P ↔ 3 F ↔ 2 F ↔ 2 Int (Num 2) e 3 Int (Num 2) e (Num 3) e (Times (Num 2) (Num 3)) e Plus (Num 1)(Times (Num 2)(Num 3)) e 2 * 3 P ↔

slide-12
SLIDE 12

Parsing and inference rules

  • The parsing problem

Given a sequence of tokens s SExpr , find t such that s SExpr ↔ t expr

  • Requirements

A parser should be

  • total for all expressions that are correct according to the concrete syntax,

that is

  • there must be a t expr for every s SExpr
  • unambiguous, that is for every t1 and t2 with
  • s SExpr ↔ t1 expr and s SExpr ↔ t2 expr

we have t1 = t2

slide-13
SLIDE 13

Parsing and pretty printing

  • The parsing problem

Given a sequence of tokens s SExpr , find t such that s SExpr ↔ t expr

  • What about the inverse?
  • given t expr, find s SExpr
  • The inverse of parsing is unparsing
  • unparsing is often ambiguous
  • unparsing is often partial (not total)
  • Pretty printing
  • unparsing together with appropriate formatting us called pretty printing
  • due to the ambiguity of unparsing, this will usually not reproduce the original

program (but a semantically equivalent one)

slide-14
SLIDE 14

Parsing and pretty printing

Example Given the abstract syntax term Times (Num 3) (Times (Num 4) (Num 5))) pretty printing may produce the string “3 * 4 * 5” or “(3 * 4) * 5”

  • it’s best to chose the most simple, readable representation
  • but usually, this requires extra effort
slide-15
SLIDE 15

Bindings

  • Local variable bindings (let)

Let’s extend our simple expression language with

  • variables and variable bindings
  • let v = e1 in e2 end
  • Example:

let x = 3 in x + 1 end let x = 3 in let y = x + 1 in x + y end end

id Ident id FExpr e1 SExpr e2 SExpr let id = e1 in e2 end FExpr

  • Concrete syntax (adding two new rules):
slide-16
SLIDE 16

Bindings

The end keyword is necessary for nested let-expressions:

let x = 3 in 2 * let y = 5 in y + x

we’ll leave it out when not needed to disambiguate

slide-17
SLIDE 17

Bindings

  • First order abstract syntax:

(Num i) expr t1 expr t2 expr (Times t1 t2 ) expr t1 expr t2 expr (Plus t1 t2 ) expr id Ident (Var id) expr (Var id) expr t1 expr t2 expr (Let id t1 t2 ) expr i ∈ Int

slide-18
SLIDE 18

Bindings

  • Scope
  • let x = e1 in e2 end introduces -or binds- the variable x for use within its

scope e2

  • we call the occurrence of x in the left-hand side of the binding its binding
  • ccurrence (or defining occurrence)
  • occurrences of x in e2 are usage occurrences
  • finding the binding occurrence of a variable is called scope resolution
  • Two types of scope resolution
  • static (or lexical) scoping: scoping resolution happens at compile time
  • dynamic scoping: resolution happens at run time
slide-19
SLIDE 19

Bindings

Example: Out of scope variable: the first occurrence of y is out of scope

scope of x

let x = y in let y = 2 in x

scope of y

slide-20
SLIDE 20

Bindings

Example: Shadowing: the inner binding of x is shadowing the outer binding

let x = 5 in let x = 3 in x + x

slide-21
SLIDE 21

Scope

  • Where the scope starts differs in different languages:

void f () { … int x = 5; int y = x; … } In C:

scope of x

function showMsg () { console.log(msg); … var msg = “hi”; … } JavaSript:

scope of msg

let y = x x = 5 … in … In Haskell:

scope of x

… where y = x x = 5 …

slide-22
SLIDE 22

Bindings

Example: what is the difference between these two expressions?

let x = 3 in x + 1 end

α-equivalence:

  • they only differ in the choice of the bound variable names
  • we call them α-equivalent
  • we call the process of consistently changing variable names α-renaming
  • the terminology is due to a conversion rule of the λ-calculus
  • we write e1 ≡α e2 if two expressions are α-equivalent
  • the relation ≡α is a equivalence relation

let y = 3 in y + 1 end

slide-23
SLIDE 23

Substitution

  • Free variables

★ a free variable is one without a binding occurrence

  • let x = 1 in x + y end
  • Substitution: replacing all occurrences of a free variable x in an expression e by

another expression e’ is called substitution

  • Example: substituting x with 2 * y in

5 * x + 7 yields 5 * (2 * y) + 7 y is free in this expression

slide-24
SLIDE 24

Substitution

  • We have to be careful when applying substitution:
  • let y = 5 in y * x + 7
  • let z = 5 in z * x + 7
  • substitute x by 2 * y in both
  • let y = 5 in y * (2 * y) + 7
  • let z = 5 in z * (2 * y) + 7
  • the free variable y of 2 * y is captured in the first expression

α-equivalent not α-equivalent anymore!

slide-25
SLIDE 25

Substitution

  • Capture-free substitution: to substitute e’ for x in e we require the free variables

in e’ to be different from the variables in e

  • We a can always arrange for a substitution to be capture free
  • use α-renaming of e’ (the expression replacing the variable)
  • change all variable names that occur in e and e’
  • or use fresh variable names
slide-26
SLIDE 26

Higher-order abstract syntax

  • Limitations of (first-order) abstract syntax
  • Defining and usage occurrence of variables are treated the same
  • abstract syntax doesn’t differentiate between binding and using occurrence of

a variable

  • it’s difficult to identify α-equivalent expressions
  • variables are just terms, like numbers

(Num i) expr t1 expr t2 expr (Times t1 t2 ) expr id Ident (Var id) expr (Var id) expr t1 expr t2 expr (Let id t1 t2 ) expr

slide-27
SLIDE 27

Higher-order abstract syntax

  • Higher-order abstract syntax has variables and abstraction as special constructs
  • A term of the form x.t is called an abstraction
  • Structure of a higher-order term: a higher-order term can have one of four forms:

(1) a constant (e.g., int, string) (2) a variable x (3) (Operator t1 ... tn)

  • Num 4
  • Plus x (Num 4)

(4) x.t (i.e., the variable x is bound in term t)

  • x. Plus x (Num 1)
  • x.y. Plus x y
slide-28
SLIDE 28

Higher-order abstract syntax

  • Higher-order abstract syntax for let-expressions

id Ident (Var id) expr (Var id) expr t1 expr t2 expr (Let id t1 t2 ) expr

first-order

id Ident id expr t1 expr t2 expr (Let t1 id.t2 ) expr

higher-order

id FExpr ↔ id expr id Ident e1 SExpr ↔ t1 expr e2 SExpr ↔ t2 expr let id = e1 in e2 end SExpr ↔ (Let t1 id.t2) expr

  • Mapping of concrete to higher-order syntax
  • Example:

let x = 5 in x+y SExpr ↔ (Let (Num 5) (x.Plus x y)) expr

slide-29
SLIDE 29

Substitution

Definition: A notation for substitution We write t[x:=t’] to denote a term t where all the free occurrences of x have been replaced by the term t’.

  • Example:

(Plus x y) [x :=(Num 1)] = (Plus (Num 1) y) Definition: Renaming If we replace a variable in the binding and the body of an abstraction, it is called renaming, and the resulting term is α-equivalent to the original term: x.t ≡α y.t [x:= y] if y doesn’t occur free in t (or y ∉ FV (t))

slide-30
SLIDE 30

Substitution

  • A inductive definition of FV(t):

FV (x) = {x} FV (Op t1 ... tn) = FV(t1) ∪ .... ∪ FV(tn) FV (x.t) = FV(t) \ {x}

  • Substituting one variable by another:

x[x:=y] = y z[x:=y] = z, if z≠x (Op t1 ... tn) [x:=y] = Op (t1 [x:=y]) ... (tn [x:=y]) x.t [x:=y] = x.t z.t [x:=y] = z. (t [x:=y]), if x≠z, y≠z y.t [x:=y] = undefined, if x≠y

slide-31
SLIDE 31

Substitution

  • Substituting a variable by a term u:

x [x:=u] = u z [x:=u] = z, if z≠x (Op t1 ... tn) [x:=u] = Op (t1 [x:=u]) ... (tn [x:=u]) x.t [x:=u] = x.t z.t [x:=u] = z. (t [x:=u]), if x≠z, z∉FV(u) y.t [x:=u] = undefined, if y∈FV(u)

slide-32
SLIDE 32

λ-Abstractions

  • The notation for bindings is (not coincidentally) very similar to the notation for λ-

abstractions also called anonymous functions

  • Anonymous functions are supported by most functional languages and more

recently also by many multi-paradigm languages:

slide-33
SLIDE 33

λ-Abstractions

map even [1,2,3,4] = [False, True, False, True] map (3+) [1,2,3,4] = [4,5,6,7] map (/2) [2,4,6,8] = [1,2,3,4]

  • Example: mapping a function over lists

let f x = x * x + 5 in map f [1,2,3,4] = [6,9,14,21] map (\x -> x * x + 5) [1,2,3,4] (\x -> x * 2) 10 = 20 let f = \x -> x * x + 5 in map f [1,2,3,4]

slide-34
SLIDE 34

The untyped λ-Calculus

  • Introduced in the 1936 by mathematician Alonzo Church
  • Very simple, Turing-complete formalism for computations
  • λ-terms:

id λ-term λ id.t λ-term t λ-term (t s) λ-term t λ-term s λ-term id ∈ Ident

  • The pure λ-calculus has no numbers, operations or anything else build-in
slide-35
SLIDE 35

The untyped λ-Calculus

  • The calculus has three rules:

★ α-conversion

  • if t ≡α s, then the two terms are equivalent in the calculus
  • λ x. λ y. y ≡α λ y. λ x. x ≡α λ a λ b. b

★ β-reduction

  • (λ x.t)s can be reduced to t[x:=s]
  • (λ x. λ y. y) (λ a. a) →β λ y. y
  • (λ x. λ y. x) (λ a. a) →β λ y. λ a. a
  • (λ x. x + 1) 5 →β 5 + 1

★ η-conversion

  • λ x. (f x) is equivalent to f if x is not free in f
  • λ x. ((λ z. z + 1) x) ≡η (λ z. z + 1)
slide-36
SLIDE 36

Avoiding names altogether

  • De Bruijn Indices:

in db-term λ t db-term t db-term (t s) db-term t db-term s db-term n ∈ Int

λx. λy. (x + y) λx. (x + (λ f. f (f x))(λ z. z + x))

λ λ (i1 + i0)

λ ( i0 + (λ i0 (i0 i1))(λ i0 + i1))

slide-37
SLIDE 37

De Bruijn indices

  • Application using De Bruijn Indices:

λ((λ λ i0 + i1 + i2 ) 5)

  • if the term t has no free variables:

(t1t2)[n := t] = (t1[n := t]) (t2[n := t]) (λt’)[n := t] = λ (t’[n+1 := t]) im[n := t] = t , if n = m im-1, if m > n im , otherwise (λt’) t = t’[0 := t]

slide-38
SLIDE 38

De Bruijn indices

  • Application using De Bruijn Indices:

λ((λ λ i0 + i1 + i2 ) (5 + i0))

  • if the term has free variables:

(t1t2)[n := t] = (t1[n := t]) (t2[n := t]) (λt’)[n := t] = λ (t’[n+1 := t↑0]) im[n := t] = t , if n = m im-1, if m > n im , otherwise im↑n = im+1, m ≥ n im, otherwise (t1t2)↑n = t1↑n t2↑n (λt)↑n = λ(t↑n+1)

slide-39
SLIDE 39

De Bruijn indices

  • With this definition, we have

λ ((λ λ i0 + i1 + i2 ) (5 + i0)) — application rule = λ ((λ i0 + i1 + i2 ) [0 := 5 + i0])) — (3) = λ (λ((i0 + i1 + i2 ) [1 := (5 + i0)↑0])) — (6) = λ (λ((i0 + i1 + i2 ) [1 := (5 + i0)↑1])) — (4,5) = λ (λ((i0 + i1 + i2 ) [1 := (5 + i1)])) — (2) = λ (λ(i0 [1 := (5 + i1)]+ i1[1 := (5 + i1)] + i2[1 := (5 + i1)] )) — (2) = λ (λ(i0 + (5 + i1) + i1 ))

(t1t2)[n := t] = (t1[n := t]) (t2[n := t]) (λt’)[n := t] = λ (t’[n+1 := t↑0]) im[n := t] = t , if n = m im-1, if m > n im , otherwise im↑n = im+1, m ≥ n im, otherwise (t1t2)↑n = t1↑n t2↑n (λt)↑n = λ(t↑n+1)

(1) (2) (3) (6) (5) (4)

slide-40
SLIDE 40

De Bruijn indices

  • De Bruijn indices are not very readable, therefore not used for user facing

representations

  • Useful for the internal representation of bindings:
  • α-equivalence not a problem
  • capture of free variables not a problem
  • more advantages we will learn about later