2016-11-23 24 views
5

İksirlerin ışın dosyalarına dönüştüğü zaman ne olacağını görmek istiyorum. Konsolda veya dosyada nasıl çevrildiğini yazdırmanın herhangi bir yolu var mı? Bu modülün erlang'da neye benzediğini bilmek istiyorum.Erlang dönüşümüne Elixir

Yukarıdakilerden herhangi birini çıkaracak bir hata ayıklama modu olup olmadığını düşünüyordum.

defmodule Test do 
    def t1(a), do: a 
    def t1(a, b \\ 2), do: a + b 
end 

Yukarıdaki kod yaptıklarım dikkate understanable bir uyarı, yükseltir:

Daha spesifik ben bu örneği var. Temel olarak, neler olup bittiğini biraz daha anlamak istiyorum.

+0

Yalnızca "a" almaya çalışıyorsanız, ikinci parametre olarak bir "0" iletmeniz gerekir.Eğer ikinci bir parametreyi geçmezseniz, 'a + 2' –

+1

elde edersiniz Eğer doğru anladıysan, yanılıyorsunuz demektir. Eğer Test.t1 (0) 'diyorsanız, çıkış" 0 "dır, fakat eğer" Test.t1 "(0, 4) 'i çağırırsanız, sonuç" 4 "olur. Temel olarak, her defasında bir argüman ile fonksiyonu çağırırsanız, ilkini çağırırsınız. Btw, elixir'dayım 1.3.4 – ipinak

cevap

8

Önce, bir .beam dosyasına İksir modülünü derlemek gerekir: Bu Elixir.Test.beam üretecektir

$ cat test.ex 
defmodule Test do 
    def t1(a), do: a 
    def t1(a, b \\ 2), do: a + b 
end 
$ elixirc test.ex 
warning: this clause cannot match because a previous clause at line 2 always matches 
    test.ex:3 

. Daha sonra, aşağıdaki eskini kullanarak bu .beam'i Erlang kaynağına dönüştürebilirsiniz (Ben bunu bir süre önce Stackoverflow'ta bir kopyasından kopyaladım) Ne yazık ki tam kaynağın yerini tespit edemiyorum ama bu kod this one .):

$ cat decompile.erl 
#!/usr/bin/env escript 

main([BeamFile]) -> 
    {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(BeamFile,[abstract_code]), 
    io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]). 

Sonra çalıştırın:

$ escript decompile.erl Elixir.Test.beam 
-compile(no_auto_import). 

-file("test.ex", 1). 

-module('Elixir.Test'). 

-export(['__info__'/1, t1/1, t1/2]). 

-spec '__info__'(attributes | compile | exports | 
     functions | macros | md5 | module | 
     native_addresses) -> atom() | 
         [{atom(), any()} | 
         {atom(), byte(), integer()}]. 

'__info__'(functions) -> [{t1, 1}, {t1, 2}]; 
'__info__'(macros) -> []; 
'__info__'(info) -> 
    erlang:get_module_info('Elixir.Test', info). 

t1([email protected]) -> [email protected]; 
t1([email protected]) -> t1([email protected], 2). 

t1([email protected], [email protected]) -> [email protected] + [email protected] 
+0

Bütün şeyler, IEx'in içinde kolayca yapılabilir, cevabımı gör. – mudasobwa

+0

Cevabınız için teşekkürler! – ipinak

+0

@mudasobwa yep, ancak bunu çoğunlukla karma projelerle kullanıyorum ve bunun için komut satırından bunu yapmak çok daha kolay, örn. (bir takma ile) 'decompile-beam _build/dev/lib/my_app/ebin/Elixir.MyApp.User.beam'. – Dogbert

4

Bu muhtemelen @ için daha fazla bir yorum olmalıdır Dogbert en yukarıdaki cevabı, ama biçimlendirme uğruna ayrı cevap olarak yayınlamayın olacaktır. Onları ışınlarının üretilmesi için üzerinde

Bir derleyici .ex dosyaları oluşturmak ve çağırmak gerekmez: şimdi (biz bu arada bytecode değişken sakladığınız yazılmış bir kiriş dosyası girmiş olabileceğini

{:module, _, bytecode, _} = 
    defmodule Elixir.Test do 
    def t1(a), do: a 
    def t1(a, b \\ 2), do: a + b 
    end 
# File.write!("Elixir.Test.beam", bytecode) 

.)

Not:.

Ayrıca varsayılan olarak yapmakbeam_lib:chunks/2 çalışır ve sadece ışın şifresiz ayıklama bilgileri içeriyorsa (iksir kirişler), Eğer yazma bozulamaz erlang koduna gerek yoktur, sadece Elixir doğrudan, orada bir ikili geçebilirim:

:beam_lib.chunks(bytecode, [:abstract_code]) 

kodun kendisini ayıklamak için:

{:ok,{_,[abstract_code: {_, code}]}} = 
    bytecode |> :beam_lib.chunks([:abstract_code]) 

Şimdi code kodu içeren Bunu incelemek için yeterli olmalı, ancak hala erlang yapılarını kullanmakta özgürsünüz:

veya: Tam olarak Dogbert cevabı @ olduğu gibi erlang kodu içeren, size ikili charlist verecektir

code |> :erl_syntax.form_list |> :erl_prettypr.format 

ikincisi. Çıktısı almak için IO.puts kullanın.

+0

Cevabınız için teşekkürler! – ipinak