-module(girard@internal@reference).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/girard/internal/reference.gleam").
-export([in_function/1, in_constant/1]).
-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/girard/internal/reference.gleam", 190).
?DOC(false).
-spec assignment_name(glance:assignment_name()) -> list(binary()).
assignment_name(Name) ->
case Name of
{named, N} ->
[N];
{discarded, _} ->
[]
end.
-file("src/girard/internal/reference.gleam", 206).
?DOC(false).
-spec pattern_names(glance:pattern()) -> list(binary()).
pattern_names(Pattern) ->
case Pattern of
{pattern_int, _, _} ->
[];
{pattern_float, _, _} ->
[];
{pattern_string, _, _} ->
[];
{pattern_discard, _, _} ->
[];
{pattern_variable, _, Name} ->
[Name];
{pattern_tuple, _, Elements} ->
gleam@list:flat_map(Elements, fun pattern_names/1);
{pattern_list, _, Elements@1, Tail} ->
case Tail of
{some, T} ->
lists:append(
gleam@list:flat_map(Elements@1, fun pattern_names/1),
pattern_names(T)
);
none ->
gleam@list:flat_map(Elements@1, fun pattern_names/1)
end;
{pattern_assignment, _, Pattern@1, Name@1} ->
[Name@1 | pattern_names(Pattern@1)];
{pattern_concatenate, _, _, Prefix_name, Rest_name} ->
lists:append(case Prefix_name of
{some, N} ->
assignment_name(N);
none ->
[]
end, assignment_name(Rest_name));
{pattern_bit_string, _, Segments} ->
gleam@list:flat_map(
Segments,
fun(Segment) -> pattern_names(erlang:element(1, Segment)) end
);
{pattern_variant, _, _, _, Arguments, _} ->
gleam@list:flat_map(Arguments, fun(Field) -> case Field of
{unlabelled_field, P} ->
pattern_names(P);
{labelled_field, _, _, P@1} ->
pattern_names(P@1);
{shorthand_field, Label, _} ->
[Label]
end end)
end.
-file("src/girard/internal/reference.gleam", 41).
?DOC(false).
-spec value({list(binary()), list(binary())}, gleam@set:set(binary()), binary()) -> {list(binary()),
list(binary())}.
value(Acc, Bound, Name) ->
gleam@bool:guard(
gleam@set:contains(Bound, Name),
Acc,
fun() -> {[Name | erlang:element(1, Acc)], erlang:element(2, Acc)} end
).
-file("src/girard/internal/reference.gleam", 46).
?DOC(false).
-spec qualifier(
{list(binary()), list(binary())},
gleam@set:set(binary()),
binary()
) -> {list(binary()), list(binary())}.
qualifier(Acc, Bound, Name) ->
gleam@bool:guard(
gleam@set:contains(Bound, Name),
Acc,
fun() -> {erlang:element(1, Acc), [Name | erlang:element(2, Acc)]} end
).
-file("src/girard/internal/reference.gleam", 201).
?DOC(false).
-spec fn_param_names(glance:fn_parameter()) -> list(binary()).
fn_param_names(Param) ->
assignment_name(erlang:element(2, Param)).
-file("src/girard/internal/reference.gleam", 82).
?DOC(false).
-spec in_optional(
gleam@option:option(glance:expression()),
gleam@set:set(binary()),
{list(binary()), list(binary())}
) -> {list(binary()), list(binary())}.
in_optional(Expr, Bound, Acc) ->
case Expr of
{some, E} ->
in_expr(E, Bound, Acc);
none ->
Acc
end.
-file("src/girard/internal/reference.gleam", 93).
?DOC(false).
-spec in_exprs(
list(glance:expression()),
gleam@set:set(binary()),
{list(binary()), list(binary())}
) -> {list(binary()), list(binary())}.
in_exprs(Exprs, Bound, Acc) ->
gleam@list:fold(Exprs, Acc, fun(Acc@1, E) -> in_expr(E, Bound, Acc@1) end).
-file("src/girard/internal/reference.gleam", 101).
?DOC(false).
-spec in_fields(
list(glance:field(glance:expression())),
gleam@set:set(binary()),
{list(binary()), list(binary())}
) -> {list(binary()), list(binary())}.
in_fields(Fields, Bound, Acc) ->
gleam@list:fold(Fields, Acc, fun(Acc@1, Field) -> case Field of
{unlabelled_field, Item} ->
in_expr(Item, Bound, Acc@1);
{labelled_field, _, _, Item@1} ->
in_expr(Item@1, Bound, Acc@1);
{shorthand_field, Label, _} ->
value(Acc@1, Bound, Label)
end end).
-file("src/girard/internal/reference.gleam", 115).
?DOC(false).
-spec in_expr(
glance:expression(),
gleam@set:set(binary()),
{list(binary()), list(binary())}
) -> {list(binary()), list(binary())}.
in_expr(Expr, Bound, Acc) ->
case Expr of
{int, _, _} ->
Acc;
{float, _, _} ->
Acc;
{string, _, _} ->
Acc;
{variable, _, Name} ->
value(Acc, Bound, Name);
{negate_int, _, V} ->
in_expr(V, Bound, Acc);
{negate_bool, _, V} ->
in_expr(V, Bound, Acc);
{block, _, Statements} ->
in_statements(Statements, Bound, Acc);
{panic, _, Message} ->
in_optional(Message, Bound, Acc);
{todo, _, Message} ->
in_optional(Message, Bound, Acc);
{tuple, _, Elements} ->
in_exprs(Elements, Bound, Acc);
{list, _, Elements@1, Rest} ->
in_optional(Rest, Bound, in_exprs(Elements@1, Bound, Acc));
{fn, _, Arguments, _, Body} ->
Bound@1 = gleam@set:union(
Bound,
gleam@set:from_list(
gleam@list:flat_map(Arguments, fun fn_param_names/1)
)
),
in_statements(Body, Bound@1, Acc);
{record_update, _, _, _, Record, Fields} ->
gleam@list:fold(
Fields,
in_expr(Record, Bound, Acc),
fun(Acc@1, Field) ->
in_optional(erlang:element(3, Field), Bound, Acc@1)
end
);
{field_access, _, {variable, _, Name@1}, _} ->
qualifier(Acc, Bound, Name@1);
{field_access, _, Container, _} ->
in_expr(Container, Bound, Acc);
{call, _, Function, Arguments@1} ->
in_fields(Arguments@1, Bound, in_expr(Function, Bound, Acc));
{tuple_index, _, Tuple, _} ->
in_expr(Tuple, Bound, Acc);
{fn_capture, _, _, Function@1, Before, After} ->
in_fields(
After,
Bound,
in_fields(Before, Bound, in_expr(Function@1, Bound, Acc))
);
{bit_string, _, Segments} ->
gleam@list:fold(
Segments,
Acc,
fun(Acc@2, Segment) ->
in_expr(erlang:element(1, Segment), Bound, Acc@2)
end
);
{'case', _, Subjects, Clauses} ->
gleam@list:fold(
Clauses,
in_exprs(Subjects, Bound, Acc),
fun(Acc@3, Clause) ->
Names = gleam@list:flat_map(
lists:append(erlang:element(2, Clause)),
fun pattern_names/1
),
Bound@2 = gleam@set:union(Bound, gleam@set:from_list(Names)),
in_optional(
erlang:element(3, Clause),
Bound@2,
in_expr(erlang:element(4, Clause), Bound@2, Acc@3)
)
end
);
{binary_operator, _, _, Left, Right} ->
in_expr(Right, Bound, in_expr(Left, Bound, Acc));
{echo, _, Expression, Message@1} ->
in_optional(Message@1, Bound, in_optional(Expression, Bound, Acc))
end.
-file("src/girard/internal/reference.gleam", 51).
?DOC(false).
-spec in_statements(
list(glance:statement()),
gleam@set:set(binary()),
{list(binary()), list(binary())}
) -> {list(binary()), list(binary())}.
in_statements(Statements, Bound, Acc) ->
{_, Acc@4} = gleam@list:fold(
Statements,
{Bound, Acc},
fun(State, Statement) ->
{Bound@1, Acc@1} = State,
case Statement of
{expression, Expr} ->
{Bound@1, in_expr(Expr, Bound@1, Acc@1)};
{assignment, _, _, Pattern, _, Value} ->
Acc@2 = in_expr(Value, Bound@1, Acc@1),
{gleam@set:union(
Bound@1,
gleam@set:from_list(pattern_names(Pattern))
),
Acc@2};
{assert, _, Expr@1, Message} ->
{Bound@1,
in_optional(
Message,
Bound@1,
in_expr(Expr@1, Bound@1, Acc@1)
)};
{use, _, Patterns, Function} ->
Acc@3 = in_expr(Function, Bound@1, Acc@1),
Names = gleam@list:flat_map(
Patterns,
fun(P) -> pattern_names(erlang:element(2, P)) end
),
{gleam@set:union(Bound@1, gleam@set:from_list(Names)),
Acc@3}
end
end
),
Acc@4.
-file("src/girard/internal/reference.gleam", 197).
?DOC(false).
-spec param_names(glance:function_parameter()) -> list(binary()).
param_names(Param) ->
assignment_name(erlang:element(3, Param)).
-file("src/girard/internal/reference.gleam", 28).
?DOC(false).
-spec in_function(glance:function_()) -> {list(binary()), list(binary())}.
in_function(Function) ->
Bound = gleam@set:from_list(
gleam@list:flat_map(erlang:element(5, Function), fun param_names/1)
),
in_statements(erlang:element(7, Function), Bound, {[], []}).
-file("src/girard/internal/reference.gleam", 34).
?DOC(false).
-spec in_constant(glance:constant()) -> {list(binary()), list(binary())}.
in_constant(Constant) ->
in_expr(erlang:element(6, Constant), gleam@set:new(), {[], []}).