Current section
Files
Jump to
Current section
Files
src/gleamgen@source.erl
-module(gleamgen@source).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleamgen/source.gleam").
-export([get_source_map_doc/1, module_from_string/1, take_until/2, fold/5, get_function_body/1]).
-export_type([source_mapped/1, source/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.
-type source_mapped(JWZ) :: {source_mapped, JWZ, source()}.
-type source() :: {source, list(binary()), integer()}.
-file("src/gleamgen/source.gleam", 119).
-spec do_trim_leading_newlines(
list(binary()),
boolean(),
boolean(),
integer(),
list(binary())
) -> {list(binary()), integer()}.
do_trim_leading_newlines(
Contents,
Line_entirely_whitespace,
Is_first_line,
Lines_removed,
Acc
) ->
case Contents of
[<<"\n"/utf8>> | Rest] when Line_entirely_whitespace andalso Is_first_line ->
do_trim_leading_newlines(Rest, true, false, Lines_removed, Acc);
[<<"\n"/utf8>> | Rest@1] when Line_entirely_whitespace ->
do_trim_leading_newlines(
Rest@1,
true,
false,
Lines_removed + 1,
Acc
);
[<<"\t"/utf8>> | Rest@2] when Line_entirely_whitespace ->
do_trim_leading_newlines(
Rest@2,
true,
Is_first_line,
Lines_removed,
Acc
);
[<<" "/utf8>> | Rest@2] when Line_entirely_whitespace ->
do_trim_leading_newlines(
Rest@2,
true,
Is_first_line,
Lines_removed,
Acc
);
[First | Rest@3] ->
do_trim_leading_newlines(
Rest@3,
false,
Is_first_line,
Lines_removed,
[First | Acc]
);
[] ->
{Acc, Lines_removed}
end.
-file("src/gleamgen/source.gleam", 105).
-spec trim_leading_newlines(binary()) -> {binary(), integer()}.
trim_leading_newlines(Input) ->
{Trimmed, Lines_removed} = begin
_pipe = gleam@string:to_graphemes(Input),
do_trim_leading_newlines(_pipe, true, true, 0, [])
end,
Trimmed_string = begin
_pipe@1 = Trimmed,
_pipe@2 = gleam@list:drop_while(
_pipe@1,
fun(S) -> (S =:= <<" "/utf8>>) orelse (S =:= <<"\t"/utf8>>) end
),
_pipe@3 = lists:reverse(_pipe@2),
gleam@string:join(_pipe@3, <<""/utf8>>)
end,
{Trimmed_string, Lines_removed}.
-file("src/gleamgen/source.gleam", 16).
?DOC(false).
-spec get_source_map_doc(source_mapped(any())) -> glam@doc:document().
get_source_map_doc(Source_map) ->
{Content, Lines_removed} = begin
_pipe = erlang:element(2, erlang:element(3, Source_map)),
_pipe@1 = gleam@string:join(_pipe, <<""/utf8>>),
trim_leading_newlines(_pipe@1)
end,
case Lines_removed of
0 ->
glam@doc:from_string(Content);
_ ->
glam@doc:append({line, 1}, glam@doc:from_string(Content))
end.
-file("src/gleamgen/source.gleam", 25).
-spec module_from_string(binary()) -> {ok, source_mapped(glance:module_())} |
{error, glance:error()}.
module_from_string(Input) ->
gleam@result:'try'(
glance:module(Input),
fun(Module) ->
{ok,
{source_mapped,
Module,
{source, gleam@string:to_graphemes(Input), 0}}}
end
).
-file("src/gleamgen/source.gleam", 35).
-spec drop_until(source(), integer()) -> source().
drop_until(Source, Pos) ->
{source,
gleam@list:drop(
erlang:element(2, Source),
Pos - erlang:element(3, Source)
),
Pos}.
-file("src/gleamgen/source.gleam", 42).
-spec drop_until_character(source(), binary()) -> source().
drop_until_character(Source, Character) ->
case erlang:element(2, Source) of
[First | Rest] when First =/= Character ->
drop_until_character(
{source, Rest, erlang:element(3, Source) + 1},
Character
);
[First@1 | Rest@1] when First@1 =:= Character ->
{source, Rest@1, erlang:element(3, Source) + 1};
_ ->
Source
end.
-file("src/gleamgen/source.gleam", 57).
?DOC(false).
-spec take_until(source(), integer()) -> {binary(), source()}.
take_until(Source, N) ->
{Taken, Remaining} = gleam@list:split(
erlang:element(2, Source),
N - erlang:element(3, Source)
),
New_source = {source, Remaining, N},
{gleam@string:join(Taken, <<""/utf8>>), New_source}.
-file("src/gleamgen/source.gleam", 64).
-spec end_source_at(source(), integer()) -> source().
end_source_at(Source, N) ->
{source,
gleam@list:take(
erlang:element(2, Source),
N - erlang:element(3, Source)
),
erlang:element(3, Source)}.
-file("src/gleamgen/source.gleam", 79).
-spec do_fold(
list(JXI),
JXK,
source(),
fun((JXI, JXK, binary(), binary(), source()) -> JXK),
fun((JXI) -> glance:span())
) -> {JXK, source()}.
do_fold(Input, Acc, Source, Handler, Get_span) ->
case Input of
[First | Rest] ->
Span = Get_span(First),
{Before, Before_source} = take_until(
Source,
erlang:element(2, Span)
),
{Main_content, Remaining_source} = take_until(
Before_source,
erlang:element(3, Span)
),
Span_source = end_source_at(Source, erlang:element(3, Span)),
{Trimmed, _} = trim_leading_newlines(Before),
Result = Handler(First, Acc, Trimmed, Main_content, Span_source),
do_fold(Rest, Result, Remaining_source, Handler, Get_span);
[] ->
{Acc, Source}
end.
-file("src/gleamgen/source.gleam", 69).
?DOC(false).
-spec fold(
list(JXF),
source(),
JXH,
fun((JXF, JXH, binary(), binary(), source()) -> JXH),
fun((JXF) -> glance:span())
) -> {JXH, source()}.
fold(Input, Module_text, Initial_value, Handler, Get_span) ->
do_fold(Input, Initial_value, Module_text, Handler, Get_span).
-file("src/gleamgen/source.gleam", 146).
-spec get_function_body(source_mapped(glance:function_())) -> list(source_mapped(glance:statement())).
get_function_body(Function) ->
Span = erlang:element(2, erlang:element(2, Function)),
Source = begin
_pipe = erlang:element(3, Function),
_pipe@1 = drop_until(_pipe, erlang:element(2, Span)),
drop_until_character(_pipe@1, <<"{"/utf8>>)
end,
{Statements, _} = fold(
erlang:element(7, erlang:element(2, Function)),
Source,
[],
fun(Statement, Acc, _, _, Source@1) ->
[{source_mapped, Statement, Source@1} | Acc]
end,
fun(S) -> case S of
{expression, E} ->
erlang:element(2, E);
{use, Location, _, _} ->
Location;
{assignment, Location, _, _, _, _} ->
Location;
{assert, Location, _, _} ->
Location
end end
),
lists:reverse(Statements).