Erlang BEAM байт-код - PullRequest
       38

Erlang BEAM байт-код

18 голосов
/ 26 февраля 2009

ну, я надеюсь, что я не нарушу здесь какое-то правило рассылки спама. Я только что задал вопрос о том, как компилятор erlang реализует сопоставление с образцом, и получил несколько отличных ответов, одним из которых является скомпилированный байт-код (полученный с помощью параметра, переданного в директиву c ()):

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

это просто простые эрлангские кортежи. Я ожидал какую-то загадочную двоичную штуку, не думаю. поэтому я спрашиваю об этом здесь импульсивно (я мог бы взглянуть на исходный код компилятора, но задавая вопросы всегда лучше заканчивая дополнительным пониманием), как этот вывод транслируется на двоичном уровне?

скажем {test,is_tuple,{f,3},[{x,0}]} например. Я предполагаю, что это одна инструкция, называемая 'test' ... в любом случае, так что этот вывод по существу будет AST языка уровня байт-кода, с которого двоичное кодирование является просто переводом 1-1? Это все так увлекательно, я даже не догадывался, что смогу легко увидеть, на что разбивает компилятор erlang.

Большое спасибо

Ответы [ 2 ]

12 голосов
/ 26 февраля 2009

хорошо, поэтому я покопался в исходном коде компилятора, чтобы найти ответ, и, к моему удивлению, файл asm, созданный с помощью параметра 'S' для функции compile: file (), фактически используется как есть (file: consult ( )) и затем кортежи проверяются один за другим для дальнейших действий (строка 661 - beam_consult_asm (St) -> - compile.erl). далее там есть сгенерированная таблица отображения (папка компиляции источника erlang), которая показывает серийный номер каждой метки байт-кода, и я предполагаю, что это используется для генерации действительной двоичной сигнатуры байт-кода. качественный товар. но вы просто должны любить функцию consult (), вы можете почти иметь синтаксис типа lispy для случайного языка и избежать необходимости полностью разбирать синтаксический анализатор / лексер и просто просматривать исходный код в компиляторе и делать с ним что-то ... код в качестве данных данных в виде кода ...

5 голосов
/ 08 января 2012

Компилятор имеет так называемый компилятор сопоставления с шаблоном , который возьмет шаблон и скомпилирует его до того, что по сути представляет собой последовательность ветвей, переключателей и тому подобного. Код для Erlang находится в v3_kernel.erl в компиляторе. Это использует Саймон Пейтон Джонс, "Реализация функциональных Языки программирования ", доступны онлайн на

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

Еще одна достойная статья - Питер Сестофт,

http://www.itu.dk/~sestoft/papers/match.ps.gz

, который выводит компилятор сопоставления с образцом путем проверки частичной оценки более простой системы. Это может быть легче читать, особенно если вы знаете ML.

Основная идея заключается в том, что если у вас есть, скажите:

% 1
f(a, b) ->
% 2
f(a, c) ->
% 3
f(b, b) ->
% 4
f(b, c) ->

Предположим, теперь у нас есть звонок f(X, Y). Скажите X = a. Тогда только 1 и 2 применимы. Итак, мы проверяем Y = b, а затем Y = c. Если, с другой стороны, X /= a, то мы знаем, что можем пропустить 1 и 2 и начать тестирование 3 и 4. Ключ в том, что если что-то не совпадает не , это нам что-то говорит о том, где матч может продолжаться, а также когда мы делаем матч. Это набор ограничений, которые мы можем решить, протестировав.

Компиляторы сопоставления с образцом стремятся оптимизировать количество тестов, чтобы их можно было сделать как можно меньше. Статически типизированный язык имеет здесь некоторые преимущества, поскольку они могут знать, что:

-type foo() :: a | b | c.

и затем, если у нас есть

-spec f(foo() -> any().
f(a) ->
f(b) ->
f(c) ->

и мы не соответствовали f(a), f(b), тогда f (c) должно соответствовать. Эрланг должен проверить, а затем потерпеть неудачу, если он не совпадает.

...