FYP Final Presentation

Preview:

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?