Erlang Notes

Core Erlang
Login

Core Erlang

Consider:

-module(example).
-export([cat/1]).

cat(string) -> "a" ++ " " ++ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ++ " long" ++ " string".

Are those concatenations performed at runtime?

A way to definitively answer that is to look at a readable intermediate compilation result - AKA, Core Erlang.

$ erlc +to_core example.erl

This yields an example.core file that answers the question:

module 'example' ['cat'/1,
		  'module_info'/0,
		  'module_info'/1]
    attributes [%% Line 1
		'file' =
		    %% Line 1
		    [{[101|[120|[97|[109|[112|[108|[101|[46|[101|[114|[108]]]]]]]]]]],1}]]
'cat'/1 =
    %% Line 4
    ( fun (_0) ->
	  ( case ( _0
		   -| [{'function',{'cat',1}}] ) of
	      <'string'> when 'true' ->
		  [97|[32|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[65|[32|[108|[111|[110|[103|[32|[115|[116|[114|[105|[110|[103]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
	      ( <_4> when 'true' ->
		    ( primop 'match_fail'
			  (( {'function_clause',_4}
			     -| [{'function',{'cat',1}}] ))
		      -| [{'function',{'cat',1}}] )
		-| ['compiler_generated'] )
	    end
	    -| [{'function',{'cat',1}}] )
      -| [{'function',{'cat',1}}] )
'module_info'/0 =
    ( fun () ->
	  call 'erlang':'get_module_info'
	      ('example')
      -| [{'function',{'module_info',0}}] )
'module_info'/1 =
    ( fun (_0) ->
	  call 'erlang':'get_module_info'
	      ('example', ( _0
			    -| [{'function',{'module_info',1}}] ))
      -| [{'function',{'module_info',1}}] )
end

Useful discussion: https://erlangforums.com/t/core-erlang-why-have-e-1-e-n/3421

Although in this case, we're better off with BEAM assembly:

$ erlc -S example.erl

yielding example.S:

{module, example}.  %% version = 0

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

{attributes, []}.

{labels, 7}.


{function, cat, 1, 2}.
  {label,1}.
    {line,[{location,"example.erl",4}]}.
    {func_info,{atom,example},{atom,cat},1}.
  {label,2}.
    {test,is_eq_exact,{f,1},[{x,0},{atom,string}]}.
    {move,{literal,"a AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA long string"},
          {x,0}}.
    return.


{function, module_info, 0, 4}.
  {label,3}.
    {line,[]}.
    {func_info,{atom,example},{atom,module_info},0}.
  {label,4}.
    {move,{atom,example},{x,0}}.
    {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.


{function, module_info, 1, 6}.
  {label,5}.
    {line,[]}.
    {func_info,{atom,example},{atom,module_info},1}.
  {label,6}.
    {move,{x,0},{x,1}}.
    {move,{atom,example},{x,0}}.
    {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.

You can go farther and get the machine assembly, but it's far from illustrative, and doesn't seem to include the string literal at all.

erl +JDdump true -eval 'example:cat(string), halt().' -noshell

yielding example.asm - along with .asm for every other loaded module.