Slide 1

Slide 1 text

LitiL Growing a (functional) language Thursday, 23 May, 13

Slide 2

Slide 2 text

LitiL J’ai crée un langage Thursday, 23 May, 13

Slide 3

Slide 3 text

LitiL C’est facile ! Thursday, 23 May, 13

Slide 4

Slide 4 text

LitiL Thursday, 23 May, 13

Slide 5

Slide 5 text

LitiL Thursday, 23 May, 13

Slide 6

Slide 6 text

LitiL à quoi ça va ressembler ? Thursday, 23 May, 13

Slide 7

Slide 7 text

En gros •Syntaxe “propre” •Fonctionnel •Inférence de types totale (HM) •Blancs significatifs Thursday, 23 May, 13

Slide 8

Slide 8 text

LitiL Exemples Thursday, 23 May, 13

Slide 9

Slide 9 text

LitiL affectations, expressions & fonctions let  five  =  3 let  twice  x  =  3  *  x  -­‐  (42  -­‐  41)  *  x let  x2  =  twice  5 let  add  x  y  =  x  +  y let  seven  =  add  4  (1  +  2) let  fact  n  =    if  n  <  2  then        1    else        n  *  fact  (n-­‐1) Thursday, 23 May, 13

Slide 10

Slide 10 text

LitiL Tuples et Listes let  x  =  (5,  "a",  true) let  pair  x  y  =  (x,  y) let  xs  =  [1,  2,  3] Thursday, 23 May, 13

Slide 11

Slide 11 text

LitiL Deconstruction let  (a,  b)  =  (4,  "d") let  d  =  ((4,  true),  ("test",  'c',  a)) let  ((_,  bool),  (_,  _,  _))  =  d Thursday, 23 May, 13

Slide 12

Slide 12 text

LitiL ADTs data  Option  a  =  Some  a  |  None let  o  =  Some  "thing" data  List  a  =  Cons  a  (List  a)  |  Nil let  l  =  Cons  5  (Cons  6  Nil) data  Tree  a  =  Null  |  Leaf  a  |  Node  (Tree  a)  a  (Tree  a) let  t  =  Node  (Leaf  5)  4  (Leaf  3) Thursday, 23 May, 13

Slide 13

Slide 13 text

LitiL Application partielle let  add  x  y  =  x  +  y let  inc  =  add  1 let  three  =  inc  2 Thursday, 23 May, 13

Slide 14

Slide 14 text

LitiL Lambdas & closures let  map  f  xs  =    match  xs        []          =>  Nil        h  ::  t  =>  (f  h)  ::  (map  f  t) let  l  =  [1,  2] let  double  x  =  2  *  x -­‐-­‐  pass  a  function  by  name let  l2  =  map  double  l -­‐-­‐  or  simply  a  lambda let  l2  =  map  (\x  =>  2  *  x)  l let  a  =  4 let  f  =  \x  =>  a  *  x  -­‐-­‐  f  captures  the  lexical  value  of  a,  i.e.  4 let  a  =  5 f  5 Thursday, 23 May, 13

Slide 15

Slide 15 text

Plan •Lexer •Parser •Descente récursive •Pratt •Type checker •Monomorphique •Polymorphique •Evaluator Thursday, 23 May, 13

Slide 16

Slide 16 text

Vue d’ensemble Lexer Parser Sources Tokens AST Type Checker Evaluator AST+Env Thursday, 23 May, 13

Slide 17

Slide 17 text

LitiL Lexer Thursday, 23 May, 13

Slide 18

Slide 18 text

Lexer •A partir du texte brut •Générer des tokens Thursday, 23 May, 13

Slide 19

Slide 19 text

Lexer :: Token •Type: SYM,  NAME,  KEYWORD,  ... •Valeur: ‘+’,  ‘x’,  ‘let’ •ligne, colonne Thursday, 23 May, 13

Slide 20

Slide 20 text

Exemple let  five  =  3 KEYWORD let NAME five SYM = NUM 3 EOF $ Thursday, 23 May, 13

Slide 21

Slide 21 text

