Presentation is loading. Please wait.

Presentation is loading. Please wait.

PPL Leftovers: LET Syntax & Formal Semantics Static Verification: Type Inference Lecture Notes: Chapter 2.

Similar presentations


Presentation on theme: "PPL Leftovers: LET Syntax & Formal Semantics Static Verification: Type Inference Lecture Notes: Chapter 2."— Presentation transcript:

1 PPL Leftovers: LET Syntax & Formal Semantics Static Verification: Type Inference Lecture Notes: Chapter 2

2 LET (let ( (x 2) (y 7)) (+ x y))  ( (lambda x y) (+ x y)) 2 7) X and y are “temporary” vars!

3 LET For internal definitions, we will use let Problematic when the internally defined function is recursive – Why? – To be discussed in the practical session – A special construct called letrec to be used instead

4 LET* What is the value of: (let ((x 3) (y x)) (+ x y)) What about (let ((x 3)) (let ((y x)) (+ x y)))

5 (define (sqrt-iter guess x) (if (good-enough? guess x) guess (sqrt-iter (improve guess x) x))) (define (good-enough? guess x) (< (abs (- (square guess) x)) precision)) (define (improve guess x) (average guess (/ x guess))) (define (sqrt x) (sqrt-iter initial-guess x)) (define initial-guess 1.0) (define precision 0.0001)

6 Good programming Style 1. Divide the task to well-defined, natural, and simple sub-tasks. E.g: good-enough? and improve. Rule of thumb : If you can easily name it, it does a well-defined task. 2. Use parameters. E.g.: precision, initial-guess. 3. Use meaningful names. 4. Encapsulate.

7 Procedural abstraction It is better to: Export only what is needed Hide internal details. The procedure SQRT is of interest for the user. The procedure improve-guess is an internal detail. Exporting only what is needed leads to: A clear interface Avoids confusion

8 Rewriting SQRT (Block structure) (define (sqrt x) (letrec (sqrt-iter (lambda (guess x) (if (good-enough? guess x) guess (sqrt-iter (improve guess x) x)))) (let* (( initial-guess 1.0)) (( precision 0.00001)) ((good-enough? (lambda (guess x)) (< (abs (- (square guess) x)) precision))))... (sqrt-iter initial-guess x)))))) Body of let*

9 Concrete Syntax -> | -> | |… ->’(if )

10 Abstract Syntax Kinds:, : Kinds:,… : Components: Predicate:, Consequence:,Alternative:

11 Operational Semantics Substitution and renaming

12 12 Applicative order vs. Normal Order Evaluation To Evaluate a combination: (other than special form) Evaluate all of the sub-expressions in any order Apply the procedure that is the value of the leftmost sub-expression to the arguments (the values of the other sub-expressions)

13 13 Applicative order evaluation rules Combination... ( …… ) Evaluate to get the procedure and evaluate to get the arguments If is primitive: do whatever magic it does If is compound: evaluate body with formal parameters replaced by arguments

14 14 Normal order evaluation Combination … ( …… ) Evaluate to get the procedure and evaluate to get the arguments If is primitive: do whatever it does If is compound: evaluate body with formal parameters replaced by arguments

15 Formalism: Definitions Binding instance or declaration: A binding instance (declaration) of a variable is a variable occurrence to which other occurrences refer. In Scheme: (a) Variables occurring as lambda parameters are binding instances (declarations). (b) Top level (non-nested) defined variables (in a define form) are binding instances (declarations). (c) Variables occurring as let local variables are binding instances (declarations). Note: No internal “defines” are allowed here!

16 Scope Scope: The scope of a binding instance is the region of the program text in which variable occurrences refer to the value that is bound by the variable declaration (where the variable declaration is recognized). In Scheme: (a) The scope of lambda parameters is the entire lambda expression. (b) The scope of define variables is the entire program, from the define expression and on: Universal / global scope. (c) The scope of let local variables is the entire let body.

17 Bound Occurence An occurrence of variable x that is not a binding instance (declaration), and is contained within the scope of a binding instance x. The binding instance (declaration) that binds an occurrence of x is the most nested declaration of x that includes the x occurrence in its scope.

18 Free Occurrence Free occurrence: An occurrence of variable x that is not a binding instance, and is not bound.

19 Applicative Evaluation Algorithm Signature: applicative-eval(e) Purpose: Evaluate a Scheme expression Type: [ union Scheme-type -> Scheme-type] Definition: applicative-eval[e] = I. atom?(e): 1. number?(e) or boolean?( e): applicative-eval[e] = e 2. variable?(e): a. If GE(e) is defined: applicative-eval[e] = GE(e) b. Otherwise: e must be a variable denoting a Primitive procedure: applicative-eval[e] = built-in code of e.

