Compilaci ó n de Pattern Matching

Post on 12-Jan-2016

18 views 2 download

description

Compilaci ó n de Pattern Matching. Un ejemplo: zipWith f [] ys = [] zipWith f (x:xs) [] = [] zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys Semántica de pattern matching Se asume: (1) testea cada ecuación por un match top to bottom - PowerPoint PPT Presentation

Transcript of Compilaci ó n de Pattern Matching

1

Compilación de Pattern Matching

Un ejemplo:

zipWith f [] ys = [] zipWith f (x:xs) [] = [] zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys

Semántica de pattern matching Se asume:(1) testea cada ecuación por un match top to bottom(2) Para cada ecuación, testea cada pattern por un match de izquierda a derecha,

si falla termina con esa ecuación y testea la siguiente.

Traduccion en expresiones case simples: una secuencia eficiente de tests, testeando cada valor sólo una vez

2

Expresiones case simples

zipWith = \ f xs' ys -> case xs' of Nil -> Nil Cons x xs -> case ys' of Nil -> Nil Cons y ys -> Cons (f x y) (zipWith f xs ys)

case e of C1 v11 ... v1k1 -> e1

... Cn vn1 ... vnkn -> en v -> e

. Sub-patterns son simple variables (vij's).

. default pattern v -> e es opcional.

3

Traducción

f p11 ...p1n = e1...f pm1 ...p mn = em

f = \ u1 ...un -> ( (( \ (p11’ ,..., p1n’) -> e1’) u1...un )(( \ (pm1’ ,..., pmn’) -> em’) u1...un )ERROR )

Nuestro objetivo entonces es transformar una expresión de esta forma en una expresión equivalente definida en función de expresiones case.

4

La función match

match [ u 1 , ..., u n ] [([ p11 , ..., p1n ] , [e1]) , ([ pm1 , ..., pmn ] , [em]) ] [ error "no match in f"]

match us qs e, donde us: una lista de variables a ser testeadas por un match, qs: una lista de ecuaciones, e: expresion por defecto, si ninguna ecuacion en qs machea entonces e es el valor retornado

5

Un ejemplo de corrida: demo

demo f [] ys = aa f ysdemo f (x:xs) [] = bb f x xs demo f (x:xs) (y:ys) = cc f x xs y ys

demo = \ u1 u2 u3 -> match [ u1 , u2 , u 3] [( [f , Nil , ys ] , [ aa f ys ]) , ( [f , Cons x xs , Nil ] , [ bb f x xs]) , ( [f , Cons x xs ,Cons y ys ] ,[cc f x xs y ys ]) ] [ error "no match in demo"]

6

La regla de la Variabledemo = \ u1 u2 u3 -> match [ u1 , u2 , u3] [( [f , Nil , ys ] ,[ aa f ys ]) , ( [f , Cons x xs ,Nil ] ,[ bb f x xs]) , ( [f , Cons x xs ,Cons y ys ] ,[cc f x xs y ys ]) ] [ error "no match in demo"]

Todos los primer patterns son variables

demo = \ u1 u2 u3 -> match [u2 , u3] [ ( Nil , ys ] , [ aa f ys ]) , ( Cons x xs , Nil ] , [ bb f x xs]) , ( Cons x xs , Cons y ys ] , [cc f x xs y ys ]) ] [ error "no match in demo"] Nota: Las variables no necesitan ser las mismas

7

Regla 2: la regla Constructor

Todos los primer patterns son constructores ejemplo: en un data type que incluye constructores A, B y C. match ([ u ] : us ) [([ A psa1 ]: ps'a1, ea1 ), ([ B psb1 ]: ps'b1, eb1 ), ([ A psa2 ]: ps'a2, ea2 ), ([ B psb2 ]: ps'b2, eb2 ), ([ C psc1 ]: ps'c1, ec1 ), ([ A psa3 ]: ps'a3, ea3 ) ] d=>

8