Types •NAME •NUM, STRING, CHAR, BOOL •KEYWORD •EOF •NEWLINE, INDENT, DEINDENT Thursday, 23 May, 13

Slide 22

Slide 22 text

Algo pop()  :  Token c  =  nextChar() if  c  =  \n  return  blackMagic() elif  c  :  [0-­‐9]  return  readNum() elif  c  =  “  return  readString() elif  c  =  ‘  return  readString() elif  c  in  symsRoots  return  readSym() elif  return  readNameOrKwOrBool() Thursday, 23 May, 13

Slide 23

Slide 23 text

Les blancs ... ligne1 ligne2 NEWLINE ligne1 ligne2 INDENT + NEWLINE ligne1 ligne2 DEINDENT + NEWLINE Thursday, 23 May, 13

Slide 24

Slide 24 text

LitiL Parser Thursday, 23 May, 13

Slide 25

Slide 25 text

Parsing •A partir des tokens •Générer l’AST Thursday, 23 May, 13

Slide 26

Slide 26 text

Exemple let  add  x  y  =  x  +  y KEYWORD let NAME add NAME x NAME y SYM = SYM + NAME x NAME y Expr.EName name:  y LetBinding name:  add type:_ args:  [x,  y] instructions EAp fn arg EAp fn arg Expr.EName name:  + Expr.EName name:  x Thursday, 23 May, 13

Slide 27

Slide 27 text

Parseurs •Plusieures méthodes et algos •Bottom-Up: LR, LALR, SLR, etc. •Top-Down: LL, RDP Thursday, 23 May, 13

Slide 28

Slide 28 text

Grammaire •BNF: Spécification formelle d’un langage •Ensemble de règles de dérivation Thursday, 23 May, 13

Slide 29

Slide 29 text

BNF let  :  “let”  id  args  “=”  body args:  id  args  |  ε id:  [a-­‐zA-­‐Z]+[a-­‐zA-­‐Z0-­‐9]* body:  ... Thursday, 23 May, 13

Slide 30

Slide 30 text

EBNF •Augmente BNF avec les opérateurs “+”, “*” et “?” •Grammaires plus compactes Thursday, 23 May, 13

Slide 31

Slide 31 text

EBNF let  :  “let”  id  args  “=”  body args:  id* id:  [a-­‐zA-­‐Z]+[a-­‐zA-­‐Z0-­‐9]* body:  ... Thursday, 23 May, 13

Slide 32

Slide 32 text

RDP •Traduction EBNF vers le code •Règle => méthode •Référence à un non terminal => appel d’une méthode Thursday, 23 May, 13

Slide 33

Slide 33 text

RDP public  LetBinding  let()  { expect(KEYWORD,  “let”); String  name  =  name(); List  args  =  args(); expect(SYM,  “=”); Body  body  =  body(); return  new  LetBinding(name,  args,  body); } Thursday, 23 May, 13

Slide 34

Slide 34 text

EBNF <-> RDP let  :  “let”  id  args  “=”   body args:  id* id:  [a-­‐zA-­‐Z]+[a-­‐zA-­‐ Z0-­‐9]* body:  ... public  LetBinding  let()  { expect(KEYWORD,  “let”); String  name  =  name(); List  args  =  args(); expect(SYM,  “=”); Body  body  =  body(); return  new  LetBinding(name,  args,   body); } Thursday, 23 May, 13

Slide 35

Slide 35 text

Parseur RDP •Un champ token •Méthodes expect(Token.Type) et expect(Token.Type, String value) •Méthodes found(Token.Type) et found(Token.Type, String value) Thursday, 23 May, 13

Slide 36

Slide 36 text

LitiL Litil::RDP::1 public  Program  program()  {        Program  p  =  new  Program();        p.instructions.addAll(body());        return  p; } private  List  body()  {        List  res  =  new  ArrayList();        while  (found(Token.Type.NEWLINE))  {                res.add(instruction());        }        return  res; } Thursday, 23 May, 13

Slide 37

Slide 37 text

