Skip to content

Instantly share code, notes, and snippets.

@habibutsu
Created March 25, 2016 19:01
Show Gist options
  • Save habibutsu/20ef5bdab57c9730da4f to your computer and use it in GitHub Desktop.
Save habibutsu/20ef5bdab57c9730da4f to your computer and use it in GitHub Desktop.
Erlang: eval & compile
-module(test).
-compile([export_all]).
-links([
"https://github.com/efcasado/forms",
"https://github.com/matwey/pybeam",
"https://gist.github.com/kuenishi/3183043",
"https://github.com/hypernumbers/LuvvieScript",
"https://github.com/erlang/otp/blob/OTP-18.2/lib/compiler/src/genop.tab",
"http://gomoripeti.github.io/beam_by_example/",
"https://www.it.uu.se/research/group/hipe/cerl/doc/core_erlang-1.0.3.pdf"
]).
eval_form() ->
InString = [
"-module(foo).",
"-export([baz/0]).",
"baz() -> A = 1, L = [1,2,3], M = #{}, {L,M}."
],
ListAbsForm = lists:foldl(
fun(String, Acc) ->
io:format("%%% Input string: ~n~s~n~n", [String]),
{ok, Tokens, _} = erl_scan:string(String),
io:format("%%% Tokens :: tokens() ~n~p~n~n", [Tokens]),
{ok, AbsForm} = erl_parse:parse_form(Tokens),
io:format("%%% AbsForm :: abstract_form() ~n~p~n~n", [AbsForm]),
{ok, CoreTokens, _Pos} = core_scan:string(String),
io:format("Core: ~p~n", [core_parse:parse(CoreTokens)]),
Acc ++ [AbsForm]
end,
[], InString),
% debug_info - for ability to decompile
{ok, foo, CompiledData, Warnings} = compile:forms(
ListAbsForm, [return, verbose,report_errors, report_warnings, debug_info]),
io:format("% Warnings: ~p~n", [Warnings]),
io:format("% Compiled module: ~p~n", [CompiledData]),
io:format("% Core representation: ~n~p~n",[
compile:forms(
ListAbsForm, [to_core, binary])
]),
io:format("% Assembly representation: ~n~p~n",[
compile:forms(
ListAbsForm, ['S', binary])
]),
code:load_binary(foo, "nofile", CompiledData),
io:format("Result: ~p~n", [foo:baz()]),
% io:format("disassemble: ~p~n", [erts_debug:disassemble({foo,baz,0})]),
%% will be created 'foo.dis'
% erts_debug:df(foo),
decompile(CompiledData),
ok.
eval_expr() ->
String = "L = [1,2,3], M = #{}, {L,M}.",
io:format("% Input string: ~n~s~n~n", [String]),
{ok, Tokens, _} = erl_scan:string(String),
io:format("% Tokens :: tokens() ~n~p~n~n", [Tokens]),
{ok, ListAbsExpr} = erl_parse:parse_exprs(Tokens),
io:format("% ListAbsExpr :: [abstract_expr()] ~n~p~n~n", [ListAbsExpr]),
io:format("% Result of erl_eval:expr(AbsExpr .. ~n"),
Result = lists:foldl(
fun(AbsExpr, Bindings) ->
{value, Value, NewBindings} = erl_eval:expr(AbsExpr, Bindings, none, none, none),
io:format("Reduce: ~p~n", [Value]),
NewBindings
end,
orddict:new(),
ListAbsExpr),
io:format("Result: ~p~n", [Result]),
ok.
decompile(BeamFile) ->
io:format("%% Decompile~n"),
{ok, {_Module, [ChunkData]}} = beam_lib:chunks(BeamFile,[abstract_code]),
{abstract_code, AbstCode} = ChunkData,
% AbstCode :: abst_code()
{AbstVersion, Forms} = AbstCode,
io:format("% Version: ~n~s~n",[AbstVersion]),
io:format("% Forms: ~n~p~n", [Forms]),
io:format("% Restore forms: ~n~s~n", [erl_prettypr:format(erl_syntax:form_list(Forms))]).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment