-module(stacky). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([erlang_module_name/1, gleam_module_name/1, function_name/1, function_arity/1, erlang_file_name/1, erlang_line_number/1, frame_to_string/1, print_frame_ln/1, frame/2, trace/0, main/0]). -export_type([stack_trace/0, stack_frame/0, erlang_module_name/0, function_name/0, function_arity/0, erlang_file_name/0, erlang_line_number/0]). -type stack_trace() :: {stack_trace, list(stack_frame())}. -type stack_frame() :: {stack_frame, erlang_module_name(), function_name(), function_arity(), erlang_file_name(), erlang_line_number()}. -type erlang_module_name() :: {erlang_module_name, binary()}. -type function_name() :: {function_name, binary()}. -type function_arity() :: {function_arity, integer()}. -type erlang_file_name() :: {erlang_file_name, binary()}. -type erlang_line_number() :: {erlang_line_number, integer()}. -spec erlang_module_name(stack_frame()) -> binary(). erlang_module_name(Stack_frame) -> {erlang_module_name, Erlang_module_name} = erlang:element(2, Stack_frame), Erlang_module_name. -spec gleam_module_name(stack_frame()) -> binary(). gleam_module_name(Stack_frame) -> Erlang_module_name = begin _pipe = Stack_frame, erlang_module_name(_pipe) end, _assert_subject = gleam@regex:from_string(<<"@@"/utf8>>), {ok, Double_at_re} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"stacky"/utf8>>, function => <<"gleam_module_name"/utf8>>, line => 86}) end, _assert_subject@1 = gleam@regex:from_string(<<"@"/utf8>>), {ok, Single_at_re} = case _assert_subject@1 of {ok, _} -> _assert_subject@1; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@1, module => <<"stacky"/utf8>>, function => <<"gleam_module_name"/utf8>>, line => 87}) end, Has_double_ats = begin _pipe@1 = Erlang_module_name, _pipe@2 = gleam@regex:scan(Double_at_re, _pipe@1), gleam@list:is_empty(_pipe@2) end =:= false, Has_ats = begin _pipe@3 = Erlang_module_name, _pipe@4 = gleam@regex:scan(Single_at_re, _pipe@3), gleam@list:is_empty(_pipe@4) end =:= false, case {Has_double_ats, Has_ats} of {true, _} -> <>; {false, false} -> Erlang_module_name; {false, true} -> _pipe@5 = Erlang_module_name, gleam@string:replace(_pipe@5, <<"@"/utf8>>, <<"/"/utf8>>) end. -spec function_name(stack_frame()) -> binary(). function_name(Stack_frame) -> {function_name, Function_name} = erlang:element(3, Stack_frame), Function_name. -spec function_arity(stack_frame()) -> integer(). function_arity(Stack_frame) -> {function_arity, Function_arity} = erlang:element(4, Stack_frame), Function_arity. -spec erlang_file_name(stack_frame()) -> binary(). erlang_file_name(Stack_frame) -> {erlang_file_name, Erlang_file_name} = erlang:element(5, Stack_frame), Erlang_file_name. -spec erlang_line_number(stack_frame()) -> integer(). erlang_line_number(Stack_frame) -> {erlang_line_number, Erlang_line_number} = erlang:element(6, Stack_frame), Erlang_line_number. -spec frame_to_string(stack_frame()) -> binary(). frame_to_string(Stack_frame) -> Erlang_module_name = begin _pipe = Stack_frame, gleam_module_name(_pipe) end, Function_name = begin _pipe@1 = Stack_frame, function_name(_pipe@1) end, Function_arity = begin _pipe@2 = Stack_frame, _pipe@3 = function_arity(_pipe@2), gleam@int:to_string(_pipe@3) end, Erlang_file_name = begin _pipe@4 = Stack_frame, erlang_file_name(_pipe@4) end, Erlang_line_number = begin _pipe@5 = Stack_frame, _pipe@6 = erlang_line_number(_pipe@5), gleam@int:to_string(_pipe@6) end, <<<<<<<<<<<<<<<>/binary, Function_name/binary>>/binary, " - arity: "/utf8>>/binary, Function_arity/binary>>/binary, " - erlang file: "/utf8>>/binary, Erlang_file_name/binary>>/binary, ":"/utf8>>/binary, Erlang_line_number/binary>>. -spec print_frame_ln(stack_frame()) -> nil. print_frame_ln(Stack_frame) -> gleam_erlang_ffi:sleep(100), _pipe = Stack_frame, _pipe@1 = frame_to_string(_pipe), gleam@io:println(_pipe@1), gleam_erlang_ffi:sleep(100). -spec list_at(list(GMJ), integer()) -> {ok, GMJ} | {error, nil}. list_at(List, Index) -> case Index >= 0 of true -> _pipe = List, _pipe@1 = gleam@list:drop(_pipe, Index), gleam@list:first(_pipe@1); false -> {error, nil} end. -spec frame(stack_trace(), integer()) -> stack_frame(). frame(Stacktrace, Index) -> {stack_trace, Stacktrace@1} = Stacktrace, case begin _pipe = Stacktrace@1, list_at(_pipe, Index) end of {ok, Stackframe} -> Stackframe; {error, _} -> Panic_msg = <<<<"No stack frame at index "/utf8, (gleam@int:to_string(Index))/binary>>/binary, "."/utf8>>, erlang:error(#{gleam_error => panic, message => Panic_msg, module => <<"stacky"/utf8>>, function => <<"frame"/utf8>>, line => 73}) end. -spec trace() -> stack_trace(). trace() -> Erlang_stack_trace = stacky_ffi:stacky_erlang_stacktrace(), _pipe = Erlang_stack_trace, _pipe@1 = gleam@list:map( _pipe, fun(Frame) -> {Erlang_module_name, Function_name, Function_arity, Erlang_file_name, Erlang_line_number} = Frame, {stack_frame, {erlang_module_name, Erlang_module_name}, {function_name, Function_name}, {function_arity, Function_arity}, {erlang_file_name, Erlang_file_name}, {erlang_line_number, Erlang_line_number}} end ), {stack_trace, _pipe@1}. -spec main() -> nil. main() -> gleam@io:println(<<"\nFor example stack traces, run:\n"/utf8>>), gleam@io:println(<<" gleam run -m stacky/internal/example\n"/utf8>>), gleam@io:println(<<"...or...\n"/utf8>>), gleam@io:println( <<" gleam run -m stacky/internal/sub_dir/example_in_sub_dir\n"/utf8>> ).