LitiL Litil::RDP::instruction private  Instruction  instruction()  {        if  (found(Token.Type.KEYWORD,  "let"))  {                return  letBinding();        }  else  if  (found(Token.Type.KEYWORD,  "data"))  {                return  dataDecl();        }  else  if  (found(Token.Type.KEYWORD,  "exception"))  {                return  exceptionDecl();        }  else  {                return  expr();        } } Thursday, 23 May, 13

Slide 38

Slide 38 text

LitiL Litil::RDP::let private  LetBinding  letBinding()  {        expect(Token.Type.NAME);        String  functionName  =  token.text;        Type  functionReturnType  =  null;        List  args  =  params();        List  argTypes  =  new  ArrayList(args.size());        for  (Named  arg  :  args)  {                argTypes.add(arg.type);        }        if  (found(Token.Type.SYM,  ":"))  {                functionReturnType  =  type();                Type  letType  =  argTypes.isEmpty()  ?  functionReturnType  :   Type.Function(argTypes,  functionReturnType);        }        expect(Token.Type.SYM,  "=");        List  instructions  =  bloc();        LetBinding  letBinding  =  new  LetBinding(functionName,   functionReturnType,  args,  instructions);        return  letBinding; } Thursday, 23 May, 13

Slide 39

Slide 39 text

LitiL Litil::RDP::match if  (found(Token.Type.KEYWORD,  "match"))  {        Expr  input  =  expr(0);        expect(Token.Type.INDENT);        List  cases  =  new   ArrayList();        while  (found(Token.Type.NEWLINE))  {                cases.add(patMatchCase());        }        expect(Token.Type.DEINDENT);        return  new  Expr.PatterMatching(input,  cases); } Thursday, 23 May, 13

Slide 40

Slide 40 text

Expressions •ça craint avec les RDP •Des stacks d’appel trop profonds Thursday, 23 May, 13

Slide 41

Slide 41 text

Priorité expr  :  expr  op  expr   |  [0-­‐9]+ op:  “+”  |  “-­‐”  |  “*”  |  “/” 1  +  2  *  3  =  ? Thursday, 23 May, 13

Slide 42

Slide 42 text

Priorité WTF ? 1  +  2  *  3 =  9 W AT ? Thursday, 23 May, 13

Slide 43

Slide 43 text

Because 1  +  2  *  3 val op expr val op val Thursday, 23 May, 13

Slide 44

Slide 44 text

Du coup •Encoder les règles de précédence dans la grammaire •En introduisant des productions intermédiaires Thursday, 23 May, 13

Slide 45

Slide 45 text

EBNF Révisé expr  :  expr  (“+”|”-­‐”)  prod  |  prod prod:  prod  (“*”|”/”)  val  |  val val:  [0-­‐9]+ Thursday, 23 May, 13

Slide 46

Slide 46 text

Mais avec N opérateurs •On finit avec beaucoup de niveaux intermédiaires •Et donc avec autant de niveaux dans la stack avec le RDP Thursday, 23 May, 13

Slide 47

Slide 47 text

Pour parser “5” •atom() •mulDivExpr() •addRemExpr() •compExpr() •andExpr() •orExpr() Thursday, 23 May, 13

Slide 48

Slide 48 text

Prattman pour nous sauver ! •Parser les expressions en un temps linéaire •Des stacks beaucoup moins profondes (fonction du nombre d’opérateurs) Thursday, 23 May, 13

Slide 49

Slide 49 text

Pratt parser •Opère sur les tokens pas les règles •Chaque token a une priorité •lbp(+) = 10 et lbp(*) = 20 par exemple •handler pour les tokens “infix”: led •nud pour les “prefix” Thursday, 23 May, 13

Slide 50

Slide 50 text

LitiL Priorités LBP.put("and",  5); LBP.put("or",  5); LBP.put("not",  7); LBP.put("=",  7); LBP.put("<",  7); LBP.put(">",  7); LBP.put("::",  11); LBP.put("+",  15); LBP.put("-­‐",  15); LBP.put("%",  20); LBP.put("*",  20); LBP.put("/",  20); LBP.put("[",  90); LBP.put("]",  1); LBP.put("(",  100); LBP.put(")",  1); Thursday, 23 May, 13

