-module(stacky). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([frame_by_stack_index/2, size/1, erlang_module_name/1, qualified_module_name/1, stack_index/1, function_name/1, function_arity/1, erlang_file_name/1, erlang_line_number/1, frame_to_string/1, trace_to_string/1, print_frame/1, print_frame_with/2, print_trace/1, print_trace_with/2, frame/2, trace/0, main/0]). -export_type([stack_trace/0, stack_frame/0, stack_index/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, stack_index(), erlang_module_name(), function_name(), function_arity(), erlang_file_name(), erlang_line_number()}. -type stack_index() :: {stack_index, integer()}. -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 frame_by_stack_index(stack_trace(), integer()) -> stack_frame(). frame_by_stack_index(Stack_trace, Index) -> {stack_trace, Stack_trace@1} = Stack_trace, case begin _pipe = Stack_trace@1, gleam@list:find( _pipe, fun(Item) -> erlang:element(2, Item) =:= {stack_index, Index} end ) end of {ok, Stackframe} -> Stackframe; {error, _} -> Panic_msg = <<<<"No stack frame with stack index "/utf8, (gleam@int:to_string(Index))/binary>>/binary, "."/utf8>>, erlang:error(#{gleam_error => panic, message => Panic_msg, module => <<"stacky"/utf8>>, function => <<"frame_by_stack_index"/utf8>>, line => 76}) end. -spec size(stack_trace()) -> integer(). size(Stack_trace) -> {stack_trace, Stack_trace@1} = Stack_trace, _pipe = Stack_trace@1, erlang:length(_pipe). -spec gleam_module_file(binary()) -> binary(). gleam_module_file(Qualified_module_name) -> <<<<"src/"/utf8, Qualified_module_name/binary>>/binary, ".gleam"/utf8>>. -spec erlang_module_name(stack_frame()) -> binary(). erlang_module_name(Stack_frame) -> {erlang_module_name, Erlang_module_name} = erlang:element(3, Stack_frame), Erlang_module_name. -spec qualified_module_name(stack_frame()) -> binary(). qualified_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 => <<"qualified_module_name"/utf8>>, line => 235}) 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 => <<"qualified_module_name"/utf8>>, line => 236}) 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 {false, true} -> _pipe@5 = Erlang_module_name, gleam@string:replace(_pipe@5, <<"@"/utf8>>, <<"/"/utf8>>); {_, _} -> Erlang_module_name end. -spec stack_index(stack_frame()) -> integer(). stack_index(Stack_frame) -> {stack_index, Stack_index} = erlang:element(2, Stack_frame), Stack_index. -spec function_name(stack_frame()) -> binary(). function_name(Stack_frame) -> {function_name, Function_name} = erlang:element(4, Stack_frame), Function_name. -spec function_arity(stack_frame()) -> integer(). function_arity(Stack_frame) -> {function_arity, Function_arity} = erlang:element(5, Stack_frame), Function_arity. -spec erlang_file_name(stack_frame()) -> binary(). erlang_file_name(Stack_frame) -> {erlang_file_name, Erlang_file_name} = erlang:element(6, 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(7, Stack_frame), Erlang_line_number. -spec frame_to_string(stack_frame()) -> binary(). frame_to_string(Stack_frame) -> Stack_index = begin _pipe = Stack_frame, _pipe@1 = stack_index(_pipe), gleam@int:to_string(_pipe@1) end, Erlang_module_name = begin _pipe@2 = Stack_frame, erlang_module_name(_pipe@2) end, Qualified_module_name = begin _pipe@3 = Stack_frame, qualified_module_name(_pipe@3) end, Function_name = begin _pipe@4 = Stack_frame, function_name(_pipe@4) end, Function_arity = begin _pipe@5 = Stack_frame, _pipe@6 = function_arity(_pipe@5), gleam@int:to_string(_pipe@6) end, Erlang_file_name = begin _pipe@7 = Stack_frame, erlang_file_name(_pipe@7) end, Erlang_line_number = begin _pipe@8 = Stack_frame, _pipe@9 = erlang_line_number(_pipe@8), gleam@int:to_string(_pipe@9) end, Line = <<<<<<"#"/utf8, " "/utf8>>/binary, (begin _pipe@10 = Stack_index, gleam@string:pad_left(_pipe@10, 2, <<"0"/utf8>>) end)/binary>>/binary, "\t"/utf8>>, Line@1 = case Qualified_module_name /= Erlang_module_name of true -> Gleam_module_file = begin _pipe@11 = Qualified_module_name, gleam_module_file(_pipe@11) end, <<<<<>/binary, "() of "/utf8>>/binary, Gleam_module_file/binary>>; false -> <<<<<<<<<>/binary, ":"/utf8>>/binary, Function_name/binary>>/binary, "/"/utf8>>/binary, Function_arity/binary>> end, <> -> <<""/utf8>>; _ -> <<<<<<"\n \tin "/utf8, Erlang_file_name/binary>>/binary, ":"/utf8>>/binary, Erlang_line_number/binary>> end)/binary>>. -spec trace_to_string(stack_trace()) -> binary(). trace_to_string(Stack_frame) -> {stack_trace, Stack_trace} = Stack_frame, _pipe = Stack_trace, _pipe@2 = gleam@list:map( _pipe, fun(Stack_frame@1) -> _pipe@1 = Stack_frame@1, frame_to_string(_pipe@1) end ), gleam@string:join(_pipe@2, <<"\n"/utf8>>). -spec print_frame(stack_frame()) -> nil. print_frame(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 print_frame_with(stack_frame(), any()) -> nil. print_frame_with(Stack_frame, C) -> gleam_erlang_ffi:sleep(100), _pipe = Stack_frame, _pipe@1 = frame_to_string(_pipe), gleam@io:print(_pipe@1), gleam@io:print(<<"\n \tcontext: "/utf8>>), pprint:debug(C), gleam_erlang_ffi:sleep(100). -spec print_trace(stack_trace()) -> nil. print_trace(Stack_trace) -> gleam_erlang_ffi:sleep(100), _pipe = Stack_trace, _pipe@1 = trace_to_string(_pipe), gleam@io:println(_pipe@1), gleam_erlang_ffi:sleep(100). -spec print_trace_with(stack_trace(), any()) -> nil. print_trace_with(Stack_trace, C) -> gleam_erlang_ffi:sleep(100), _pipe = Stack_trace, _pipe@1 = trace_to_string(_pipe), gleam@io:print(_pipe@1), gleam@io:print(<<"\nwith context: "/utf8>>), pprint:debug(C), gleam_erlang_ffi:sleep(100). -spec list_at(list(GRT), integer()) -> {ok, GRT} | {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(Stack_trace, Index) -> {stack_trace, Stack_trace@1} = Stack_trace, case begin _pipe = Stack_trace@1, list_at(_pipe, Index) end of {ok, Stackframe} -> Stackframe; {error, _} -> Panic_msg = <<<<"No stack frame at list 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 => 56}) end. -spec trace() -> stack_trace(). trace() -> Erlang_stack_trace = stacky_ffi:stacky_erlang_stack_trace(), _pipe = Erlang_stack_trace, _pipe@1 = gleam@list:map( _pipe, fun(Frame) -> {Stack_index, {Erlang_module_name, Function_name, Function_arity, Erlang_file_name, Erlang_line_number}} = Frame, {stack_frame, {stack_index, Stack_index}, {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 --module stacky/internal/example\n"/utf8>> ), gleam@io:println(<<"...or...\n"/utf8>>), gleam@io:println( <<" gleam run --module stacky/internal/sub_dir/example_in_sub_dir\n"/utf8>> ), gleam@io:println(<<"...or...\n"/utf8>>), gleam@io:println(<<" gleam run --module my_gleam_module\n"/utf8>>).