Review: Scope and Lexical Contours scope = area of program where declared name can be used. Bindex: Naming, Show scope in Racket via lexical contour s in scope diagrams . Free Variables, and Environments (define add-n ( λ ( x ) (+ n x )) ) (define add-2n ( λ ( y ) (add-n (add-n y )))) (define n 17) (define f ( λ ( z ) CS251 Programming Languages Spring 2019, Lyn Turbak (let {[ c (add-2n z ) ] Department of Computer Science [ d (- z 3) ]} Wellesley College (+ z (* c d ))) ) ) Bindex 2 Review: DeclaraHons vs. References Review: Shadowing An inner declaraHon of a name shadows uses of outer declaraHons A declara>on introduces an idenHfier (variable) into a scope. of the same name. A reference is a use of an idenHfier (variable) within a scope. (let {[x 2]} We can box declaraHons, circle references, and draw a line (- (let {[x (* x x)]} from each reference to its declaraHon. Dr. Racket does this for us (except it puts ovals around both declaraHons and Can’t refer to (+ x 3)) outer x here. references). x )) An idenHfier (variable) reference is unbound if there is no declaraHon to which it refers. Bindex 3 Bindex 4
Review: Alpha-renaming Review: Scope, Free Variables, and Higher-order FuncHons Can consistently rename idenHfiers as long as it doesn’t change the In a lexical contour, an idenHfier is a free variable if it is not connecHons between uses and declaraHons. defined by a declaraHon within that contour. Scope diagrams are especially helpful for understanding the (define (f w z) (define (f c d) meaning of free variables in higher order funcHons. OK (* w (* c (let {[c (add-2n z)] (let {[b (add-2n d)] (define (make-sub n ) [d (- z 3)]} [c (- d 3)]} ( λ ( x ) (- x n )) ) (+ z (* c d)))))) (+ d (* b c)))))) Not OK (define (f x y) (define (map-scale factor ns ) (* x (let {[x (add-2n y)] (map ( λ ( num ) (* factor num )) ns) ) [y (- d y)]} (+ y (* x y)))))) Bindex 5 Bindex 6 Bindex REPL Interpreter in acHon A New Mini-Language: Bindex REPL = Read/Eval/Print Loop. Our goal is to see how this all works. Bindex adds variable names to Intex in two ways: - BindexEnvInterp.repl(); Try it out: 1. The arguments of Bindex programs are expressed via variable names ~/sml/bindex/BindexEnvInterp.sml rather than posiHonally. E.g.: bindex> (+ (/ 6 3) ( * 5 8)) 42 (bindex (a b) (/ (+ a b) 2)) bindex> (bind a (+ 1 2) (bind b ( * a 5) (- a b))) (bindex (a b c x) (+ (* a (* x x)) (+ (* b x) c))) ~12 2. Bindex has a local naming construct (bind I_defn E_defn E_body) bindex> (#args (num 5) (p 10) (q 8)) that behaves like Racket’s (let {[I_defn E_defn]} E_body) bindex> ( * (- q num) p) (bindex (p q) (bindex (x y) 30 (bind sum (+ p q) (+ (bind a (/ y x) (/ sum 2))) (bind b (- a y) bindex> (#run (bindex (x y) (+ ( * x x) ( * y y))) 3 4) (* a b))) 25 (bindex (a b) (bind c (bind d (+ x y) (bind a_sq (* a a) (* d y)) bindex> (#run (bindex (a b) (bind sum (+ a b) (/ sum 2))) 5 15) (bind b_sq (* b b) (/ c x)))) 10 (bind numer (+ a_sq b_sq) (bind denom (- a_sq b_sq) bindex> (#quit) Can use bind in any (/ numer denom)))))) Moriturus te saluto! expression posiHon val it = () : unit Bindex 7 Bindex 8
Bindex Abstract Syntax Bindex AST example (bindex (x y) (+ (bind a (/ y x) type ident = string (* introduce ident as synonym for string *) (bind b (- a y) (* a b))) datatype pgm = Bindex of ident list * exp (* param names , body *) (bind c (bind d (+ x y) (* d y)) and exp = Int of int (* integer literal with value *) (/ c x)))) | Var of ident(* variable reference *) | BinApp of binop * exp * exp (* binary application of rator to rand1 & rand2 *) | Bind of ident * exp * exp (* bind name to value of defn in body *) and binop = Add | Sub | Mul | Div | Rem (* binary arithmetic ops *) val stringToExp : string -> exp val stringToPgm : string -> pgm val expToString : exp -> string val pgmToString : pgm -> string - Bindex.stringToPgm "(bindex (a b) (bind sum (+ a b) (/ sum 2)))" val it = Bindex (["a","b"], Bind ("sum",BinApp (Add,Var "a",Var "b"), BinApp (Div,Var "sum",Int 2))) : Bindex.pgm Bindex 9 Bindex 10 Bindex Lexical Contours and Free Variables CalculaHng Free Variables in Bindex The Analog of BoYom-up StaHc Arg Index Checking in Intex Bindex 11 Bindex 12
String sets Bindex: Code for handling free variables (similar to PS7 sets, but specialized to strings) structure S = StringSetList signature STRING_SET = (* val freeVarsPgm : pgm -> S.t *) sig (* Returns the free variables of a program *) type t (* The type of a string set *) fun freeVarsPgm (Bindex(fmls,body)) = val empty : t S.difference (freeVarsExp body) (S.fromList fmls) val singleton : string -> t val isEmpty : t -> bool (* val freeVarsExp : exp -> S.t *) val size : t -> int (* Returns the free variables of an expression *) val member : string -> t -> bool and freeVarsExp (Int i) = S.empty val insert : string -> t -> t | freeVarsExp (Var name) = S.singleton name val delete : string -> t -> t | freeVarsExp (BinApp(_,rand1,rand2)) = val union : t -> t -> t S.union (freeVarsExp rand1) (freeVarsExp rand2) val intersection : t -> t -> t | freeVarsExp (Bind(name,defn,body)) = val difference : t -> t -> t S.union (freeVarsExp defn) val fromList : string list -> t (S.difference (freeVarsExp body) (S.singleton name)) val toList : t -> string list val toPred : t -> (string -> bool) (* val freeVarsExps : exp list -> S.t *) val toString : t -> string (* Returns the free variables of a list of expressions *) end and freeVarsExps exps = foldr (fn (s1,s2) => S.union s1 s2) S.empty (map freeVarsExp exps) structure StringSetList :> STRING_SET = struct (* See ~wx/sml/utils/StringSet.sml for details *) (* val varCheck : pgm -> bool *) end and varCheck pgm = S.isEmpty (freeVarsPgm pgm) Bindex 13 Bindex 14 Environments bind names to values Environment Examples env0 a 7 signature ENV = sig - val env0 = Env.make ["a", "b"] [7, 3] b 3 val env0 = - : int Env.env type 'a env val empty: 'a env - Env.lookup "a" env0; val bind : string -> 'a -> 'a env -> 'a env env1 env2 val it = SOME 7 : int option val bindAll : string list -> 'a list -> 'a env -> 'a env sum 10 b 42 val make : string list -> 'a list -> 'a env - Env.lookup "b" env0; d 17 val lookup : string -> 'a env -> 'a option val it = SOME 3 : int option val map: ('a -> 'a) -> 'a env -> 'a env val remove : string -> 'a env -> 'a env - Env.lookup "c" env0; - Env.lookup "d" env2; val it = NONE : int option val removeAll : string list -> 'a env -> 'a env val it = SOME 17 : int option val merge : 'a env -> 'a env -> 'a env - val env1 = Env.bind "sum" 10 env0; end - Env.lookup "b" env2; val env1 = - : int Env.env val it = SOME 42 : int option structure Env :> ENV = struct - Env.lookup "sum" env1; (* See ~wx/sml/utils/Env.sml for details *) - Env.lookup "a" env2; val it = SOME 10 : int option val it = SOME 7 : int option end - Env.lookup "sum" env0; val it = NONE : int option - Env.lookup "a" env1; val it = SOME 7 : int option - val env2 = Env.bindAll ["b", "d"] [42, 17] env0; val env2 = - : int Env.env Bindex 15 Bindex 16
Recommend
More recommend