Regla 2 (cont.)case u of A us'a -> match ( us'a ++ us ) [ ( psa1 ++ ps'a1 , ea1 ), ( psa2 ++ ps'a2 , ea2 ), ( psa3 ++ ps'a3 , ea3 )] d

B us'b -> match ( us'b ++ us ) [ ( psb1 ++ ps'b1 , eb1 ), ( psb2 ++ ps'b2 , eb2 )] d

C us'c -> match ( us'c ++ us ) [ ( psc1 ++ ps'c1 , ec1 )] d u' -> d

9

Una nota sobre el orden de ecuaciones

match ([ u ] : us ) [([ A psa1 ]: ps'a1, ea1 ), ([ B psb1 ]: ps'b1, eb1 ), ([ A psa2 ]: ps'a2, ea2 ), ([ B psb2 ]: ps'b2, eb2 ), ([ C psc1 ]: ps'c1, ec1 ), ([ A psa3 ]: ps'a3, ea3 ) ] d=>

match ([ u ] : us ) [([ A psa1 ]: ps'a1, ea1 ), ([ A psa2 ]: ps'a2, ea2 ), ([ A psa3 ]: ps'a3, ea3 ) ([ B psb1 ]: ps'b1, eb1 ), ([ B psb2 ]: ps'b2, eb2 ), ([ C psc1 ]: ps'c1, ec1 ), ] d

Es siempre seguro permutar ecuaciones adyacentes con diferentes constructores. Entonces, en general se podría ordenar la lista con clave el constructor usando un sort estable.

10

Usando la regla 2Los primeros patterns son constructores

demo = \ u1 u2 u3 -> case u2 of Nil -> match [u3] [( [ ys ] , [ aa u1 ys]) ] [ error "no match in demo"] Cons u4 u5 -> match [u4, u5, u3] [ ( [ x xs , Nil ] , [ bb u1 x xs]) , ( [ x xs , Cons y ys ] , [ cc u1 x xs y ys ]) ] [ error "no match in demo"]

v -> [ error "no match in demo"]

11

Regla 2 (cont.)demo = \ u1 u2 u3 -> case u2 of Nil -> match [u3] [( [ ys ] , [ aa u1 ys]) ] [ error "no match in demo"] Cons u4 u5 -> match [u4, u5, u3] [ ( [ x xs , Nil ] , [ bb u1 x xs]) , ( [ x xs , Cons y ys ] , [ cc u1 x xs y ys ]) ] [ error "no match in demo"]

v -> [ error "no match in demo"]

Aplicamos la regla de variable 3 veces

12

Regla 2 (cont.)demo = \ u1 u2 u3 -> case u2 of Nil -> match [ ] [( [ ] , [ aa u1 u3]) ] [ error "no match in demo"] Cons u4 u5 -> match [ u3 ] [ ( [ Nil ] , [ bb u1 u4 u5]) , ( [ Cons y ys ] , [ cc u1 u4 u5 y ys ]) ] [ error "no match in demo"]

v -> [ error "no match in demo"]

Regla 3:la regla Vacía

match [] [([] , e1 )] ... [([] , em )] d => e1 … …em…d

13

demo (cont.)

demo = \ u1 u2 u3 -> case u2 of Nil -> aa u1 u3 Cons u4 u5 -> case u3 of Nil -> match [ ] [([ ] , [ bb u1 u4 u5])] [ error "no match in demo"] Cons u6 u7 -> match [ ] [([ ] , [ cc u1 u4 u5 u6 u7])] [ error "no match in demo"] v -> [ error "no match in demo"]

v -> [ error "no match in demo"]

14

... y finalmentedemo = \ u1 u2 u3 -> case u2 of Nil -> aa u1 u3 Cons u4 u5 -> case u3 of Nil -> bb u1 u4 u5 Cons u6 u7 -> cc u1 u4 u5 u6 u7 v -> [ error "no match in demo"]

v -> [ error "no match in demo"]

Si todos los constructores de un data type están presentes en el case, entonces el caso por defecto puede ser eliminado.

15

demo’: otra versión de demo

demo' f [] ys = aa f ysdemo' f xs [] = bb f x xs demo' f (x:xs) (y:ys) = cc f x xs y ys

=>

demo' = \ u1 u2 u3 -> match [ u1 , u2 , u3] [ ( [ f , Nil , ys ] , [ aa f ys ]) , ( [ f , xs , Nil ] , [ bb f x xs]) , ( [ f , Cons x xs , Cons y ys ] , [cc f x xs y ys ]) ] [ error "no match in demo"]

16

demo’ (2)

demo' = \ u1 u2 u3 -> match [ u2 , u3] [ ( [ Nil , ys ] , [ aa u1 ys ]) , ( [ xs , Nil ] , [ bb u1 x xs]) , ( [ Cons x xs ,Cons y ys ] , [cc u1 x xs y ys ]) ] [ error "no match in demo"]

Los primer patterns no son enteramente variables ni enteramente constructores.

17

Regla 4: la regla Mixta

match us qs d

donde los primer patterns en qs no son enteramente variables ni enteramente constructores.

Efectuamos una partición de qs en k listas

qs = qs1 ++ qs2 ++ ... ++ qsk

tal que los primer patterns de cada qsi son todos variables o todos constructores.

Entonces match us qs d = match us qs1 (match us qs2 (...(match us qsk d)...))

Nota: la regla mixta siempre puede ser aplicada, pero su uso es sólo necesario en el caso de primer patterns mezclados.

18

demo’ (cont.)

demo' = \ u1 u2 u3 -> match [ u2 , u3] [ ( [ Nil , ys ] , [ aa u1 ys ]) ] ( match [ u2 , u3] [ ( [ xs , Nil ] , [ bb u1 x xs])] ( match [ u2 , u3] [ ( [ Cons x xs ,Cons y ys ] , [cc u1 x xs y ys ]) ] [ error "no match in demo"] ))

Deficiencias: La regla mixta fácilmente causa que la misma variable sea examinada más de una vez. Esto puede ser optimizado en una pasada posterior.

19

Completitud

Ahora es posible reducir toda posible llamada a match a una expresión case. Podemos razonar haciendo un simple análisis de casos.

Dada una aplicación (match us qs e) :

• si us es [] entonces aplicamos la regla Vacía• sino, entonces cada ecuación debe contener una lista no vacía de patrones, la que debe empezar o con una variable o con un constructor.

• si todos son variables => se aplica la regla Variable• si todos son constructores => se aplica la regla Constructor• sino => se aplica la regla Mixta

20

Terminacióndata Pattern = Var Vars | Cons Const [Pattern]type Vars = Stringtype Const = String

type Eq = ([ Pattern ] , Exp)type Eqs = [Eq]

sizeeqs :: Eqs -> Int

Se puede demostrar fácilmente que para las cuatro reglas que definimos las llamadas recursivas a match son efectuadas sobre listas de ecuaciones de menor tamaño. Esto garantiza que el algoritmo termina.