Valex: A New Mini-Language: Valex Mul*ple Value Types, Condi*onals, Valex extends Bindex in the following ways: o In addi*on to integer values, Valex also has boolean, character, string, Dynamic Type Checking symbol, and list values. and Desugaring • A Valex program s*ll takes a list of integers as arguments, but the result and intermediate values may be of any type. o Valex has an easy-to-extend library of primi*ve operators for manipula*ng values of different types o Valex has a generalized primi*ve operator applica*on mechanism that performs dynamic type checking on the operands of primi*ve operators CS251 Programming Languages o Valex has a condi*onal ( if ) expression. Spring 2019, Lyn Turbak o Valex desugars numerous special forms into a small set of five kernel Department of Computer Science constructs: literals, variable references, primi*ve applica*ons, Wellesley College bind expressions, condi*onal expressions. Valex 2 Valex Booleans Dynamic Type Checking of Primapps Valex dynamically checks the number and types of operands valex> (< 3 4) valex> (or (> 3 4) (> 5 5)) to primi*ve applica*ons and reports dynamic type errors. #t #f valex> (= 3 4) valex> (< 5) valex> (and (< 4 3) #f Error: Expected two arguments but got: (5) (< 5 (/ 1 0))) Error: Division by 0: 1 valex> (!= 3 4) valex> (= 5 6 7) #t Error: Expected two arguments but got: (5 6 7) valex> (&& (< 4 3) (< 5 (/ 1 0))) valex> (not (= 3 4)) valex> (+ 1 #t) #f ; && is short-circuit and #t Error: Expected an integer but got: #t valex> (or (> 4 3) valex> (and (< 3 4) (>= 5 5)) valex> (and #t 3) (< 5 (/ 1 0))) #t Error: Expected a boolean but got: 3 Error: Division by 0: 1 valex> (and (< 3 4) (> 5 5)) valex> (= #t #f) valex> (|| (> 4 3) #f Error: Expected an integer but got: #t (< 5 (/ 1 0))) #t ; || is short-circuit or valex> (or (< 3 4) (> 5 5)) valex> (bool= #t #f) #t #f Valex 3 Valex 4
Condi*onal ( if ) expresssions Mul*branch condi*onals ( cond ) Valex includes a mul*branch cond condi*onal like Racket’s cond : valex> (if (< 1 2) (+ 3 4) (* 5 6)) 7 (valex (x y) valex> (if (> 1 2) (+ 3 4) (* 5 6)) (cond ((< x y) -1) 30 ((= x y) 0) valex> (if (< 1 2) (+ 3 4) (/ 5 0)) (else 1))) 7 ; only evaluates then branch valex> (if (> 1 2) (+ 3 4 5) (* 5 6)) 30 ; only evaluates else branch valex> (if (- 1 2) (+ 3 4) (* 5 6)) Error: Non-boolean test value -1 in if expression racket> (if (- 1 2) (+ 3 4) (* 5 6)) 7 Valex 5 Valex 6 Strings Characters valex> (str= "foo" "bar") valex> (toString (* 3 4)) valex> (char= 'a' 'b') #f "12" #f valex> (str< "bar" "foo") valex> (toString (= 3 4)) valex> (char< 'a' 'b') #t "#f" #t valex> (str< "foo" "bar") valex> (char->int 'a') #f 97 Notes: The only string comparison ops • valex> (strlen "foo") valex> (int->char (- (char->int 'a') 32)) are str= and str< , though it 3 'A' would be easy to add others toString turns any Valex value • valex> (strlen "") The only character comparison ops are char= and char< , into a string. 0 though it would be easy to add others valex> (str+ "foo" "bar") "foobar” Valex 7 Valex 8
Symbols Lists Valex has Racket-like symbols that can only be valex> (prep 1 (prep 2 (prep 3 #e))) (1) tested for equality and (list 1 2 3) (2) converted to/from strings. valex> (prep (+ 3 4) (prep (= 3 4) (prep (str+ "foo" "bar") #e))) valex> (sym= (sym foo) (sym foo)) (list 7 #t "foo")) #t valex> (list (+ 3 4) (= 3 4) (str+ "foo" "bar")) valex> (sym= (sym foo) (sym bar)) (list 7 #f "foobar") #f valex> (head (list 7 #t "foo")) valex> (sym->string (sym baz)) 7 "baz" valex> (tail (list 7 #t "foo")) valex> (string->sym "quux") (list #t "foo") (sym quux) valex> (head (tail (list 7 #t "foo"))) #t valex> (head #e) EvalError: Head of an empty list Valex 9 Valex 10 Type Predicates More Lists Explode and implode valex> (string? 'a') #f valex> (empty? #e) valex> (explode "foobar") valex> (int? 3) valex> (string? "a") #t #t (list 'f' 'o' 'o' #t 'b' 'a' 'r') valex> (empty? (list 7 #t "foo")) valex> (int? #t) valex> (string? (sym a)) #f #f #f valex> (implode (list 'C' 'S' '2' '5' '1')) valex> (nth 1 (list 7 #t "foo")) valex> (bool? #t) valex> (sym? 'a') "CS251" 7 #t #f valex> (nth 2 (list 7 #t "foo")) valex> (bool? 3) valex> (sym? "a") #t #f #f valex> (nth 3 (list 7 #t "foo")) valex> (char? ’a’) valex> (sym? (sym a)) "foo" #t #t valex> (nth 0 (list 7 #t "foo")) valex> (char? "a") valex> (list? #e) EvalError: nth -- #f #t out-of-bounds index 0 valex> (char? (sym a)) valex> (list? (list 7 #f "foobar")) valex> (nth 4 (list 7 #t "foo")) #f #t EvalError: nth -- out-of-bounds index 4 valex> (string? 'a') valex> (list? "foo") #f #f Valex 11 Valex 12
General Equality User-signaled errors The Valex error operator takes a string message and any value and valex> (equal? 3 3) #t halts computa*on with an error message including this value: valex> (equal? 3 (+ 1 2)) #t valex> (bind x 3 (if (< x 0) (error "negative!" x) valex> (equal? (> 2 3) (< 6 5)) (* x x))) #t 9 valex> (equal? (> 2 3) (< 5 6)) #f valex> (bind x -3 (if (< x 0) valex> (equal? (+ 1 2) (< 1 2)) (error "negative!" x) #f (* x x))) EvalError: Valex Error -- negative!: -3 valex> (equal? (list 5 6) (list (+ 2 3) (* 2 3))) #t valex> (equal? (list #t) (list (< 1 2) (> 1 2))) #f Valex 13 Valex 14 bind vs. bindpar vs. bindseq Racket-like quote In addi*on to bind , Valex also has a bindpar construct similar to valex> (quote CS251) Racket’s let and a bindseq construct similar to Racket’s let* . (sym CS251) valex> (quote 42) valex> (#args (a 2) (b 3)) 42 valex> (bindpar ((a (+ a b)) (b (* a b))) (list a b)) valex> (quote #t) #t (list 5 6) valex> (quote "bunny") valex> (bindseq ((a (+ a b)) (b (* a b))) (list a b)) "bunny" (list 5 15) Valex> (quote 'c') 'c' valex> (quote (CS251 42 #t "bunny" 'c' (just like Racket!))) (list (sym CS251) 42 #t "bunny" 'c' (list (sym just) (sym like) (sym Racket!))) Valex 15 Valex 16
Implementa*on Strategy Valex has a Small Kernel Kernel has only 5 kinds of expressions! 1. Literals: integers, booleans, strings, characters, symbols 2. Variable references, 3. Primi*ve applica*ons (unlike in Bindex these can have kernel any number of operands of any type), 4. Single-variable local variable declara*ons (i.e., bind ), primitive 5. Condi*onal expressions (i.e., if ). values/datatypes Unlike Bindex, where the only expression values are integers, Valex has 6 kinds of expression values: syntactic sugar 1. Integers system libraries 2. Booleans 3. Strings 4. Characters user libraries 5. Symbols 6. Lists of values (recursively defined) Valex 17 Valex 18 Core of Valex Interpreter Valex datatypes (* val run : Valex.pgm -> int list -> value *) type ident = string fun run (Valex(fmls,body)) ints = let val flen = List.length fmls datatype pgm = Valex of ident list * exp (* param names, body *) val ilen = List.length ints in if flen = ilen then and exp = eval body (Env.make fmls (List.map (fn i => Int i) ints ) ) Lit of value else | Var of ident (* variable reference *) raise (EvalError ("Program expected " ^ (Int.toString flen) | PrimApp of primop * exp list (* prim application with rator, rands *) ^ " arguments but got " ^ (Int.toString ilen))) | Bind of ident * exp * exp (* bind name to value of defn in body *) end | If of exp * exp * exp (* conditional with test, then, else *) (* val eval : Valex.exp -> value Env.env -> value *) and value = (* use value rather than val because val is an SML keyword *) and eval (Lit v) env = v Int of int | eval (Var name) env = | Bool of bool ( case Env.lookup name env of | Char of char SOME(v) => v | String of string | NONE => raise (EvalError("Unbound variable: " ^ name))) | Symbol of string | eval (PrimApp(primop, rands)) env = (* see slides 22-24 *) | List of value list (* recursively defined value *) (primopFunction primop) (List.map (Utils.flip2 eval env) rands ) | eval (Bind(name,defn,body)) env = and primop = Primop of ident * (value list -> value) eval body (Env.bind name (eval defn env) env) (* Valex bakes the primop meaning function into the syntax! *) | eval (If(tst,thn,els)) env = (* see slide 21 *) (case eval tst env of fun primopName (Primop(name,_)) = name Bool b => if b then eval thn env else eval els env fun primopFunction (Primop(_,fcn)) = fcn | _ => v => raise (EvalError …)) Valex 19 Valex 20
Recommend
More recommend