Pattern matching - implementation

后端 未结 4 663
执念已碎
执念已碎 2020-12-13 09:14

I am wondering how pattern matching is usually implemented. for example in Erlang do you think its implemented at the byte-code level( there\'s a byte-code for it so that it

相关标签:
4条回答
  • 2020-12-13 09:54

    A very good description of compiling pattern matching is given in "The implementation of functional programming languages" by Simon Peyton Jones. It is a bit old but a very good book. It also contains, amongst other things, a description of compiling list comprehensions.

    The Erlang compiler uses both of these algorithms from the book.

    0 讨论(0)
  • 2020-12-13 09:55

    If you want to build your own pattern matcher there is a paper by Scott and Ramsey and a paper by Luc Maranget which both describe how to compile patterns to efficient decision trees (aka nested switch statements).

    0 讨论(0)
  • 2020-12-13 10:00

    The best thing I can suggest is to compile up some test functions and have a look at the generated code.

    erlc -S test.erl
    

    generates test.S which is fairly readable.

    To answer the question, pattern matches are built up in an efficient way from more primitive operations. Here's part of the code from a function clause matching {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}]}.
    
    0 讨论(0)
  • 2020-12-13 10:05

    You can see what happen if compile some code

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

    When you want see how looks like core

    > c(match, to_core).
    

    or

    $ erlc +to_core match.erl
    

    result is

    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)
    

    If you want see asm code of beam you can do

    > c(match, 'S').
    

    or

    $ erlc -S match.erl
    

    and result

    {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}}.
    

    As you can see {test,is_tuple,..., {test,test_arity,..., {get_tuple_element,... and {test,is_eq_exact,... are instruction how this match is performed in beam and it's transformed directly to byte-code of beam.

    Erlang compiler is implemented in Erlang itself and you can look at each phase of compilation in source code of compile module and details in depend modules.

    0 讨论(0)
提交回复
热议问题