Hi, everyone, I’m to elixir and have prior experience with python.
# I try this simple expression in iex.
# Seems that elixir is the same as python as a strong typed language.
iex(5)> 1+"1"
** (ArithmeticError) bad argument in arithmetic expression: 1 + "1"
:erlang.+(1, "1")
iex:5: (file)
# In python, I can use the builtin lib to see the compiled bytecode.
# Are there any similar tools in elixir?
>>> import dis
>>> dis.dis("1+'1'")
1 0 LOAD_CONST 0 (1)
2 LOAD_CONST 1 ('1')
4 BINARY_ADD
6 RETURN_VALUE
You can use quote
to see the AST for a given statement:
$ iex
Erlang/OTP 25 [erts-13.2.2.7] [source] [64-bit] [smp:20:20] [ds:20:20:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.15.7) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> quote do 1+"1" end
{:+, [context: Elixir, imports: [{1, Kernel}, {2, Kernel}]], [1, "1"]}
1 Like
Yes I try it and can get the AST tree of elixir code.
But I want to see the low-level BEAM bytecode.
# foo.ex
x=1+1
IO.puts "x=#{x}"
# I tried to use elixirc to compile foo.ex into BEAM file.
# But got nothing in current directory, except foo.ex.
# Instead elixirc seems to run the file directly.
# Where's the output file?
> elixirc ./foo.ex --verbose
x=2
Compiling foo.ex
> ls
foo.ex
# I also tried the `c` function in iex.
# Seems the same as elixirc.
$ iex
Erlang/OTP 27 [erts-15.1.2] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.17.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> c("./foo.ex")
x=2
[]
Compiled BEAM code can’t exist outside of modules. Throw it in a module and you can see the bite code:
defmodule Foo do
def test do
1 + 1
end
end
Then you’ll get .beam
file with elixirc
. I don’t think it’s going to be what you’re looking for but maybe?
1 Like
Yes I put the code into module, and it compiled.
Finally I get what I want.
Still a lot to learn to fully understand the bytecode, but just made a good start.
Thanks, everyone!
# foo.ex
defmodule Foo do
def foox do
123+"456"
end
end
> elixirc foo.ex --verbose
Compiling foo.ex
> ls
Elixir.Foo.beam foo.ex
$ iex
iex> Foo # iex automatically loads the BEAM file for us.
Foo
iex> :beam_lib.chunks(Foo, [:abstract_code])
# Output a quite long code.
# But at the end we can find the bytecode of `foox` method.
{:function, 2, :foox, 0,
[
{:clause, 2, [], [],
[
{:op, 3, :+, {:integer, 3, 123},
{:bin, 3,
[{:bin_element, 3, {:string, 3, ~c"456"}, :default, :default}]}}
]}
]}
2 Likes
You might also be interested in GitHub - hrzndhrn/beam_file: BeamFile - A peek into the BEAM file which is a convenience wrapper for :beam_lib
.
Here is an example use case from mix_install_examples/beam_file.exs at main · wojtekmach/mix_install_examples · GitHub
Mix.install([:beam_file])
defmodule MyServer do
use GenServer
def init(_) do
{:ok, nil}
end
end
|> BeamFile.elixir_code!()
|> IO.puts()
7 Likes