pattern matching - la mise en œuvre
-
06-09-2019 - |
Question
Im se demandant comment pattern matching est généralement mis en œuvre. par exemple dans Erlang pensez-vous que sa mise en œuvre au niveau de bytecode (il y a un bytecode pour cela de sorte que son efficacité fait) ou est-il généré une série d'instructions (série de bytecode) par le compilateur? il est une chose utile que je viens de le mettre dans une langue de jouets bâtiment Im je vous remercie beaucoup
(liens sont plus de bienvenue)
La solution
Vous pouvez voir ce qui se passe si la compilation du code
-module(match).
-export([match/1]).
match(X) -> {a,Y} = X.
Si vous voulez voir comment ressemble
> c(match, to_core).
ou
$ erlc +to_core match.erl
résultat est
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)
Si vous voulez voir le code asm du faisceau que vous pouvez faire
> c(match, 'S').
ou
$ erlc -S match.erl
et le résultat
{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}}.
Comme vous pouvez le voir {test,is_tuple,...
, {test,test_arity,...
, {get_tuple_element,...
et {test,is_eq_exact,...
sont l'instruction comment cette correspondance est réalisée en faisceau et il est transformé directement à octet code de faisceau.
compilateur Erlang est mis en œuvre Erlang lui-même et vous pouvez regarder à chaque phase de compilation dans le code source de
Autres conseils
Une très bonne description de la compilation pattern matching est donnée dans « La mise en œuvre des langages de programmation fonctionnelle » par Simon Peyton Jones. Il est un peu vieux, mais un très bon livre. Il contient également, entre autres, une description de la compilation compréhensions de la liste.
Le compilateur Erlang utilise ces deux algorithmes du livre.
Si vous voulez construire votre propre modèle matcher il y a un par Scott et Ramsey et un par Luc Maranget qui décrivent tous deux comment compiler des modèles pour les arbres de décision efficaces (états de commutation aka imbriquées).
La meilleure chose que je peux suggérer, est de compiler quelques fonctions de test et regarder le code généré.
erlc -S test.erl
génère test.S qui est assez lisible.
Pour répondre à la question, les matches de motif sont construits de manière efficace des opérations plus primitives. Voici une partie du code à partir d'une correspondance de clause de fonction {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}]}.