2009-02-25 15 views
27

Mi chiedo come viene solitamente implementata la corrispondenza di modelli. per esempio in Erlang pensi che sia implementato a livello di byte-code (c'è un bytecode per farlo funzionare in modo efficiente) o è generato come una serie di istruzioni (serie di bytecode) dal compilatore? si tratta di una cosa così utile che mi resta che metterla in un linguaggio giocattolo Im edificio vi ringrazio molto- implementazione

(i collegamenti sono più che benvenuti)

risposta

18

Si può vedere che cosa succederebbe se la compilazione del codice

-module(match). 
-export([match/1]). 
match(X) -> {a,Y} = X. 

Quando si desidera vedere come si presenta come core

> c(match, to_core). 

o

$ erlc +to_core match.erl 

risultato è

module 'match' ['match'/1, 
       'module_info'/0, 
       'module_info'/1] 
    attributes [] 
'match'/1 = 
    %% Line 3 
    fun (_cor0) -> 
     case _cor0 of 
      <{'a',Y}> when 'true' -> 
       _cor0 
      (<_cor1> when 'true' -> 
       primop 'match_fail' 
        ({'badmatch',_cor1}) 
      -| ['compiler_generated']) 
     end 
'module_info'/0 = 
    fun() -> 
     call 'erlang':'get_module_info' 
      ('match') 
'module_info'/1 = 
    fun (_cor0) -> 
     call 'erlang':'get_module_info' 
      ('match', _cor0) 

Se volete vedere il codice asm del fascio si può fare

> c(match, 'S'). 

o

$ erlc -S match.erl 

e risultato

{module, match}. %% version = 0 

{exports, [{match,1},{module_info,0},{module_info,1}]}. 

{attributes, []}. 

{labels, 8}. 


{function, match, 1, 2}. 
    {label,1}. 
    {func_info,{atom,match},{atom,match},1}. 
    {label,2}. 
    {test,is_tuple,{f,3},[{x,0}]}. 
    {test,test_arity,{f,3},[{x,0},2]}. 
    {get_tuple_element,{x,0},0,{x,1}}. 
    {test,is_eq_exact,{f,3},[{x,1},{atom,a}]}. 
    return. 
    {label,3}. 
    {badmatch,{x,0}}. 


{function, module_info, 0, 5}. 
    {label,4}. 
    {func_info,{atom,match},{atom,module_info},0}. 
    {label,5}. 
    {move,{atom,match},{x,0}}. 
    {call_ext_only,1,{extfunc,erlang,get_module_info,1}}. 


{function, module_info, 1, 7}. 
    {label,6}. 
    {func_info,{atom,match},{atom,module_info},1}. 
    {label,7}. 
    {move,{x,0},{x,1}}. 
    {move,{atom,match},{x,0}}. 
    {call_ext_only,2,{extfunc,erlang,get_module_info,2}}. 

Come si può vedere {test,is_tuple,..., {test,test_arity,..., {get_tuple_element,... e {test,is_eq_exact,... sono istruzioni su come questa corrispondenza viene eseguita in beam e viene trasformata direttamente in byte-code di beam.

Il compilatore di Erlang è implementato in Erlang stesso ed è possibile esaminare ciascuna fase della compilazione nel codice sorgente del modulo compile e i dettagli nei moduli dipendenti.

+1

risposta meravigliosa, molte informazioni interessanti qui (in particolare le direttive di compilazione). grazie – deepblue

+0

+1 per una risposta eccellente. –

2

La cosa migliore che posso suggerire è di compilare up alcune funzioni di test e dare un'occhiata al codice generato.

erlc -S test.erl 

genera test.S che è abbastanza leggibile.

Per rispondere alla domanda, le corrispondenze di modello vengono create in modo efficiente da operazioni più primitive. Ecco parte del codice da una clausola di funzione che corrisponde a {X, [H | T]}.

{test,is_tuple,{f,1},[{x,0}]}. 
{test,test_arity,{f,1},[{x,0},2]}. 
{get_tuple_element,{x,0},0,{x,1}}. 
{get_tuple_element,{x,0},1,{x,2}}. 
{test,is_nonempty_list,{f,4},[{x,2}]}. 
11

Se si desidera creare il proprio modello di corrispondenza, è disponibile uno paper by Scott and Ramsey e uno paper by Luc Maranget che descrivono entrambi come compilare i modelli su efficienti alberi decisionali (ovvero istruzioni di commutazione annidate).

+0

fantastico. apprezzalo, sembra un sacco di cose utili – deepblue

+0

+1 Link molto interessanti, una buona lettura. –

28

Una descrizione molto buona della corrispondenza del modello di compilazione è riportata in "L'implementazione dei linguaggi di programmazione funzionale" di Simon Peyton Jones. È un po 'vecchio ma un ottimo libro. Contiene anche, tra le altre cose, una descrizione della compilazione delle liste di comprensione.

Il compilatore Erlang utilizza entrambi questi algoritmi dal libro.

+1

grazie. Ho scaricato questo libro per un po 'di tempo ma non ho mai avuto il tempo di leggerlo. come fai a sapere che Erlang usa algoritmi da esso? – deepblue

+6

Ci scusiamo per non aver risposto prima, molto prima. La ragione per cui so è che ho implementato la corrispondenza dei pattern di compilazione per il compilatore corrente e questo è il punto da cui ho preso l'algoritmo. – rvirding

+1

che funziona;). grazie per aver lavorato su Erlang, è un po 'strano ma sicuramente una boccata d'aria fresca. reso la mia vita un posto migliore di sicuro – deepblue