erlang bytecode bytecode-manipulation beam

código de bytes erlang BEAM



bytecode bytecode-manipulation (2)

El compilador tiene el llamado compilador de coincidencia de patrón que tomará un patrón y lo compilará en lo que es esencialmente una serie de ramas, interruptores y demás. El código para Erlang está en v3_kernel.erl en el compilador. Utiliza Simon Peyton Jones, "La implementación de lenguajes de programación funcionales", disponible en línea en

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

Otro papel digno es el de Peter Sestoft,

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

que deriva un compilador de coincidencia de patrones mediante la inspección parcial de un sistema más simple. Puede ser una lectura más fácil, especialmente si sabes ML.

La idea básica es que si tienes, di:

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

Supongamos que ahora tenemos una llamada f(X, Y) . Di X = a . Entonces solo 1 y 2 son aplicables. Entonces verificamos Y = b y luego Y = c . Si, por otra parte, X /= a entonces sabemos que podemos omitir 1 y 2 y comenzar las pruebas 3 y 4. La clave es que si algo no coincide, nos dice algo sobre dónde puede continuar el partido y cuándo. hacer coincidir Es un conjunto de restricciones que podemos resolver mediante pruebas.

Los compiladores de coincidencia de patrones buscan optimizar el número de pruebas para que haya la menor cantidad posible antes de que tengamos una conclusión. El lenguaje tipificado estáticamente tiene algunas ventajas aquí, ya que pueden saber que:

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

y luego si tenemos

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

y no coincidimos con f(a), f(b) entonces f (c) debe coincidir. Erlang tiene que verificar y luego fallar si no coincide.

Bueno, espero que no esté rompiendo alguna regla de spam aquí con esto. Acabo de hacer una pregunta sobre cómo el compilador de Erlang implementa la coincidencia de patrones y obtuve algunas respuestas excelentes, una de las cuales es el código de bytes compilado (obtenido con un parámetro pasado a la directiva 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}}

todo es simplemente tuplas erlang. Esperaba alguna cosa binaria críptica, supongo que no. así que estoy preguntando por impulso aquí (podría ver la fuente del compilador pero hacer preguntas siempre termina mejor con una visión extra), ¿cómo se traduce esta salida en el nivel binario?

diga {test,is_tuple,{f,3},[{x,0}]} por ejemplo. Supongo que esta es una instrucción, llamada ''prueba'' ... de todos modos, entonces esta salida sería esencialmente el AST del lenguaje de nivel de bytecode, desde el cual la codificación binaria es solo una traducción 1-1. Todo esto es tan emocionante, no tenía idea de que puedo ver fácilmente en qué consiste el compilador de Erlang.

muchas gracias


ok, busqué en el código fuente del compilador para encontrar la respuesta, y para mi sorpresa, el archivo asm producido con el parámetro ''S'' en la función compile: file () se consulta como está (file: consult ()) y luego se comprueban las tuplas una por una para una acción adicional (línea 661 - beam_consult_asm (St) -> - compile.erl). más adelante hay una tabla de mapeo generada allí (carpeta de compilación de la fuente erlang) que muestra cuál es el número de serie de cada etiqueta de bytecode, y supongo que se usa para generar la firma binaria real del bytecode. Buena cosa. pero simplemente debes amar la función consult (), puedes tener una sintaxis de tipo lispy para un lenguaje aleatorio y evitar la necesidad de un analizador / lexer por completo y solo consultar el código fuente en el compilador y hacer cosas con él ... código como datos de datos como código ...