Slide 51

Slide 51 text

LitiL Pratt parser :: expr public  Expr  expr(int  rbp)  {        Token  tk  =  advance();        Expr  left  =  nud(tk);        while  (rbp  <  lbp(lexer.peek(1)))  {                tk  =  advance();                left  =  led(left,  tk);        }        return  left; } Thursday, 23 May, 13

Slide 52

Slide 52 text

LitiL Pratt parser :: nud private  Expr  nud(Token  tk)  {        if  (is(tk,  Token.Type.SYM,  "-­‐"))  {                Expr  expr  =  expr(100);                return  new  Expr.EAp(new  Expr.EName("-­‐/1"),  expr);        }  else  if  (is(tk,  Token.Type.NUM))  {                return  new  Expr.ENum(Integer.parseInt(tk.text));        }  else  if  (is(tk,  Token.Type.BOOL))  {                return  new  Expr.EBool(Boolean.parseBoolean(tk.text));        }  else  if  (is(tk,  Token.Type.NAME))  {                return  new  Expr.EName(tk.text);        } } Thursday, 23 May, 13

Slide 53

Slide 53 text

LitiL Pratt parser :: led private  Expr  led(Expr  left,  Token  tk)  {        int  bp  =  lbp(tk);        if  (is(tk,  Token.Type.SYM,  "+")  ||  is(tk,  Token.Type.SYM,  "*"))  {                Expr  right  =  expr(bp);  return  new  Expr.EAp( new  Expr.EAp(new  Expr.EName(tk.text),  left), right);        }  else  if  (left  instanceof  Expr.EName)  {                return  new  Expr.EAp(left,  nud(tk));        }  else  {                throw  error("Unexpected  token  "  +  tk);        } } Thursday, 23 May, 13

Slide 54

Slide 54 text

LitiL Type Checker Thursday, 23 May, 13

Slide 55

Slide 55 text

Type checker •Plusieures possiblités: •Typage explicite •Typage mono-mophique avec inférence •Typage poly-morphique avec inférence (HM) Thursday, 23 May, 13

Slide 56

Slide 56 text

Type •Oper: couple •nom •List de sous types Thursday, 23 May, 13

Slide 57

Slide 57 text

Types “natifs” •Num  =  Oper(“Num”,  []) •Bool  =  Oper(“Bool”,  []) •Char  =  Oper(“Char”,  []) •String  =  Oper(“List”,  [Type.Char]) •... Thursday, 23 May, 13

Slide 58

Slide 58 text

Prelude •not  :  Oper(“-­‐>”,  [Bool,  Bool]) •+  :  Oper(“-­‐>”,  [Num,  Num,  Num]) •... Thursday, 23 May, 13

Slide 59

Slide 59 text

Type checker •Etant donné: •Un noeud de l’AST •Et un environnement de types •Retourner le type du noeud •Ou exception en cas de problème Thursday, 23 May, 13

Slide 60

Slide 60 text

Typage explicite •Pas d’inférence •On vérifie que tous les types sont renseignés •Et qu’ils sont compatibles Thursday, 23 May, 13

Slide 61

Slide 61 text

LitiL Typage explicite let  max  (x:  Num)  (y:  Num)  :  Num  =   if  x  >  y     x   else     y • Vérifier que les arguments (x, y) déclarent leur type • Vérifier que le type de retour est précisé •Vérifier que le type de la condition de if est Bool • Vérifier que le type de retour du “then” est le même que celui déclaré comme retour • Idem pour le “else” Thursday, 23 May, 13

Slide 62

Slide 62 text

