-module(gleeam_code@internal@codegen).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleeam_code/internal/codegen.gleam").
-export([generate_solution/5, extract_outputs/1, format_gleam_value/1, format_gleam_value_typed/2, generate_test/4]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(false).
-file("src/gleeam_code/internal/codegen.gleam", 43).
?DOC(false).
-spec generate_imports(gleeam_code@internal@spec_parser:function_spec()) -> binary().
generate_imports(Spec) ->
Needs_tree = gleeam_code@internal@spec_parser:uses_tree_node(Spec),
Needs_list = gleeam_code@internal@spec_parser:uses_list_node(Spec),
case Needs_tree orelse Needs_list of
false ->
<<""/utf8>>;
true ->
Option_import = <<"\nimport gleam/option.{type Option, None, Some}\n"/utf8>>,
Type_imports = case {Needs_tree, Needs_list} of
{true, true} ->
<<"import types.{type TreeNode, TreeNode, type ListNode, ListNode}\n"/utf8>>;
{true, false} ->
<<"import types.{type TreeNode, TreeNode}\n"/utf8>>;
{false, true} ->
<<"import types.{type ListNode, ListNode}\n"/utf8>>;
{false, false} ->
<<""/utf8>>
end,
<<Option_import/binary, Type_imports/binary>>
end.
-file("src/gleeam_code/internal/codegen.gleam", 6).
?DOC(false).
-spec generate_solution(
binary(),
binary(),
binary(),
binary(),
gleeam_code@internal@spec_parser:function_spec()
) -> binary().
generate_solution(Frontend_id, Title, Title_slug, Difficulty, Spec) ->
Header = <<<<<<<<<<<<<<<<"//// Problem "/utf8, Frontend_id/binary>>/binary,
": "/utf8>>/binary,
Title/binary>>/binary,
"\n//// https://leetcode.com/problems/"/utf8>>/binary,
Title_slug/binary>>/binary,
"/\n//// Difficulty: "/utf8>>/binary,
Difficulty/binary>>/binary,
"\n"/utf8>>,
Imports = generate_imports(Spec),
Params_str = begin
_pipe = erlang:element(3, Spec),
_pipe@1 = gleam@list:map(
_pipe,
fun(P) ->
<<<<(erlang:element(2, P))/binary, ": "/utf8>>/binary,
(erlang:element(3, P))/binary>>
end
),
gleam@string:join(_pipe@1, <<", "/utf8>>)
end,
Func = <<<<<<<<<<<<"\npub fn "/utf8, (erlang:element(2, Spec))/binary>>/binary,
"("/utf8>>/binary,
Params_str/binary>>/binary,
") -> "/utf8>>/binary,
(erlang:element(4, Spec))/binary>>/binary,
" {\n todo\n}\n"/utf8>>,
<<<<Header/binary, Imports/binary>>/binary, Func/binary>>.
-file("src/gleeam_code/internal/codegen.gleam", 123).
?DOC(false).
-spec pad_outputs(list(binary()), integer()) -> list(binary()).
pad_outputs(Outputs, Target_len) ->
Current_len = erlang:length(Outputs),
case Current_len >= Target_len of
true ->
Outputs;
false ->
lists:append(
Outputs,
gleam@list:repeat(<<"todo"/utf8>>, Target_len - Current_len)
)
end.
-file("src/gleeam_code/internal/codegen.gleam", 151).
?DOC(false).
-spec take_until_delimiter(list(binary()), binary()) -> binary().
take_until_delimiter(Chars, Acc) ->
case Chars of
[] ->
Acc;
[<<"\n"/utf8>> | _] ->
Acc;
[<<"<"/utf8>> | _] ->
Acc;
[C | Rest] ->
take_until_delimiter(Rest, <<Acc/binary, C/binary>>)
end.
-file("src/gleeam_code/internal/codegen.gleam", 160).
?DOC(false).
-spec decode_html_entities(binary()) -> binary().
decode_html_entities(S) ->
_pipe = S,
_pipe@1 = gleam@string:replace(_pipe, <<"""/utf8>>, <<"\""/utf8>>),
_pipe@2 = gleam@string:replace(_pipe@1, <<"&"/utf8>>, <<"&"/utf8>>),
_pipe@3 = gleam@string:replace(_pipe@2, <<"<"/utf8>>, <<"<"/utf8>>),
_pipe@4 = gleam@string:replace(_pipe@3, <<">"/utf8>>, <<">"/utf8>>),
_pipe@5 = gleam@string:replace(_pipe@4, <<"'"/utf8>>, <<"'"/utf8>>),
gleam@string:replace(_pipe@5, <<" "/utf8>>, <<" "/utf8>>).
-file("src/gleeam_code/internal/codegen.gleam", 145).
?DOC(false).
-spec extract_output_value(binary()) -> binary().
extract_output_value(S) ->
_pipe = take_until_delimiter(gleam@string:to_graphemes(S), <<""/utf8>>),
_pipe@1 = gleam@string:trim(_pipe),
decode_html_entities(_pipe@1).
-file("src/gleeam_code/internal/codegen.gleam", 135).
?DOC(false).
-spec do_extract_outputs(binary(), list(binary())) -> list(binary()).
do_extract_outputs(Content, Acc) ->
case gleam@string:split_once(Content, <<"<strong>Output:</strong>"/utf8>>) of
{error, _} ->
lists:reverse(Acc);
{ok, {_, After}} ->
Value = extract_output_value(gleam@string:trim_start(After)),
do_extract_outputs(After, [Value | Acc])
end.
-file("src/gleeam_code/internal/codegen.gleam", 131).
?DOC(false).
-spec extract_outputs(binary()) -> list(binary()).
extract_outputs(Content) ->
do_extract_outputs(Content, []).
-file("src/gleeam_code/internal/codegen.gleam", 258).
?DOC(false).
-spec split_list_items(binary()) -> list(binary()).
split_list_items(S) ->
gleeam_code@internal@spec_parser:split_params(S).
-file("src/gleeam_code/internal/codegen.gleam", 198).
?DOC(false).
-spec format_tree_value(binary()) -> binary().
format_tree_value(Raw) ->
case Raw of
<<"null"/utf8>> ->
<<"None"/utf8>>;
<<"[]"/utf8>> ->
<<"None"/utf8>>;
<<"["/utf8, _/binary>> ->
Inner = begin
_pipe = Raw,
_pipe@1 = gleam@string:drop_start(_pipe, 1),
gleam@string:drop_end(_pipe@1, 1)
end,
Items = begin
_pipe@2 = split_list_items(Inner),
_pipe@3 = gleam@list:map(
_pipe@2,
fun(Item) ->
V = gleam@string:trim(Item),
case V of
<<"null"/utf8>> ->
<<"None"/utf8>>;
_ ->
<<<<"Some("/utf8, V/binary>>/binary, ")"/utf8>>
end
end
),
gleam@string:join(_pipe@3, <<", "/utf8>>)
end,
<<<<"tree_from_level_order(["/utf8, Items/binary>>/binary,
"])"/utf8>>;
_ ->
Raw
end.
-file("src/gleeam_code/internal/codegen.gleam", 222).
?DOC(false).
-spec format_list_node_value(binary()) -> binary().
format_list_node_value(Raw) ->
case Raw of
<<"null"/utf8>> ->
<<"None"/utf8>>;
<<"[]"/utf8>> ->
<<"None"/utf8>>;
<<"["/utf8, _/binary>> ->
Inner = begin
_pipe = Raw,
_pipe@1 = gleam@string:drop_start(_pipe, 1),
gleam@string:drop_end(_pipe@1, 1)
end,
Items = begin
_pipe@2 = split_list_items(Inner),
_pipe@3 = gleam@list:map(
_pipe@2,
fun(Item) -> gleam@string:trim(Item) end
),
gleam@string:join(_pipe@3, <<", "/utf8>>)
end,
<<<<"list_from_list(["/utf8, Items/binary>>/binary, "])"/utf8>>;
_ ->
Raw
end.
-file("src/gleeam_code/internal/codegen.gleam", 177).
?DOC(false).
-spec format_gleam_value(binary()) -> binary().
format_gleam_value(Raw) ->
format_gleam_value_typed(Raw, <<""/utf8>>).
-file("src/gleeam_code/internal/codegen.gleam", 181).
?DOC(false).
-spec format_gleam_value_typed(binary(), binary()) -> binary().
format_gleam_value_typed(Raw, Type_str) ->
Trimmed = gleam@string:trim(Raw),
case Type_str of
<<"Option(TreeNode)"/utf8>> ->
format_tree_value(Trimmed);
<<"Option(ListNode)"/utf8>> ->
format_list_node_value(Trimmed);
_ ->
case Trimmed of
<<"\""/utf8, _/binary>> ->
Trimmed;
<<"["/utf8, _/binary>> ->
format_gleam_list(Trimmed);
<<"true"/utf8>> ->
<<"True"/utf8>>;
<<"false"/utf8>> ->
<<"False"/utf8>>;
<<"null"/utf8>> ->
<<"None"/utf8>>;
_ ->
Trimmed
end
end.
-file("src/gleeam_code/internal/codegen.gleam", 240).
?DOC(false).
-spec format_gleam_list(binary()) -> binary().
format_gleam_list(S) ->
Inner = begin
_pipe = S,
_pipe@1 = gleam@string:drop_start(_pipe, 1),
gleam@string:drop_end(_pipe@1, 1)
end,
case gleam@string:trim(Inner) of
<<""/utf8>> ->
<<"[]"/utf8>>;
Content ->
Items = begin
_pipe@2 = split_list_items(Content),
_pipe@3 = gleam@list:map(
_pipe@2,
fun(Item) -> format_gleam_value(gleam@string:trim(Item)) end
),
gleam@string:join(_pipe@3, <<", "/utf8>>)
end,
<<<<"["/utf8, Items/binary>>/binary, "]"/utf8>>
end.
-file("src/gleeam_code/internal/codegen.gleam", 170).
?DOC(false).
-spec parse_testcase_input(
binary(),
list(gleeam_code@internal@spec_parser:param())
) -> binary().
parse_testcase_input(Input, Params) ->
Lines = gleam@string:split(Input, <<"\n"/utf8>>),
_pipe = gleam@list:zip(Lines, Params),
_pipe@1 = gleam@list:map(
_pipe,
fun(Pair) ->
format_gleam_value_typed(
erlang:element(1, Pair),
erlang:element(3, erlang:element(2, Pair))
)
end
),
gleam@string:join(_pipe@1, <<", "/utf8>>).
-file("src/gleeam_code/internal/codegen.gleam", 62).
?DOC(false).
-spec generate_test(
binary(),
gleeam_code@internal@spec_parser:function_spec(),
list(binary()),
list(binary())
) -> binary().
generate_test(Module_path, Spec, Inputs, Outputs) ->
Import_line = <<<<"import "/utf8, Module_path/binary>>/binary,
"/solution\n"/utf8>>,
Needs_tree = gleeam_code@internal@spec_parser:uses_tree_node(Spec),
Needs_list = gleeam_code@internal@spec_parser:uses_list_node(Spec),
Extra_imports = case Needs_tree orelse Needs_list of
false ->
<<""/utf8>>;
true ->
Option_import = <<"import gleam/option.{None, Some}\n"/utf8>>,
Types_import = case {Needs_tree, Needs_list} of
{true, true} ->
<<"import types.{tree_from_level_order, list_from_list}\n"/utf8>>;
{true, false} ->
<<"import types.{tree_from_level_order}\n"/utf8>>;
{false, true} ->
<<"import types.{list_from_list}\n"/utf8>>;
{false, false} ->
<<""/utf8>>
end,
<<Option_import/binary, Types_import/binary>>
end,
Padded_outputs = pad_outputs(Outputs, erlang:length(Inputs)),
Pairs = gleam@list:zip(Inputs, Padded_outputs),
Uses_nodes = Needs_tree orelse Needs_list,
Tests = begin
_pipe = gleam@list:index_map(
Pairs,
fun(Pair, Idx) ->
Example_num = erlang:integer_to_binary(Idx + 1),
Args = parse_testcase_input(
erlang:element(1, Pair),
erlang:element(3, Spec)
),
Expected = format_gleam_value_typed(
erlang:element(2, Pair),
erlang:element(4, Spec)
),
case Uses_nodes of
true ->
<<<<<<<<<<<<<<<<"\npub fn example_"/utf8,
Example_num/binary>>/binary,
"_test() {\n let expected = "/utf8>>/binary,
Expected/binary>>/binary,
"\n let result = solution."/utf8>>/binary,
(erlang:element(2, Spec))/binary>>/binary,
"("/utf8>>/binary,
Args/binary>>/binary,
")\n let assert True = expected == result\n}\n"/utf8>>;
false ->
<<<<<<<<<<<<<<<<"\npub fn example_"/utf8,
Example_num/binary>>/binary,
"_test() {\n let assert "/utf8>>/binary,
Expected/binary>>/binary,
" = solution."/utf8>>/binary,
(erlang:element(2, Spec))/binary>>/binary,
"("/utf8>>/binary,
Args/binary>>/binary,
")\n}\n"/utf8>>
end
end
),
gleam@string:join(_pipe, <<""/utf8>>)
end,
<<<<Import_line/binary, Extra_imports/binary>>/binary, Tests/binary>>.