Current section
Files
Jump to
Current section
Files
src/gladvent@internal@cmd@run.erl
-module(gladvent@internal@cmd@run).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([run_command/0, run_all_command/0]).
-export_type([run_err/0, solve_err/0, direction/0, gleam_err/0]).
-type run_err() :: {failed_to_read_input, binary()} |
{failed_to_parse_input, binary()} |
{unregistered, integer()} |
{other, binary()}.
-type solve_err() :: undef | {run_failed, binary()}.
-type direction() :: both.
-type gleam_err() :: {gleam_err,
gleam@erlang@atom:atom_(),
binary(),
binary(),
integer(),
binary(),
gleam@option:option(gleam@dynamic:dynamic_())}.
-spec run_err_to_snag(run_err()) -> snag:snag().
run_err_to_snag(Err) ->
_pipe = case Err of
{unregistered, Day} ->
<<<<<<<<"day"/utf8, " "/utf8>>/binary,
(gleam@int:to_string(Day))/binary>>/binary,
" "/utf8>>/binary,
"unregistered"/utf8>>;
{failed_to_read_input, Input_path} ->
<<"failed to read input file: "/utf8, Input_path/binary>>;
{failed_to_parse_input, Err@1} ->
<<"failed to parse input: "/utf8, Err@1/binary>>;
{other, S} ->
S
end,
snag:new(_pipe).
-spec string_trim(binary(), direction(), binary()) -> binary().
string_trim(S, Dir, Sub) ->
string:trim(S, Dir, unicode:characters_to_list(Sub)).
-spec crash_to_dyn(gleam@erlang:crash()) -> gleam@dynamic:dynamic_().
crash_to_dyn(Err) ->
case Err of
{errored, Dyn} ->
Dyn;
{exited, Dyn} ->
Dyn;
{thrown, Dyn} ->
Dyn
end.
-spec decode_gleam_err() -> fun((gleam@dynamic:dynamic_()) -> {ok, gleam_err()} |
{error, list(gleam@dynamic:decode_error())}).
decode_gleam_err() ->
gleam@dynamic:decode6(
fun(Field@0, Field@1, Field@2, Field@3, Field@4, Field@5) -> {gleam_err, Field@0, Field@1, Field@2, Field@3, Field@4, Field@5} end,
gleam@dynamic:field(
erlang:binary_to_atom(<<"gleam_error"/utf8>>),
fun gleam_erlang_ffi:atom_from_dynamic/1
),
gleam@dynamic:field(
erlang:binary_to_atom(<<"module"/utf8>>),
fun gleam@dynamic:string/1
),
gleam@dynamic:field(
erlang:binary_to_atom(<<"function"/utf8>>),
fun gleam@dynamic:string/1
),
gleam@dynamic:field(
erlang:binary_to_atom(<<"line"/utf8>>),
fun gleam@dynamic:int/1
),
gleam@dynamic:field(
erlang:binary_to_atom(<<"message"/utf8>>),
fun gleam@dynamic:string/1
),
gleam@dynamic:any(
[gleam@dynamic:field(
erlang:binary_to_atom(<<"value"/utf8>>),
gleam@dynamic:optional(fun gleam@dynamic:dynamic/1)
),
fun(_) -> {ok, none} end]
)
).
-spec gleam_err_to_string(gleam_err()) -> binary().
gleam_err_to_string(G) ->
gleam@string:join(
[<<"error:"/utf8>>,
erlang:atom_to_binary(erlang:element(2, G)),
<<"-"/utf8>>,
erlang:element(6, G),
<<"in module"/utf8>>,
erlang:element(3, G),
<<"in function"/utf8>>,
erlang:element(4, G),
<<"at line"/utf8>>,
gleam@int:to_string(erlang:element(5, G)),
begin
_pipe = erlang:element(7, G),
_pipe@1 = gleam@option:map(
_pipe,
fun(Val) ->
<<"with value "/utf8,
(gleam@string:inspect(Val))/binary>>
end
),
gleam@option:unwrap(_pipe@1, <<""/utf8>>)
end],
<<" "/utf8>>
).
-spec crash_to_string(gleam@erlang:crash()) -> binary().
crash_to_string(Err) ->
_pipe = crash_to_dyn(Err),
_pipe@1 = (decode_gleam_err())(_pipe),
_pipe@2 = gleam@result:map(_pipe@1, fun gleam_err_to_string/1),
gleam@result:lazy_unwrap(
_pipe@2,
fun() ->
<<"run failed for some reason: "/utf8,
(gleam@string:inspect(Err))/binary>>
end
).
-spec crash_to_solve_err(gleam@erlang:crash()) -> solve_err().
crash_to_solve_err(Err) ->
_pipe = Err,
_pipe@1 = crash_to_string(_pipe),
{run_failed, _pipe@1}.
-spec do(
integer(),
integer(),
gleam@dict:dict(integer(), {fun((gleam@dynamic:dynamic_()) -> gleam@dynamic:dynamic_()),
fun((gleam@dynamic:dynamic_()) -> gleam@dynamic:dynamic_()),
gleam@option:option(fun((binary()) -> gleam@dynamic:dynamic_()))}),
boolean()
) -> {ok,
{{ok, gleam@dynamic:dynamic_()} | {error, solve_err()},
{ok, gleam@dynamic:dynamic_()} | {error, solve_err()}}} |
{error, run_err()}.
do(Year, Day, Runners, Allow_crash) ->
gleam@result:'try'(
begin
_pipe = Runners,
_pipe@1 = gleam@dict:get(_pipe, Day),
gleam@result:replace_error(_pipe@1, {unregistered, Day})
end,
fun(_use0) ->
{Pt_1, Pt_2, Parse} = _use0,
Input_path = <<<<<<<<"input/"/utf8,
(gleam@int:to_string(Year))/binary>>/binary,
"/"/utf8>>/binary,
(gleam@int:to_string(Day))/binary>>/binary,
".txt"/utf8>>,
gleam@result:'try'(
begin
_pipe@2 = Input_path,
_pipe@3 = simplifile:read(_pipe@2),
_pipe@4 = gleam@result:map(
_pipe@3,
fun(_capture) ->
string_trim(_capture, both, <<"\n"/utf8>>)
end
),
gleam@result:replace_error(
_pipe@4,
{failed_to_read_input, Input_path}
)
end,
fun(Input) ->
Parse@1 = gleam@option:unwrap(
Parse,
fun gleam@dynamic:from/1
),
case Allow_crash of
true ->
Input@1 = Parse@1(Input),
{ok, {{ok, Pt_1(Input@1)}, {ok, Pt_2(Input@1)}}};
false ->
gleam@result:'try'(
begin
_pipe@5 = fun() -> Parse@1(Input) end,
_pipe@6 = gleam_erlang_ffi:rescue(_pipe@5),
_pipe@7 = gleam@result:map_error(
_pipe@6,
fun crash_to_string/1
),
gleam@result:map_error(
_pipe@7,
fun(Field@0) -> {failed_to_parse_input, Field@0} end
)
end,
fun(Input@2) ->
Pt_1@1 = begin
_pipe@8 = fun() -> Pt_1(Input@2) end,
_pipe@9 = gleam_erlang_ffi:rescue(
_pipe@8
),
gleam@result:map_error(
_pipe@9,
fun crash_to_solve_err/1
)
end,
Pt_2@1 = begin
_pipe@10 = fun() -> Pt_2(Input@2) end,
_pipe@11 = gleam_erlang_ffi:rescue(
_pipe@10
),
gleam@result:map_error(
_pipe@11,
fun crash_to_solve_err/1
)
end,
{ok, {Pt_1@1, Pt_2@1}}
end
)
end
end
)
end
).
-spec solve_err_to_string(solve_err()) -> binary().
solve_err_to_string(Solve_err) ->
case Solve_err of
undef ->
<<"function undefined"/utf8>>;
{run_failed, S} ->
S
end.
-spec solve_res_to_string({ok, gleam@dynamic:dynamic_()} | {error, solve_err()}) -> binary().
solve_res_to_string(Res) ->
case Res of
{ok, Res@1} ->
gleam@string:inspect(Res@1);
{error, Err} ->
solve_err_to_string(Err)
end.
-spec collect(
integer(),
{integer(),
{ok,
{{ok, gleam@dynamic:dynamic_()} | {error, solve_err()},
{ok, gleam@dynamic:dynamic_()} | {error, solve_err()}}} |
{error, run_err()}}
) -> binary().
collect(Year, X) ->
Day = gleam@int:to_string(erlang:element(1, X)),
case erlang:element(2, X) of
{ok, {Res_1, Res_2}} ->
<<<<<<<<<<<<<<<<<<"Ran "/utf8, (gleam@int:to_string(Year))/binary>>/binary,
" day "/utf8>>/binary,
Day/binary>>/binary,
":\n"/utf8>>/binary,
" Part 1: "/utf8>>/binary,
(solve_res_to_string(Res_1))/binary>>/binary,
"\n"/utf8>>/binary,
" Part 2: "/utf8>>/binary,
(solve_res_to_string(Res_2))/binary>>;
{error, Err} ->
_pipe = Err,
_pipe@1 = run_err_to_snag(_pipe),
_pipe@2 = snag:layer(
_pipe@1,
<<<<<<"Failed to run "/utf8,
(gleam@int:to_string(Year))/binary>>/binary,
" day "/utf8>>/binary,
Day/binary>>
),
snag:pretty_print(_pipe@2)
end.
-spec collect_async(
integer(),
{integer(),
{ok,
{ok,
{{ok, gleam@dynamic:dynamic_()} | {error, solve_err()},
{ok, gleam@dynamic:dynamic_()} |
{error, solve_err()}}} |
{error, run_err()}} |
{error, binary()}}
) -> binary().
collect_async(Year, X) ->
_pipe = X,
_pipe@1 = gleam@pair:map_second(
_pipe,
fun(_capture) ->
gleam@result:map_error(
_capture,
fun(Field@0) -> {other, Field@0} end
)
end
),
_pipe@2 = gleam@pair:map_second(_pipe@1, fun gleam@result:flatten/1),
collect(Year, _pipe@2).
-spec timeout_flag() -> glint@flag:flag_builder(integer()).
timeout_flag() ->
_pipe = glint@flag:int(),
_pipe@1 = glint@flag:constraint(_pipe, fun(I) -> case I > 0 of
true ->
{ok, nil};
false ->
snag:error(<<"timeout value must greater than zero"/utf8>>)
end end),
glint@flag:description(_pipe@1, <<"Run with specified timeout"/utf8>>).
-spec allow_crash_flag() -> glint@flag:flag_builder(boolean()).
allow_crash_flag() ->
_pipe = glint@flag:bool(),
_pipe@1 = glint@flag:default(_pipe, false),
glint@flag:description(
_pipe@1,
<<"Don't catch exceptions thrown by runners"/utf8>>
).
-spec all_days(gleam@dict:dict(integer(), any())) -> list(integer()).
all_days(Runners) ->
_pipe = Runners,
_pipe@1 = gleam@dict:keys(_pipe),
gleam@list:sort(_pipe@1, fun gleam@int:compare/2).
-spec timing(gleam@dict:dict(binary(), glint@flag:flag())) -> gladvent@internal@cmd:timing().
timing(Flags) ->
_pipe = glint@flag:get_int(Flags, <<"timeout"/utf8>>),
_pipe@1 = gleam@result:map(_pipe, fun(Field@0) -> {ending, Field@0} end),
gleam@result:unwrap(_pipe@1, endless).
-spec run_command() -> glint:command({ok, list(binary())} | {error, snag:snag()}).
run_command() ->
_pipe@2 = (glint:command(
fun(Input) ->
_assert_subject = glint@flag:get_int(
erlang:element(3, Input),
<<"year"/utf8>>
),
{ok, Year} = 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 => <<"gladvent/internal/cmd/run"/utf8>>,
function => <<"run_command"/utf8>>,
line => 253})
end,
gleam@result:then(
gladvent@internal@runners:build_from_days_dir(Year),
fun(Runners) ->
gleam@result:'try'(
glint@flag:get_bool(
erlang:element(3, Input),
<<"allow-crash"/utf8>>
),
fun(Allow_crash) ->
gleam@result:then(
gladvent@internal@parse:days(
erlang:element(2, Input)
),
fun(Days) -> _pipe = Days,
_pipe@1 = gladvent@internal@cmd:exec(
_pipe,
timing(erlang:element(3, Input)),
fun(_capture) ->
do(
Year,
_capture,
Runners,
Allow_crash
)
end,
fun(_capture@1) ->
collect_async(Year, _capture@1)
end
),
{ok, _pipe@1} end
)
end
)
end
)
end
)),
_pipe@3 = glint:flag(_pipe@2, <<"timeout"/utf8>>, timeout_flag()),
_pipe@4 = glint:flag(_pipe@3, <<"allow-crash"/utf8>>, allow_crash_flag()),
_pipe@5 = glint:description(_pipe@4, <<"Run the specified days"/utf8>>),
glint:unnamed_args(_pipe@5, {min_args, 1}).
-spec run_all_command() -> glint:command({ok, list(binary())} |
{error, snag:snag()}).
run_all_command() ->
_pipe@3 = (glint:command(
fun(Input) ->
gleam@result:then(
glint@flag:get_bool(
erlang:element(3, Input),
<<"allow-crash"/utf8>>
),
fun(Allow_crash) ->
_assert_subject = glint@flag:get_int(
erlang:element(3, Input),
<<"year"/utf8>>
),
{ok, Year} = 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 => <<"gladvent/internal/cmd/run"/utf8>>,
function => <<"run_all_command"/utf8>>,
line => 276})
end,
gleam@result:then(
gladvent@internal@runners:build_from_days_dir(Year),
fun(Runners) -> _pipe = Runners,
_pipe@1 = all_days(_pipe),
_pipe@2 = gladvent@internal@cmd:exec(
_pipe@1,
timing(erlang:element(3, Input)),
fun(_capture) ->
do(Year, _capture, Runners, Allow_crash)
end,
fun(_capture@1) ->
collect_async(Year, _capture@1)
end
),
{ok, _pipe@2} end
)
end
)
end
)),
_pipe@4 = glint:flag(_pipe@3, <<"timeout"/utf8>>, timeout_flag()),
_pipe@5 = glint:flag(_pipe@4, <<"allow-crash"/utf8>>, allow_crash_flag()),
glint:description(_pipe@5, <<"Run all registered days"/utf8>>).