LitiL Typage statique :: impl public  Type  analyze(AstNode  node,  TypeScope  env)  {        if  (node  instanceof  Expr.ENum)  {                return  Type.INT;        }  else  if  (node  instanceof  Expr.EName)  {                Type  res  =  env.get(((Expr.EName)  node).name);                if  (res  ==  null)                        throw  new  TypeError("Undeclared  entity  '"  +  node  +  "'");                return  res;        }  else  if  (node  instanceof  Expr.EIf)  {                Expr.EIf  eif  =  (Expr.EIf)  node;                Type  condType  =  analyze(eif.cond,  env);                unify(condType,  Type.BOOL);                Type  thenType  =  null;                for  (Instruction  instr  :  eif.thenInstructions)                        thenType  =  analyze(instr,  env);                Type  elseType  =  null;                for  (Instruction  instr  :  eif.elseInstructions)                        elseType  =  analyze(instr,  env);                unify(thenType,  elseType);                return  thenType;        } } Thursday, 23 May, 13

Slide 63

Slide 63 text

TypeChecker mono-morphique •Peut inférer les types non présents •Pas de généralisation Thursday, 23 May, 13

Slide 64

Slide 64 text

mono-morphisme let  first  x  y  =  x let  f  =  first  4  false “first” sera typé: Num  -­‐>  Bool  -­‐>  Num Et non pas a  -­‐>  b  -­‐>  a static    X  first(X  x,  Y  y)  {   return  x } Thursday, 23 May, 13

Slide 65

Slide 65 text

Type variable •Type qu’on cherche à déterminer •identifié par un nom généré automatiquement •Peut être “remplacée” par un autre type Thursday, 23 May, 13

Slide 66

Slide 66 text

Unification •Etant donné 2 types •On cherche à vérifier qu’ils sont compatibles/équivalents •En effectuant de l’inférence s’il le faut Thursday, 23 May, 13

Slide 67

Slide 67 text

Unify(t1, t2) ‣ Si  t1  est  une  variable  =>  t1  inféré  à   t2 ‣ Si  t2  variable,  unifier  t2  et  t1  (cas   1) ‣ Sinon,  t1  et  t2  sont  du  type  Oper ‣ Si  t1.name  !=  t2.name  =>  erreur ‣ Si  t1.types.size  !=  t2  =>  erreur ‣ Unifier  t1.types  et  t2.types Thursday, 23 May, 13

Slide 68

Slide 68 text

Algo •Même que typage explicite •Sans la vérif de la présence obligatoire des déclarations de types •unify qui effectue l’inférence Thursday, 23 May, 13

Slide 69

Slide 69 text

LitiL Typage monomorphique :: impl public  Type  analyze(AstNode  node,  TypeScope  env)  {        if  (node  instanceof  Expr.ENum)  {                return  Type.INT;        }  else  if  (node  instanceof  Expr.EName)  {                Type  res  =  env.get(((Expr.EName)  node).name);                if  (res  ==  null)                        throw  new  TypeError("Undeclared  entity  '"  +  node  +  "'");                return  res;        }  else  if  (node  instanceof  Expr.EIf)  {                Expr.EIf  eif  =  (Expr.EIf)  node;                Type  condType  =  analyze(eif.cond,  env);                unify(condType,  Type.BOOL);                Type  thenType  =  null;                for  (Instruction  instr  :  eif.thenInstructions)                        thenType  =  analyze(instr,  env);                Type  elseType  =  null;                for  (Instruction  instr  :  eif.elseInstructions)                        elseType  =  analyze(instr,  env);                unify(thenType,  elseType);                return  thenType;        } } Thursday, 23 May, 13

Slide 70

Slide 70 text

LitiL Typage monomorphique :: impl :: let if  (node  instanceof  LetBinding)  {        LetBinding  let  =  (LetBinding)  node;        TypeScope  ss  =  new  TypeScope(scope);        List  argTypes  =  new  ArrayList();        ss.define(let.name,  new  Type.Variable());        for  (Named  arg  :  let.args)  {                Type  argType  =  new  Type.Variable();                argTypes.add(argType);                ss.define(arg.name,  argType);        }        Type  resultType  =  null;        for  (Instruction  instr  :  let.instructions)  {                resultType  =  analyze(instr,  ss);        }        if  (let.type  !=  null)  {                unify(resultType,  let.type);        }        Type  letType  =  Type.Function(argTypes,  resultType);        scope.define(let.name,  letType);        return  letType; } Thursday, 23 May, 13

Slide 71

Slide 71 text

