Current section

Files

Jump to
graded src graded@internal@checker.erl
Raw

src/graded@internal@checker.erl

-module(graded@internal@checker).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/graded/internal/checker.gleam").
-export([build_scc_ids/4, build_function_map/1, check/6, infer_with_returns/6, infer/6, closure_field_operator/6]).
-export_type([local_cache/0, memo/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 local_cache() :: {local_cache,
gleam@dict:dict(binary(), integer()),
gleam@dict:dict(integer(), list(binary())),
gleam@set:set(integer())}.
-type memo() :: {memo,
gleam@dict:dict({binary(), list(binary())}, list({graded@internal@types:resolved_call(),
graded@internal@types:effect_term()})),
gleam@dict:dict(integer(), list({graded@internal@types:resolved_call(),
graded@internal@types:effect_term()})),
gleam@dict:dict({binary(), list(binary())}, graded@internal@types:effect_term()),
gleam@dict:dict({integer(),
list(integer()),
list(binary()),
list(binary())}, graded@internal@types:effect_term())}.
-file("src/graded/internal/checker.gleam", 744).
?DOC(false).
-spec collect_reference_warnings(
binary(),
list(graded@internal@types:resolved_call()),
graded@internal@effects:knowledge_base()
) -> list(graded@internal@types:warning()).
collect_reference_warnings(Function_name, References, Knowledge_base) ->
gleam@list:filter_map(
References,
fun(Ref) ->
case graded@internal@effects:lookup(
Knowledge_base,
erlang:element(2, Ref)
) of
{known, Term} ->
Effect_set = graded@internal@effect_term:to_effect_set(Term),
case Effect_set =:= graded@internal@types:empty() of
true ->
{error, nil};
false ->
{ok,
{untracked_effect_warning,
Function_name,
erlang:element(2, Ref),
erlang:element(3, Ref),
Effect_set}}
end;
unknown ->
{error, nil}
end
end
).
-file("src/graded/internal/checker.gleam", 313).
?DOC(false).
-spec without_returned_closure(glance:function_()) -> glance:function_().
without_returned_closure(Function) ->
case lists:reverse(erlang:element(7, Function)) of
[{expression, {fn, _, _, _, _}} | Rest] ->
{function,
erlang:element(2, Function),
erlang:element(3, Function),
erlang:element(4, Function),
erlang:element(5, Function),
erlang:element(6, Function),
lists:reverse(Rest)};
_ ->
Function
end.
-file("src/graded/internal/checker.gleam", 2102).
?DOC(false).
-spec resolve_argument_effects(
graded@internal@types:call_argument(),
graded@internal@effects:knowledge_base(),
list(graded@internal@types:param_bound())
) -> graded@internal@types:effect_term().
resolve_argument_effects(Arg, Knowledge_base, Caller_param_bounds) ->
case erlang:element(4, Arg) of
{function_ref, Name} ->
graded@internal@effects:lookup_effects(Knowledge_base, Name);
constructor_ref ->
graded@internal@effect_term:pure();
{local_ref, Name@1} ->
case gleam@list:find(
Caller_param_bounds,
fun(B) -> erlang:element(2, B) =:= Name@1 end
) of
{ok, Bound} ->
erlang:element(3, Bound);
{error, nil} ->
graded@internal@effect_term:unknown()
end;
{closure, _, _} ->
graded@internal@effect_term:unknown();
{choice, _} ->
graded@internal@effect_term:unknown();
{returned_operator, _, _} ->
graded@internal@effect_term:unknown();
other_expression ->
graded@internal@effect_term:unknown()
end.
-file("src/graded/internal/checker.gleam", 217).
?DOC(false).
-spec operator_argument_effect(
gleam@dict:dict(integer(), list(graded@internal@types:call_argument())),
integer(),
integer(),
graded@internal@effects:knowledge_base(),
list(graded@internal@types:param_bound())
) -> graded@internal@types:effect_term().
operator_argument_effect(
Call_args,
Span_start,
Callback_position,
Knowledge_base,
Caller_param_bounds
) ->
Args = begin
_pipe = gleam_stdlib:map_get(Call_args, Span_start),
gleam@result:unwrap(_pipe, [])
end,
case gleam@list:find(
Args,
fun(A) -> erlang:element(2, A) =:= Callback_position end
) of
{ok, Arg} ->
resolve_argument_effects(Arg, Knowledge_base, Caller_param_bounds);
{error, nil} ->
graded@internal@effect_term:unknown()
end.
-file("src/graded/internal/checker.gleam", 237).
?DOC(false).
-spec curried_operator_application(
graded@internal@types:effect_term(),
list(integer()),
gleam@dict:dict(integer(), list(graded@internal@types:call_argument())),
integer(),
graded@internal@effects:knowledge_base(),
list(graded@internal@types:param_bound())
) -> graded@internal@types:effect_term().
curried_operator_application(
Operator,
Callback_positions,
Call_args,
Span_start,
Knowledge_base,
Caller_param_bounds
) ->
gleam@list:fold(
Callback_positions,
Operator,
fun(Acc, Position) ->
{t_app,
Acc,
operator_argument_effect(
Call_args,
Span_start,
Position,
Knowledge_base,
Caller_param_bounds
)}
end
).
-file("src/graded/internal/checker.gleam", 1437).
?DOC(false).
-spec rename_binder(binary(), {binary(), graded@internal@types:effect_term()}) -> graded@internal@types:effect_term().
rename_binder(Binder, Abstraction) ->
{Param, Body} = Abstraction,
case Param =:= Binder of
true ->
Body;
false ->
graded@internal@effect_term:subst(
Body,
maps:from_list([{Param, {t_var, Binder}}])
)
end.
-file("src/graded/internal/checker.gleam", 1406).
?DOC(false).
-spec join_operators(list(graded@internal@types:effect_term())) -> graded@internal@types:effect_term().
join_operators(Terms) ->
case Terms of
[] ->
graded@internal@effect_term:unknown();
[Single] ->
Single;
_ ->
Abstractions = gleam@list:filter_map(
Terms,
fun(Term) -> case Term of
{t_abs, Param, Body} ->
{ok, {Param, Body}};
_ ->
{error, nil}
end end
),
All_abstractions = erlang:length(Abstractions) =:= erlang:length(
Terms
),
case Abstractions of
[{Binder, _} | _] when All_abstractions ->
Bodies = gleam@list:map(
Abstractions,
fun(_capture) -> rename_binder(Binder, _capture) end
),
{t_abs, Binder, join_operators(Bodies)};
[_ | _] ->
graded@internal@effect_term:unknown();
[] ->
graded@internal@effect_term:normalize({t_union, Terms})
end
end.
-file("src/graded/internal/checker.gleam", 1347).
?DOC(false).
-spec operator_term_for_argument(
graded@internal@types:call_argument(),
list(integer()),
graded@internal@effects:knowledge_base(),
list(graded@internal@types:param_bound()),
graded@internal@signatures:signature_registry(),
fun((graded@internal@types:argument_value(), list(integer()), memo()) -> {{ok,
graded@internal@types:effect_term()} |
{error, nil},
memo()}),
memo()
) -> {graded@internal@types:effect_term(), memo()}.
operator_term_for_argument(
Arg,
Positions,
Knowledge_base,
Caller_param_bounds,
Registry,
Lift_operator_arg,
Memo
) ->
case erlang:element(4, Arg) of
{function_ref, Name} ->
Body = graded@internal@effects:lookup_effects(Knowledge_base, Name),
Operator = begin
_pipe = graded@internal@signatures:fn_typed_param_names_ordered(
Registry,
Name
),
gleam@list:fold_right(
_pipe,
Body,
fun(Acc, Param) -> {t_abs, Param, Acc} end
)
end,
{Operator, Memo};
{choice, Options} ->
{Memo@3, Operators} = gleam@list:map_fold(
Options,
Memo,
fun(Memo@1, Option) ->
{Op, Memo@2} = operator_term_for_argument(
{call_argument,
erlang:element(2, Arg),
erlang:element(3, Arg),
Option},
Positions,
Knowledge_base,
Caller_param_bounds,
Registry,
Lift_operator_arg,
Memo@1
),
{Memo@2, Op}
end
),
{join_operators(Operators), Memo@3};
_ ->
{Lifted, Memo@4} = Lift_operator_arg(
erlang:element(4, Arg),
Positions,
Memo
),
case Lifted of
{ok, Operator@1} ->
{Operator@1, Memo@4};
{error, nil} ->
{resolve_argument_effects(
Arg,
Knowledge_base,
Caller_param_bounds
),
Memo@4}
end
end.
-file("src/graded/internal/checker.gleam", 1082).
?DOC(false).
-spec operator_spine_arity(graded@internal@types:effect_term()) -> integer().
operator_spine_arity(Term) ->
case Term of
{t_abs, _, Body} ->
1 + operator_spine_arity(Body);
{t_union, Members} ->
gleam@list:fold(
Members,
0,
fun(Max, Member) ->
gleam@int:max(Max, operator_spine_arity(Member))
end
);
_ ->
0
end.
-file("src/graded/internal/checker.gleam", 1025).
?DOC(false).
-spec positions_up_to(integer()) -> list(integer()).
positions_up_to(N) ->
case N =< 0 of
true ->
[];
false ->
lists:append(positions_up_to(N - 1), [N - 1])
end.
-file("src/graded/internal/checker.gleam", 1069).
?DOC(false).
-spec discharge_operator(graded@internal@types:effect_term()) -> graded@internal@types:effect_term().
discharge_operator(Operator) ->
case Operator of
{t_abs, Param, Body} ->
discharge_operator(
graded@internal@effect_term:normalize(
graded@internal@effect_term:subst(
Body,
maps:from_list(
[{Param, graded@internal@effect_term:pure()}]
)
)
)
);
Other ->
Other
end.
-file("src/graded/internal/checker.gleam", 1038).
?DOC(false).
-spec first_order_arg_effect(
graded@internal@types:call_argument(),
graded@internal@effects:knowledge_base(),
list(graded@internal@types:param_bound()),
fun((graded@internal@types:argument_value(), list(integer()), memo()) -> {{ok,
graded@internal@types:effect_term()} |
{error, nil},
memo()}),
memo()
) -> {graded@internal@types:effect_term(), memo()}.
first_order_arg_effect(
Arg,
Knowledge_base,
Caller_param_bounds,
Lift_operator_arg,
Memo
) ->
case erlang:element(4, Arg) of
{closure, _, _} ->
{Lifted, Memo@1} = Lift_operator_arg(
erlang:element(4, Arg),
[],
Memo
),
case Lifted of
{ok, Operator} ->
{discharge_operator(Operator), Memo@1};
{error, nil} ->
{resolve_argument_effects(
Arg,
Knowledge_base,
Caller_param_bounds
),
Memo@1}
end;
_ ->
{resolve_argument_effects(Arg, Knowledge_base, Caller_param_bounds),
Memo}
end.
-file("src/graded/internal/checker.gleam", 2062).
?DOC(false).
-spec find_arg_at_position(
list(graded@internal@types:call_argument()),
integer()
) -> gleam@option:option(graded@internal@types:call_argument()).
find_arg_at_position(Args, Position) ->
_pipe = gleam@list:find(
Args,
fun(Arg) ->
(erlang:element(2, Arg) =:= Position) andalso (erlang:element(
3,
Arg
)
=:= none)
end
),
gleam@option:from_result(_pipe).
-file("src/graded/internal/checker.gleam", 2089).
?DOC(false).
-spec find_param_position(
list(graded@internal@signatures:parameter_info()),
fun((graded@internal@signatures:parameter_info()) -> boolean())
) -> gleam@option:option(integer()).
find_param_position(Params, Predicate) ->
_pipe = gleam@list:find(Params, Predicate),
_pipe@1 = gleam@result:map(_pipe, fun(P) -> erlang:element(2, P) end),
gleam@option:from_result(_pipe@1).
-file("src/graded/internal/checker.gleam", 2073).
?DOC(false).
-spec position_from_registry(
graded@internal@types:qualified_name(),
binary(),
graded@internal@signatures:signature_registry()
) -> gleam@option:option(integer()).
position_from_registry(Callee_name, Param_name, Registry) ->
gleam@option:then(
graded@internal@signatures:lookup(Registry, Callee_name),
fun(Params) ->
By_name = find_param_position(
Params,
fun(P) -> erlang:element(4, P) =:= {some, Param_name} end
),
gleam@option:lazy_or(
By_name,
fun() ->
find_param_position(
Params,
fun(P@1) ->
erlang:element(3, P@1) =:= {some, Param_name}
end
)
end
)
end
).
-file("src/graded/internal/checker.gleam", 2054).
?DOC(false).
-spec find_arg_by_label(list(graded@internal@types:call_argument()), binary()) -> gleam@option:option(graded@internal@types:call_argument()).
find_arg_by_label(Args, Label) ->
_pipe = gleam@list:find(
Args,
fun(Arg) -> erlang:element(3, Arg) =:= {some, Label} end
),
gleam@option:from_result(_pipe).
-file("src/graded/internal/checker.gleam", 2034).
?DOC(false).
-spec find_matching_arg(
graded@internal@types:qualified_name(),
graded@internal@types:param_bound(),
list(graded@internal@types:call_argument()),
graded@internal@signatures:signature_registry()
) -> gleam@option:option(graded@internal@types:call_argument()).
find_matching_arg(Callee_name, Bound, Args, Registry) ->
By_label = find_arg_by_label(Args, erlang:element(2, Bound)),
gleam@option:lazy_or(
By_label,
fun() ->
_pipe = position_from_registry(
Callee_name,
erlang:element(2, Bound),
Registry
),
gleam@option:then(
_pipe,
fun(Pos) -> find_arg_at_position(Args, Pos) end
)
end
).
-file("src/graded/internal/checker.gleam", 1270).
?DOC(false).
-spec bind_variables(
graded@internal@types:qualified_name(),
list(graded@internal@types:param_bound()),
list(graded@internal@types:call_argument()),
graded@internal@effects:knowledge_base(),
list(graded@internal@types:param_bound()),
graded@internal@signatures:signature_registry(),
fun((graded@internal@types:argument_value(), list(integer()), memo()) -> {{ok,
graded@internal@types:effect_term()} |
{error, nil},
memo()}),
memo()
) -> {gleam@dict:dict(binary(), graded@internal@types:effect_term()), memo()}.
bind_variables(
Callee_name,
Callee_bounds,
Args,
Knowledge_base,
Caller_param_bounds,
Registry,
Lift_operator_arg,
Memo
) ->
Operator_params = graded@internal@signatures:operator_param_names(
Registry,
Callee_name
),
gleam@list:fold(
Callee_bounds,
{maps:new(), Memo},
fun(State, Bound) ->
{Acc, Memo@1} = State,
Matched = find_matching_arg(Callee_name, Bound, Args, Registry),
case Matched of
{some, Arg} ->
{Arg_effects, Memo@2} = case gleam@set:contains(
Operator_params,
erlang:element(2, Bound)
) of
true ->
operator_term_for_argument(
Arg,
graded@internal@signatures:operator_callback_positions(
Registry,
Callee_name,
erlang:element(2, Bound)
),
Knowledge_base,
Caller_param_bounds,
Registry,
Lift_operator_arg,
Memo@1
);
false ->
first_order_arg_effect(
Arg,
Knowledge_base,
Caller_param_bounds,
Lift_operator_arg,
Memo@1
)
end,
Var_names = begin
_pipe = erlang:element(3, Bound),
_pipe@1 = graded@internal@effect_term:free_vars(_pipe),
gleam@set:to_list(_pipe@1)
end,
Acc@1 = gleam@list:fold(
Var_names,
Acc,
fun(D, Var) ->
gleam@dict:insert(D, Var, Arg_effects)
end
),
{Acc@1, Memo@2};
none ->
{Acc, Memo@1}
end
end
).
-file("src/graded/internal/checker.gleam", 274).
?DOC(false).
-spec union_of(
list({graded@internal@types:resolved_call(),
graded@internal@types:effect_term()})
) -> graded@internal@types:effect_term().
union_of(Pairs) ->
graded@internal@effect_term:normalize(
{t_union,
gleam@list:map(Pairs, fun(Pair) -> erlang:element(2, Pair) end)}
).
-file("src/graded/internal/checker.gleam", 264).
?DOC(false).
-spec self_referential_bound(binary()) -> graded@internal@types:param_bound().
self_referential_bound(Name) ->
{param_bound, Name, {t_var, Name}}.
-file("src/graded/internal/checker.gleam", 528).
?DOC(false).
-spec memo_key(binary(), gleam@set:set(binary()), local_cache()) -> {binary(),
list(binary())}.
memo_key(Name, Visited, Cache) ->
Scc = gleam_stdlib:map_get(erlang:element(2, Cache), Name),
Ancestors = begin
_pipe = Visited,
_pipe@1 = gleam@set:to_list(_pipe),
_pipe@2 = gleam@list:filter(
_pipe@1,
fun(Ancestor) ->
gleam_stdlib:map_get(erlang:element(2, Cache), Ancestor) =:= Scc
end
),
gleam@list:sort(_pipe@2, fun gleam@string:compare/2)
end,
{Name, Ancestors}.
-file("src/graded/internal/checker.gleam", 2022).
?DOC(false).
-spec ordered_fn_typed_param_names(glance:function_()) -> list(binary()).
ordered_fn_typed_param_names(Function) ->
gleam@list:filter_map(
erlang:element(5, Function),
fun(Param) ->
case {erlang:element(4, Param), erlang:element(3, Param)} of
{{some, {function_type, _, _, _}}, {named, Name}} ->
{ok, Name};
{_, _} ->
{error, nil}
end
end
).
-file("src/graded/internal/checker.gleam", 1902).
?DOC(false).
-spec statement_start(glance:statement()) -> integer().
statement_start(Statement) ->
case Statement of
{use, Location, _, _} ->
erlang:element(2, Location);
{assignment, Location@1, _, _, _, _} ->
erlang:element(2, Location@1);
{assert, Location@2, _, _} ->
erlang:element(2, Location@2);
{expression, Expression} ->
erlang:element(2, erlang:element(2, Expression))
end.
-file("src/graded/internal/checker.gleam", 1895).
?DOC(false).
-spec closure_body_start(list(glance:statement())) -> integer().
closure_body_start(Body) ->
case Body of
[Statement | _] ->
statement_start(Statement);
[] ->
-1
end.
-file("src/graded/internal/checker.gleam", 1740).
?DOC(false).
-spec compute_returned_operator_result(graded@internal@types:effect_term()) -> {ok,
graded@internal@types:effect_term()} |
{error, nil}.
compute_returned_operator_result(Operator) ->
case Operator of
{t_abs, _, _} ->
{ok, Operator};
{t_var, _} ->
{ok, Operator};
{t_union, _} ->
{ok, Operator};
{t_labels, _} ->
case Operator =:= graded@internal@effect_term:unknown() of
true ->
{error, nil};
false ->
{ok, Operator}
end;
t_top ->
case Operator =:= graded@internal@effect_term:unknown() of
true ->
{error, nil};
false ->
{ok, Operator}
end;
{t_app, _, _} ->
{error, nil}
end.
-file("src/graded/internal/checker.gleam", 2516).
?DOC(false).
-spec concretize(graded@internal@types:effect_term()) -> graded@internal@types:effect_term().
concretize(Term) ->
Bindings = begin
_pipe = Term,
_pipe@1 = graded@internal@effect_term:free_vars(_pipe),
gleam@set:fold(
_pipe@1,
maps:new(),
fun(D, Var) ->
gleam@dict:insert(D, Var, graded@internal@effect_term:unknown())
end
)
end,
graded@internal@effect_term:normalize(
graded@internal@effect_term:subst(Term, Bindings)
).
-file("src/graded/internal/checker.gleam", 269).
?DOC(false).
-spec has_vars(graded@internal@types:effect_term()) -> boolean().
has_vars(Term) ->
not gleam@set:is_empty(graded@internal@effect_term:free_vars(Term)).
-file("src/graded/internal/checker.gleam", 2508).
?DOC(false).
-spec apply_args(
graded@internal@types:effect_term(),
list(graded@internal@types:effect_term())
) -> graded@internal@types:effect_term().
apply_args(Operator, Arg_terms) ->
gleam@list:fold(Arg_terms, Operator, fun(Acc, Arg) -> {t_app, Acc, Arg} end).
-file("src/graded/internal/checker.gleam", 2458).
?DOC(false).
-spec is_operator_valued(graded@internal@types:effect_term()) -> boolean().
is_operator_valued(Term) ->
case Term of
{t_abs, _, _} ->
true;
{t_union, Members} ->
gleam@list:any(Members, fun is_operator_valued/1);
_ ->
false
end.
-file("src/graded/internal/checker.gleam", 2481).
?DOC(false).
-spec apply_field_operator(
graded@internal@types:effect_term(),
list(graded@internal@types:call_argument()),
graded@internal@effects:knowledge_base(),
list(graded@internal@types:param_bound())
) -> graded@internal@types:effect_term().
apply_field_operator(Operator, Args, Knowledge_base, Caller_param_bounds) ->
Arg_terms = begin
_pipe = Args,
_pipe@1 = gleam@list:sort(
_pipe,
fun(A, B) ->
gleam@int:compare(erlang:element(2, A), erlang:element(2, B))
end
),
gleam@list:map(
_pipe@1,
fun(_capture) ->
resolve_argument_effects(
_capture,
Knowledge_base,
Caller_param_bounds
)
end
)
end,
case Operator of
{t_union, Members} ->
_pipe@2 = Members,
_pipe@3 = gleam@list:map(
_pipe@2,
fun(Member) -> case is_operator_valued(Member) of
true ->
apply_args(Member, Arg_terms);
false ->
Member
end end
),
_pipe@4 = {t_union, _pipe@3},
concretize(_pipe@4);
_ ->
concretize(apply_args(Operator, Arg_terms))
end.
-file("src/graded/internal/checker.gleam", 2403).
?DOC(false).
-spec resolve_field_effect(
graded@internal@types:type_field_effect(),
graded@internal@types:field_call(),
gleam@dict:dict(integer(), list(graded@internal@types:call_argument())),
graded@internal@effects:knowledge_base(),
list(graded@internal@types:param_bound()),
graded@internal@signatures:signature_registry(),
fun((graded@internal@types:argument_value(), list(integer()), memo()) -> {{ok,
graded@internal@types:effect_term()} |
{error, nil},
memo()}),
memo()
) -> {graded@internal@types:effect_term(), memo()}.
resolve_field_effect(
Field_effect,
Field_call,
Call_args,
Knowledge_base,
Caller_param_bounds,
Registry,
Lift_operator_arg,
Memo
) ->
gleam@bool:guard(
is_operator_valued(erlang:element(2, Field_effect)),
{apply_field_operator(
erlang:element(2, Field_effect),
begin
_pipe = gleam_stdlib:map_get(
Call_args,
erlang:element(2, erlang:element(4, Field_call))
),
gleam@result:unwrap(_pipe, [])
end,
Knowledge_base,
Caller_param_bounds
),
Memo},
fun() ->
case {has_vars(erlang:element(2, Field_effect)),
erlang:element(4, Field_effect)} of
{false, _} ->
{erlang:element(2, Field_effect), Memo};
{true, none} ->
{concretize(erlang:element(2, Field_effect)), Memo};
{true, {some, Source}} ->
Args = begin
_pipe@1 = gleam_stdlib:map_get(
Call_args,
erlang:element(2, erlang:element(4, Field_call))
),
gleam@result:unwrap(_pipe@1, [])
end,
{Bindings, Memo@1} = bind_variables(
Source,
erlang:element(3, Field_effect),
Args,
Knowledge_base,
Caller_param_bounds,
Registry,
Lift_operator_arg,
Memo
),
{concretize(
graded@internal@effect_term:subst(
erlang:element(2, Field_effect),
Bindings
)
),
Memo@1}
end
end
).
-file("src/graded/internal/checker.gleam", 2529).
?DOC(false).
-spec syntactic_param_type(glance:function_(), binary()) -> gleam@option:option(binary()).
syntactic_param_type(Function, Object) ->
case gleam@list:find(
erlang:element(5, Function),
fun(Param) -> case erlang:element(3, Param) of
{named, Name} ->
Name =:= Object;
{discarded, _} ->
false
end end
) of
{ok,
{function_parameter, _, _, {some, {named_type, _, Type_name, _, _}}}} ->
{some, Type_name};
_ ->
none
end.
-file("src/graded/internal/checker.gleam", 2346).
?DOC(false).
-spec resolve_field_call(
graded@internal@types:field_call(),
glance:function_(),
graded@internal@effects:knowledge_base(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
gleam@dict:dict(integer(), list(graded@internal@types:call_argument())),
list(graded@internal@types:param_bound()),
graded@internal@signatures:signature_registry(),
fun((graded@internal@types:argument_value(), list(integer()), memo()) -> {{ok,
graded@internal@types:effect_term()} |
{error, nil},
memo()}),
memo()
) -> {graded@internal@types:effect_term(), memo()}.
resolve_field_call(
Field_call,
Function,
Knowledge_base,
Module_types,
Call_args,
Caller_param_bounds,
Registry,
Lift_operator_arg,
Memo
) ->
Receiver_type = begin
_pipe = graded@internal@typeinfo:receiver_type(
Module_types,
erlang:element(2, erlang:element(5, Field_call)),
erlang:element(3, erlang:element(5, Field_call))
),
gleam@option:lazy_or(
_pipe,
fun() ->
_pipe@1 = syntactic_param_type(
Function,
erlang:element(2, Field_call)
),
gleam@option:map(
_pipe@1,
fun(Type_name) -> {<<""/utf8>>, Type_name} end
)
end
)
end,
case Receiver_type of
none ->
{graded@internal@effect_term:unknown(), Memo};
{some, {Module, Type_name@1}} ->
case graded@internal@effects:lookup_type_field(
Knowledge_base,
Module,
Type_name@1,
erlang:element(3, Field_call)
) of
{error, nil} ->
{graded@internal@effect_term:unknown(), Memo};
{ok, Field_effect} ->
resolve_field_effect(
Field_effect,
Field_call,
Call_args,
Knowledge_base,
Caller_param_bounds,
Registry,
Lift_operator_arg,
Memo
)
end
end.
-file("src/graded/internal/checker.gleam", 282).
?DOC(false).
-spec synthetic_fn_typed_bounds(gleam@set:set(binary())) -> list(graded@internal@types:param_bound()).
synthetic_fn_typed_bounds(Fn_typed_params) ->
_pipe = Fn_typed_params,
_pipe@1 = gleam@set:to_list(_pipe),
gleam@list:map(_pipe@1, fun self_referential_bound/1).
-file("src/graded/internal/checker.gleam", 1162).
?DOC(false).
-spec local_polymorphic_bounds(glance:function_()) -> list(graded@internal@types:param_bound()).
local_polymorphic_bounds(Function) ->
synthetic_fn_typed_bounds(
graded@internal@signatures:fn_typed_params_from_function(Function)
).
-file("src/graded/internal/checker.gleam", 1102).
?DOC(false).
-spec substitute_local_call_effects(
list({graded@internal@types:resolved_call(),
graded@internal@types:effect_term()}),
graded@internal@types:local_call(),
gleam@dict:dict(integer(), list(graded@internal@types:call_argument())),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@effects:knowledge_base(),
list(graded@internal@types:param_bound()),
graded@internal@signatures:signature_registry(),
fun((graded@internal@types:argument_value(), list(integer()), memo()) -> {{ok,
graded@internal@types:effect_term()} |
{error, nil},
memo()}),
memo()
) -> {list({graded@internal@types:resolved_call(),
graded@internal@types:effect_term()}),
memo()}.
substitute_local_call_effects(
Recursive,
Local_call,
Call_args,
Function_map,
Knowledge_base,
Caller_param_bounds,
Registry,
Lift_operator_arg,
Memo
) ->
Any_polymorphic = gleam@list:any(
Recursive,
fun(P) -> has_vars(erlang:element(2, P)) end
),
gleam@bool:guard(
not Any_polymorphic,
{Recursive, Memo},
fun() ->
case gleam_stdlib:map_get(
Function_map,
erlang:element(2, Local_call)
) of
{error, nil} ->
{Recursive, Memo};
{ok, Local_definition} ->
Bounds = local_polymorphic_bounds(
erlang:element(3, Local_definition)
),
Args = begin
_pipe = gleam_stdlib:map_get(
Call_args,
erlang:element(2, erlang:element(3, Local_call))
),
gleam@result:unwrap(_pipe, [])
end,
Callee_name = {qualified_name,
<<"<local>"/utf8>>,
erlang:element(2, Local_call)},
Local_registry = graded@internal@signatures:from_glance_module(
<<"<local>"/utf8>>,
{module, [], [], [], [], [Local_definition]}
),
Merged_registry = graded@internal@signatures:merge(
Registry,
Local_registry
),
{Bindings, Memo@1} = bind_variables(
Callee_name,
Bounds,
Args,
Knowledge_base,
Caller_param_bounds,
Merged_registry,
Lift_operator_arg,
Memo
),
Substituted = gleam@list:map(
Recursive,
fun(Pair) ->
{Call, Term} = Pair,
{Call,
graded@internal@effect_term:normalize(
graded@internal@effect_term:subst(
Term,
Bindings
)
)}
end
),
{Substituted, Memo@1}
end
end
).
-file("src/graded/internal/checker.gleam", 634).
?DOC(false).
-spec is_opaque_external(glance:definition(glance:function_())) -> boolean().
is_opaque_external(Definition) ->
gleam@list:any(
erlang:element(2, Definition),
fun(Attribute) ->
erlang:element(2, Attribute) =:= <<"external"/utf8>>
end
).
-file("src/graded/internal/checker.gleam", 1225).
?DOC(false).
-spec auto_bounds_from_registry(
graded@internal@types:qualified_name(),
graded@internal@types:effect_term(),
list(graded@internal@types:call_argument()),
graded@internal@signatures:signature_registry()
) -> {graded@internal@types:effect_term(),
list(graded@internal@types:param_bound())}.
auto_bounds_from_registry(Callee_name, Existing_effects, Args, Registry) ->
Fn_labels = graded@internal@signatures:fn_typed_param_names(
Registry,
Callee_name
),
gleam@bool:guard(
gleam@set:is_empty(Fn_labels),
{Existing_effects, []},
fun() ->
Tracked_bounds = begin
_pipe = Fn_labels,
_pipe@1 = gleam@set:to_list(_pipe),
_pipe@2 = gleam@list:sort(_pipe@1, fun gleam@string:compare/2),
gleam@list:filter_map(
_pipe@2,
fun(Label) ->
Bound = self_referential_bound(Label),
case find_matching_arg(
Callee_name,
Bound,
Args,
Registry
) of
{some, Arg} ->
case erlang:element(4, Arg) of
{closure, _, _} ->
{error, nil};
{choice, _} ->
{error, nil};
other_expression ->
{error, nil};
_ ->
{ok, Bound}
end;
none ->
{error, nil}
end
end
)
end,
case Tracked_bounds of
[] ->
{Existing_effects, []};
_ ->
Tracked_vars = gleam@list:map(
Tracked_bounds,
fun(B) -> {t_var, erlang:element(2, B)} end
),
{graded@internal@effect_term:normalize(
{t_union, [Existing_effects | Tracked_vars]}
),
Tracked_bounds}
end
end
).
-file("src/graded/internal/checker.gleam", 1172).
?DOC(false).
-spec substitute_at_call_site(
graded@internal@types:resolved_call(),
graded@internal@types:effect_term(),
gleam@dict:dict(integer(), list(graded@internal@types:call_argument())),
graded@internal@effects:knowledge_base(),
list(graded@internal@types:param_bound()),
graded@internal@signatures:signature_registry(),
fun((graded@internal@types:argument_value(), list(integer()), memo()) -> {{ok,
graded@internal@types:effect_term()} |
{error, nil},
memo()}),
memo()
) -> {graded@internal@types:effect_term(), memo()}.
substitute_at_call_site(
Call,
Effect,
Call_args,
Knowledge_base,
Caller_param_bounds,
Registry,
Lift_operator_arg,
Memo
) ->
Callee_kb_bounds = graded@internal@effects:lookup_param_bounds(
Knowledge_base,
erlang:element(2, Call)
),
gleam@bool:guard(
not has_vars(Effect) andalso (Callee_kb_bounds /= []),
{Effect, Memo},
fun() ->
Args = begin
_pipe = gleam_stdlib:map_get(
Call_args,
erlang:element(2, erlang:element(3, Call))
),
gleam@result:unwrap(_pipe, [])
end,
{Effective_effects, Effective_bounds} = case Callee_kb_bounds of
[_ | _] ->
{Effect, Callee_kb_bounds};
[] ->
auto_bounds_from_registry(
erlang:element(2, Call),
Effect,
Args,
Registry
)
end,
gleam@bool:guard(
not has_vars(Effective_effects),
{Effective_effects, Memo},
fun() ->
{Bindings, Memo@1} = bind_variables(
erlang:element(2, Call),
Effective_bounds,
Args,
Knowledge_base,
Caller_param_bounds,
Registry,
Lift_operator_arg,
Memo
),
{graded@internal@effect_term:normalize(
graded@internal@effect_term:subst(
Effective_effects,
Bindings
)
),
Memo@1}
end
)
end
).
-file("src/graded/internal/checker.gleam", 1984).
?DOC(false).
-spec lift_operator_miss(
binary(),
glance:function_(),
list(binary()),
{binary(), list(binary())},
graded@internal@extract:import_context(),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@effects:knowledge_base(),
gleam@set:set(binary()),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
local_cache(),
memo()
) -> {graded@internal@types:effect_term(), memo()}.
lift_operator_miss(
Name,
Function,
Fn_param_names,
Key,
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Cache,
Memo
) ->
Bounds = gleam@list:map(Fn_param_names, fun self_referential_bound/1),
{Body_pairs, Memo@1} = collect_effects(
without_returned_closure(Function),
Function_map,
Context,
Knowledge_base,
gleam@set:insert(Visited, Name),
Bounds,
Registry,
Module_types,
maps:new(),
Cache,
Memo
),
Body_term = union_of(Body_pairs),
Operator = gleam@list:fold_right(
Fn_param_names,
Body_term,
fun(Acc, Param) -> {t_abs, Param, Acc} end
),
{Operator,
{memo,
erlang:element(2, Memo@1),
erlang:element(3, Memo@1),
gleam@dict:insert(erlang:element(4, Memo@1), Key, Operator),
erlang:element(5, Memo@1)}}.
-file("src/graded/internal/checker.gleam", 2312).
?DOC(false).
-spec collapsed_member(
binary(),
list({graded@internal@types:resolved_call(),
graded@internal@types:effect_term()}),
gleam@set:set(binary()),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@extract:import_context(),
graded@internal@effects:knowledge_base(),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
local_cache(),
memo()
) -> {list({graded@internal@types:resolved_call(),
graded@internal@types:effect_term()}),
memo()}.
collapsed_member(
Name,
Acc,
Scc_set,
Function_map,
Context,
Knowledge_base,
Registry,
Module_types,
Cache,
Memo
) ->
case gleam_stdlib:map_get(Function_map, Name) of
{ok, Definition} ->
{Member_effects, Memo@1} = collect_effects(
without_returned_closure(erlang:element(3, Definition)),
Function_map,
Context,
Knowledge_base,
Scc_set,
[],
Registry,
Module_types,
maps:new(),
Cache,
Memo
),
{lists:append(Acc, Member_effects), Memo@1};
{error, nil} ->
{Acc, Memo}
end.
-file("src/graded/internal/checker.gleam", 2273).
?DOC(false).
-spec collapsed_scc(
integer(),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@extract:import_context(),
graded@internal@effects:knowledge_base(),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
local_cache(),
memo()
) -> {list({graded@internal@types:resolved_call(),
graded@internal@types:effect_term()}),
memo()}.
collapsed_scc(
Scc,
Function_map,
Context,
Knowledge_base,
Registry,
Module_types,
Cache,
Memo
) ->
case gleam_stdlib:map_get(erlang:element(3, Memo), Scc) of
{ok, Cached} ->
{Cached, Memo};
{error, nil} ->
Members = begin
_pipe = gleam_stdlib:map_get(erlang:element(3, Cache), Scc),
gleam@result:unwrap(_pipe, [])
end,
Scc_set = gleam@set:from_list(Members),
{Result, Memo@2} = gleam@list:fold(
Members,
{[], Memo},
fun(State, Name) ->
{Acc, Memo@1} = State,
collapsed_member(
Name,
Acc,
Scc_set,
Function_map,
Context,
Knowledge_base,
Registry,
Module_types,
Cache,
Memo@1
)
end
),
{Result,
{memo,
erlang:element(2, Memo@2),
gleam@dict:insert(erlang:element(3, Memo@2), Scc, Result),
erlang:element(4, Memo@2),
erlang:element(5, Memo@2)}}
end.
-file("src/graded/internal/checker.gleam", 1918).
?DOC(false).
-spec lift_local_function(
binary(),
glance:definition(glance:function_()),
graded@internal@extract:import_context(),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@effects:knowledge_base(),
gleam@set:set(binary()),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
local_cache(),
memo()
) -> {graded@internal@types:effect_term(), memo()}.
lift_local_function(
Name,
Definition,
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Cache,
Memo
) ->
Function = erlang:element(3, Definition),
Fn_param_names = ordered_fn_typed_param_names(Function),
Scc = begin
_pipe = gleam_stdlib:map_get(erlang:element(2, Cache), Name),
gleam@result:unwrap(_pipe, -1)
end,
case gleam@set:contains(erlang:element(4, Cache), Scc) of
true ->
{Pairs, Memo@1} = collapsed_scc(
Scc,
Function_map,
Context,
Knowledge_base,
Registry,
Module_types,
Cache,
Memo
),
{union_of(Pairs), Memo@1};
false ->
{_, Ancestors} = memo_key(Name, Visited, Cache),
Key = {Name, Ancestors},
case gleam_stdlib:map_get(erlang:element(4, Memo), Key) of
{ok, Cached} ->
{Cached, Memo};
{error, nil} ->
lift_operator_miss(
Name,
Function,
Fn_param_names,
Key,
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Cache,
Memo
)
end
end.
-file("src/graded/internal/checker.gleam", 1826).
?DOC(false).
-spec analyze_closure_uncached(
list(binary()),
list(glance:statement()),
list(integer()),
graded@internal@extract:import_context(),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@effects:knowledge_base(),
gleam@set:set(binary()),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
gleam@dict:dict(binary(), list(integer())),
local_cache(),
memo()
) -> {graded@internal@types:effect_term(), memo()}.
analyze_closure_uncached(
Params,
Body,
Positions,
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Ambient_operators,
Cache,
Memo
) ->
Synthetic = {function,
{span, 0, 0},
<<"<closure>"/utf8>>,
private,
[],
none,
Body},
Bounds = lists:append(
gleam@list:map(Params, fun self_referential_bound/1),
gleam@list:map(
maps:keys(Ambient_operators),
fun self_referential_bound/1
)
),
{Body_pairs, Memo@1} = collect_effects(
Synthetic,
Function_map,
Context,
Knowledge_base,
Visited,
Bounds,
Registry,
Module_types,
Ambient_operators,
Cache,
Memo
),
Body_term = union_of(Body_pairs),
Callback_params = case Positions of
[] ->
case Params of
[First | _] ->
[First];
[] ->
[]
end;
_ ->
gleam@list:filter_map(
Positions,
fun(Position) ->
graded@internal@extract:at(Params, Position)
end
)
end,
Operator = gleam@list:fold_right(
Callback_params,
Body_term,
fun(Acc, Param) -> {t_abs, Param, Acc} end
),
{Operator, Memo@1}.
-file("src/graded/internal/checker.gleam", 1774).
?DOC(false).
-spec analyze_closure(
list(binary()),
list(glance:statement()),
list(integer()),
graded@internal@extract:import_context(),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@effects:knowledge_base(),
gleam@set:set(binary()),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
gleam@dict:dict(binary(), list(integer())),
local_cache(),
memo()
) -> {graded@internal@types:effect_term(), memo()}.
analyze_closure(
Params,
Body,
Positions,
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Ambient_operators,
Cache,
Memo
) ->
Key = {closure_body_start(Body),
Positions,
gleam@list:sort(
maps:keys(Ambient_operators),
fun gleam@string:compare/2
),
gleam@list:sort(gleam@set:to_list(Visited), fun gleam@string:compare/2)},
case gleam_stdlib:map_get(erlang:element(5, Memo), Key) of
{ok, Cached} ->
{Cached, Memo};
{error, nil} ->
{Operator, Memo@1} = analyze_closure_uncached(
Params,
Body,
Positions,
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Ambient_operators,
Cache,
Memo
),
{Operator,
{memo,
erlang:element(2, Memo@1),
erlang:element(3, Memo@1),
erlang:element(4, Memo@1),
gleam@dict:insert(erlang:element(5, Memo@1), Key, Operator)}}
end.
-file("src/graded/internal/checker.gleam", 1457).
?DOC(false).
-spec build_lift_operator_arg(
graded@internal@extract:import_context(),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@effects:knowledge_base(),
gleam@set:set(binary()),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
gleam@dict:dict(binary(), list(integer())),
local_cache()
) -> fun((graded@internal@types:argument_value(), list(integer()), memo()) -> {{ok,
graded@internal@types:effect_term()} |
{error, nil},
memo()}).
build_lift_operator_arg(
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Ambient_operators,
Cache
) ->
fun(Value, Positions, Memo) -> case Value of
{closure, Params, Body} ->
{Operator, Memo@1} = analyze_closure(
Params,
Body,
Positions,
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Ambient_operators,
Cache,
Memo
),
{{ok, Operator}, Memo@1};
{local_ref, Name} ->
case {gleam@set:contains(Visited, Name),
gleam_stdlib:map_get(Function_map, Name)} of
{false, {ok, Definition}} ->
{Operator@1, Memo@2} = lift_local_function(
Name,
Definition,
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Cache,
Memo
),
{{ok, Operator@1}, Memo@2};
{_, _} ->
{{error, nil}, Memo}
end;
{returned_operator, Callee, Args} ->
resolve_returned_operator(
Callee,
Args,
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Cache,
Memo
);
_ ->
{{error, nil}, Memo}
end end.
-file("src/graded/internal/checker.gleam", 1601).
?DOC(false).
-spec bind_producer_params(
graded@internal@types:effect_term(),
graded@internal@types:qualified_name(),
list(graded@internal@types:call_argument()),
graded@internal@extract:import_context(),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@effects:knowledge_base(),
gleam@set:set(binary()),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
local_cache(),
memo()
) -> {graded@internal@types:effect_term(), memo()}.
bind_producer_params(
Operator,
Callee,
Args,
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Cache,
Memo
) ->
{Bounds@1, Effective_registry} = case erlang:element(2, Callee) of
<<""/utf8>> ->
case gleam_stdlib:map_get(Function_map, erlang:element(3, Callee)) of
{ok, Definition} ->
Local_registry = graded@internal@signatures:from_glance_module(
<<""/utf8>>,
{module, [], [], [], [], [Definition]}
),
Bounds = begin
_pipe = erlang:element(3, Definition),
_pipe@1 = ordered_fn_typed_param_names(_pipe),
gleam@list:map(_pipe@1, fun self_referential_bound/1)
end,
{Bounds,
graded@internal@signatures:merge(
Registry,
Local_registry
)};
{error, nil} ->
{[], Registry}
end;
_ ->
{graded@internal@effects:lookup_param_bounds(Knowledge_base, Callee),
Registry}
end,
Lift = build_lift_operator_arg(
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
maps:new(),
Cache
),
{Bindings, Memo@1} = bind_variables(
Callee,
Bounds@1,
Args,
Knowledge_base,
[],
Effective_registry,
Lift,
Memo
),
{graded@internal@effect_term:normalize(
graded@internal@effect_term:subst(Operator, Bindings)
),
Memo@1}.
-file("src/graded/internal/checker.gleam", 1678).
?DOC(false).
-spec compute_returned_operator(
glance:function_(),
graded@internal@extract:import_context(),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@effects:knowledge_base(),
gleam@set:set(binary()),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
local_cache(),
memo()
) -> {{ok, graded@internal@types:effect_term()} | {error, nil}, memo()}.
compute_returned_operator(
Function,
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Cache,
Memo
) ->
Gated = begin
gleam@result:'try'(
gleam@option:to_result(erlang:element(6, Function), nil),
fun(Return_type) ->
gleam@bool:guard(
not graded@internal@signatures:is_function_return_type(
Return_type
),
{error, nil},
fun() ->
gleam@result:'try'(
graded@internal@extract:return_value(
Function,
Context
),
fun(Value) -> {ok, {Return_type, Value}} end
)
end
)
end
)
end,
case Gated of
{error, nil} ->
{{error, nil}, Memo};
{ok, {Return_type@1, Value@1}} ->
Positions = graded@internal@signatures:operator_callback_positions_of_type(
Return_type@1
),
Producer_operators = graded@internal@signatures:operator_params_from_function(
Function
),
Producer_bounds = begin
_pipe = Function,
_pipe@1 = ordered_fn_typed_param_names(_pipe),
gleam@list:map(_pipe@1, fun self_referential_bound/1)
end,
Lift = build_lift_operator_arg(
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Producer_operators,
Cache
),
{Operator, Memo@1} = operator_term_for_argument(
{call_argument, 0, none, Value@1},
Positions,
Knowledge_base,
Producer_bounds,
Registry,
Lift,
Memo
),
{compute_returned_operator_result(Operator), Memo@1}
end.
-file("src/graded/internal/checker.gleam", 1534).
?DOC(false).
-spec resolve_returned_operator(
graded@internal@types:qualified_name(),
list(graded@internal@types:call_argument()),
graded@internal@extract:import_context(),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@effects:knowledge_base(),
gleam@set:set(binary()),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
local_cache(),
memo()
) -> {{ok, graded@internal@types:effect_term()} | {error, nil}, memo()}.
resolve_returned_operator(
Callee,
Args,
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Cache,
Memo
) ->
{Lookup, Memo@1} = case erlang:element(2, Callee) of
<<""/utf8>> ->
case {gleam@set:contains(Visited, erlang:element(3, Callee)),
gleam_stdlib:map_get(Function_map, erlang:element(3, Callee))} of
{false, {ok, Definition}} ->
compute_returned_operator(
erlang:element(3, Definition),
Context,
Function_map,
Knowledge_base,
gleam@set:insert(Visited, erlang:element(3, Callee)),
Registry,
Module_types,
Cache,
Memo
);
{_, _} ->
{{error, nil}, Memo}
end;
_ ->
{graded@internal@effects:lookup_returned_operator(
Knowledge_base,
Callee
),
Memo}
end,
case Lookup of
{error, nil} ->
{{error, nil}, Memo@1};
{ok, Operator} ->
case gleam@set:is_empty(
graded@internal@effect_term:free_vars(Operator)
) of
true ->
{{ok, Operator}, Memo@1};
false ->
{Bound, Memo@2} = bind_producer_params(
Operator,
Callee,
Args,
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Cache,
Memo@1
),
{{ok, Bound}, Memo@2}
end
end.
-file("src/graded/internal/checker.gleam", 2208).
?DOC(false).
-spec memoized_local(
graded@internal@types:local_call(),
glance:definition(glance:function_()),
gleam@set:set(binary()),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@extract:import_context(),
graded@internal@effects:knowledge_base(),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
local_cache(),
memo()
) -> {list({graded@internal@types:resolved_call(),
graded@internal@types:effect_term()}),
memo()}.
memoized_local(
Local_call,
Local_definition,
Visited,
Function_map,
Context,
Knowledge_base,
Registry,
Module_types,
Cache,
Memo
) ->
Scc = begin
_pipe = gleam_stdlib:map_get(
erlang:element(2, Cache),
erlang:element(2, Local_call)
),
gleam@result:unwrap(_pipe, -1)
end,
case gleam@set:contains(erlang:element(4, Cache), Scc) of
true ->
collapsed_scc(
Scc,
Function_map,
Context,
Knowledge_base,
Registry,
Module_types,
Cache,
Memo
);
false ->
Nested_bounds = synthetic_fn_typed_bounds(
graded@internal@signatures:fn_typed_params_from_function(
erlang:element(3, Local_definition)
)
),
Key = memo_key(erlang:element(2, Local_call), Visited, Cache),
case gleam_stdlib:map_get(erlang:element(2, Memo), Key) of
{ok, Cached} ->
{Cached, Memo};
{error, nil} ->
New_visited = gleam@set:insert(
Visited,
erlang:element(2, Local_call)
),
{Result, Memo@1} = collect_effects(
without_returned_closure(
erlang:element(3, Local_definition)
),
Function_map,
Context,
Knowledge_base,
New_visited,
Nested_bounds,
Registry,
Module_types,
maps:new(),
Cache,
Memo
),
{Result,
{memo,
gleam@dict:insert(
erlang:element(2, Memo@1),
Key,
Result
),
erlang:element(3, Memo@1),
erlang:element(4, Memo@1),
erlang:element(5, Memo@1)}}
end
end.
-file("src/graded/internal/checker.gleam", 2128).
?DOC(false).
-spec resolve_unknown_local(
graded@internal@types:local_call(),
gleam@set:set(binary()),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@extract:import_context(),
graded@internal@effects:knowledge_base(),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
local_cache(),
memo()
) -> {list({graded@internal@types:resolved_call(),
graded@internal@types:effect_term()}),
memo()}.
resolve_unknown_local(
Local_call,
Visited,
Function_map,
Context,
Knowledge_base,
Registry,
Module_types,
Cache,
Memo
) ->
gleam@bool:guard(
gleam@set:contains(Visited, erlang:element(2, Local_call)),
{[], Memo},
fun() ->
case gleam_stdlib:map_get(
Function_map,
erlang:element(2, Local_call)
) of
{error, nil} ->
Synthetic_call = {resolved_call,
{qualified_name,
<<"<local>"/utf8>>,
erlang:element(2, Local_call)},
erlang:element(3, Local_call)},
{[{Synthetic_call, graded@internal@effect_term:unknown()}],
Memo};
{ok, Local_definition} ->
case is_opaque_external(Local_definition) of
true ->
{[{{resolved_call,
{qualified_name,
<<"<local>"/utf8>>,
erlang:element(2, Local_call)},
erlang:element(3, Local_call)},
graded@internal@effect_term:unknown()}],
Memo};
false ->
memoized_local(
Local_call,
Local_definition,
Visited,
Function_map,
Context,
Knowledge_base,
Registry,
Module_types,
Cache,
Memo
)
end
end
end
).
-file("src/graded/internal/checker.gleam", 777).
?DOC(false).
-spec collect_effects(
glance:function_(),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@extract:import_context(),
graded@internal@effects:knowledge_base(),
gleam@set:set(binary()),
list(graded@internal@types:param_bound()),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
gleam@dict:dict(binary(), list(integer())),
local_cache(),
memo()
) -> {list({graded@internal@types:resolved_call(),
graded@internal@types:effect_term()}),
memo()}.
collect_effects(
Function,
Function_map,
Context,
Knowledge_base,
Visited,
Param_bounds,
Registry,
Module_types,
Ambient_operators,
Cache,
Memo
) ->
Result = graded@internal@extract:extract_calls(
erlang:element(7, Function),
Context
),
Operator_params = maps:merge(
Ambient_operators,
graded@internal@signatures:operator_params_from_function(Function)
),
Lift_operator_arg = build_lift_operator_arg(
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Ambient_operators,
Cache
),
{Memo@3, Resolved_effects} = gleam@list:map_fold(
erlang:element(2, Result),
Memo,
fun(Memo@1, Call) ->
Effect_set = graded@internal@effects:lookup_effects(
Knowledge_base,
erlang:element(2, Call)
),
{Concrete, Memo@2} = substitute_at_call_site(
Call,
Effect_set,
erlang:element(8, Result),
Knowledge_base,
Param_bounds,
Registry,
Lift_operator_arg,
Memo@1
),
{Memo@2, {Call, Concrete}}
end
),
{Memo@6, Local_effects_nested} = gleam@list:map_fold(
erlang:element(3, Result),
Memo@3,
fun(Memo@4, Local_call) ->
case gleam@list:find(
Param_bounds,
fun(Param) ->
erlang:element(2, Param) =:= erlang:element(2, Local_call)
end
) of
{ok, Bound} ->
Synthetic_call = {resolved_call,
{qualified_name,
<<"<param>"/utf8>>,
erlang:element(2, Local_call)},
erlang:element(3, Local_call)},
Effect = case gleam_stdlib:map_get(
Operator_params,
erlang:element(2, Local_call)
) of
{error, nil} ->
erlang:element(3, Bound);
{ok, Positions} ->
curried_operator_application(
erlang:element(3, Bound),
Positions,
erlang:element(8, Result),
erlang:element(2, erlang:element(3, Local_call)),
Knowledge_base,
Param_bounds
)
end,
{Memo@4, [{Synthetic_call, Effect}]};
{error, nil} ->
{Recursive, Memo@5} = resolve_unknown_local(
Local_call,
Visited,
Function_map,
Context,
Knowledge_base,
Registry,
Module_types,
Cache,
Memo@4
),
_pipe = substitute_local_call_effects(
Recursive,
Local_call,
erlang:element(8, Result),
Function_map,
Knowledge_base,
Param_bounds,
Registry,
Lift_operator_arg,
Memo@5
),
(fun(Pair) ->
{erlang:element(2, Pair), erlang:element(1, Pair)}
end)(_pipe)
end
end
),
Local_effects = lists:append(Local_effects_nested),
{Memo@9, Field_effects} = gleam@list:map_fold(
erlang:element(4, Result),
Memo@6,
fun(Memo@7, Field_call) ->
Synthetic_call@1 = {resolved_call,
{qualified_name,
<<"<field>"/utf8>>,
<<<<(erlang:element(2, Field_call))/binary, "."/utf8>>/binary,
(erlang:element(3, Field_call))/binary>>},
erlang:element(4, Field_call)},
{Effect_set@1, Memo@8} = resolve_field_call(
Field_call,
Function,
Knowledge_base,
Module_types,
erlang:element(8, Result),
Param_bounds,
Registry,
Lift_operator_arg,
Memo@7
),
{Memo@8, {Synthetic_call@1, Effect_set@1}}
end
),
{Memo@12, Direct_op_effects} = gleam@list:map_fold(
erlang:element(6, Result),
Memo@9,
fun(Memo@10, Op) ->
Synthetic_call@2 = {resolved_call,
{qualified_name,
<<"<returned>"/utf8>>,
erlang:element(3, erlang:element(2, Op))},
erlang:element(4, Op)},
{Resolved_op, Memo@11} = resolve_returned_operator(
erlang:element(2, Op),
erlang:element(3, Op),
Context,
Function_map,
Knowledge_base,
Visited,
Registry,
Module_types,
Cache,
Memo@10
),
Effect@1 = case Resolved_op of
{ok, Operator} ->
Positions@1 = positions_up_to(
operator_spine_arity(Operator)
),
curried_operator_application(
Operator,
Positions@1,
erlang:element(8, Result),
erlang:element(2, erlang:element(4, Op)),
Knowledge_base,
Param_bounds
);
{error, nil} ->
graded@internal@effect_term:unknown()
end,
{Memo@11, {Synthetic_call@2, Effect@1}}
end
),
{Memo@15, Direct_pipe_effects} = gleam@list:map_fold(
erlang:element(7, Result),
Memo@12,
fun(Memo@13, Op@1) ->
Synthetic_call@3 = {resolved_call,
{qualified_name, <<"<pipe>"/utf8>>, <<"<operator>"/utf8>>},
erlang:element(3, Op@1)},
{Operator@1, Memo@14} = operator_term_for_argument(
{call_argument, 0, none, erlang:element(2, Op@1)},
[0],
Knowledge_base,
Param_bounds,
Registry,
Lift_operator_arg,
Memo@13
),
Effect@2 = curried_operator_application(
Operator@1,
[0],
erlang:element(8, Result),
erlang:element(2, erlang:element(3, Op@1)),
Knowledge_base,
Param_bounds
),
{Memo@14, {Synthetic_call@3, Effect@2}}
end
),
{lists:append(
[Resolved_effects,
Local_effects,
Field_effects,
Direct_op_effects,
Direct_pipe_effects]
),
Memo@15}.
-file("src/graded/internal/checker.gleam", 678).
?DOC(false).
-spec check_annotation(
graded@internal@types:effect_annotation(),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@extract:import_context(),
graded@internal@effects:knowledge_base(),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
local_cache(),
memo()
) -> {{list(graded@internal@types:violation()),
list(graded@internal@types:warning())},
memo()}.
check_annotation(
Annotation,
Function_map,
Context,
Knowledge_base,
Registry,
Module_types,
Cache,
Memo
) ->
case gleam_stdlib:map_get(Function_map, erlang:element(3, Annotation)) of
{error, nil} ->
{{[], []}, Memo};
{ok, Function_definition} ->
{Body_effects, Memo@1} = collect_effects(
without_returned_closure(erlang:element(3, Function_definition)),
Function_map,
Context,
Knowledge_base,
gleam@set:new(),
erlang:element(4, Annotation),
Registry,
Module_types,
maps:new(),
Cache,
Memo
),
Declared = graded@internal@effect_term:to_effect_set(
erlang:element(5, Annotation)
),
Violations = begin
_pipe = Body_effects,
gleam@list:filter_map(
_pipe,
fun(Pair) ->
{Call, Call_term} = Pair,
Actual = graded@internal@effect_term:to_effect_set(
Call_term
),
case graded@internal@types:is_subset(Actual, Declared) of
true ->
{error, nil};
false ->
{ok,
{violation,
erlang:element(3, Annotation),
erlang:element(2, Call),
erlang:element(3, Call),
Declared,
Actual}}
end
end
)
end,
Extract_result = graded@internal@extract:extract_calls(
erlang:element(7, erlang:element(3, Function_definition)),
Context
),
Warnings = collect_reference_warnings(
erlang:element(3, Annotation),
erlang:element(5, Extract_result),
Knowledge_base
),
{{Violations, Warnings}, Memo@1}
end.
-file("src/graded/internal/checker.gleam", 572).
?DOC(false).
-spec new_memo() -> memo().
new_memo() ->
{memo, maps:new(), maps:new(), maps:new(), maps:new()}.
-file("src/graded/internal/checker.gleam", 597).
?DOC(false).
-spec recursion_edges(
glance:function_(),
graded@internal@extract:import_context(),
gleam@set:set(binary())
) -> gleam@set:set(binary()).
recursion_edges(Function, Context, Names) ->
Result = graded@internal@extract:extract_calls(
erlang:element(7, Function),
Context
),
Local = gleam@list:map(
erlang:element(3, Result),
fun(Call) -> erlang:element(2, Call) end
),
Returned = gleam@list:filter_map(
erlang:element(6, Result),
fun(Op) -> case erlang:element(2, erlang:element(2, Op)) of
<<""/utf8>> ->
{ok, erlang:element(3, erlang:element(2, Op))};
_ ->
{error, nil}
end end
),
Lifted = begin
_pipe = erlang:element(8, Result),
_pipe@1 = maps:values(_pipe),
_pipe@2 = lists:append(_pipe@1),
gleam@list:filter_map(
_pipe@2,
fun(Argument) -> case erlang:element(4, Argument) of
{local_ref, Name} ->
{ok, Name};
_ ->
{error, nil}
end end
)
end,
_pipe@3 = lists:append([Local, Returned, Lifted]),
_pipe@4 = gleam@set:from_list(_pipe@3),
gleam@set:intersection(_pipe@4, Names).
-file("src/graded/internal/checker.gleam", 509).
?DOC(false).
-spec local_call_graph(
list(glance:definition(glance:function_())),
graded@internal@extract:import_context()
) -> gleam@dict:dict(binary(), gleam@set:set(binary())).
local_call_graph(Definitions, Context) ->
Names = begin
_pipe = Definitions,
_pipe@1 = gleam@list:map(
_pipe,
fun(Definition) ->
erlang:element(3, erlang:element(3, Definition))
end
),
gleam@set:from_list(_pipe@1)
end,
gleam@list:fold(
Definitions,
maps:new(),
fun(Graph, Definition@1) ->
Edges = recursion_edges(
erlang:element(3, Definition@1),
Context,
Names
),
gleam@dict:insert(
Graph,
erlang:element(3, erlang:element(3, Definition@1)),
Edges
)
end
).
-file("src/graded/internal/checker.gleam", 482).
?DOC(false).
-spec alias_fn_typed_params(glance:function_(), gleam@set:set(binary())) -> gleam@set:set(binary()).
alias_fn_typed_params(Function, Fn_aliases) ->
_pipe = gleam@list:filter_map(
erlang:element(5, Function),
fun(Parameter) ->
case {erlang:element(3, Parameter), erlang:element(4, Parameter)} of
{{named, Name}, {some, {named_type, _, Type_name, none, _}}} ->
case gleam@set:contains(Fn_aliases, Type_name) of
true ->
{ok, Name};
false ->
{error, nil}
end;
{_, _} ->
{error, nil}
end
end
),
gleam@set:from_list(_pipe).
-file("src/graded/internal/checker.gleam", 457).
?DOC(false).
-spec resolves_to_function(
glance:type(),
gleam@dict:dict(binary(), glance:type()),
gleam@set:set(binary())
) -> boolean().
resolves_to_function(Type_, Alias_map, Seen) ->
case Type_ of
{function_type, _, _, _} ->
true;
{named_type, _, Name, none, _} ->
case gleam@set:contains(Seen, Name) of
true ->
false;
false ->
case gleam_stdlib:map_get(Alias_map, Name) of
{ok, Aliased} ->
resolves_to_function(
Aliased,
Alias_map,
gleam@set:insert(Seen, Name)
);
{error, nil} ->
false
end
end;
_ ->
false
end.
-file("src/graded/internal/checker.gleam", 428).
?DOC(false).
-spec function_type_aliases(list(glance:definition(glance:type_alias()))) -> gleam@set:set(binary()).
function_type_aliases(Aliases) ->
Alias_map = gleam@list:fold(
Aliases,
maps:new(),
fun(Acc, Definition) ->
gleam@dict:insert(
Acc,
erlang:element(3, erlang:element(3, Definition)),
erlang:element(6, erlang:element(3, Definition))
)
end
),
_pipe = gleam@list:filter_map(
maps:keys(Alias_map),
fun(Name) ->
case resolves_to_function(
{named_type, {span, 0, 0}, Name, none, []},
Alias_map,
gleam@set:new()
) of
true ->
{ok, Name};
false ->
{error, nil}
end
end
),
gleam@set:from_list(_pipe).
-file("src/graded/internal/checker.gleam", 370).
?DOC(false).
-spec build_scc_ids(
glance:module_(),
graded@internal@extract:import_context(),
gleam@dict:dict(binary(), gleam@set:set(binary())),
boolean()
) -> local_cache().
build_scc_ids(Module, Context, Girard_fn_typed, Collapse) ->
Definitions = erlang:element(6, Module),
Fn_aliases = function_type_aliases(erlang:element(4, Module)),
Needs_exact = begin
_pipe@3 = gleam@list:filter_map(
Definitions,
fun(Definition) ->
Name = erlang:element(3, erlang:element(3, Definition)),
First_order = begin
_pipe = graded@internal@signatures:fn_typed_params_from_function(
erlang:element(3, Definition)
),
_pipe@1 = gleam@set:union(
_pipe,
alias_fn_typed_params(
erlang:element(3, Definition),
Fn_aliases
)
),
_pipe@2 = gleam@set:union(
_pipe@1,
graded@internal@typeinfo:fn_typed_params(
Girard_fn_typed,
Name
)
),
gleam@set:is_empty(_pipe@2)
end,
case First_order andalso not is_opaque_external(Definition) of
true ->
{error, nil};
false ->
{ok, Name}
end
end
),
gleam@set:from_list(_pipe@3)
end,
_pipe@4 = graded@internal@topo:scc_order(
local_call_graph(Definitions, Context)
),
gleam@list:index_fold(
_pipe@4,
{local_cache, maps:new(), maps:new(), gleam@set:new()},
fun(Cache, Component, Id) ->
Scc_id = gleam@list:fold(
Component,
erlang:element(2, Cache),
fun(Ids, Name@1) -> gleam@dict:insert(Ids, Name@1, Id) end
),
Collapsible = case Collapse andalso not gleam@list:any(
Component,
fun(Name@2) -> gleam@set:contains(Needs_exact, Name@2) end
) of
true ->
gleam@set:insert(erlang:element(4, Cache), Id);
false ->
erlang:element(4, Cache)
end,
{local_cache,
Scc_id,
gleam@dict:insert(erlang:element(3, Cache), Id, Component),
Collapsible}
end
).
-file("src/graded/internal/checker.gleam", 322).
?DOC(false).
-spec build_function_map(glance:module_()) -> gleam@dict:dict(binary(), glance:definition(glance:function_())).
build_function_map(Module) ->
_pipe = erlang:element(6, Module),
_pipe@1 = gleam@list:map(
_pipe,
fun(Definition) ->
{erlang:element(3, erlang:element(3, Definition)), Definition}
end
),
maps:from_list(_pipe@1).
-file("src/graded/internal/checker.gleam", 27).
?DOC(false).
-spec check(
glance:module_(),
list(graded@internal@types:effect_annotation()),
graded@internal@effects:knowledge_base(),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
gleam@dict:dict(binary(), gleam@set:set(binary()))
) -> {list(graded@internal@types:violation()),
list(graded@internal@types:warning())}.
check(
Module,
Annotations,
Knowledge_base,
Registry,
Module_types,
Girard_fn_typed
) ->
Context = begin
_pipe = graded@internal@extract:build_import_context(Module),
_pipe@1 = graded@internal@extract:with_factories(
_pipe,
graded@internal@extract:factory_map(Module)
),
graded@internal@extract:with_cross_factories(
_pipe@1,
graded@internal@effects:factories(Knowledge_base)
)
end,
Function_map = build_function_map(Module),
Cache = build_scc_ids(Module, Context, Girard_fn_typed, true),
{_, Results} = gleam@list:map_fold(
Annotations,
new_memo(),
fun(Memo, Annotation) ->
{Result, Memo@1} = check_annotation(
Annotation,
Function_map,
Context,
Knowledge_base,
Registry,
Module_types,
Cache,
Memo
),
{Memo@1, Result}
end
),
Violations = gleam@list:flat_map(
Results,
fun(R) -> erlang:element(1, R) end
),
Warnings = gleam@list:flat_map(
Results,
fun(R@1) -> erlang:element(2, R@1) end
),
{Violations, Warnings}.
-file("src/graded/internal/checker.gleam", 291).
?DOC(false).
-spec polymorphic_param_bounds(
graded@internal@types:effect_term(),
gleam@set:set(binary())
) -> list(graded@internal@types:param_bound()).
polymorphic_param_bounds(Term, Fn_typed_params) ->
_pipe = Term,
_pipe@1 = graded@internal@effect_term:free_vars(_pipe),
_pipe@2 = gleam@set:to_list(_pipe@1),
_pipe@3 = gleam@list:filter(
_pipe@2,
fun(V) -> gleam@set:contains(Fn_typed_params, V) end
),
_pipe@4 = gleam@list:sort(_pipe@3, fun gleam@string:compare/2),
gleam@list:map(_pipe@4, fun self_referential_bound/1).
-file("src/graded/internal/checker.gleam", 88).
?DOC(false).
-spec infer_with_returns(
glance:module_(),
graded@internal@effects:knowledge_base(),
list(graded@internal@types:effect_annotation()),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
gleam@dict:dict(binary(), gleam@set:set(binary()))
) -> {list(graded@internal@types:effect_annotation()),
gleam@dict:dict(binary(), graded@internal@types:effect_term())}.
infer_with_returns(
Module,
Knowledge_base,
Existing_checks,
Registry,
Module_types,
Girard_fn_typed
) ->
Context = begin
_pipe = graded@internal@extract:build_import_context(Module),
_pipe@1 = graded@internal@extract:with_factories(
_pipe,
graded@internal@extract:factory_map(Module)
),
graded@internal@extract:with_cross_factories(
_pipe@1,
graded@internal@effects:factories(Knowledge_base)
)
end,
Function_map = build_function_map(Module),
Cache = build_scc_ids(Module, Context, Girard_fn_typed, true),
Public_functions = gleam@list:filter(
erlang:element(6, Module),
fun(Definition) ->
erlang:element(4, erlang:element(3, Definition)) =:= public
end
),
{Memo@2, Returned_pairs} = gleam@list:map_fold(
Public_functions,
new_memo(),
fun(Memo, Definition@1) ->
{Returned, Memo@1} = compute_returned_operator(
erlang:element(3, Definition@1),
Context,
Function_map,
Knowledge_base,
gleam@set:new(),
Registry,
Module_types,
Cache,
Memo
),
{Memo@1,
gleam@result:map(
Returned,
fun(Operator) ->
{erlang:element(3, erlang:element(3, Definition@1)),
Operator}
end
)}
end
),
Returned_operators = begin
_pipe@2 = Returned_pairs,
_pipe@3 = gleam@list:filter_map(_pipe@2, fun(Pair) -> Pair end),
maps:from_list(_pipe@3)
end,
Bounds_map = begin
_pipe@4 = Existing_checks,
_pipe@5 = gleam@list:filter(
_pipe@4,
fun(Annotation) -> erlang:element(4, Annotation) /= [] end
),
_pipe@6 = gleam@list:map(
_pipe@5,
fun(Annotation@1) ->
{erlang:element(3, Annotation@1),
erlang:element(4, Annotation@1)}
end
),
maps:from_list(_pipe@6)
end,
{_, Annotations} = gleam@list:map_fold(
Public_functions,
Memo@2,
fun(Memo@3, Definition@2) ->
Param_bounds = begin
_pipe@7 = gleam_stdlib:map_get(
Bounds_map,
erlang:element(3, erlang:element(3, Definition@2))
),
gleam@result:unwrap(_pipe@7, [])
end,
Declared_bound_names = begin
_pipe@8 = Param_bounds,
_pipe@9 = gleam@list:map(
_pipe@8,
fun(B) -> erlang:element(2, B) end
),
gleam@set:from_list(_pipe@9)
end,
Fn_typed_params = begin
_pipe@10 = graded@internal@signatures:fn_typed_params_from_function(
erlang:element(3, Definition@2)
),
_pipe@11 = gleam@set:union(
_pipe@10,
graded@internal@typeinfo:fn_typed_params(
Girard_fn_typed,
erlang:element(3, erlang:element(3, Definition@2))
)
),
gleam@set:filter(
_pipe@11,
fun(Name) ->
not gleam@set:contains(Declared_bound_names, Name)
end
)
end,
Effective_bounds = lists:append(
Param_bounds,
synthetic_fn_typed_bounds(Fn_typed_params)
),
{Effects_term, Memo@5} = case is_opaque_external(Definition@2) of
true ->
{graded@internal@effect_term:unknown(), Memo@3};
false ->
{Pairs, Memo@4} = collect_effects(
without_returned_closure(
erlang:element(3, Definition@2)
),
Function_map,
Context,
Knowledge_base,
gleam@set:new(),
Effective_bounds,
Registry,
Module_types,
maps:new(),
Cache,
Memo@3
),
{union_of(Pairs), Memo@4}
end,
Inferred_params = polymorphic_param_bounds(
Effects_term,
Fn_typed_params
),
{Memo@5,
{effect_annotation,
effects,
erlang:element(3, erlang:element(3, Definition@2)),
Inferred_params,
Effects_term}}
end
),
{Annotations, Returned_operators}.
-file("src/graded/internal/checker.gleam", 66).
?DOC(false).
-spec infer(
glance:module_(),
graded@internal@effects:knowledge_base(),
list(graded@internal@types:effect_annotation()),
graded@internal@signatures:signature_registry(),
gleam@dict:dict({integer(), integer()}, girard@types:type()),
gleam@dict:dict(binary(), gleam@set:set(binary()))
) -> list(graded@internal@types:effect_annotation()).
infer(
Module,
Knowledge_base,
Existing_checks,
Registry,
Module_types,
Girard_fn_typed
) ->
erlang:element(
1,
infer_with_returns(
Module,
Knowledge_base,
Existing_checks,
Registry,
Module_types,
Girard_fn_typed
)
).
-file("src/graded/internal/checker.gleam", 646).
?DOC(false).
-spec closure_field_operator(
list(binary()),
list(glance:statement()),
graded@internal@extract:import_context(),
gleam@dict:dict(binary(), glance:definition(glance:function_())),
graded@internal@effects:knowledge_base(),
local_cache()
) -> graded@internal@types:effect_term().
closure_field_operator(
Params,
Body,
Context,
Function_map,
Knowledge_base,
Scc_ids
) ->
Positions = gleam@list:index_map(Params, fun(_, Index) -> Index end),
erlang:element(
1,
analyze_closure(
Params,
Body,
Positions,
Context,
Function_map,
Knowledge_base,
gleam@set:new(),
graded@internal@signatures:empty(),
maps:new(),
maps:new(),
Scc_ids,
new_memo()
)
).