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 its done efficiently) or is it generated as a series of instructions (series of byte-codes) by the compiler?
It is such a useful thing that I just have to put it into a toy language I am building.
Pattern matching occurs when evaluating a function call, case- receive- try- expressions and match operator (=) expressions. In a pattern matching, a left-hand side pattern is matched against a right-hand side term. If the matching succeeds, any unbound variables in the pattern become bound.
Pattern Matching works by "reading" through text strings to match patterns that are defined using Pattern Matching Expressions, also known as Regular Expressions. Pattern Matching can be used in Identification as well as in Pre-Classification Processing, Page Processing, or Storage Processing.
Regular programming languages make use of regular expressions (regex) for pattern matching. Pattern matching is used to determine whether source files of high-level languages are syntactically correct. It is also used to find and replace a matching pattern in a text or code with another text/code.
Pattern matching is a technique where you test an expression to determine if it has certain characteristics. C# pattern matching provides more concise syntax for testing expressions and taking action when an expression matches.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With