2016-11-23 19 views
5

Tôi muốn xem điều gì sẽ xảy ra khi elixir được chuyển thành các tệp dầm. Có cách nào để in trong bảng điều khiển hoặc trong một tệp được dịch như thế nào không? Tôi muốn biết module này sẽ trông như thế nào trong erlang.Elixir vào chuyển đổi Erlang

Tôi đã suy nghĩ nếu có một chế độ gỡ lỗi của elixir, sẽ xuất ra bất kỳ điều nào ở trên.

Cụ thể hơn tôi có ví dụ này:

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

Đoạn mã trên đặt ra một cảnh báo, đó là understanable xem xét những gì tôi đã thực hiện. Về cơ bản tôi muốn hiểu thêm một chút về những gì đang xảy ra.

+0

Nếu bạn đang cố gắng nhận 'a' chỉ, bạn sẽ phải chuyển' 0' làm thông số thứ hai.Nếu bạn không vượt qua tham số thứ hai, bạn sẽ nhận được 'a + 2' –

+1

Nếu tôi hiểu bạn đúng, thì bạn đã sai. Nếu bạn gọi 'Test.t1 (0)' thì đầu ra là '0', nhưng nếu bạn gọi' Test.t1 (0, 4) 'thì kết quả là' 4'. Về cơ bản mỗi khi bạn gọi hàm với một đối số, bạn sẽ gọi hàm đầu tiên. Btw, tôi đang trên elixir 1.3.4 – ipinak

Trả lời

8

Trước tiên, bạn cần phải biên dịch các module Elixir vào một tập tin .beam:

$ 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 

này sẽ tạo ra Elixir.Test.beam. Sau đó, bạn có thể dịch ngược này .beam để Erlang nguồn bằng cách sử dụng sau đây escript (Tôi sao chép này từ một số câu trả lời ở đây trên Stackoverflow một trong khi trước đây. .):

$ 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))]). 

Sau đó chạy 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

Toàn bộ nội dung có thể dễ dàng thực hiện bên trong 'IEx', xem câu trả lời của tôi. – mudasobwa

+0

Cảm ơn bạn đã trả lời! – ipinak

+0

@mudasobwa yep, nhưng tôi chủ yếu sử dụng điều này với các dự án Mix và dễ dàng hơn để thực hiện điều đó từ dòng lệnh cho điều đó, ví dụ: (với một bí danh) 'decompile-beam _build/dev/lib/my_app/ebin/Elixir.MyApp.User.beam'. – Dogbert

4

này có lẽ nên được nhiều hơn một bình luận cho @ Dogbert của câu trả lời ở trên, nhưng tôi sẽ gửi nó như một câu trả lời riêng biệt vì lợi ích của định dạng.

Một không cần phải tạo ra .ex tập tin và gọi trình biên dịch vào chúng để sản xuất dầm:

{: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) 

bây giờ bạn có thể có một tập tin chùm bằng văn bản (chúng tôi có nó được lưu trữ trong biến bytecode bằng cách này .)

NB:.beam_lib:chunks/2 công trình khi và chỉ chùm chứa thông tin gỡ lỗi mã hóa (dầm elixir theo mặc định làm)

Ngoài ra, bạn không cần phải ghi decompiled đang erlang, bạn có thể chỉ đơn giản là vượt qua một nhị phân đó, trực tiếp trong Elixir:

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

Để trích xuất mã riêng của mình:

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

Bây giờ code chứa mã , cần đủ để kiểm tra, nhưng bạn vẫn được tự do sử dụng các công cụ xây dựng erlang:

code |> :erl_syntax.form_list 

hoặc:

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

Sau này sẽ cung cấp cho bạn charlist nhị phân, chứa mã erlang, chính xác như trong câu trả lời @ Dogbert của. Sử dụng IO.puts để xuất.

+0

Cảm ơn bạn đã trả lời! – ipinak

Các vấn đề liên quan