Upload
jason-yeo-jie-shun
View
325
Download
2
Tags:
Embed Size (px)
Citation preview
Language Extensions and Abstractions�
OCaml �
PROJECT OBJECTIVES�
DEBUGGING�EXTENSION�
LAZY EVALUATION�EXTENSION�
WHAT IS CAMLP4?�
WHAT IS CAMLP4?�Caml Preprocessor and Pretty
Printer�
let rec fib = | 0 -‐> 0 | 1 -‐> 1 | n when n > 1 -‐> fib (n -‐ 1) + fib (n -‐ 2)
let rec fib = memo | 0 -‐> 0 | 1 -‐> 1 | n when n > 1 -‐> fib (n -‐ 1) + fib (n -‐ 2)
let rec fib = let tbl = Hashtbl.create 100 in fun x -‐> try Hashtbl.find tbl x with Not_found -‐> let result = match x with | 0 -‐> 0 | 1 -‐> 1 | n when n > 1 -‐> fib (n -‐ 1) + fib (n -‐ 2) in do { Hashtbl.replace tbl x result; ;result }
let rec fib = let tbl = Hashtbl.create 100 in fun x -‐> try Hashtbl.find tbl x with Not_found -‐> let result = match x with | 0 -‐> 0 | 1 -‐> 1 | n when n > 1 -‐> fib (n -‐ 1) + fib (n -‐ 2) in do { Hashtbl.replace tbl x result; ;result }
THINK MACROS�
C MACROS?�
LISP MACROS�For a statically typed language�
let simple_optimize = object inherit Ast.map as super method expr e = match super#expr e with | <:expr< 1 * $e$ >> -‐> <:expr< $e$ >> | <:expr< 0 + $e$ >> -‐> <:expr< $e$ >> | e -‐> e end
let simple_optimize = object inherit Ast.map as super method expr e = match super#expr e with | <:expr< 1 * $e$ >> -‐> <:expr< $e$ >> | <:expr< 0 + $e$ >> -‐> <:expr< $e$ >> | e -‐> e end
let simple_optimize = object inherit Ast.map as super method expr e = match super#expr e with | <:expr< 1 * $e$ >> -‐> <:expr< $e$ >> | <:expr< 0 + $e$ >> -‐> <:expr< $e$ >> | e -‐> e end
1 * humblepi BECOMES humblepi 0 + humblepi BECOMES humblepi
DEBUGGING EXTENSION�Easier function tracing and debugging
using annotations�
PROBLEM�Functions are hard�
to debug�
type env = (string * expr) list and expr = | Var of string | IntConst of int | Plus of expr * expr | Minus of expr * expr | Lambda of string * expr | Apply of expr * expr | Closure of env * string * expr
let rec eval env e = let rec aux env e = match e with | IntConst _ -‐> e | Plus (e1, e2) -‐> ... in aux env e
NO GENERIC PRINTERS�
let rec string_of_expr e =! match e with! ... (* for every variant *)!and string_of_env env =! (* Map string_of_expr over elements *)!
let rec eval env e = let rec aux env e = match e with | IntConst _ -‐> e | Plus (e1, e2) -‐> … in let _ = printf "Input: env = %s, e = %s" (string_of_env env) (string_of_expr e) in let out = aux env e in let _ = printf "Output: %s" (string_of_expr e) in out
let rec eval env e = let rec aux env e = match e with | IntConst _ -‐> e | Plus (e1, e2) -‐> … in let _ = printf "Input: env = %s, e = %s" (string_of_env env) (string_of_expr e) in let out = aux env e in let _ = printf "Output: %s" (string_of_expr e) in out
let rec eval env e = let rec aux env e = match e with | IntConst _ -‐> e | Plus (e1, e2) -‐> … in let _ = printf "Input: env = %s, e = %s" (string_of_env env) (string_of_expr e) in let out = aux env e in let _ = printf "Output: %s" (string_of_expr e) in out
Tedious and Cumbersome�
SOLUTION�Generate debugging code from function�
annotated with debug keyword�
let rec eval env e = let rec aux env e = match e with | IntConst _ -‐> e | Plus (e1, e2) -‐> ... in aux env e
let debug rec eval env e = let rec aux env e = match e with | IntConst _ -‐> e | Plus (e1, e2) -‐> ... in aux env e
DEMO�
HOW DOES IT WORK?�
Annotated�Expression�
Camlp4 Lexer & Parser �
Annotated�Expression�
Camlp4 Lexer & Parser �
Type Inference �
Annotated�Expression�
Camlp4 Lexer & Parser �
Type Inference �
Deriving Library�
Annotated�Expression�
Camlp4 Lexer & Parser �
Type Inference �
Deriving Library�
AST Transformer �
Annotated�Expression�
Camlp4 Lexer & Parser �
Type Inference �
Deriving Library�
AST Transformer �
Annotated�Expression�
Generated�OCaml Code �
Camlp4 Lexer & Parser �
Type Inference �
Deriving Library�
AST Transformer �
Annotated�Expression�
Generated�OCaml Code �
Camlp4 Lexer & Parser �
Type Inference �
Deriving Library�
AST Transformer �
Annotated�Expression�
Generated�OCaml Code �
TYPE INFERENCE�
let sqr x = x * x!
TYPE INFERENCE STEP�RETURNS�[“int”; “int”]!
let fact count x = match x with | 1 -> x | n -> fact (count – 1) (n * x)!
let fact count x = match x with | 1 -> x | n -> fact (count – 1) (n * x)!
TYPE INFERENCE STEP�RETURNS�[“int”; “int”; “int”]!
Camlp4 Lexer & Parser �
Type Inference �
Deriving Library�
AST Transformer �
Annotated�Expression�
Generated�OCaml Code �
DERIVING LIBRARY�Third party open source library that
generates printing functions from types�
type env = (string * expr) list and expr = | Var of string | IntConst of int | Plus of expr * expr | Minus of expr * expr | Lambda of string * expr | Apply of expr * expr | Closure of env * string * expr deriving (Show)
Show.show<expr> (Plus (IntConst 40) (IntConst 2))
LAZY EVALUATION EXTENSION�Automatic generation �
of lazy and force �
PROBLEM�Lazy streams are�
difficult to work with�
type 'a node_t = | Nil | Cons of 'a * ('a node_t)!
type 'a node_t = | Nil | Cons of 'a * ('a node_t) Lazy.t!
let map f l = let rec aux rest = match Lazy.force rest with | Cons (x, r) -> Cons (f x, lazy (aux r)) | Nil -> Nil in lazy (aux l)!
let map f l = let rec aux rest = match Lazy.force rest with | Cons (x, r) -> Cons (f x, lazy (aux r)) | Nil -> Nil in lazy (aux l)!
let zipwith f l1 l2 = let rec aux r1 r2 = match Lazy.force r1, Lazy.force r2 with | Cons (x1, r1), Cons (x2, r2) -> Cons ((f x1 x2), lazy (aux r1 r2)) | Cons (x, r), Nil -> Cons (x, lazy (aux r (lazy Nil))) | Nil, Cons (x, r) -> Cons (x, lazy (aux (lazy Nil) r)) | Nil, Nil -> Nil in lazy (aux l1 l2)!
let zipwith f l1 l2 = let rec aux r1 r2 = match Lazy.force r1, Lazy.force r2 with | Cons (x1, r1), Cons (x2, r2) -> Cons ((f x1 x2), lazy (aux r1 r2)) | Cons (x, r), Nil -> Cons (x, lazy (aux r (lazy Nil))) | Nil, Cons (x, r) -> Cons (x, lazy (aux (lazy Nil) r)) | Nil, Nil -> Nil in lazy (aux l1 l2)!
SOLUTION�Annotate with keyword�and insert lazy and force when type error occurs�
let ilazy map f l = let rec aux rest = match rest with | Cons (x, r) -> Cons (f x, aux r) | Nil -> Nil in aux l!
let ilazy zipwith f l1 l2 = let rec aux r1 r2 = match r1, r2 with | Cons (x1, r1), Cons (x2, r2) -> Cons ((f x1 x2), (aux r1 r2)) | Cons (x, r), Nil -> Cons (x, (aux r Nil)) | Nil, Cons (x, r) -> Cons (x, (aux Nil r)) | Nil, Nil -> Nil in (aux l1 l2)!
HOW DOES IT WORK?�
Annotated�Expression�
Camlp4 Lexer & Parser �
Annotated�Expression�
Camlp4 Lexer & Parser �
Type Checker�
Annotated�Expression�
Camlp4 Lexer & Parser �
Type Checker�
AST Transformer �
Annotated�Expression�
Camlp4 Lexer & Parser �
Type Checker�
AST Transformer �
Annotated�Expression�
Generated�OCaml Code �
Camlp4 Lexer & Parser �
Type Checker�
AST Transformer �
Annotated�Expression�
Generated�OCaml Code �
TYPE CHECKER�OUTPUT�
Error: This expression has type 'a lazy_t! but an expression was expected of type! 'b Batteries.LazyList.node_t = 'b BatLazyList.node_t!
Error: This expression has type 'a lazy_t! but an expression was expected of type! 'b node_t!
THIS SAYS INSERT Lazy.force!
Error: This expression has type! 'a node_t! but an expression was expected of type!! ! !int node_t lazy_t!
Error: This expression has type! 'a node_t! but an expression was expected of type!! ! !int node_t lazy_t!
THIS SAYS INSERT�lazy!
TYPE CHECKER�OUTPUT�
Output is in the form of a typed tree�
TECHNICAL CHALLENGES�
UNFAMILIARITY�WITH LANGUAGE�
Lots of mucking around�
OPEN RECURSION�A feature in most OO languages�
let insert_lazy_at loc = object inherit Ast.map as super method expr e = match super#expr e with | <:expr@_loc< $e1$ $e2$ >> when _loc = loc -‐> <:expr< lazy ($e1$ $e2$) >> | <:expr@_loc< $id:i$ >> when _loc = loc -‐> <:expr< lazy $id:i$ >> | e -‐> e end
LACK OF DOCUMENTATION�
Lots of code reading�
ASKING QUESTIONS ON IRC�
SEARCHING AND READING COMPILER SOURCE CODE�
QUESTIONS?