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
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
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
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
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
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
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
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
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
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
Type checker •Plusieures possiblités: •Typage explicite •Typage mono-mophique avec inférence •Typage poly-morphique avec inférence (HM) Thursday, 23 May, 13
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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