20 Applicative Evaluation Algorithm (cont.) II. composite?(e): e = (e0 e1... en)(n >= 0): 1. e0 is a Special Operator: applicative-eval[e] is defined by the special evaluation rules of e0 (see separately). 2. a. Evaluate: compute applicative-eval[ei] = ei’ for all ei. b. primitive-procedure?(e0’): applicative-eval[e] = system application e0’(e1’,..., en’).

21 c. procedure?(e0’): e0’ is a closure: i. Substitute: For each bj, 1 <= j =< m, compute sub[,, bj] = bj’ ;The substitution is simultaneous - no order is specified. ;Recall that substitution is preceded by renaming. ii. Reduce: applicative-eval[b1’],..., applicative-eval [b(m-1)’]. applicative-eval[e] = applicative-eval[bm’]. III. value?(e): applicative-eval[e] = e

22 Special Forms Special operators evaluation rules: 1. e = (define x e1): GE = GE* 2. e = (lambda (x1 x2... xn) b1... bm) at least one bi is required: applicative-eval[e] = …..

23 Normal Order (Part of) Algorithm II. (composite? e): e = (e0 e1... en)(n >= 0): 1. e0 is a Special Operator: normal-eval[e] is defined by the special evaluation rules of e0. 2. Evaluate: normal-eval[e0] = e0’. b. (primitive-procedure? e0’): Evaluate: compute normal-eval[ei] = ei’ for all ei. normal-eval[e] = system application e0’(e1’,..., en’). c. (procedure? e0’): e0’ is a closure: : i. Substitute (Expansion): For each bj, 1 <= j =< m, compute sub[,, bj] = bj’ ;Recall that substitution is preceded by renaming. ii. Reduce: normal-eval[b1’],..., normal-eval[bm’] iii. Return: normal-eval[e] = normal-eval[bm’]

24 24 The Difference Applicative ((lambda (x) (+ x x)) (* 3 4)) (+ 12 12) 24 Normal ((lambda (x) (+ x x)) (* 3 4)) (+ (* 3 4) (* 3 4)) (+ 12 12) 24 This may matter in some cases: ((lambda (x y) (+ x 2)) 3 (/ 1 0)) Your interperter works in Applicative Order!

25 Another Example (define f (lambda (x) (f x))) (define g (lambda (x) 5)) (g (f 0)) What will happen with applicative evaluation? What about Normal?

26 Type Inference Based on S. Krishnamurthi. Programming Languages: Application and Interpretation 2007. Chapters 24-26 Lecture notes p90-127 (Chapter 2.3)

27 Verification Type correctness – Verify that the types of expressions in the program are “correct” – E.g. + is applied to numbers – In other languages: we should also check that the type of value stored in a variable correspond to the variable declared type Program Verification – Verify that the program halts and produces the “correct” output – Somewhat easier with design-by-contract, where it can be done in a modular fashion

28 Languages and Types Fully typed – C, Pascal, Java.. Semi-typed – Scheme Untyped – Prolog Well-typing rules – Define relationships between types

29 Type Checking and Inference Type Checking. Given an expression, and a “goal” type T, verify that the expression type is T Example: Given the expression (+ (f 3) 7), we need to verify that (f 3) is a number Type Inference. Infer the type of an expression Example: (define x (f 3))

30 Types in Scheme Numbers, booleans, symbols… Union: – No value constructor – Type Constrcutor is union – Simplification rules S union S = S S union T = T union S Unit Type – “Void”

31 Procedures and Type Polymorphism What is the type of: – (lambda (x) x) – (lambda (f x) (f x)) – (lambda (f x) ( (f x) x)) Instantiations, type variables renaming... Next we construct a static type inference system

32 Type assignment and Typing statement Type Environment – Mapping variables to types – Example: Tenv= {x T]} – Notation: Tenv(x) = Number Typing statement – Tenv |- e:T – Under Tenv, the expression e has the type T {x<-Number} |- (+ x 5):Number – Type variables (as well as unbound variables) used in such statements are defined to be universally quantified {x:[T1 –> T2], y:T1} |- (x y):T2 – A typing statement can be instantiated by consistent replacement of type variables

33 Type Environment Extension {x T]}°{z<-Boolean} = {x T], z<-Boolean} EMPTY° {x1<-T1,..., xn<- Tn} = {x1<-T1,..., xn<- Tn} Extension pre-condition: new variables are different from old ones.

34 Restricted Scheme (syntax) -> -> | -> | | -> | -> Numbers -> ’#t’ | ’#f’ -> Restricted sequences of letters, digits, punctuation marks -> |

35 -> ’(’ + ’)’ -> ’(’ ’lambda’ ’(’ * ’)’ + ’)’ -> ’(’ ’quote’ ’)’ For now, no define and if expressions

36 Typing Axioms To infer the type of an expression (as well as whether or not it is well-typed), we need to define rules To be used on sub-expressions, to derive types of the more complex expression Only abbreviated forms are given here, see lecture notes for full description of rules.

37 Typing axioms (Well-typing rules) Typing axiom Number: For every type environment _Tenv and number _n: _Tenv |- _n:Number Typing axiom Boolean : For every type environment _Tenv and boolean_ b: _Tenv |- _b:Boolean Typing axiom Variable : For type environment _Tenv and variable _v: _Tenv |- _v: _Tenv (_v) Typing axioms Primitive procedure : _Tenv |- +:[Number*... *Number -> Number] _Tenv |- not:[S -> Boolean] where S is a type variable. _Tenv |- display:[S -> Void] …

38 Cont. Typing rule Procedure : For all _xi,_Si,_bi,U_i…. If Tenv ° {_x1<-_S1,..., _xn<-_Sn} |- _b:_Ui for all i=1..m, Then Tenv |- (lambda (_x1... _xn) _b1..._ bm):[_S1*...*_Sn -> _Um] Parameter-less Procedure: If Tenv |- bi:Ui for all i=1..m, Then Tenv |- (lambda ( ) b1... bm):[Void-> Um] Typing rule Application : If Tenv |- f:[S1*...*Sn -> S], Tenv |- e1:S1,..., Tenv |- en:Sn Then Tenv |- (f e1... en):S

39 More properties Monotonicity: Type environments in typing statements in derivations can be extended. That is, addition of type environments to a type environment does not invalidate an already derived typing statement for that type environment If a type derivation includes Tenv |- e:T, then it can include also Tenv ° {v : S} |- e:T for every variable v not in Tenv, and every type expression S. We try to derive the “maximal” type

40 More properties Instantiation: Every instance of a derived typing statement in a derivation is also a derived typing statement (an instance typing statement).

41 Expression Trees The nesting of expressions can be viewed as a tree Sub-trees correspond to composite expressions For lambda expressions, their body expressions reside in their children Leaves correspond to atomic ones

42 Type Derivation (inference) Algorithm Main idea: go bottom-up on the expression tree, deriving new type statements by using the “type-statements-pool”, rules and substitution Add the result to the type-statements-pool Declare T if you get |-e:T, FAIL otherwise See exact algorithm in lecture notes!

43 Well-typeness Definition: If Type-derivation(e) ends with { } |- e:t, We say that e is well typed, and its type is t. The sequence of typing statements in derived-ts- pool is a type derivation for e.

44 Throwing in definitions 1. A definition expression (define x e) is well typed if e is well typed. 2. An expression e, that follows (occurs after) well typed definitions (define xi ei) i =1…n, in which ei has type Ti, is well typed and has type S, if Type- derivation(e) outputs a typing statement Tenv |- e:S, where Tenv may include only the type assumptions xi:Ti’ for Ti’, an instance of Ti. 3. No repeated definition for a variable are allowed.

45 Throwing in control flow (if) For every type environment _Tenv, expressions _p, _c, _a, and type expression _S: If _Tenv |- _p:Boolean and _Tenv |- _c:_S and _Tenv |- _a:_S Then _Tenv |- (if _p _c _a):S

46 Throwing in recursion Changing the rule for (define f e): e is well typed and has type [S1*...Sn–> S], for n>0 or [Empty –> S] for n=0, if Type-derivation(e) outputs a typing statement Tenv |- e:[S1*...Sn –> S] (alternatively Tenv |- e:[Empty –> S]), where Tenv satisfies: If there are no previous well typed definitions, Tenv = {f:[S1*...Sn –> S]} for n>0, or Tenv = {f:[Empty –> S]} for n=0. If there are m previous well typed definitions (define xi ei) (m>0), in which ei has type Ti, Tenv = Tenv’ °{f:[S1*...Sn –> S]} where Tenv’ may include only type assumptions xi:Ti’ where Ti’ is an instance of Ti.

47 Examples On the board, also in lecture notes

48 Type constraints approach Create a (meta-) variable for each sub- expression Construct type equations over these variables – 1. Numbers, booleans, quoted symbols, primitive procedures: Construct equations using their types.. – 2. Intuitive rules for lambda and applications (on the blackboard)

49 Solving the equations 1. Apply the current substitution on the equation, i.e., replace variables by their substituting expressions. 2. If the equation includes atomic types on both sides then, if they are the same the equation is ignored, and if they are different, the type inference fails: Output FAIL. 3. If one side of the equation is a variable and the other side is not the same variable, apply the equation to the current substitution, and add the equation to the substitution. If a circular substitution is created, i.e., a type variable T is substituted by a type expression that includes T, output FAIL. 4. If both sides of the equation are composite and have the same type constructor, split the equation into equations between corresponding components.

50 Example On the board & in the notes


Download ppt "PPL Leftovers: LET Syntax & Formal Semantics Static Verification: Type Inference Lecture Notes: Chapter 2."

Similar presentations


Ads by Google