TypeChecker poly- morphique •Peut inférer les types non présents de façon globale •Trouve systématiquement le type le plus général et plus générique •Utilise L’algo W de Hindley-Milner Thursday, 23 May, 13

Slide 72

Slide 72 text

poly-morphisme let  first  x  y  =  x let  f  =  first  4  false “first” sera typé: a  -­‐>  b  -­‐>  a Et non pas Num  -­‐>  Bool  -­‐>  Num static    X  first(X  x,  Y  y)  {   return  x } Thursday, 23 May, 13

Slide 73

Slide 73 text

L’astuce ? •Dupliquer les variables d’un type à chaque unification •Ainsi, on garde la forme la plus générale Thursday, 23 May, 13

Slide 74

Slide 74 text

Exemple • analyze(let  first  ...) • Types  {first=v1,  x=v2,  y=v3} • Au  final,  first:  a  -­‐>  b  -­‐>  a • analyze(let  f  =  ...) • unify(Num  -­‐>  Bool  -­‐>  v4,  a2  -­‐>  b2  -­‐>  a2) • a2  =  Num,  b2  =  Bool • v4  =  a2  =  Num • f:  Num • mais  first  est  toujours  a  -­‐>  b  -­‐>  c let  first  x  y  =  x let  f  =  first  4  false Fresh Thursday, 23 May, 13

Slide 75

Slide 75 text

I lied •C’est plus compliqué que ça en fait ... •Ne pas dupliquer systématiquement •Sinon on va laisser passer des erreurs Thursday, 23 May, 13

Slide 76

Slide 76 text

Exemple let  f  x  =   let  y  =  x  +  1  -­‐-­‐  x  inferred  to  be  Num   if  x  -­‐-­‐  x  inferred  to  be  Bool     2   else     3 Thursday, 23 May, 13

Slide 77

Slide 77 text

Donc •Ne pas dupliquer les arguments et le type de retour d’un let dans sa définition •Celui de l’expression du match dans les cases •etc. Thursday, 23 May, 13

Slide 78

Slide 78 text

Bref •Hindley et Milner s’en sont déjà occupé •Tout que j’avais à faire c’était de: •Décoder les papiers de recherche •Adapter à Litil: •Pas de pattern-matching dans HM •Let différent •... Thursday, 23 May, 13

Slide 79

Slide 79 text

LitiL Evaluator Thursday, 23 May, 13

Slide 80

Slide 80 text

Evaluator •Pour que ça tourne •Plus facile à faire qu’un compilateur Thursday, 23 May, 13

Slide 81

Slide 81 text

Comment ? •Etant donné: •Un noeud de l’AST •Et un environnement de valeurs •Retourner le resultat de l’évaluation du noeud •Ou exception en cas de problème Thursday, 23 May, 13

Slide 82

Slide 82 text

