-module(gleeam_code@internal@stdlib_extractor).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleeam_code/internal/stdlib_extractor.gleam").
-export([list_exported/1, extract_function/2, extract_functions/2]).
-export_type([function_block/0]).
-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).
-type function_block() :: {function_block, binary(), integer(), binary()}.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 52).
?DOC(false).
-spec collect_multiline_export(list(binary()), binary()) -> binary().
collect_multiline_export(Lines, Acc) ->
case Lines of
[] ->
Acc;
[Line | Rest] ->
New_acc = <<<<Acc/binary, " "/utf8>>/binary,
(gleam@string:trim(Line))/binary>>,
case gleam_stdlib:contains_string(Line, <<"])."/utf8>>) of
true ->
New_acc;
false ->
collect_multiline_export(Rest, New_acc)
end
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 35).
?DOC(false).
-spec find_export_line(list(binary()), binary()) -> binary().
find_export_line(Lines, Acc) ->
case Lines of
[] ->
Acc;
[Line | Rest] ->
Trimmed = gleam@string:trim(Line),
case gleam_stdlib:string_starts_with(Trimmed, <<"-export(["/utf8>>) of
true ->
case gleam_stdlib:contains_string(Trimmed, <<"])."/utf8>>) of
true ->
Trimmed;
false ->
collect_multiline_export(Rest, Trimmed)
end;
false ->
find_export_line(Rest, Acc)
end
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 65).
?DOC(false).
-spec parse_export_entries(binary()) -> list(binary()).
parse_export_entries(Export_line) ->
case gleam@string:split_once(Export_line, <<"["/utf8>>) of
{error, _} ->
[];
{ok, {_, After_bracket}} ->
case gleam@string:split_once(After_bracket, <<"]"/utf8>>) of
{error, _} ->
[];
{ok, {Entries_str, _}} ->
_pipe = Entries_str,
_pipe@1 = gleam@string:split(_pipe, <<","/utf8>>),
_pipe@5 = gleam@list:map(
_pipe@1,
fun(Entry) -> _pipe@2 = Entry,
_pipe@3 = gleam@string:trim(_pipe@2),
_pipe@4 = gleam@string:split(_pipe@3, <<"/"/utf8>>),
(fun(Parts) -> case Parts of
[Name | _] ->
gleam@string:trim(Name);
_ ->
<<""/utf8>>
end end)(_pipe@4) end
),
gleam@list:filter(_pipe@5, fun(S) -> S /= <<""/utf8>> end)
end
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 28).
?DOC(false).
-spec list_exported(binary()) -> list(binary()).
list_exported(Erl_source) ->
_pipe = Erl_source,
_pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>),
_pipe@2 = find_export_line(_pipe@1, <<""/utf8>>),
parse_export_entries(_pipe@2).
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 90).
?DOC(false).
-spec find_block(list(function_block()), binary()) -> {ok, function_block()} |
{error, nil}.
find_block(Blocks, Func_name) ->
gleam@list:find(Blocks, fun(B) -> erlang:element(2, B) =:= Func_name end).
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 136).
?DOC(false).
-spec is_toplevel_func_start(binary()) -> boolean().
is_toplevel_func_start(Line) ->
case gleam@string:to_graphemes(Line) of
[] ->
false;
[First | _] ->
case gleeam_code@internal@char:is_lowercase(First) of
true ->
gleam_stdlib:contains_string(Line, <<"("/utf8>>);
false ->
false
end
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 203).
?DOC(false).
-spec is_file_directive(binary()) -> boolean().
is_file_directive(Line) ->
gleam_stdlib:string_starts_with(Line, <<"-file("/utf8>>).
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 273).
?DOC(false).
-spec is_doc_content(binary()) -> boolean().
is_doc_content(Line) ->
((gleam_stdlib:string_starts_with(Line, <<"\""/utf8>>) andalso gleam_stdlib:string_ends_with(
Line,
<<"\""/utf8>>
))
orelse (Line =:= <<")."/utf8>>))
orelse (gleam_stdlib:string_starts_with(Line, <<" \""/utf8>>) andalso gleam_stdlib:string_ends_with(
Line,
<<"\""/utf8>>
)).
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 323).
?DOC(false).
-spec count_top_level_commas(list(binary()), integer(), integer()) -> integer().
count_top_level_commas(Chars, Depth, Count) ->
case Chars of
[] ->
Count;
[C | Rest] ->
case C of
<<"("/utf8>> ->
count_top_level_commas(Rest, Depth + 1, Count);
<<"["/utf8>> ->
count_top_level_commas(Rest, Depth + 1, Count);
<<"{"/utf8>> ->
count_top_level_commas(Rest, Depth + 1, Count);
<<")"/utf8>> ->
count_top_level_commas(Rest, Depth - 1, Count);
<<"]"/utf8>> ->
count_top_level_commas(Rest, Depth - 1, Count);
<<"}"/utf8>> ->
count_top_level_commas(Rest, Depth - 1, Count);
<<","/utf8>> when Depth =:= 0 ->
count_top_level_commas(Rest, Depth, Count + 1);
_ ->
count_top_level_commas(Rest, Depth, Count)
end
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 310).
?DOC(false).
-spec count_args(binary()) -> integer().
count_args(Args_str) ->
case gleam@string:split_once(Args_str, <<")"/utf8>>) of
{error, _} ->
0;
{ok, {Inside, _}} ->
Trimmed = gleam@string:trim(Inside),
case Trimmed of
<<""/utf8>> ->
0;
_ ->
count_top_level_commas(
gleam@string:to_graphemes(Trimmed),
0,
1
)
end
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 294).
?DOC(false).
-spec parse_function_head(binary()) -> {ok, {binary(), integer()}} |
{error, nil}.
parse_function_head(Line) ->
case gleam@string:split_once(Line, <<"("/utf8>>) of
{error, _} ->
{error, nil};
{ok, {Name, Args_rest}} ->
Trimmed_name = gleam@string:trim(Name),
case Trimmed_name of
<<""/utf8>> ->
{error, nil};
_ ->
Arity = count_args(Args_rest),
{ok, {Trimmed_name, Arity}}
end
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 279).
?DOC(false).
-spec extract_func_info(list(binary())) -> {ok, function_block()} | {error, nil}.
extract_func_info(Lines) ->
case Lines of
[] ->
{error, nil};
[First | _] ->
case parse_function_head(gleam@string:trim(First)) of
{ok, {Name, Arity}} ->
Body = gleam@string:join(Lines, <<"\n"/utf8>>),
{ok, {function_block, Name, Arity, Body}};
{error, _} ->
{error, nil}
end
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 147).
?DOC(false).
-spec finalize_plain_block(list(binary())) -> {ok, function_block()} |
{error, nil}.
finalize_plain_block(Lines) ->
Meaningful = gleam@list:filter(
Lines,
fun(Line) ->
Trimmed = gleam@string:trim(Line),
((((((((Trimmed /= <<""/utf8>>) andalso not gleam_stdlib:string_starts_with(
Trimmed,
<<"-module("/utf8>>
))
andalso not gleam_stdlib:string_starts_with(
Trimmed,
<<"-compile("/utf8>>
))
andalso not gleam_stdlib:string_starts_with(
Trimmed,
<<"-export("/utf8>>
))
andalso not gleam_stdlib:string_starts_with(
Trimmed,
<<"-define("/utf8>>
))
andalso not gleam_stdlib:string_starts_with(
Trimmed,
<<"-if("/utf8>>
))
andalso not gleam_stdlib:string_starts_with(
Trimmed,
<<"-else."/utf8>>
))
andalso not gleam_stdlib:string_starts_with(
Trimmed,
<<"-endif."/utf8>>
))
andalso not gleam_stdlib:string_starts_with(Trimmed, <<"%"/utf8>>)
end
),
case Meaningful of
[] ->
{error, nil};
_ ->
extract_func_info(Meaningful)
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 105).
?DOC(false).
-spec split_plain_blocks(list(binary()), list(binary()), list(function_block())) -> list(function_block()).
split_plain_blocks(Lines, Current_block, Acc) ->
case Lines of
[] ->
case Current_block of
[] ->
lists:reverse(Acc);
_ ->
case finalize_plain_block(lists:reverse(Current_block)) of
{ok, Block} ->
lists:reverse([Block | Acc]);
{error, _} ->
lists:reverse(Acc)
end
end;
[Line | Rest] ->
case is_toplevel_func_start(Line) andalso (Current_block /= []) of
true ->
New_acc = case finalize_plain_block(
lists:reverse(Current_block)
) of
{ok, Block@1} ->
[Block@1 | Acc];
{error, _} ->
Acc
end,
split_plain_blocks(Rest, [Line], New_acc);
false ->
split_plain_blocks(Rest, [Line | Current_block], Acc)
end
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 240).
?DOC(false).
-spec skip_spec_block(binary(), list(binary())) -> list(binary()).
skip_spec_block(First_line, Rest) ->
case gleam_stdlib:string_ends_with(First_line, <<"."/utf8>>) of
true ->
skip_non_code(Rest);
false ->
skip_until_spec_end(Rest)
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 247).
?DOC(false).
-spec skip_until_spec_end(list(binary())) -> list(binary()).
skip_until_spec_end(Lines) ->
case Lines of
[] ->
[];
[Line | Rest] ->
Trimmed = gleam@string:trim(Line),
case gleam_stdlib:string_ends_with(Trimmed, <<"."/utf8>>) of
true ->
skip_non_code(Rest);
false ->
skip_until_spec_end(Rest)
end
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 215).
?DOC(false).
-spec skip_non_code(list(binary())) -> list(binary()).
skip_non_code(Lines) ->
case Lines of
[] ->
[];
[Line | Rest] ->
Trimmed = gleam@string:trim(Line),
case is_file_directive(Trimmed) of
true ->
skip_non_code(Rest);
false ->
case gleam_stdlib:string_starts_with(
Trimmed,
<<"?DOC("/utf8>>
) of
true ->
skip_doc_block(Rest);
false ->
case gleam_stdlib:string_starts_with(
Trimmed,
<<"-spec "/utf8>>
) of
true ->
skip_spec_block(Trimmed, Rest);
false ->
case is_doc_content(Trimmed) of
true ->
skip_non_code(Rest);
false ->
[Line | Rest]
end
end
end
end
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 207).
?DOC(false).
-spec finalize_block(list(binary())) -> {ok, function_block()} | {error, nil}.
finalize_block(Lines) ->
Meaningful = skip_non_code(Lines),
case Meaningful of
[] ->
{error, nil};
_ ->
extract_func_info(Meaningful)
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 167).
?DOC(false).
-spec split_into_blocks(list(binary()), list(binary()), list(function_block())) -> list(function_block()).
split_into_blocks(Lines, Current_block, Acc) ->
case Lines of
[] ->
case Current_block of
[] ->
lists:reverse(Acc);
_ ->
case finalize_block(lists:reverse(Current_block)) of
{ok, Block} ->
lists:reverse([Block | Acc]);
{error, _} ->
lists:reverse(Acc)
end
end;
[Line | Rest] ->
Trimmed = gleam@string:trim(Line),
case is_file_directive(Trimmed) of
true ->
New_acc = case Current_block of
[] ->
Acc;
_ ->
case finalize_block(lists:reverse(Current_block)) of
{ok, Block@1} ->
[Block@1 | Acc];
{error, _} ->
Acc
end
end,
split_into_blocks(Rest, [Line], New_acc);
false ->
split_into_blocks(Rest, [Line | Current_block], Acc)
end
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 97).
?DOC(false).
-spec parse_blocks(binary()) -> list(function_block()).
parse_blocks(Erl_source) ->
Lines = gleam@string:split(Erl_source, <<"\n"/utf8>>),
case gleam_stdlib:contains_string(Erl_source, <<"-file("/utf8>>) of
true ->
split_into_blocks(Lines, [], []);
false ->
split_plain_blocks(Lines, [], [])
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 9).
?DOC(false).
-spec extract_function(binary(), binary()) -> {ok, binary()} | {error, nil}.
extract_function(Erl_source, Func_name) ->
Blocks = parse_blocks(Erl_source),
case find_block(Blocks, Func_name) of
{ok, Block} ->
{ok, erlang:element(4, Block)};
{error, _} ->
{error, nil}
end.
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 20).
?DOC(false).
-spec extract_functions(binary(), list(binary())) -> binary().
extract_functions(Erl_source, Func_names) ->
Blocks = parse_blocks(Erl_source),
_pipe = Func_names,
_pipe@1 = gleam@list:filter_map(
_pipe,
fun(Name) -> find_block(Blocks, Name) end
),
_pipe@2 = gleam@list:map(_pipe@1, fun(B) -> erlang:element(4, B) end),
gleam@string:join(_pipe@2, <<"\n\n"/utf8>>).
-file("src/gleeam_code/internal/stdlib_extractor.gleam", 260).
?DOC(false).
-spec skip_doc_block(list(binary())) -> list(binary()).
skip_doc_block(Lines) ->
case Lines of
[] ->
[];
[Line | Rest] ->
Trimmed = gleam@string:trim(Line),
case Trimmed =:= <<")."/utf8>> of
true ->
skip_non_code(Rest);
false ->
skip_doc_block(Rest)
end
end.