LitiL Expr :: Name public  Object  eval(AstNode  node,  ValScope  scope)  {        if  (node  instanceof  Expr)  {                if  (node  instanceof  Expr.EName)  {                        Object  val  =  scope.get(((Expr.EName)  node).name);                        if  (val  ==  null)  {                                throw  new  EvalException("Unknwon  identifier  "  +  node);                        }  else  {                                return  val;                        }                } Thursday, 23 May, 13

Slide 83

Slide 83 text

LitiL Expr :: Types simples public  Object  eval(AstNode  node,  ValScope  scope)  {        else  if  (node  instanceof  Expr.ENum)  {                return  ((Expr.ENum)  node).value;        }  else  if  (node  instanceof  Expr.EBool)  {                return  ((Expr.EBool)  node).value;        }  else  if  (node  instanceof  Expr.EChar)  {                return  ((Expr.EChar)  node).value;        }  ... Thursday, 23 May, 13

Slide 84

Slide 84 text

LitiL Expr :: Tuples public  Object  eval(AstNode  node,  ValScope  scope)  {        if  (node  instanceof  Expr.ETuple)  {                Expr.ETuple  tuple  =  ((Expr.ETuple)  node);                List  res  =  new  ArrayList();                for  (Expr  value  :  tuple.values)  {                        res.add(eval(value,  scope));                }                return  res;        } Thursday, 23 May, 13

Slide 85

Slide 85 text

LitiL Expr :: If if  (node  instanceof  Expr.EIf)  {        Expr.EIf  eif  =  (Expr.EIf)  node;        Object  cond  =  eval(eif.cond,  scope);        if  (cond  instanceof  Boolean)  {                if  ((Boolean)  cond)  {                        Object  val  =  null;                        ValScope  thenScope  =  scope.child();                        for  (Instruction  instr  :  eif.thenInstructions)  {                                val  =  eval(instr,  thenScope);                        }                        return  val;                }  else  {                        Object  val  =  null;                        ValScope  elseScope  =  scope.child();                        for  (Instruction  instr  :  eif.elseInstructions)  {                                try  {                                        val  =  eval(instr,  elseScope);                                }  catch  (LitilException  e)  {                                        //erreur                                }                        }                        return  val;                }        }  else  ... Thursday, 23 May, 13

Slide 86

Slide 86 text

LitiL Expr :: Let if  (node  instanceof  LetBinding)  {        LetBinding  let  =  (LetBinding)  node;        ValScope  letScope  =  scope.child();        Fn  fn  =  null;        for  (int  i  =  let.args.size()  -­‐  1;  i  >=  0;  i-­‐-­‐)  {                Named  arg  =  let.args.get(i);                if  (i  ==  let.args.size()  -­‐  1)  {//last  argument                        fn  =  new  ChaininLastFn(arg.name,  let.instructions);                }  else  {                        fn  =  new  ChainingFn(arg.name,  fn);                }        }        fn  =  new  EnvCapturingFnWrapper(fn,  let,  scope);        scope.define(let.name,  fn);        return  fn; } Thursday, 23 May, 13

Slide 87

Slide 87 text

LitiL Expr :: Ap if  (node  instanceof  Expr.EAp)  {        ValScope  ss  =  scope.child();        Expr.EAp  ap  =  (Expr.EAp)  node;        Object  fn  =  eval(ap.fn,  ss);        if  (fn  instanceof  Fn)  {                Object  evalArg  =  eval(ap.arg,  ss);                return  ((Fn)  fn).eval(evalArg,  ss);        } } Thursday, 23 May, 13

Slide 88

Slide 88 text

LitiL What the Fn ? public  interface  Fn  {        public  Object  eval(Object  arg,  ValScope  scope); } ChainingFn argName nextFn eval: •Reprend les arguments précédents {name, value} •Rajoute le sien (arg) de façon anonyme •Retourne une implem de Fn (argument arg2) qui: •Reprend l’arg anonyme et l’indexe sous argName •Done la main à next ChainingLastFn argName instructions eval: •Reprend les arguments précédents {name, value} •Reprend l’arg anonyme et l’indexe sous argName •Prépare un environnement avec les args •Exécute instructions •Retourne le résultat Thursday, 23 May, 13

Slide 89

Slide 89 text

LitiL And suddently boxes ! let  add  x  y  =  x  +  y Expr.EName name:  y LetBinding name:  add type:_ args:  [x,  y] instructions EAp fn arg EAp fn arg Expr.EName name:  + Expr.EName name:  x AST add  1  2 ChainingFn argName:  x next ChainingLastFn argName:  y instructions Trop com pliqué* * En fait j’avais plus de temps pour préparer les schémas, et puis ça fait longtemps que j’avais pas touché à ça Thursday, 23 May, 13

Slide 90

Slide 90 text

LitiL Thursday, 23 May, 13

Slide 91

Slide 91 text

La suite •Refaire la partie records •Compilation vers bytecode (rapide) •Typeclasses, exhaustivité patmat, GADT ? •Intégration Java •Inception •A moi broadway ! Thursday, 23 May, 13

Slide 92

Slide 92 text

LitiL github.com/ jawher/litil Thursday, 23 May, 13

Slide 93

Slide 93 text

LitiL jawher.me blog.zenika.com Thursday, 23 May, 13

Slide 94

Slide 94 text

LitiL Merci ! Thursday, 23 May, 13