-module(girard@internal@infer).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/girard/internal/infer.gleam").
-export([set_module/2, register_field_map/3, declare_type/3, register_type_alias/2, fresh_var/1, define/3, mark_live/2, prelude/0, prelude_interface/0, lookup/2, build_interface/6, import_qualified/3, import_value/4, import_type/4, zonk/2, unify/3, generalize/3, has_annotation_vars/1, signature_skeleton/3, bind_params/3, check_body/4, rigid_scheme/3, function_scheme/4, rigid_self_scheme/2, infer_function/3, infer_constant/3, register_custom_type/3, resolve_pending/2]).
-export_type([state/0, pending/0, env/0, module_interface/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 state() :: {state,
integer(),
gleam@dict:dict(integer(), girard@types:type()),
list({glance:span(), girard@types:type()}),
list(pending()),
gleam@set:set(integer())}.
-type pending() :: {pending_field,
girard@types:type(),
binary(),
girard@types:type()} |
{pending_index, girard@types:type(), integer(), girard@types:type()}.
-type env() :: {env,
gleam@dict:dict(binary(), girard@types:scheme()),
gleam@dict:dict(binary(), girard@types:scheme()),
gleam@dict:dict(binary(), {list(binary()), glance:type()}),
gleam@dict:dict(binary(), {list(integer()), girard@types:type()}),
gleam@dict:dict(binary(), gleam@dict:dict(binary(), girard@types:scheme())),
gleam@dict:dict(binary(), {binary(), binary(), integer()}),
gleam@dict:dict(binary(), list(gleam@option:option(binary()))),
gleam@dict:dict(binary(), gleam@dict:dict(binary(), girard@types:type())),
binary(),
gleam@dict:dict(binary(), module_interface()),
gleam@dict:dict(binary(), module_interface()),
gleam@set:set(binary())}.
-type module_interface() :: {module_interface,
binary(),
gleam@dict:dict(binary(), girard@types:scheme()),
gleam@dict:dict(binary(), {binary(), binary(), integer()}),
gleam@dict:dict(binary(), {list(integer()), girard@types:type()}),
gleam@dict:dict(binary(), gleam@dict:dict(binary(), girard@types:scheme())),
gleam@dict:dict(binary(), list(gleam@option:option(binary()))),
gleam@dict:dict(binary(), module_interface())}.
-file("src/girard/internal/infer.gleam", 145).
?DOC(false).
-spec new_state() -> state().
new_state() ->
{state, 0, maps:new(), [], [], gleam@set:new()}.
-file("src/girard/internal/infer.gleam", 155).
?DOC(false).
-spec mark_rigid(state(), list(integer())) -> state().
mark_rigid(St, Ids) ->
{state,
erlang:element(2, St),
erlang:element(3, St),
erlang:element(4, St),
erlang:element(5, St),
gleam@list:fold(Ids, erlang:element(6, St), fun gleam@set:insert/2)}.
-file("src/girard/internal/infer.gleam", 159).
?DOC(false).
-spec is_rigid(state(), integer()) -> boolean().
is_rigid(St, Id) ->
gleam@set:contains(erlang:element(6, St), Id).
-file("src/girard/internal/infer.gleam", 163).
?DOC(false).
-spec new_env() -> env().
new_env() ->
{env,
maps:new(),
maps:new(),
maps:new(),
maps:new(),
maps:new(),
maps:new(),
maps:new(),
maps:new(),
<<""/utf8>>,
maps:new(),
maps:new(),
gleam@set:new()}.
-file("src/girard/internal/infer.gleam", 181).
?DOC(false).
-spec set_module(env(), binary()) -> env().
set_module(Env, Name) ->
{env,
erlang:element(2, Env),
erlang:element(3, Env),
erlang:element(4, Env),
erlang:element(5, Env),
erlang:element(6, Env),
erlang:element(7, Env),
erlang:element(8, Env),
erlang:element(9, Env),
Name,
erlang:element(11, Env),
erlang:element(12, Env),
erlang:element(13, Env)}.
-file("src/girard/internal/infer.gleam", 186).
?DOC(false).
-spec register_field_map(env(), binary(), list(gleam@option:option(binary()))) -> env().
register_field_map(Env, Name, Labels) ->
gleam@bool:guard(
not gleam@list:any(Labels, fun(L) -> L /= none end),
Env,
fun() ->
{env,
erlang:element(2, Env),
erlang:element(3, Env),
erlang:element(4, Env),
erlang:element(5, Env),
erlang:element(6, Env),
erlang:element(7, Env),
gleam@dict:insert(erlang:element(8, Env), Name, Labels),
erlang:element(9, Env),
erlang:element(10, Env),
erlang:element(11, Env),
erlang:element(12, Env),
erlang:element(13, Env)}
end
).
-file("src/girard/internal/infer.gleam", 199).
?DOC(false).
-spec declare_type(env(), binary(), integer()) -> env().
declare_type(Env, Name, Arity) ->
{env,
erlang:element(2, Env),
erlang:element(3, Env),
erlang:element(4, Env),
erlang:element(5, Env),
erlang:element(6, Env),
gleam@dict:insert(
erlang:element(7, Env),
Name,
{erlang:element(10, Env), Name, Arity}
),
erlang:element(8, Env),
erlang:element(9, Env),
erlang:element(10, Env),
erlang:element(11, Env),
erlang:element(12, Env),
erlang:element(13, Env)}.
-file("src/girard/internal/infer.gleam", 211).
?DOC(false).
-spec register_type_alias(env(), glance:type_alias()) -> env().
register_type_alias(Env, Alias) ->
{env,
erlang:element(2, Env),
erlang:element(3, Env),
gleam@dict:insert(
erlang:element(4, Env),
erlang:element(3, Alias),
{erlang:element(5, Alias), erlang:element(6, Alias)}
),
erlang:element(5, Env),
erlang:element(6, Env),
erlang:element(7, Env),
erlang:element(8, Env),
erlang:element(9, Env),
erlang:element(10, Env),
erlang:element(11, Env),
erlang:element(12, Env),
erlang:element(13, Env)}.
-file("src/girard/internal/infer.gleam", 221).
?DOC(false).
-spec fresh_id(state()) -> {integer(), state()}.
fresh_id(St) ->
{erlang:element(2, St),
{state,
erlang:element(2, St) + 1,
erlang:element(3, St),
erlang:element(4, St),
erlang:element(5, St),
erlang:element(6, St)}}.
-file("src/girard/internal/infer.gleam", 225).
?DOC(false).
-spec fresh(state()) -> {girard@types:type(), state()}.
fresh(St) ->
{Id, St@1} = fresh_id(St),
{{var, Id}, St@1}.
-file("src/girard/internal/infer.gleam", 233).
?DOC(false).
-spec var_id(girard@types:type()) -> {ok, integer()} | {error, nil}.
var_id(Type_) ->
case Type_ of
{var, Id} ->
{ok, Id};
_ ->
{error, nil}
end.
-file("src/girard/internal/infer.gleam", 241).
?DOC(false).
-spec fresh_var(state()) -> {girard@types:type(), state()}.
fresh_var(St) ->
fresh(St).
-file("src/girard/internal/infer.gleam", 364).
?DOC(false).
-spec all_vars_bound(girard@types:type(), gleam@set:set(integer())) -> boolean().
all_vars_bound(Type_, Bound) ->
case Type_ of
{var, Id} ->
gleam@set:contains(Bound, Id);
{named, _, _, Args} ->
gleam@list:all(
Args,
fun(_capture) -> all_vars_bound(_capture, Bound) end
);
{fn, Args@1, Ret} ->
gleam@list:all(
Args@1,
fun(_capture@1) -> all_vars_bound(_capture@1, Bound) end
)
andalso all_vars_bound(Ret, Bound);
{tuple, Elements} ->
gleam@list:all(
Elements,
fun(_capture@2) -> all_vars_bound(_capture@2, Bound) end
)
end.
-file("src/girard/internal/infer.gleam", 359).
?DOC(false).
-spec scheme_is_closed(girard@types:scheme()) -> boolean().
scheme_is_closed(Scheme) ->
Bound = gleam@set:from_list(erlang:element(2, Scheme)),
all_vars_bound(erlang:element(3, Scheme), Bound).
-file("src/girard/internal/infer.gleam", 334).
?DOC(false).
-spec bind_value(env(), binary(), girard@types:scheme()) -> env().
bind_value(Env, Name, Scheme) ->
{env,
gleam@dict:insert(erlang:element(2, Env), Name, Scheme),
case scheme_is_closed(Scheme) of
true ->
gleam@dict:delete(erlang:element(3, Env), Name);
false ->
gleam@dict:insert(erlang:element(3, Env), Name, Scheme)
end,
erlang:element(4, Env),
erlang:element(5, Env),
erlang:element(6, Env),
erlang:element(7, Env),
erlang:element(8, Env),
gleam@dict:delete(erlang:element(9, Env), Name),
erlang:element(10, Env),
erlang:element(11, Env),
erlang:element(12, Env),
erlang:element(13, Env)}.
-file("src/girard/internal/infer.gleam", 247).
?DOC(false).
-spec define(env(), binary(), girard@types:scheme()) -> env().
define(Env, Name, Scheme) ->
bind_value(Env, Name, Scheme).
-file("src/girard/internal/infer.gleam", 254).
?DOC(false).
-spec mark_live(env(), list(binary())) -> env().
mark_live(Env, Names) ->
{env,
erlang:element(2, Env),
erlang:element(3, Env),
erlang:element(4, Env),
erlang:element(5, Env),
erlang:element(6, Env),
erlang:element(7, Env),
erlang:element(8, Env),
erlang:element(9, Env),
erlang:element(10, Env),
erlang:element(11, Env),
erlang:element(12, Env),
gleam@set:from_list(Names)}.
-file("src/girard/internal/infer.gleam", 260).
?DOC(false).
-spec prelude() -> {env(), state()}.
prelude() ->
St = new_state(),
Env = begin
_pipe = new_env(),
_pipe@1 = bind_value(
_pipe,
<<"True"/utf8>>,
{scheme, [], girard@internal@prelude:bool()}
),
_pipe@2 = bind_value(
_pipe@1,
<<"False"/utf8>>,
{scheme, [], girard@internal@prelude:bool()}
),
bind_value(
_pipe@2,
<<"Nil"/utf8>>,
{scheme, [], girard@internal@prelude:nil()}
)
end,
{Ok_a, St@1} = fresh_id(St),
{Ok_e, St@2} = fresh_id(St@1),
Env@1 = bind_value(
Env,
<<"Ok"/utf8>>,
{scheme,
[Ok_a, Ok_e],
{fn,
[{var, Ok_a}],
girard@internal@prelude:result({var, Ok_a}, {var, Ok_e})}}
),
{Err_a, St@3} = fresh_id(St@2),
{Err_e, St@4} = fresh_id(St@3),
Env@2 = bind_value(
Env@1,
<<"Error"/utf8>>,
{scheme,
[Err_a, Err_e],
{fn,
[{var, Err_e}],
girard@internal@prelude:result({var, Err_a}, {var, Err_e})}}
),
{Env@2, St@4}.
-file("src/girard/internal/infer.gleam", 301).
?DOC(false).
-spec prelude_interface() -> module_interface().
prelude_interface() ->
Module = <<"gleam"/utf8>>,
Values = maps:from_list(
[{<<"True"/utf8>>, {scheme, [], girard@internal@prelude:bool()}},
{<<"False"/utf8>>, {scheme, [], girard@internal@prelude:bool()}},
{<<"Nil"/utf8>>, {scheme, [], girard@internal@prelude:nil()}},
{<<"Ok"/utf8>>,
{scheme,
[0, 1],
{fn,
[{var, 0}],
girard@internal@prelude:result({var, 0}, {var, 1})}}},
{<<"Error"/utf8>>,
{scheme,
[0, 1],
{fn,
[{var, 1}],
girard@internal@prelude:result({var, 0}, {var, 1})}}}]
),
Types_ = maps:from_list(
[{<<"Int"/utf8>>, {Module, <<"Int"/utf8>>, 0}},
{<<"Float"/utf8>>, {Module, <<"Float"/utf8>>, 0}},
{<<"String"/utf8>>, {Module, <<"String"/utf8>>, 0}},
{<<"Bool"/utf8>>, {Module, <<"Bool"/utf8>>, 0}},
{<<"Nil"/utf8>>, {Module, <<"Nil"/utf8>>, 0}},
{<<"BitArray"/utf8>>, {Module, <<"BitArray"/utf8>>, 0}},
{<<"UtfCodepoint"/utf8>>, {Module, <<"UtfCodepoint"/utf8>>, 0}},
{<<"List"/utf8>>, {Module, <<"List"/utf8>>, 1}},
{<<"Result"/utf8>>, {Module, <<"Result"/utf8>>, 2}}]
),
{module_interface,
Module,
Values,
Types_,
maps:new(),
maps:new(),
maps:new(),
maps:new()}.
-file("src/girard/internal/infer.gleam", 375).
?DOC(false).
-spec lookup(env(), binary()) -> {ok, girard@types:scheme()} | {error, nil}.
lookup(Env, Name) ->
gleam_stdlib:map_get(erlang:element(2, Env), Name).
-file("src/girard/internal/infer.gleam", 437).
?DOC(false).
-spec take(gleam@dict:dict(binary(), GQW), list(binary())) -> gleam@dict:dict(binary(), GQW).
take(D, Keys) ->
gleam@list:fold(
Keys,
maps:new(),
fun(Acc, Key) -> case gleam_stdlib:map_get(D, Key) of
{ok, Value} ->
gleam@dict:insert(Acc, Key, Value);
{error, _} ->
Acc
end end
).
-file("src/girard/internal/infer.gleam", 802).
?DOC(false).
-spec substitute(
gleam@dict:dict(integer(), girard@types:type()),
girard@types:type()
) -> girard@types:type().
substitute(Mapping, Type_) ->
case Type_ of
{var, Id} ->
case gleam_stdlib:map_get(Mapping, Id) of
{ok, Replacement} ->
Replacement;
{error, _} ->
Type_
end;
{named, Module, Name, Args} ->
{named,
Module,
Name,
gleam@list:map(
Args,
fun(_capture) -> substitute(Mapping, _capture) end
)};
{fn, Args@1, Ret} ->
{fn,
gleam@list:map(
Args@1,
fun(_capture@1) -> substitute(Mapping, _capture@1) end
),
substitute(Mapping, Ret)};
{tuple, Elements} ->
{tuple,
gleam@list:map(
Elements,
fun(_capture@2) -> substitute(Mapping, _capture@2) end
)}
end.
-file("src/girard/internal/infer.gleam", 429).
?DOC(false).
-spec instantiate_alias(
list(integer()),
girard@types:type(),
list(girard@types:type())
) -> girard@types:type().
instantiate_alias(Params, Body, Arguments) ->
substitute(maps:from_list(gleam@list:zip(Params, Arguments)), Body).
-file("src/girard/internal/infer.gleam", 2511).
?DOC(false).
-spec resolve_qualified_type(
env(),
state(),
binary(),
binary(),
list(girard@types:type())
) -> {girard@types:type(), state()}.
resolve_qualified_type(Env, St, Alias, Name, Arg_types) ->
case gleam_stdlib:map_get(erlang:element(11, Env), Alias) of
{error, _} ->
{{named, Alias, Name, Arg_types}, St};
{ok, Interface} ->
case gleam_stdlib:map_get(erlang:element(5, Interface), Name) of
{ok, {Params, Body}} ->
{instantiate_alias(Params, Body, Arg_types), St};
{error, _} ->
Origin@1 = case gleam_stdlib:map_get(
erlang:element(4, Interface),
Name
) of
{ok, {Origin, _, _}} ->
Origin;
{error, _} ->
Alias
end,
{{named, Origin@1, Name, Arg_types}, St}
end
end.
-file("src/girard/internal/infer.gleam", 2497).
?DOC(false).
-spec resolve_named_origin(env(), binary(), list(girard@types:type())) -> girard@types:type().
resolve_named_origin(Env, Name, Arg_types) ->
case gleam_stdlib:map_get(erlang:element(5, Env), Name) of
{ok, {Params, Body}} ->
instantiate_alias(Params, Body, Arg_types);
{error, _} ->
case gleam_stdlib:map_get(erlang:element(7, Env), Name) of
{ok, {Origin, Origin_name, _}} ->
{named, Origin, Origin_name, Arg_types};
{error, _} ->
{named, <<"gleam"/utf8>>, Name, Arg_types}
end
end.
-file("src/girard/internal/infer.gleam", 2478).
?DOC(false).
-spec resolve_unqualified_type(
env(),
state(),
binary(),
list(girard@types:type())
) -> {girard@types:type(), state()}.
resolve_unqualified_type(Env, St, Name, Arg_types) ->
case gleam_stdlib:map_get(erlang:element(4, Env), Name) of
{ok, {Params, Aliased}} ->
Alias_names = maps:from_list(gleam@list:zip(Params, Arg_types)),
{{T, St@1}, _} = hydrate_with(Env, Alias_names, St, Aliased),
{T, St@1};
{error, _} ->
{resolve_named_origin(Env, Name, Arg_types), St}
end.
-file("src/girard/internal/infer.gleam", 2465).
?DOC(false).
-spec resolve_named_type(
env(),
state(),
gleam@option:option(binary()),
binary(),
list(girard@types:type())
) -> {girard@types:type(), state()}.
resolve_named_type(Env, St, Module, Name, Arg_types) ->
case Module of
none ->
resolve_unqualified_type(Env, St, Name, Arg_types);
{some, Alias} ->
resolve_qualified_type(Env, St, Alias, Name, Arg_types)
end.
-file("src/girard/internal/infer.gleam", 2534).
?DOC(false).
-spec hydrate_with(
env(),
gleam@dict:dict(binary(), girard@types:type()),
state(),
glance:type()
) -> {{girard@types:type(), state()},
gleam@dict:dict(binary(), girard@types:type())}.
hydrate_with(Env, Names, St, Ast) ->
case Ast of
{named_type, _, Name, Module, Parameters} ->
{Arg_types, St@3, Names@3} = gleam@list:fold(
Parameters,
{[], St, Names},
fun(Acc, P) ->
{Types_, St@1, Names@1} = Acc,
{{T, St@2}, Names@2} = hydrate_with(Env, Names@1, St@1, P),
{[T | Types_], St@2, Names@2}
end
),
Arg_types@1 = lists:reverse(Arg_types),
{T@1, St@4} = resolve_named_type(
Env,
St@3,
Module,
Name,
Arg_types@1
),
{{T@1, St@4}, Names@3};
{tuple_type, _, Elements} ->
{Elem_types, St@7, Names@6} = gleam@list:fold(
Elements,
{[], St, Names},
fun(Acc@1, E) ->
{Types_@1, St@5, Names@4} = Acc@1,
{{T@2, St@6}, Names@5} = hydrate_with(Env, Names@4, St@5, E),
{[T@2 | Types_@1], St@6, Names@5}
end
),
{{{tuple, lists:reverse(Elem_types)}, St@7}, Names@6};
{function_type, _, Parameters@1, Return} ->
{Param_types, St@10, Names@9} = gleam@list:fold(
Parameters@1,
{[], St, Names},
fun(Acc@2, P@1) ->
{Types_@2, St@8, Names@7} = Acc@2,
{{T@3, St@9}, Names@8} = hydrate_with(
Env,
Names@7,
St@8,
P@1
),
{[T@3 | Types_@2], St@9, Names@8}
end
),
{{Ret, St@11}, Names@10} = hydrate_with(Env, Names@9, St@10, Return),
{{{fn, lists:reverse(Param_types), Ret}, St@11}, Names@10};
{variable_type, _, Name@1} ->
case gleam_stdlib:map_get(Names, Name@1) of
{ok, T@4} ->
{{T@4, St}, Names};
{error, _} ->
{T@5, St@12} = fresh(St),
{{T@5, St@12}, gleam@dict:insert(Names, Name@1, T@5)}
end;
{hole_type, _, _} ->
{T@6, St@13} = fresh(St),
{{T@6, St@13}, Names}
end.
-file("src/girard/internal/infer.gleam", 3020).
?DOC(false).
-spec hydrate_in(
env(),
gleam@dict:dict(binary(), girard@types:type()),
state(),
glance:type()
) -> {girard@types:type(), state()}.
hydrate_in(Env, Names, St, Ast) ->
erlang:element(1, hydrate_with(Env, Names, St, Ast)).
-file("src/girard/internal/infer.gleam", 1493).
?DOC(false).
-spec fresh_n(state(), integer()) -> {list(girard@types:type()), state()}.
fresh_n(St, N) ->
gleam@bool:guard(
N =< 0,
{[], St},
fun() ->
{T, St@1} = fresh(St),
{Rest, St@2} = fresh_n(St@1, N - 1),
{[T | Rest], St@2}
end
).
-file("src/girard/internal/infer.gleam", 408).
?DOC(false).
-spec resolve_aliases(env(), state(), list(binary())) -> gleam@dict:dict(binary(), {list(integer()),
girard@types:type()}).
resolve_aliases(Env, St, Type_names) ->
erlang:element(
1,
gleam@list:fold(
Type_names,
{maps:new(), St},
fun(Acc, Name) ->
{Resolved, St@1} = Acc,
case gleam_stdlib:map_get(erlang:element(4, Env), Name) of
{error, _} ->
{Resolved, St@1};
{ok, {Params, Body}} ->
{Param_vars, St@2} = fresh_n(
St@1,
erlang:length(Params)
),
Param_ids = gleam@list:filter_map(
Param_vars,
fun var_id/1
),
Names = maps:from_list(
gleam@list:zip(Params, Param_vars)
),
{Type_, St@3} = hydrate_in(Env, Names, St@2, Body),
{gleam@dict:insert(Resolved, Name, {Param_ids, Type_}),
St@3}
end
end
)
).
-file("src/girard/internal/infer.gleam", 383).
?DOC(false).
-spec build_interface(
env(),
state(),
binary(),
list(binary()),
list(binary()),
list(binary())
) -> module_interface().
build_interface(Env, St, Name, Value_names, Type_names, Accessor_type_names) ->
{module_interface,
Name,
take(erlang:element(2, Env), Value_names),
take(erlang:element(7, Env), Type_names),
resolve_aliases(Env, St, Type_names),
take(erlang:element(6, Env), Accessor_type_names),
take(erlang:element(8, Env), Value_names),
erlang:element(11, Env)}.
-file("src/girard/internal/infer.gleam", 473).
?DOC(false).
-spec index_interface(
gleam@dict:dict(binary(), module_interface()),
module_interface()
) -> gleam@dict:dict(binary(), module_interface()).
index_interface(Index, Interface) ->
gleam@bool:guard(
gleam@dict:has_key(Index, erlang:element(2, Interface)),
Index,
fun() ->
gleam@dict:fold(
erlang:element(8, Interface),
gleam@dict:insert(
Index,
erlang:element(2, Interface),
Interface
),
fun(Acc, _, Nested) -> index_interface(Acc, Nested) end
)
end
).
-file("src/girard/internal/infer.gleam", 447).
?DOC(false).
-spec import_qualified(env(), binary(), module_interface()) -> env().
import_qualified(Env, Alias, Interface) ->
Modules = gleam@dict:fold(
erlang:element(11, Env),
erlang:element(8, Interface),
fun(Acc, Alias@1, Interface@1) ->
gleam@dict:insert(Acc, Alias@1, Interface@1)
end
),
{env,
erlang:element(2, Env),
erlang:element(3, Env),
erlang:element(4, Env),
erlang:element(5, Env),
erlang:element(6, Env),
erlang:element(7, Env),
erlang:element(8, Env),
erlang:element(9, Env),
erlang:element(10, Env),
gleam@dict:insert(Modules, Alias, Interface),
index_interface(erlang:element(12, Env), Interface),
erlang:element(13, Env)}.
-file("src/girard/internal/infer.gleam", 487).
?DOC(false).
-spec import_value(env(), binary(), module_interface(), binary()) -> env().
import_value(Env, Local, Interface, Original) ->
Env@1 = case gleam_stdlib:map_get(erlang:element(3, Interface), Original) of
{ok, Scheme} ->
bind_value(Env, Local, Scheme);
{error, _} ->
Env
end,
case gleam_stdlib:map_get(erlang:element(7, Interface), Original) of
{ok, Field_map} ->
{env,
erlang:element(2, Env@1),
erlang:element(3, Env@1),
erlang:element(4, Env@1),
erlang:element(5, Env@1),
erlang:element(6, Env@1),
erlang:element(7, Env@1),
gleam@dict:insert(erlang:element(8, Env@1), Local, Field_map),
erlang:element(9, Env@1),
erlang:element(10, Env@1),
erlang:element(11, Env@1),
erlang:element(12, Env@1),
erlang:element(13, Env@1)};
{error, _} ->
Env@1
end.
-file("src/girard/internal/infer.gleam", 505).
?DOC(false).
-spec import_type(env(), binary(), module_interface(), binary()) -> env().
import_type(Env, Local, Interface, Original) ->
Env@1 = case gleam_stdlib:map_get(erlang:element(4, Interface), Original) of
{ok, Info} ->
{env,
erlang:element(2, Env),
erlang:element(3, Env),
erlang:element(4, Env),
erlang:element(5, Env),
erlang:element(6, Env),
gleam@dict:insert(erlang:element(7, Env), Local, Info),
erlang:element(8, Env),
erlang:element(9, Env),
erlang:element(10, Env),
erlang:element(11, Env),
erlang:element(12, Env),
erlang:element(13, Env)};
{error, _} ->
Env
end,
Env@2 = case gleam_stdlib:map_get(erlang:element(5, Interface), Original) of
{ok, Alias} ->
{env,
erlang:element(2, Env@1),
erlang:element(3, Env@1),
erlang:element(4, Env@1),
gleam@dict:insert(erlang:element(5, Env@1), Local, Alias),
erlang:element(6, Env@1),
erlang:element(7, Env@1),
erlang:element(8, Env@1),
erlang:element(9, Env@1),
erlang:element(10, Env@1),
erlang:element(11, Env@1),
erlang:element(12, Env@1),
erlang:element(13, Env@1)};
{error, _} ->
Env@1
end,
case gleam_stdlib:map_get(erlang:element(6, Interface), Original) of
{ok, Accessors} ->
{env,
erlang:element(2, Env@2),
erlang:element(3, Env@2),
erlang:element(4, Env@2),
erlang:element(5, Env@2),
gleam@dict:insert(erlang:element(6, Env@2), Local, Accessors),
erlang:element(7, Env@2),
erlang:element(8, Env@2),
erlang:element(9, Env@2),
erlang:element(10, Env@2),
erlang:element(11, Env@2),
erlang:element(12, Env@2),
erlang:element(13, Env@2)};
{error, _} ->
Env@2
end.
-file("src/girard/internal/infer.gleam", 534).
?DOC(false).
-spec resolve(state(), girard@types:type()) -> girard@types:type().
resolve(St, Type_) ->
case Type_ of
{var, Id} ->
case gleam_stdlib:map_get(erlang:element(3, St), Id) of
{ok, Bound} ->
resolve(St, Bound);
{error, _} ->
Type_
end;
_ ->
Type_
end.
-file("src/girard/internal/infer.gleam", 546).
?DOC(false).
-spec zonk(state(), girard@types:type()) -> girard@types:type().
zonk(St, Type_) ->
case resolve(St, Type_) of
{named, Module, Name, Args} ->
{named,
Module,
Name,
gleam@list:map(Args, fun(_capture) -> zonk(St, _capture) end)};
{fn, Args@1, Ret} ->
{fn,
gleam@list:map(
Args@1,
fun(_capture@1) -> zonk(St, _capture@1) end
),
zonk(St, Ret)};
{tuple, Elements} ->
{tuple,
gleam@list:map(
Elements,
fun(_capture@2) -> zonk(St, _capture@2) end
)};
{var, Id} ->
{var, Id}
end.
-file("src/girard/internal/infer.gleam", 560).
?DOC(false).
-spec free_vars_loop(girard@types:type(), list(integer())) -> list(integer()).
free_vars_loop(Type_, Acc) ->
case Type_ of
{var, Id} ->
case gleam@list:contains(Acc, Id) of
true ->
Acc;
false ->
[Id | Acc]
end;
{named, _, _, Args} ->
gleam@list:fold(Args, Acc, fun(A, T) -> free_vars_loop(T, A) end);
{fn, Args@1, Ret} ->
free_vars_loop(
Ret,
gleam@list:fold(
Args@1,
Acc,
fun(A@1, T@1) -> free_vars_loop(T@1, A@1) end
)
);
{tuple, Elements} ->
gleam@list:fold(
Elements,
Acc,
fun(A@2, T@2) -> free_vars_loop(T@2, A@2) end
)
end.
-file("src/girard/internal/infer.gleam", 556).
?DOC(false).
-spec free_vars(state(), girard@types:type()) -> list(integer()).
free_vars(St, Type_) ->
free_vars_loop(zonk(St, Type_), []).
-file("src/girard/internal/infer.gleam", 597).
?DOC(false).
-spec scheme_free_vars(
state(),
girard@types:type(),
list(integer()),
list(integer())
) -> list(integer()).
scheme_free_vars(St, Type_, Bound, Acc) ->
case Type_ of
{var, Id} ->
case gleam@list:contains(Bound, Id) of
true ->
Acc;
false ->
case resolve(St, Type_) of
{var, Resolved} ->
case gleam@list:contains(Acc, Resolved) of
true ->
Acc;
false ->
[Resolved | Acc]
end;
Other ->
scheme_free_vars(St, Other, Bound, Acc)
end
end;
{named, _, _, Args} ->
gleam@list:fold(
Args,
Acc,
fun(A, T) -> scheme_free_vars(St, T, Bound, A) end
);
{fn, Args@1, Ret} ->
scheme_free_vars(
St,
Ret,
Bound,
gleam@list:fold(
Args@1,
Acc,
fun(A@1, T@1) -> scheme_free_vars(St, T@1, Bound, A@1) end
)
);
{tuple, Elements} ->
gleam@list:fold(
Elements,
Acc,
fun(A@2, T@2) -> scheme_free_vars(St, T@2, Bound, A@2) end
)
end.
-file("src/girard/internal/infer.gleam", 578).
?DOC(false).
-spec env_free_vars(state(), env()) -> list(integer()).
env_free_vars(St, Env) ->
gleam@dict:fold(
erlang:element(3, Env),
[],
fun(Acc, _, Scheme) ->
scheme_free_vars(
St,
erlang:element(3, Scheme),
erlang:element(2, Scheme),
Acc
)
end
).
-file("src/girard/internal/infer.gleam", 694).
?DOC(false).
-spec occurs(state(), integer(), girard@types:type()) -> boolean().
occurs(St, Id, Type_) ->
gleam@list:contains(free_vars(St, Type_), Id).
-file("src/girard/internal/infer.gleam", 686).
?DOC(false).
-spec bind_var(state(), integer(), girard@types:type()) -> {ok, state()} |
{error, girard@types:error()}.
bind_var(St, Id, Type_) ->
gleam@bool:guard(
occurs(St, Id, Type_),
{error, {recursive_type, Id, Type_}},
fun() ->
{ok,
{state,
erlang:element(2, St),
gleam@dict:insert(erlang:element(3, St), Id, Type_),
erlang:element(4, St),
erlang:element(5, St),
erlang:element(6, St)}}
end
).
-file("src/girard/internal/infer.gleam", 671).
?DOC(false).
-spec unify_many(state(), list(girard@types:type()), list(girard@types:type())) -> {ok,
state()} |
{error, girard@types:error()}.
unify_many(St, Left, Right) ->
case {Left, Right} of
{[], []} ->
{ok, St};
{[X | Xs], [Y | Ys]} ->
gleam@result:'try'(
unify(St, X, Y),
fun(St@1) -> unify_many(St@1, Xs, Ys) end
);
{_, _} ->
{error, arity_mismatch}
end.
-file("src/girard/internal/infer.gleam", 633).
?DOC(false).
-spec unify(state(), girard@types:type(), girard@types:type()) -> {ok, state()} |
{error, girard@types:error()}.
unify(St, Left, Right) ->
Left@1 = resolve(St, Left),
Right@1 = resolve(St, Right),
case {Left@1, Right@1} of
{{var, I}, {var, J}} when I =:= J ->
{ok, St};
{{var, I@1}, {var, J@1}} ->
case {is_rigid(St, I@1), is_rigid(St, J@1)} of
{true, true} ->
{error, {type_mismatch, Left@1, Right@1}};
{true, false} ->
bind_var(St, J@1, Left@1);
{false, _} ->
bind_var(St, I@1, Right@1)
end;
{{var, I@2}, Other} ->
case is_rigid(St, I@2) of
true ->
{error, {type_mismatch, Left@1, Right@1}};
false ->
bind_var(St, I@2, Other)
end;
{Other@1, {var, J@2}} ->
case is_rigid(St, J@2) of
true ->
{error, {type_mismatch, Left@1, Right@1}};
false ->
bind_var(St, J@2, Other@1)
end;
{{named, M1, N1, A1}, {named, M2, N2, A2}} when (M1 =:= M2) andalso (N1 =:= N2) ->
unify_many(St, A1, A2);
{{fn, Args1, R1}, {fn, Args2, R2}} ->
gleam@result:'try'(
unify_many(St, Args1, Args2),
fun(St@1) -> unify(St@1, R1, R2) end
);
{{tuple, E1}, {tuple, E2}} ->
unify_many(St, E1, E2);
{_, _} ->
{error, {type_mismatch, Left@1, Right@1}}
end.
-file("src/girard/internal/infer.gleam", 702).
?DOC(false).
-spec generalize(state(), env(), girard@types:type()) -> girard@types:scheme().
generalize(St, Env, Type_) ->
Zonked = zonk(St, Type_),
Env_vars = env_free_vars(St, Env),
Quantified = gleam@list:filter(
free_vars(St, Zonked),
fun(Id) -> not gleam@list:contains(Env_vars, Id) end
),
{scheme, Quantified, Zonked}.
-file("src/girard/internal/infer.gleam", 713).
?DOC(false).
-spec generalize_over(state(), env(), girard@types:type(), list(integer())) -> girard@types:scheme().
generalize_over(St, Env, Type_, Candidate_ids) ->
Zonked = zonk(St, Type_),
Env_vars = env_free_vars(St, Env),
Free = free_vars(St, Zonked),
Reps = gleam@list:filter_map(
Candidate_ids,
fun(Id) -> case zonk(St, {var, Id}) of
{var, Rep} ->
{ok, Rep};
_ ->
{error, nil}
end end
),
Quantified = gleam@list:unique(
gleam@list:filter(
Reps,
fun(Id@1) ->
gleam@list:contains(Free, Id@1) andalso not gleam@list:contains(
Env_vars,
Id@1
)
end
)
),
{scheme, Quantified, Zonked}.
-file("src/girard/internal/infer.gleam", 758).
?DOC(false).
-spec type_var_names(glance:type()) -> list(binary()).
type_var_names(Ast) ->
case Ast of
{variable_type, _, Name} ->
[Name];
{named_type, _, _, _, Parameters} ->
gleam@list:flat_map(Parameters, fun type_var_names/1);
{tuple_type, _, Elements} ->
gleam@list:flat_map(Elements, fun type_var_names/1);
{function_type, _, Parameters@1, Return} ->
lists:append(
gleam@list:flat_map(Parameters@1, fun type_var_names/1),
type_var_names(Return)
);
{hole_type, _, _} ->
[]
end.
-file("src/girard/internal/infer.gleam", 741).
?DOC(false).
-spec fn_annotation_var_names(
list(glance:fn_parameter()),
gleam@option:option(glance:type())
) -> list(binary()).
fn_annotation_var_names(Params, Return_annotation) ->
From_params = gleam@list:flat_map(
Params,
fun(P) -> case erlang:element(3, P) of
{some, T} ->
type_var_names(T);
none ->
[]
end end
),
case Return_annotation of
{some, T@1} ->
lists:append(From_params, type_var_names(T@1));
none ->
From_params
end.
-file("src/girard/internal/infer.gleam", 774).
?DOC(false).
-spec instantiate(state(), girard@types:scheme()) -> {girard@types:type(),
state()}.
instantiate(St, Scheme) ->
{Mapping@1, St@3} = gleam@list:fold(
erlang:element(2, Scheme),
{maps:new(), St},
fun(Acc, Old) ->
{Mapping, St@1} = Acc,
{Fresh_type, St@2} = fresh(St@1),
{gleam@dict:insert(Mapping, Old, Fresh_type), St@2}
end
),
{substitute(Mapping@1, erlang:element(3, Scheme)), St@3}.
-file("src/girard/internal/infer.gleam", 790).
?DOC(false).
-spec instantiate_in(env(), state(), binary(), girard@types:scheme()) -> {girard@types:type(),
state()}.
instantiate_in(Env, St, Name, Scheme) ->
case gleam@set:contains(erlang:element(13, Env), Name) of
true ->
instantiate(
St,
{scheme,
erlang:element(2, Scheme),
zonk(St, erlang:element(3, Scheme))}
);
false ->
instantiate(St, Scheme)
end.
-file("src/girard/internal/infer.gleam", 3047).
?DOC(false).
-spec span(glance:expression()) -> glance:span().
span(Expr) ->
case Expr of
{int, S, _} ->
S;
{float, S@1, _} ->
S@1;
{string, S@2, _} ->
S@2;
{variable, S@3, _} ->
S@3;
{negate_int, S@4, _} ->
S@4;
{negate_bool, S@5, _} ->
S@5;
{block, S@6, _} ->
S@6;
{panic, S@7, _} ->
S@7;
{todo, S@8, _} ->
S@8;
{tuple, S@9, _} ->
S@9;
{list, S@10, _, _} ->
S@10;
{fn, S@11, _, _, _} ->
S@11;
{record_update, S@12, _, _, _, _} ->
S@12;
{field_access, S@13, _, _} ->
S@13;
{call, S@14, _, _} ->
S@14;
{tuple_index, S@15, _, _} ->
S@15;
{fn_capture, S@16, _, _, _, _} ->
S@16;
{bit_string, S@17, _} ->
S@17;
{'case', S@18, _, _} ->
S@18;
{binary_operator, S@19, _, _, _} ->
S@19;
{echo, S@20, _, _} ->
S@20
end.
-file("src/girard/internal/infer.gleam", 3043).
?DOC(false).
-spec record(state(), glance:span(), girard@types:type()) -> state().
record(St, Span, Type_) ->
{state,
erlang:element(2, St),
erlang:element(3, St),
[{Span, Type_} | erlang:element(4, St)],
erlang:element(5, St),
erlang:element(6, St)}.
-file("src/girard/internal/infer.gleam", 1213).
?DOC(false).
-spec constructor_field_map(env(), gleam@option:option(binary()), binary()) -> list(gleam@option:option(binary())).
constructor_field_map(Env, Module, Constructor) ->
Maps = case Module of
{some, Alias} ->
case gleam_stdlib:map_get(erlang:element(11, Env), Alias) of
{ok, Interface} ->
erlang:element(7, Interface);
{error, _} ->
erlang:element(8, Env)
end;
none ->
erlang:element(8, Env)
end,
case gleam_stdlib:map_get(Maps, Constructor) of
{ok, Labels} ->
Labels;
{error, _} ->
[]
end.
-file("src/girard/internal/infer.gleam", 2330).
?DOC(false).
-spec constructor_scheme(env(), gleam@option:option(binary()), binary()) -> {ok,
girard@types:scheme()} |
{error, girard@types:error()}.
constructor_scheme(Env, Module, Constructor) ->
case Module of
{some, Alias} ->
case gleam_stdlib:map_get(erlang:element(11, Env), Alias) of
{ok, Interface} ->
case gleam_stdlib:map_get(
erlang:element(3, Interface),
Constructor
) of
{ok, Scheme} ->
{ok, Scheme};
{error, _} ->
{error, {no_such_export, Alias, Constructor}}
end;
{error, _} ->
{error, {unknown_module, Alias}}
end;
none ->
case gleam_stdlib:map_get(erlang:element(2, Env), Constructor) of
{ok, Scheme@1} ->
{ok, Scheme@1};
{error, _} ->
{error, {unknown_constructor, Constructor}}
end
end.
-file("src/girard/internal/infer.gleam", 1268).
?DOC(false).
-spec record_variant(
env(),
state(),
gleam@option:option(binary()),
binary(),
girard@types:type(),
binary()
) -> {env(), state()}.
record_variant(Env, St, Module, Constructor, Value_type, Name) ->
Recorded = begin
gleam@result:'try'(
constructor_scheme(Env, Module, Constructor),
fun(Scheme) ->
{Ctor_type, St@1} = instantiate(St, Scheme),
{Field_types, Ret@1} = case Ctor_type of
{fn, Args, Ret} ->
{Args, Ret};
Other ->
{[], Other}
end,
gleam@result:'try'(
unify(St@1, Value_type, Ret@1),
fun(St@2) ->
Labels = constructor_field_map(Env, Module, Constructor),
Fields = gleam@list:fold(
gleam@list:zip(Labels, Field_types),
maps:new(),
fun(Acc, Pair) -> case erlang:element(1, Pair) of
{some, Label} ->
gleam@dict:insert(
Acc,
Label,
resolve(
St@2,
erlang:element(2, Pair)
)
);
none ->
Acc
end end
),
{ok, {Fields, St@2}}
end
)
end
)
end,
case Recorded of
{ok, {Fields@1, St@3}} ->
{{env,
erlang:element(2, Env),
erlang:element(3, Env),
erlang:element(4, Env),
erlang:element(5, Env),
erlang:element(6, Env),
erlang:element(7, Env),
erlang:element(8, Env),
gleam@dict:insert(erlang:element(9, Env), Name, Fields@1),
erlang:element(10, Env),
erlang:element(11, Env),
erlang:element(12, Env),
erlang:element(13, Env)},
St@3};
{error, _} ->
{Env, St}
end.
-file("src/girard/internal/infer.gleam", 1257).
?DOC(false).
-spec is_upper(binary()) -> boolean().
is_upper(Name) ->
case gleam@string:first(Name) of
{ok, C} ->
(string:uppercase(C) =:= C) andalso (string:lowercase(C) /= C);
{error, _} ->
false
end.
-file("src/girard/internal/infer.gleam", 1235).
?DOC(false).
-spec constructor_call(glance:expression()) -> {ok,
{gleam@option:option(binary()), binary()}} |
{error, nil}.
constructor_call(Expr) ->
Callee = case Expr of
{call, _, Function, _} ->
Function;
_ ->
Expr
end,
case Callee of
{variable, _, Name} ->
case is_upper(Name) of
true ->
{ok, {none, Name}};
false ->
{error, nil}
end;
{field_access, _, {variable, _, Module}, Name@1} ->
case is_upper(Name@1) of
true ->
{ok, {{some, Module}, Name@1}};
false ->
{error, nil}
end;
_ ->
{error, nil}
end.
-file("src/girard/internal/infer.gleam", 2356).
?DOC(false).
-spec segment_value_type(
list(glance:bit_string_segment_option(any())),
girard@types:type()
) -> girard@types:type().
segment_value_type(Options, Default) ->
gleam@list:fold(Options, Default, fun(Acc, Option) -> case Option of
float_option ->
girard@internal@prelude:float();
utf8_option ->
girard@internal@prelude:string();
utf16_option ->
girard@internal@prelude:string();
utf32_option ->
girard@internal@prelude:string();
utf8_codepoint_option ->
girard@internal@prelude:utf_codepoint();
utf16_codepoint_option ->
girard@internal@prelude:utf_codepoint();
utf32_codepoint_option ->
girard@internal@prelude:utf_codepoint();
bytes_option ->
girard@internal@prelude:bit_array();
bits_option ->
girard@internal@prelude:bit_array();
int_option ->
girard@internal@prelude:int();
_ ->
Acc
end end).
-file("src/girard/internal/infer.gleam", 2448).
?DOC(false).
-spec indices_loop(integer(), list(integer())) -> list(integer()).
indices_loop(I, Acc) ->
gleam@bool:guard(I < 0, Acc, fun() -> indices_loop(I - 1, [I | Acc]) end).
-file("src/girard/internal/infer.gleam", 2444).
?DOC(false).
-spec indices(integer()) -> list(integer()).
indices(N) ->
indices_loop(N - 1, []).
-file("src/girard/internal/infer.gleam", 1613).
?DOC(false).
-spec label_index(gleam@dict:dict(binary(), integer()), binary()) -> {ok,
integer()} |
{error, girard@types:error()}.
label_index(Index_of, Label) ->
case gleam_stdlib:map_get(Index_of, Label) of
{ok, Index} ->
{ok, Index};
{error, _} ->
{error, {unknown_label, Label}}
end.
-file("src/girard/internal/infer.gleam", 2377).
?DOC(false).
-spec order_pattern_args(
env(),
gleam@option:option(binary()),
binary(),
list(glance:field(glance:pattern())),
integer()
) -> {ok, list(glance:pattern())} | {error, girard@types:error()}.
order_pattern_args(Env, Module, Constructor, Arguments, Arity) ->
Field_maps = case Module of
{some, Alias} ->
case gleam_stdlib:map_get(erlang:element(11, Env), Alias) of
{ok, Interface} ->
erlang:element(7, Interface);
{error, _} ->
erlang:element(8, Env)
end;
none ->
erlang:element(8, Env)
end,
Labels@1 = case gleam_stdlib:map_get(Field_maps, Constructor) of
{ok, Labels} ->
Labels;
{error, _} ->
[]
end,
Index_of = gleam@list:index_fold(
Labels@1,
maps:new(),
fun(Acc, Label, Index) -> case Label of
{some, Name} ->
gleam@dict:insert(Acc, Name, Index);
none ->
Acc
end end
),
gleam@result:'try'(
gleam@list:try_fold(
Arguments,
maps:new(),
fun(Placed, Field) -> case Field of
{unlabelled_field, _} ->
{ok, Placed};
{labelled_field, Label@1, _, Item} ->
gleam@result:'try'(
label_index(Index_of, Label@1),
fun(Index@1) ->
{ok, gleam@dict:insert(Placed, Index@1, Item)}
end
);
{shorthand_field, Label@2, Location} ->
gleam@result:'try'(
label_index(Index_of, Label@2),
fun(Index@2) ->
{ok,
gleam@dict:insert(
Placed,
Index@2,
{pattern_variable, Location, Label@2}
)}
end
)
end end
),
fun(Labelled) ->
Positional = gleam@list:filter_map(
Arguments,
fun(Field@1) -> case Field@1 of
{unlabelled_field, Item@1} ->
{ok, Item@1};
_ ->
{error, nil}
end end
),
Free = gleam@list:filter(
indices(Arity),
fun(I) -> not gleam@dict:has_key(Labelled, I) end
),
Placed@2 = gleam@list:fold(
gleam@list:zip(Free, Positional),
Labelled,
fun(Placed@1, Pair) ->
gleam@dict:insert(
Placed@1,
erlang:element(1, Pair),
erlang:element(2, Pair)
)
end
),
{ok,
gleam@list:map(
indices(Arity),
fun(Index@3) ->
case gleam_stdlib:map_get(Placed@2, Index@3) of
{ok, Pattern} ->
Pattern;
{error, _} ->
{pattern_discard, {span, 0, 0}, <<"_"/utf8>>}
end
end
)}
end
).
-file("src/girard/internal/infer.gleam", 2322).
?DOC(false).
-spec with_env(env(), {ok, state()} | {error, girard@types:error()}) -> {ok,
{env(), state()}} |
{error, girard@types:error()}.
with_env(Env, St) ->
gleam@result:map(St, fun(St@1) -> {Env, St@1} end).
-file("src/girard/internal/infer.gleam", 2291).
?DOC(false).
-spec infer_bit_pattern_segment(
env(),
state(),
{glance:pattern(), list(glance:bit_string_segment_option(glance:pattern()))}
) -> {ok, {env(), state()}} | {error, girard@types:error()}.
infer_bit_pattern_segment(Env, St, Segment) ->
{Pattern, Options} = Segment,
Default = case Pattern of
{pattern_string, _, _} ->
girard@internal@prelude:string();
{pattern_float, _, _} ->
girard@internal@prelude:float();
_ ->
girard@internal@prelude:int()
end,
gleam@result:'try'(
infer_pattern(Env, St, Pattern, segment_value_type(Options, Default)),
fun(_use0) ->
{Env@1, St@1} = _use0,
gleam@list:try_fold(
Options,
{Env@1, St@1},
fun(Acc, Option) ->
{Env@2, St@2} = Acc,
case Option of
{size_value_option, Size} ->
infer_pattern(
Env@2,
St@2,
Size,
girard@internal@prelude:int()
);
_ ->
{ok, {Env@2, St@2}}
end
end
)
end
).
-file("src/girard/internal/infer.gleam", 2175).
?DOC(false).
-spec infer_pattern(env(), state(), glance:pattern(), girard@types:type()) -> {ok,
{env(), state()}} |
{error, girard@types:error()}.
infer_pattern(Env, St, Pattern, Expected) ->
case Pattern of
{pattern_int, _, _} ->
with_env(Env, unify(St, Expected, girard@internal@prelude:int()));
{pattern_float, _, _} ->
with_env(Env, unify(St, Expected, girard@internal@prelude:float()));
{pattern_string, _, _} ->
with_env(Env, unify(St, Expected, girard@internal@prelude:string()));
{pattern_discard, _, _} ->
{ok, {Env, St}};
{pattern_variable, _, Name} ->
{ok, {bind_value(Env, Name, {scheme, [], Expected}), St}};
{pattern_tuple, _, Elements} ->
{Elem_types, St@3} = gleam@list:fold(
Elements,
{[], St},
fun(Acc, _) ->
{Types_, St@1} = Acc,
{T, St@2} = fresh(St@1),
{[T | Types_], St@2}
end
),
Elem_types@1 = lists:reverse(Elem_types),
gleam@result:'try'(
unify(St@3, Expected, {tuple, Elem_types@1}),
fun(St@4) ->
gleam@list:try_fold(
gleam@list:zip(Elements, Elem_types@1),
{Env, St@4},
fun(Acc@1, Pair) ->
{Env@1, St@5} = Acc@1,
{Pattern@1, T@1} = Pair,
infer_pattern(Env@1, St@5, Pattern@1, T@1)
end
)
end
);
{pattern_list, _, Elements@1, Tail} ->
{Elem, St@6} = fresh(St),
gleam@result:'try'(
unify(St@6, Expected, girard@internal@prelude:list(Elem)),
fun(St@7) ->
gleam@result:'try'(
gleam@list:try_fold(
Elements@1,
{Env, St@7},
fun(Acc@2, P) ->
{Env@2, St@8} = Acc@2,
infer_pattern(Env@2, St@8, P, Elem)
end
),
fun(_use0) ->
{Env@3, St@9} = _use0,
case Tail of
{some, T@2} ->
infer_pattern(
Env@3,
St@9,
T@2,
girard@internal@prelude:list(Elem)
);
none ->
{ok, {Env@3, St@9}}
end
end
)
end
);
{pattern_assignment, _, Pattern@2, Name@1} ->
Env@4 = bind_value(Env, Name@1, {scheme, [], Expected}),
{Env@5, St@10} = case Pattern@2 of
{pattern_variant, _, Module, Constructor, _, _} ->
record_variant(
Env@4,
St,
Module,
Constructor,
Expected,
Name@1
);
_ ->
{Env@4, St}
end,
infer_pattern(Env@5, St@10, Pattern@2, Expected);
{pattern_concatenate, _, _, Prefix_name, Rest_name} ->
gleam@result:'try'(
unify(St, Expected, girard@internal@prelude:string()),
fun(St@11) ->
Bind_name = fun(Env@6, Name@2) -> case Name@2 of
{named, N} ->
bind_value(
Env@6,
N,
{scheme,
[],
girard@internal@prelude:string()}
);
{discarded, _} ->
Env@6
end end,
Env@7 = case Prefix_name of
{some, Name@3} ->
Bind_name(Env, Name@3);
none ->
Env
end,
{ok, {Bind_name(Env@7, Rest_name), St@11}}
end
);
{pattern_variant, _, Module@1, Constructor@1, Arguments, _} ->
gleam@result:'try'(
constructor_scheme(Env, Module@1, Constructor@1),
fun(Scheme) ->
{Ctor_type, St@12} = instantiate(St, Scheme),
{Field_types, Ret@1} = case Ctor_type of
{fn, Args, Ret} ->
{Args, Ret};
Other ->
{[], Other}
end,
gleam@result:'try'(
unify(St@12, Expected, Ret@1),
fun(St@13) ->
gleam@result:'try'(
order_pattern_args(
Env,
Module@1,
Constructor@1,
Arguments,
erlang:length(Field_types)
),
fun(Arg_patterns) ->
gleam@list:try_fold(
gleam@list:zip(
Arg_patterns,
Field_types
),
{Env, St@13},
fun(Acc@3, Pair@1) ->
{Env@8, St@14} = Acc@3,
{Pattern@3, T@3} = Pair@1,
infer_pattern(
Env@8,
St@14,
Pattern@3,
T@3
)
end
)
end
)
end
)
end
);
{pattern_bit_string, _, Segments} ->
gleam@result:'try'(
unify(St, Expected, girard@internal@prelude:bit_array()),
fun(St@15) ->
gleam@list:try_fold(
Segments,
{Env, St@15},
fun(Acc@4, Segment) ->
{Env@9, St@16} = Acc@4,
infer_bit_pattern_segment(Env@9, St@16, Segment)
end
)
end
)
end.
-file("src/girard/internal/infer.gleam", 2458).
?DOC(false).
-spec hydrate(env(), state(), glance:type()) -> {girard@types:type(), state()}.
hydrate(Env, St, Ast) ->
erlang:element(1, hydrate_with(Env, maps:new(), St, Ast)).
-file("src/girard/internal/infer.gleam", 1551).
?DOC(false).
-spec label_indices(list(gleam@option:option(binary()))) -> gleam@dict:dict(binary(), integer()).
label_indices(Labels) ->
gleam@list:index_fold(
Labels,
maps:new(),
fun(Acc, Label, Index) -> case Label of
{some, Name} ->
gleam@dict:insert(Acc, Name, Index);
none ->
Acc
end end
).
-file("src/girard/internal/infer.gleam", 1535).
?DOC(false).
-spec callee_labels(env(), glance:expression()) -> {ok,
list(gleam@option:option(binary()))} |
{error, nil}.
callee_labels(Env, Callee) ->
case Callee of
{variable, _, Name} ->
gleam_stdlib:map_get(erlang:element(8, Env), Name);
{field_access, _, {variable, _, Alias}, Name@1} ->
case gleam_stdlib:map_get(erlang:element(11, Env), Alias) of
{ok, Interface} ->
gleam_stdlib:map_get(erlang:element(7, Interface), Name@1);
{error, _} ->
gleam_stdlib:map_get(erlang:element(8, Env), Name@1)
end;
_ ->
{error, nil}
end.
-file("src/girard/internal/infer.gleam", 1500).
?DOC(false).
-spec field_item(glance:field(glance:expression())) -> glance:expression().
field_item(Field) ->
case Field of
{unlabelled_field, Item} ->
Item;
{labelled_field, _, _, Item@1} ->
Item@1;
{shorthand_field, Label, Location} ->
{variable, Location, Label}
end.
-file("src/girard/internal/infer.gleam", 1560).
?DOC(false).
-spec is_unlabelled(glance:field(any())) -> boolean().
is_unlabelled(Field) ->
case Field of
{unlabelled_field, _} ->
true;
_ ->
false
end.
-file("src/girard/internal/infer.gleam", 2913).
?DOC(false).
-spec accessors_of_module(env(), binary()) -> gleam@dict:dict(binary(), gleam@dict:dict(binary(), girard@types:scheme())).
accessors_of_module(Env, Module) ->
case Module =:= erlang:element(10, Env) of
true ->
erlang:element(6, Env);
false ->
case gleam_stdlib:map_get(erlang:element(12, Env), Module) of
{ok, Interface} ->
erlang:element(6, Interface);
{error, _} ->
erlang:element(6, Env)
end
end.
-file("src/girard/internal/infer.gleam", 2896).
?DOC(false).
-spec accessor(env(), girard@types:type(), binary()) -> {ok,
girard@types:scheme()} |
{error, girard@types:error()}.
accessor(Env, Record, Label) ->
case Record of
{named, Module, Name, _} ->
Accessors = accessors_of_module(Env, Module),
case gleam_stdlib:map_get(Accessors, Name) of
{ok, Labels} ->
case gleam_stdlib:map_get(Labels, Label) of
{ok, Scheme} ->
{ok, Scheme};
{error, _} ->
{error, {no_such_field, Name, Label}}
end;
{error, _} ->
{error, {no_such_field, Name, Label}}
end;
_ ->
{error, not_a_record}
end.
-file("src/girard/internal/infer.gleam", 1120).
?DOC(false).
-spec field_type(env(), state(), girard@types:type(), binary()) -> {ok,
{girard@types:type(), state()}} |
{error, girard@types:error()}.
field_type(Env, St, Record, Label) ->
gleam@result:'try'(
accessor(Env, resolve(St, Record), Label),
fun(Accessor_scheme) ->
{Accessor_type, St@1} = instantiate(St, Accessor_scheme),
{Field, St@2} = fresh(St@1),
gleam@result:'try'(
unify(St@2, Accessor_type, {fn, [Record], Field}),
fun(St@3) -> {ok, {Field, St@3}} end
)
end
).
-file("src/girard/internal/infer.gleam", 3073).
?DOC(false).
-spec list_at(list(HAM), integer()) -> {ok, HAM} | {error, nil}.
list_at(Items, Index) ->
case {Items, Index} of
{[X | _], 0} ->
{ok, X};
{[_ | Rest], N} when N > 0 ->
list_at(Rest, N - 1);
{_, _} ->
{error, nil}
end.
-file("src/girard/internal/infer.gleam", 1567).
?DOC(false).
-spec reorder(
list(glance:field(GVD)),
list(gleam@option:option(binary())),
fun((binary(), glance:span()) -> GVD)
) -> {ok, list(GVD)} | {error, girard@types:error()}.
reorder(Fields, Labels, Shorthand) ->
Index_of = label_indices(Labels),
gleam@result:'try'(
gleam@list:try_fold(
Fields,
maps:new(),
fun(Placed, Field) -> case Field of
{unlabelled_field, _} ->
{ok, Placed};
{labelled_field, Label, _, Item} ->
gleam@result:'try'(
label_index(Index_of, Label),
fun(Index) ->
{ok, gleam@dict:insert(Placed, Index, Item)}
end
);
{shorthand_field, Label@1, Location} ->
gleam@result:'try'(
label_index(Index_of, Label@1),
fun(Index@1) ->
{ok,
gleam@dict:insert(
Placed,
Index@1,
Shorthand(Label@1, Location)
)}
end
)
end end
),
fun(Labelled) ->
Positional = gleam@list:filter_map(
Fields,
fun(Field@1) -> case Field@1 of
{unlabelled_field, Item@1} ->
{ok, Item@1};
_ ->
{error, nil}
end end
),
Free = gleam@list:filter(
indices(erlang:length(Labels)),
fun(I) -> not gleam@dict:has_key(Labelled, I) end
),
Placed@2 = gleam@list:fold(
gleam@list:zip(Free, Positional),
Labelled,
fun(Placed@1, Pair) ->
gleam@dict:insert(
Placed@1,
erlang:element(1, Pair),
erlang:element(2, Pair)
)
end
),
gleam@list:try_map(
indices(erlang:length(Labels)),
fun(Index@2) -> case gleam_stdlib:map_get(Placed@2, Index@2) of
{ok, Item@2} ->
{ok, Item@2};
{error, _} ->
{error, missing_argument}
end end
)
end
).
-file("src/girard/internal/infer.gleam", 1511).
?DOC(false).
-spec order_fields(
env(),
glance:expression(),
list(glance:field(GUN)),
fun((binary(), glance:span()) -> GUN)
) -> {ok, list(GUN)} | {error, girard@types:error()}.
order_fields(Env, Callee, Fields, Shorthand) ->
gleam@bool:lazy_guard(
gleam@list:all(Fields, fun is_unlabelled/1),
fun() -> {ok, gleam@list:filter_map(Fields, fun(Field) -> case Field of
{unlabelled_field, Item} ->
{ok, Item};
_ ->
{error, nil}
end end)} end,
fun() -> case callee_labels(Env, Callee) of
{ok, Labels} ->
reorder(Fields, Labels, Shorthand);
{error, _} ->
{error, ambiguous_call}
end end
).
-file("src/girard/internal/infer.gleam", 1452).
?DOC(false).
-spec field_label_is_fn(env(), state(), girard@types:type(), binary()) -> boolean().
field_label_is_fn(Env, St, Record, Label) ->
case field_type(Env, St, Record, Label) of
{error, _} ->
false;
{ok, {Field, St@1}} ->
case resolve(St@1, Field) of
{fn, _, _} ->
true;
_ ->
false
end
end.
-file("src/girard/internal/infer.gleam", 1438).
?DOC(false).
-spec field_is_callable(env(), state(), binary(), binary()) -> boolean().
field_is_callable(Env, St, Name, Label) ->
case gleam_stdlib:map_get(erlang:element(2, Env), Name) of
{error, _} ->
false;
{ok, Scheme} ->
{Value_type, St@1} = instantiate(St, Scheme),
case resolve(St@1, Value_type) of
{named, _, _, _} = Record ->
field_label_is_fn(Env, St@1, Record, Label);
_ ->
false
end
end.
-file("src/girard/internal/infer.gleam", 2065).
?DOC(false).
-spec infer_expr_assignment(
env(),
state(),
glance:pattern(),
gleam@option:option(glance:type()),
glance:expression()
) -> {ok, {girard@types:type(), env(), state()}} | {error, girard@types:error()}.
infer_expr_assignment(Env, St, Pattern, Annotation, Value) ->
gleam@result:'try'(
infer_expr(Env, St, Value),
fun(_use0) ->
{Value_type, St@1} = _use0,
gleam@result:'try'(case Annotation of
{some, Ann} ->
{T, St@2} = hydrate(Env, St@1, Ann),
unify(St@2, Value_type, T);
none ->
{ok, St@1}
end, fun(St@3) ->
gleam@result:'try'(
infer_pattern(Env, St@3, Pattern, Value_type),
fun(_use0@1) ->
{Env@1, St@4} = _use0@1,
{Env@2, St@5} = case {Pattern, Value} of
{{pattern_variable, _, Name}, _} ->
case constructor_call(Value) of
{ok, {Module, Constructor}} ->
record_variant(
Env@1,
St@4,
Module,
Constructor,
Value_type,
Name
);
{error, _} ->
{Env@1, St@4}
end;
{{pattern_variant,
_,
Module@1,
Constructor@1,
_,
_},
{variable, _, Name@1}} ->
record_variant(
Env@1,
St@4,
Module@1,
Constructor@1,
Value_type,
Name@1
);
{_, _} ->
{Env@1, St@4}
end,
{ok, {Value_type, Env@2, St@5}}
end
)
end)
end
).
-file("src/girard/internal/infer.gleam", 2001).
?DOC(false).
-spec infer_statement(env(), state(), glance:statement()) -> {ok,
{girard@types:type(), env(), state()}} |
{error, girard@types:error()}.
infer_statement(Env, St, Statement) ->
case Statement of
{expression, Expr} ->
gleam@result:'try'(
infer_expr(Env, St, Expr),
fun(_use0) ->
{T, St@1} = _use0,
{ok, {T, Env, St@1}}
end
);
{assignment,
_,
_,
{pattern_variable, _, Name} = Pattern,
none,
{fn, Fspan, Fparams, Freturn, Fbody} = Value} ->
case fn_annotation_var_names(Fparams, Freturn) of
[] ->
infer_expr_assignment(Env, St, Pattern, none, Value);
Ann_names ->
{Names@1, Ann_ids, St@4} = gleam@list:fold(
Ann_names,
{maps:new(), [], St},
fun(Acc, Nm) ->
{Names, Ids, St@2} = Acc,
{Id, St@3} = fresh_id(St@2),
{gleam@dict:insert(Names, Nm, {var, Id}),
[Id | Ids],
St@3}
end
),
{Seeds, St@5} = fresh_n(St@4, erlang:length(Fparams)),
gleam@result:'try'(
infer_lambda(
Env,
St@5,
Fparams,
Freturn,
Fbody,
Seeds,
none,
Names@1
),
fun(_use0@1) ->
{Value_type, St@6} = _use0@1,
St@7 = record(St@6, Fspan, Value_type),
Scheme = generalize_over(
St@7,
Env,
Value_type,
Ann_ids
),
{ok,
{Value_type,
bind_value(Env, Name, Scheme),
St@7}}
end
)
end;
{assignment, _, _, Pattern@1, Annotation, Value@1} ->
infer_expr_assignment(Env, St, Pattern@1, Annotation, Value@1);
{assert, _, Expression, _} ->
gleam@result:'try'(
check(Env, St, Expression, girard@internal@prelude:bool()),
fun(St@8) ->
{ok, {girard@internal@prelude:nil(), Env, St@8}}
end
);
{use, _, _, _} ->
{error, {unsupported, <<"use in non-tail position"/utf8>>}}
end.
-file("src/girard/internal/infer.gleam", 1625).
?DOC(false).
-spec classify_call_arg(
env(),
gleam@dict:dict(binary(), integer()),
{gleam@dict:dict(integer(), girard@types:type()),
list(girard@types:type()),
state()},
glance:field(glance:expression())
) -> {ok,
{gleam@dict:dict(integer(), girard@types:type()),
list(girard@types:type()),
state()}} |
{error, girard@types:error()}.
classify_call_arg(Env, Index_of, Acc, Field) ->
{Labelled, Positional, St} = Acc,
case Field of
{unlabelled_field, Item} ->
gleam@result:'try'(
infer_expr(Env, St, Item),
fun(_use0) ->
{T, St@1} = _use0,
{ok, {Labelled, [T | Positional], St@1}}
end
);
{labelled_field, Label, _, Item@1} ->
gleam@result:'try'(
label_index(Index_of, Label),
fun(Index) ->
gleam@result:'try'(
infer_expr(Env, St, Item@1),
fun(_use0@1) ->
{T@1, St@2} = _use0@1,
{ok,
{gleam@dict:insert(Labelled, Index, T@1),
Positional,
St@2}}
end
)
end
);
{shorthand_field, Label@1, Location} ->
gleam@result:'try'(
label_index(Index_of, Label@1),
fun(Index@1) ->
gleam@result:'try'(
infer_expr(Env, St, {variable, Location, Label@1}),
fun(_use0@2) ->
{T@2, St@3} = _use0@2,
{ok,
{gleam@dict:insert(Labelled, Index@1, T@2),
Positional,
St@3}}
end
)
end
)
end.
-file("src/girard/internal/infer.gleam", 1305).
?DOC(false).
-spec infer_each(env(), state(), list(glance:expression())) -> {ok,
{list(girard@types:type()), state()}} |
{error, girard@types:error()}.
infer_each(Env, St, Exprs) ->
gleam@result:'try'(
gleam@list:try_fold(
Exprs,
{[], St},
fun(Acc, E) ->
{Types_, St@1} = Acc,
gleam@result:'try'(
infer_expr(Env, St@1, E),
fun(_use0) ->
{T, St@2} = _use0,
{ok, {[T | Types_], St@2}}
end
)
end
),
fun(_use0@1) ->
{Rev, St@3} = _use0@1,
{ok, {lists:reverse(Rev), St@3}}
end
).
-file("src/girard/internal/infer.gleam", 1945).
?DOC(false).
-spec infer_use_call(
env(),
state(),
glance:expression(),
list(glance:field(glance:expression())),
girard@types:type(),
girard@types:type()
) -> {ok, state()} | {error, girard@types:error()}.
infer_use_call(Env, St, Callee, Arguments, Callback_type, Result) ->
gleam@result:'try'(
infer_expr(Env, St, Callee),
fun(_use0) ->
{Callee_type, St@1} = _use0,
case gleam@list:all(Arguments, fun is_unlabelled/1) of
true ->
gleam@result:'try'(
infer_each(
Env,
St@1,
gleam@list:map(Arguments, fun field_item/1)
),
fun(_use0@1) ->
{Arg_types, St@2} = _use0@1,
unify(
St@2,
Callee_type,
{fn,
lists:append(Arg_types, [Callback_type]),
Result}
)
end
);
false ->
gleam@result:'try'(
gleam@result:replace_error(
callee_labels(Env, Callee),
ambiguous_call
),
fun(Labels) ->
Index_of = label_indices(Labels),
gleam@result:'try'(
gleam@list:try_fold(
Arguments,
{maps:new(), [], St@1},
fun(Acc, Field) ->
classify_call_arg(
Env,
Index_of,
Acc,
Field
)
end
),
fun(_use0@2) ->
{Labelled, Rev_positional, St@3} = _use0@2,
Trailing = lists:append(
lists:reverse(Rev_positional),
[Callback_type]
),
Free = gleam@list:filter(
indices(erlang:length(Labels)),
fun(I) ->
not gleam@dict:has_key(Labelled, I)
end
),
Placed@1 = gleam@list:fold(
gleam@list:zip(Free, Trailing),
Labelled,
fun(Placed, Pair) ->
gleam@dict:insert(
Placed,
erlang:element(1, Pair),
erlang:element(2, Pair)
)
end
),
gleam@result:'try'(
gleam@list:try_map(
indices(erlang:length(Labels)),
fun(Index) ->
gleam@result:replace_error(
gleam_stdlib:map_get(
Placed@1,
Index
),
missing_argument
)
end
),
fun(Arg_types@1) ->
unify(
St@3,
Callee_type,
{fn, Arg_types@1, Result}
)
end
)
end
)
end
)
end
end
).
-file("src/girard/internal/infer.gleam", 1899).
?DOC(false).
-spec infer_use(
env(),
state(),
list(glance:use_pattern()),
glance:expression(),
list(glance:statement())
) -> {ok, {girard@types:type(), state()}} | {error, girard@types:error()}.
infer_use(Env, St, Use_patterns, Function, Rest) ->
gleam@result:'try'(
gleam@list:try_fold(
Use_patterns,
{[], Env, St},
fun(Acc, Use_pattern) ->
{Types_, Env@1, St@1} = Acc,
{Param, St@2} = case erlang:element(3, Use_pattern) of
{some, Ann} ->
hydrate(Env@1, St@1, Ann);
none ->
fresh(St@1)
end,
gleam@result:'try'(
infer_pattern(
Env@1,
St@2,
erlang:element(2, Use_pattern),
Param
),
fun(_use0) ->
{Env@2, St@3} = _use0,
{ok, {[Param | Types_], Env@2, St@3}}
end
)
end
),
fun(_use0@1) ->
{Rev_param_types, Callback_env, St@4} = _use0@1,
Param_types = lists:reverse(Rev_param_types),
gleam@result:'try'(
infer_statements(Callback_env, St@4, Rest),
fun(_use0@2) ->
{Body_type, St@5} = _use0@2,
Callback_type = {fn, Param_types, Body_type},
{Result, St@6} = fresh(St@5),
gleam@result:'try'(case Function of
{call, _, Callee, Arguments} ->
infer_use_call(
Env,
St@6,
Callee,
Arguments,
Callback_type,
Result
);
Other ->
gleam@result:'try'(
infer_expr(Env, St@6, Other),
fun(_use0@3) ->
{Callee_type, St@7} = _use0@3,
unify(
St@7,
Callee_type,
{fn, [Callback_type], Result}
)
end
)
end, fun(St@8) -> {ok, {Result, St@8}} end)
end
)
end
).
-file("src/girard/internal/infer.gleam", 1876).
?DOC(false).
-spec infer_statements(env(), state(), list(glance:statement())) -> {ok,
{girard@types:type(), state()}} |
{error, girard@types:error()}.
infer_statements(Env, St, Statements) ->
case Statements of
[] ->
{ok, {girard@internal@prelude:nil(), St}};
[{use, _, Patterns, Function} | Rest] ->
infer_use(Env, St, Patterns, Function, Rest);
[Last] ->
gleam@result:'try'(
infer_statement(Env, St, Last),
fun(_use0) ->
{T, _, St@1} = _use0,
{ok, {T, St@1}}
end
);
[First | Rest@1] ->
gleam@result:'try'(
infer_statement(Env, St, First),
fun(_use0@1) ->
{_, Env@1, St@2} = _use0@1,
infer_statements(Env@1, St@2, Rest@1)
end
)
end.
-file("src/girard/internal/infer.gleam", 1352).
?DOC(false).
-spec infer_lambda(
env(),
state(),
list(glance:fn_parameter()),
gleam@option:option(glance:type()),
list(glance:statement()),
list(girard@types:type()),
gleam@option:option(girard@types:type()),
gleam@dict:dict(binary(), girard@types:type())
) -> {ok, {girard@types:type(), state()}} | {error, girard@types:error()}.
infer_lambda(
Env,
St,
Params,
Return_annotation,
Body,
Seed_params,
Expected_return,
Names
) ->
gleam@result:'try'(
gleam@list:try_fold(
gleam@list:zip(Params, Seed_params),
{[], Env, St},
fun(Acc, Pair) ->
{Types_, Env@1, St@1} = Acc,
{Param, Seed} = Pair,
gleam@result:'try'(case erlang:element(3, Param) of
{some, Ann} ->
{Annotated, St@2} = hydrate_in(
Env@1,
Names,
St@1,
Ann
),
gleam@result:'try'(
unify(St@2, Annotated, Seed),
fun(St@3) -> {ok, {Seed, St@3}} end
);
none ->
{ok, {Seed, St@1}}
end, fun(_use0) ->
{T, St@4} = _use0,
Env@2 = case erlang:element(2, Param) of
{named, Name} ->
bind_value(Env@1, Name, {scheme, [], T});
{discarded, _} ->
Env@1
end,
{ok, {[T | Types_], Env@2, St@4}}
end)
end
),
fun(_use0@1) ->
{Rev_param_types, Body_env, St@5} = _use0@1,
Param_types = lists:reverse(Rev_param_types),
gleam@result:'try'(
infer_statements(Body_env, St@5, Body),
fun(_use0@2) ->
{Body_type, St@6} = _use0@2,
gleam@result:'try'(case Return_annotation of
{some, Ann@1} ->
{T@1, St@7} = hydrate_in(
Env,
Names,
St@6,
Ann@1
),
unify(St@7, Body_type, T@1);
none ->
{ok, St@6}
end, fun(St@8) ->
gleam@result:'try'(case Expected_return of
{some, Expected} ->
unify(St@8, Body_type, Expected);
none ->
{ok, St@8}
end, fun(St@9) ->
{ok, {{fn, Param_types, Body_type}, St@9}}
end)
end)
end
)
end
).
-file("src/girard/internal/infer.gleam", 1834).
?DOC(false).
-spec check(env(), state(), glance:expression(), girard@types:type()) -> {ok,
state()} |
{error, girard@types:error()}.
check(Env, St, Expr, Expected) ->
Seeded = case Expr of
{fn, _, Params, _, _} ->
case resolve(St, Expected) of
{fn, Expected_params, Expected_return} ->
case erlang:length(Expected_params) =:= erlang:length(
Params
) of
true ->
{ok, {Expected_params, Expected_return}};
false ->
{error, nil}
end;
_ ->
{error, nil}
end;
_ ->
{error, nil}
end,
case {Expr, Seeded} of
{{fn, Span, Params@1, Return_annotation, Body}, {ok, {Seeds, Ret}}} ->
gleam@result:'try'(
infer_lambda(
Env,
St,
Params@1,
Return_annotation,
Body,
Seeds,
{some, Ret},
maps:new()
),
fun(_use0) ->
{Fn_type, St@1} = _use0,
St@2 = record(St@1, Span, Fn_type),
unify(St@2, Fn_type, Expected)
end
);
{_, _} ->
gleam@result:'try'(
infer_expr(Env, St, Expr),
fun(_use0@1) ->
{T, St@3} = _use0@1,
unify(St@3, T, Expected)
end
)
end.
-file("src/girard/internal/infer.gleam", 965).
?DOC(false).
-spec infer_bit_segment(
env(),
state(),
{glance:expression(),
list(glance:bit_string_segment_option(glance:expression()))}
) -> {ok, state()} | {error, girard@types:error()}.
infer_bit_segment(Env, St, Segment) ->
{Value, Options} = Segment,
Default = case Value of
{string, _, _} ->
girard@internal@prelude:string();
{float, _, _} ->
girard@internal@prelude:float();
_ ->
girard@internal@prelude:int()
end,
gleam@result:'try'(
check(Env, St, Value, segment_value_type(Options, Default)),
fun(St@1) ->
gleam@list:try_fold(
Options,
St@1,
fun(St@2, Option) -> case Option of
{size_value_option, Size} ->
check(
Env,
St@2,
Size,
girard@internal@prelude:int()
);
_ ->
{ok, St@2}
end end
)
end
).
-file("src/girard/internal/infer.gleam", 941).
?DOC(false).
-spec update_field(
env(),
state(),
glance:record_update_field(glance:expression()),
gleam@dict:dict(binary(), girard@types:type()),
binary()
) -> {ok, state()} | {error, girard@types:error()}.
update_field(Env, St, Field, Label_types, Type_name) ->
gleam@result:'try'(case erlang:element(3, Field) of
{some, Value} ->
infer_expr(Env, St, Value);
none ->
case gleam_stdlib:map_get(
erlang:element(2, Env),
erlang:element(2, Field)
) of
{ok, Scheme} ->
{ok, instantiate(St, Scheme)};
{error, _} ->
{error, {unbound_variable, erlang:element(2, Field)}}
end
end, fun(_use0) ->
{Value_type, St@1} = _use0,
case gleam_stdlib:map_get(Label_types, erlang:element(2, Field)) of
{ok, Expected} ->
unify(St@1, Value_type, Expected);
{error, _} ->
{error,
{no_such_field, Type_name, erlang:element(2, Field)}}
end
end).
-file("src/girard/internal/infer.gleam", 1135).
?DOC(false).
-spec infer_record_update(
env(),
state(),
gleam@option:option(binary()),
binary(),
glance:expression(),
list(glance:record_update_field(glance:expression()))
) -> {ok, {girard@types:type(), state()}} | {error, girard@types:error()}.
infer_record_update(Env, St, Module, Constructor, Record, Fields) ->
gleam@result:'try'(
constructor_scheme(Env, Module, Constructor),
fun(Scheme) ->
{Ctor_type, St@1} = instantiate(St, Scheme),
{Field_types, Return_type} = case Ctor_type of
{fn, Arguments, Return} ->
{Arguments, Return};
Other ->
{[], Other}
end,
case Return_type of
{named, Type_module, Type_name, Type_parameters} ->
Labels = constructor_field_map(Env, Module, Constructor),
Label_types = gleam@list:fold(
gleam@list:zip(Labels, Field_types),
maps:new(),
fun(Acc, Pair) -> case erlang:element(1, Pair) of
{some, Label} ->
gleam@dict:insert(
Acc,
Label,
erlang:element(2, Pair)
);
none ->
Acc
end end
),
Updated = gleam@list:map(
Fields,
fun(Field) -> erlang:element(2, Field) end
),
{Record_parameters, St@2} = fresh_n(
St@1,
erlang:length(Type_parameters)
),
gleam@result:'try'(
infer_expr(Env, St@2, Record),
fun(_use0) ->
{Record_type, St@3} = _use0,
gleam@result:'try'(
unify(
St@3,
Record_type,
{named,
Type_module,
Type_name,
Record_parameters}
),
fun(St@4) ->
gleam@result:'try'(
gleam@list:try_fold(
Fields,
St@4,
fun(St@5, Field@1) ->
update_field(
Env,
St@5,
Field@1,
Label_types,
Type_name
)
end
),
fun(St@6) ->
To_record_params = maps:from_list(
gleam@list:zip(
gleam@list:filter_map(
Type_parameters,
fun var_id/1
),
Record_parameters
)
),
gleam@result:'try'(
gleam@list:try_fold(
maps:to_list(Label_types),
St@6,
fun(St@7, Pair@1) ->
{Label@1, Expected} = Pair@1,
case gleam@list:contains(
Updated,
Label@1
) of
true ->
{ok, St@7};
false ->
unify(
St@7,
substitute(
To_record_params,
Expected
),
Expected
)
end
end
),
fun(St@8) ->
{ok, {Return_type, St@8}}
end
)
end
)
end
)
end
);
_ ->
{error, not_a_record}
end
end
).
-file("src/girard/internal/infer.gleam", 1088).
?DOC(false).
-spec module_or_record(
env(),
state(),
glance:expression(),
binary(),
{ok, girard@types:scheme()} | {error, nil}
) -> {ok, {girard@types:type(), state()}} | {error, girard@types:error()}.
module_or_record(Env, St, Container, Label, Module_access) ->
case Module_access of
{ok, Scheme} ->
{ok, instantiate(St, Scheme)};
{error, _} ->
gleam@result:'try'(
infer_expr(Env, St, Container),
fun(_use0) ->
{Container_type, St@1} = _use0,
case resolve(St@1, Container_type) of
{named, _, _, _} = Record ->
gleam@result:'try'(
field_type(Env, St@1, Record, Label),
fun(_use0@1) ->
{Field, St@2} = _use0@1,
{ok, {Field, St@2}}
end
);
{var, _} ->
{Field@1, St@3} = fresh(St@1),
St@4 = {state,
erlang:element(2, St@3),
erlang:element(3, St@3),
erlang:element(4, St@3),
[{pending_field, Container_type, Label, Field@1} |
erlang:element(5, St@3)],
erlang:element(6, St@3)},
{ok, {Field@1, St@4}};
_ ->
{error, not_a_record}
end
end
)
end.
-file("src/girard/internal/infer.gleam", 1044).
?DOC(false).
-spec value_field(
env(),
state(),
glance:expression(),
binary(),
{ok, girard@types:scheme()} | {error, nil}
) -> {ok, {girard@types:type(), state()}} | {error, girard@types:error()}.
value_field(Env, St, Container, Label, Module_access) ->
gleam@result:'try'(
infer_expr(Env, St, Container),
fun(_use0) ->
{Container_type, St@1} = _use0,
case resolve(St@1, Container_type) of
{named, _, _, _} = Record ->
case accessor(Env, Record, Label) of
{ok, _} ->
field_type(Env, St@1, Record, Label);
{error, Field_error} ->
case Module_access of
{ok, Scheme} ->
{ok, instantiate(St@1, Scheme)};
{error, _} ->
{error, Field_error}
end
end;
{var, _} ->
case Module_access of
{ok, Scheme@1} ->
{ok, instantiate(St@1, Scheme@1)};
{error, _} ->
{Field, St@2} = fresh(St@1),
St@3 = {state,
erlang:element(2, St@2),
erlang:element(3, St@2),
erlang:element(4, St@2),
[{pending_field, Container_type, Label, Field} |
erlang:element(5, St@2)],
erlang:element(6, St@2)},
{ok, {Field, St@3}}
end;
_ ->
case Module_access of
{ok, Scheme@2} ->
{ok, instantiate(St@1, Scheme@2)};
{error, _} ->
{error, not_a_record}
end
end
end
).
-file("src/girard/internal/infer.gleam", 993).
?DOC(false).
-spec infer_field_access(env(), state(), glance:expression(), binary()) -> {ok,
{girard@types:type(), state()}} |
{error, girard@types:error()}.
infer_field_access(Env, St, Container, Label) ->
Variant_field = case Container of
{variable, _, Name} ->
case gleam_stdlib:map_get(erlang:element(9, Env), Name) of
{ok, Fields} ->
gleam_stdlib:map_get(Fields, Label);
{error, _} ->
{error, nil}
end;
_ ->
{error, nil}
end,
Module_access = case Container of
{variable, _, Name@1} ->
case gleam_stdlib:map_get(erlang:element(11, Env), Name@1) of
{ok, Interface} ->
gleam_stdlib:map_get(erlang:element(3, Interface), Label);
{error, _} ->
{error, nil}
end;
_ ->
{error, nil}
end,
case Variant_field of
{ok, Field} ->
{ok, {Field, St}};
{error, _} ->
case Container of
{variable, _, Name@2} ->
case gleam@dict:has_key(erlang:element(2, Env), Name@2) of
true ->
value_field(
Env,
St,
Container,
Label,
Module_access
);
false ->
module_or_record(
Env,
St,
Container,
Label,
Module_access
)
end;
_ ->
module_or_record(Env, St, Container, Label, Module_access)
end
end.
-file("src/girard/internal/infer.gleam", 2119).
?DOC(false).
-spec infer_clause(
env(),
state(),
glance:clause(),
list(glance:expression()),
list(girard@types:type()),
girard@types:type()
) -> {ok, state()} | {error, girard@types:error()}.
infer_clause(Env, St, Clause, Subjects, Subject_types, Result) ->
gleam@list:try_fold(
erlang:element(2, Clause),
St,
fun(St@1, Patterns) ->
gleam@result:'try'(
gleam@list:try_fold(
gleam@list:zip(
Patterns,
gleam@list:zip(Subjects, Subject_types)
),
{Env, St@1},
fun(Acc, Pair) ->
{Env@1, St@2} = Acc,
{Pattern, {Subject, Subject_type}} = Pair,
gleam@result:'try'(
infer_pattern(Env@1, St@2, Pattern, Subject_type),
fun(_use0) ->
{Env@2, St@3} = _use0,
case {Subject, Pattern} of
{{variable, _, Name},
{pattern_variant,
_,
Module,
Constructor,
_,
_}} ->
{ok,
record_variant(
Env@2,
St@3,
Module,
Constructor,
Subject_type,
Name
)};
{_, _} ->
{ok, {Env@2, St@3}}
end
end
)
end
),
fun(_use0@1) ->
{Clause_env, St@4} = _use0@1,
gleam@result:'try'(case erlang:element(3, Clause) of
{some, Guard} ->
check(
Clause_env,
St@4,
Guard,
girard@internal@prelude:bool()
);
none ->
{ok, St@4}
end, fun(St@5) ->
gleam@result:'try'(
infer_expr(
Clause_env,
St@5,
erlang:element(4, Clause)
),
fun(_use0@2) ->
{Body_type, St@6} = _use0@2,
unify(St@6, Body_type, Result)
end
)
end)
end
)
end
).
-file("src/girard/internal/infer.gleam", 2103).
?DOC(false).
-spec infer_case(
env(),
state(),
list(glance:expression()),
list(glance:clause())
) -> {ok, {girard@types:type(), state()}} | {error, girard@types:error()}.
infer_case(Env, St, Subjects, Clauses) ->
gleam@result:'try'(
infer_each(Env, St, Subjects),
fun(_use0) ->
{Subject_types, St@1} = _use0,
{Result, St@2} = fresh(St@1),
gleam@result:'try'(
gleam@list:try_fold(
Clauses,
St@2,
fun(St@3, Clause) ->
infer_clause(
Env,
St@3,
Clause,
Subjects,
Subject_types,
Result
)
end
),
fun(St@4) -> {ok, {Result, St@4}} end
)
end
).
-file("src/girard/internal/infer.gleam", 1405).
?DOC(false).
-spec infer_callee(env(), state(), glance:expression()) -> {ok,
{girard@types:type(), state()}} |
{error, girard@types:error()}.
infer_callee(Env, St, Function) ->
case Function of
{field_access, _, {variable, _, Name}, Label} ->
Module_export = case gleam_stdlib:map_get(
erlang:element(11, Env),
Name
) of
{ok, Interface} ->
gleam_stdlib:map_get(erlang:element(3, Interface), Label);
{error, _} ->
{error, nil}
end,
case {Module_export, field_is_callable(Env, St, Name, Label)} of
{{ok, Scheme}, false} ->
{Type_, St@1} = instantiate(St, Scheme),
{ok, {Type_, record(St@1, span(Function), Type_)}};
{_, _} ->
infer_expr(Env, St, Function)
end;
_ ->
infer_expr(Env, St, Function)
end.
-file("src/girard/internal/infer.gleam", 1463).
?DOC(false).
-spec infer_call(
env(),
state(),
glance:span(),
glance:expression(),
list(glance:field(glance:expression()))
) -> {ok, {girard@types:type(), state()}} | {error, girard@types:error()}.
infer_call(Env, St, Span, Function, Arguments) ->
gleam@result:'try'(
infer_callee(Env, St, Function),
fun(_use0) ->
{Fn_type, St@1} = _use0,
gleam@result:'try'(
order_fields(
Env,
Function,
Arguments,
fun(Label, Location) -> {variable, Location, Label} end
),
fun(Ordered) ->
{Arg_holes, St@2} = fresh_n(St@1, erlang:length(Ordered)),
{Result, St@3} = fresh(St@2),
gleam@result:'try'(
unify(St@3, Fn_type, {fn, Arg_holes, Result}),
fun(St@4) ->
gleam@result:'try'(
gleam@list:try_fold(
gleam@list:zip(Ordered, Arg_holes),
St@4,
fun(St@5, Pair) ->
check(
Env,
St@5,
erlang:element(1, Pair),
erlang:element(2, Pair)
)
end
),
fun(St@6) ->
{ok, {Result, record(St@6, Span, Result)}}
end
)
end
)
end
)
end
).
-file("src/girard/internal/infer.gleam", 1781).
?DOC(false).
-spec infer_pipe(
env(),
state(),
glance:span(),
glance:expression(),
glance:expression()
) -> {ok, {girard@types:type(), state()}} | {error, girard@types:error()}.
infer_pipe(Env, St, Span, Left, Right) ->
case Right of
{call, Call_span, Function, Arguments} ->
gleam@result:'try'(
infer_expr(Env, St, Function),
fun(_use0) ->
{Ft, St@1} = _use0,
Saturated = case resolve(St@1, Ft) of
{fn, Params, _} ->
erlang:length(Params) =:= erlang:length(Arguments);
_ ->
false
end,
case Saturated of
true ->
gleam@result:'try'(
infer_call(
Env,
St@1,
Call_span,
Function,
Arguments
),
fun(_use0@1) ->
{Call_type, St@2} = _use0@1,
gleam@result:'try'(
infer_expr(Env, St@2, Left),
fun(_use0@2) ->
{Lt, St@3} = _use0@2,
{Result, St@4} = fresh(St@3),
gleam@result:'try'(
unify(
St@4,
Call_type,
{fn, [Lt], Result}
),
fun(St@5) ->
{ok,
{Result,
record(
St@5,
Span,
Result
)}}
end
)
end
)
end
);
false ->
infer_call(
Env,
St@1,
Call_span,
Function,
[{unlabelled_field, Left} | Arguments]
)
end
end
);
_ ->
gleam@result:'try'(
infer_expr(Env, St, Left),
fun(_use0@3) ->
{Lt@1, St@6} = _use0@3,
gleam@result:'try'(
infer_expr(Env, St@6, Right),
fun(_use0@4) ->
{Ft@1, St@7} = _use0@4,
{Result@1, St@8} = fresh(St@7),
gleam@result:'try'(
unify(St@8, Ft@1, {fn, [Lt@1], Result@1}),
fun(St@9) ->
{ok,
{Result@1, record(St@9, Span, Result@1)}}
end
)
end
)
end
)
end.
-file("src/girard/internal/infer.gleam", 1721).
?DOC(false).
-spec infer_binop(
env(),
state(),
glance:span(),
glance:binary_operator(),
glance:expression(),
glance:expression()
) -> {ok, {girard@types:type(), state()}} | {error, girard@types:error()}.
infer_binop(Env, St, Span, Op, Left, Right) ->
case Op of
pipe ->
infer_pipe(Env, St, Span, Left, Right);
'and' ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:bool()),
fun(St@1) ->
gleam@result:'try'(
check(Env, St@1, Right, girard@internal@prelude:bool()),
fun(St@2) ->
{ok, {girard@internal@prelude:bool(), St@2}}
end
)
end
);
'or' ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:bool()),
fun(St@1) ->
gleam@result:'try'(
check(Env, St@1, Right, girard@internal@prelude:bool()),
fun(St@2) ->
{ok, {girard@internal@prelude:bool(), St@2}}
end
)
end
);
eq ->
gleam@result:'try'(
infer_expr(Env, St, Left),
fun(_use0) ->
{Lt, St@3} = _use0,
gleam@result:'try'(
infer_expr(Env, St@3, Right),
fun(_use0@1) ->
{Rt, St@4} = _use0@1,
gleam@result:'try'(
unify(St@4, Lt, Rt),
fun(St@5) ->
{ok, {girard@internal@prelude:bool(), St@5}}
end
)
end
)
end
);
not_eq ->
gleam@result:'try'(
infer_expr(Env, St, Left),
fun(_use0) ->
{Lt, St@3} = _use0,
gleam@result:'try'(
infer_expr(Env, St@3, Right),
fun(_use0@1) ->
{Rt, St@4} = _use0@1,
gleam@result:'try'(
unify(St@4, Lt, Rt),
fun(St@5) ->
{ok, {girard@internal@prelude:bool(), St@5}}
end
)
end
)
end
);
concatenate ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:string()),
fun(St@6) ->
gleam@result:'try'(
check(
Env,
St@6,
Right,
girard@internal@prelude:string()
),
fun(St@7) ->
{ok, {girard@internal@prelude:string(), St@7}}
end
)
end
);
add_int ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:int()),
fun(St@8) ->
gleam@result:'try'(
check(Env, St@8, Right, girard@internal@prelude:int()),
fun(St@9) ->
{ok, {girard@internal@prelude:int(), St@9}}
end
)
end
);
sub_int ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:int()),
fun(St@8) ->
gleam@result:'try'(
check(Env, St@8, Right, girard@internal@prelude:int()),
fun(St@9) ->
{ok, {girard@internal@prelude:int(), St@9}}
end
)
end
);
mult_int ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:int()),
fun(St@8) ->
gleam@result:'try'(
check(Env, St@8, Right, girard@internal@prelude:int()),
fun(St@9) ->
{ok, {girard@internal@prelude:int(), St@9}}
end
)
end
);
div_int ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:int()),
fun(St@8) ->
gleam@result:'try'(
check(Env, St@8, Right, girard@internal@prelude:int()),
fun(St@9) ->
{ok, {girard@internal@prelude:int(), St@9}}
end
)
end
);
remainder_int ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:int()),
fun(St@8) ->
gleam@result:'try'(
check(Env, St@8, Right, girard@internal@prelude:int()),
fun(St@9) ->
{ok, {girard@internal@prelude:int(), St@9}}
end
)
end
);
add_float ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:float()),
fun(St@10) ->
gleam@result:'try'(
check(
Env,
St@10,
Right,
girard@internal@prelude:float()
),
fun(St@11) ->
{ok, {girard@internal@prelude:float(), St@11}}
end
)
end
);
sub_float ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:float()),
fun(St@10) ->
gleam@result:'try'(
check(
Env,
St@10,
Right,
girard@internal@prelude:float()
),
fun(St@11) ->
{ok, {girard@internal@prelude:float(), St@11}}
end
)
end
);
mult_float ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:float()),
fun(St@10) ->
gleam@result:'try'(
check(
Env,
St@10,
Right,
girard@internal@prelude:float()
),
fun(St@11) ->
{ok, {girard@internal@prelude:float(), St@11}}
end
)
end
);
div_float ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:float()),
fun(St@10) ->
gleam@result:'try'(
check(
Env,
St@10,
Right,
girard@internal@prelude:float()
),
fun(St@11) ->
{ok, {girard@internal@prelude:float(), St@11}}
end
)
end
);
lt_int ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:int()),
fun(St@12) ->
gleam@result:'try'(
check(Env, St@12, Right, girard@internal@prelude:int()),
fun(St@13) ->
{ok, {girard@internal@prelude:bool(), St@13}}
end
)
end
);
lt_eq_int ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:int()),
fun(St@12) ->
gleam@result:'try'(
check(Env, St@12, Right, girard@internal@prelude:int()),
fun(St@13) ->
{ok, {girard@internal@prelude:bool(), St@13}}
end
)
end
);
gt_int ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:int()),
fun(St@12) ->
gleam@result:'try'(
check(Env, St@12, Right, girard@internal@prelude:int()),
fun(St@13) ->
{ok, {girard@internal@prelude:bool(), St@13}}
end
)
end
);
gt_eq_int ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:int()),
fun(St@12) ->
gleam@result:'try'(
check(Env, St@12, Right, girard@internal@prelude:int()),
fun(St@13) ->
{ok, {girard@internal@prelude:bool(), St@13}}
end
)
end
);
lt_float ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:float()),
fun(St@14) ->
gleam@result:'try'(
check(
Env,
St@14,
Right,
girard@internal@prelude:float()
),
fun(St@15) ->
{ok, {girard@internal@prelude:bool(), St@15}}
end
)
end
);
lt_eq_float ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:float()),
fun(St@14) ->
gleam@result:'try'(
check(
Env,
St@14,
Right,
girard@internal@prelude:float()
),
fun(St@15) ->
{ok, {girard@internal@prelude:bool(), St@15}}
end
)
end
);
gt_float ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:float()),
fun(St@14) ->
gleam@result:'try'(
check(
Env,
St@14,
Right,
girard@internal@prelude:float()
),
fun(St@15) ->
{ok, {girard@internal@prelude:bool(), St@15}}
end
)
end
);
gt_eq_float ->
gleam@result:'try'(
check(Env, St, Left, girard@internal@prelude:float()),
fun(St@14) ->
gleam@result:'try'(
check(
Env,
St@14,
Right,
girard@internal@prelude:float()
),
fun(St@15) ->
{ok, {girard@internal@prelude:bool(), St@15}}
end
)
end
)
end.
-file("src/girard/internal/infer.gleam", 1690).
?DOC(false).
-spec infer_fields_typed(
env(),
state(),
list(glance:field(glance:expression()))
) -> {ok, {list(glance:field(girard@types:type())), state()}} |
{error, girard@types:error()}.
infer_fields_typed(Env, St, Fields) ->
gleam@result:'try'(
gleam@list:try_fold(
Fields,
{[], St},
fun(Acc, Field) ->
{Typed, St@1} = Acc,
case Field of
{unlabelled_field, Item} ->
gleam@result:'try'(
infer_expr(Env, St@1, Item),
fun(_use0) ->
{T, St@2} = _use0,
{ok, {[{unlabelled_field, T} | Typed], St@2}}
end
);
{labelled_field, Label, Location, Item@1} ->
gleam@result:'try'(
infer_expr(Env, St@1, Item@1),
fun(_use0@1) ->
{T@1, St@3} = _use0@1,
{ok,
{[{labelled_field, Label, Location, T@1} |
Typed],
St@3}}
end
);
{shorthand_field, Label@1, Location@1} ->
gleam@result:'try'(
infer_expr(
Env,
St@1,
{variable, Location@1, Label@1}
),
fun(_use0@2) ->
{T@2, St@4} = _use0@2,
{ok,
{[{labelled_field, Label@1, Location@1, T@2} |
Typed],
St@4}}
end
)
end
end
),
fun(_use0@3) ->
{Rev, St@5} = _use0@3,
{ok, {lists:reverse(Rev), St@5}}
end
).
-file("src/girard/internal/infer.gleam", 1654).
?DOC(false).
-spec infer_capture(
env(),
state(),
glance:span(),
gleam@option:option(binary()),
glance:expression(),
list(glance:field(glance:expression())),
list(glance:field(glance:expression()))
) -> {ok, {girard@types:type(), state()}} | {error, girard@types:error()}.
infer_capture(Env, St, Span, Label, Function, Before, After) ->
{Hole, St@1} = fresh(St),
gleam@result:'try'(
infer_expr(Env, St@1, Function),
fun(_use0) ->
{Fn_type, St@2} = _use0,
gleam@result:'try'(
infer_fields_typed(Env, St@2, Before),
fun(_use0@1) ->
{Before_typed, St@3} = _use0@1,
gleam@result:'try'(
infer_fields_typed(Env, St@3, After),
fun(_use0@2) ->
{After_typed, St@4} = _use0@2,
Hole_field = case Label of
{some, Name} ->
{labelled_field, Name, Span, Hole};
none ->
{unlabelled_field, Hole}
end,
Fields = lists:append(
[Before_typed, [Hole_field], After_typed]
),
gleam@result:'try'(
order_fields(
Env,
Function,
Fields,
fun(_, _) -> Hole end
),
fun(Arg_types) ->
{Result, St@5} = fresh(St@4),
gleam@result:'try'(
unify(
St@5,
Fn_type,
{fn, Arg_types, Result}
),
fun(St@6) ->
Captured = {fn, [Hole], Result},
{ok,
{Captured,
record(St@6, Span, Captured)}}
end
)
end
)
end
)
end
)
end
).
-file("src/girard/internal/infer.gleam", 1320).
?DOC(false).
-spec infer_fn(
env(),
state(),
list(glance:fn_parameter()),
gleam@option:option(glance:type()),
list(glance:statement())
) -> {ok, {girard@types:type(), state()}} | {error, girard@types:error()}.
infer_fn(Env, St, Params, Return_annotation, Body) ->
{Names@1, St@3} = gleam@list:fold(
gleam@list:unique(fn_annotation_var_names(Params, Return_annotation)),
{maps:new(), St},
fun(Acc, Nm) ->
{Names, St@1} = Acc,
{Id, St@2} = fresh_id(St@1),
{gleam@dict:insert(Names, Nm, {var, Id}), St@2}
end
),
{Seeds, St@4} = fresh_n(St@3, erlang:length(Params)),
infer_lambda(
Env,
St@4,
Params,
Return_annotation,
Body,
Seeds,
none,
Names@1
).
-file("src/girard/internal/infer.gleam", 828).
?DOC(false).
-spec infer_expr_inner(env(), state(), glance:expression()) -> {ok,
{girard@types:type(), state()}} |
{error, girard@types:error()}.
infer_expr_inner(Env, St, Expr) ->
case Expr of
{int, _, _} ->
{ok, {girard@internal@prelude:int(), St}};
{float, _, _} ->
{ok, {girard@internal@prelude:float(), St}};
{string, _, _} ->
{ok, {girard@internal@prelude:string(), St}};
{variable, _, Name} ->
case gleam_stdlib:map_get(erlang:element(2, Env), Name) of
{ok, Scheme} ->
{ok, instantiate_in(Env, St, Name, Scheme)};
{error, _} ->
{error, {unbound_variable, Name}}
end;
{negate_int, _, Value} ->
gleam@result:'try'(
infer_expr(Env, St, Value),
fun(_use0) ->
{T, St@1} = _use0,
gleam@result:'try'(
unify(St@1, T, girard@internal@prelude:int()),
fun(St@2) ->
{ok, {girard@internal@prelude:int(), St@2}}
end
)
end
);
{negate_bool, _, Value@1} ->
gleam@result:'try'(
infer_expr(Env, St, Value@1),
fun(_use0@1) ->
{T@1, St@3} = _use0@1,
gleam@result:'try'(
unify(St@3, T@1, girard@internal@prelude:bool()),
fun(St@4) ->
{ok, {girard@internal@prelude:bool(), St@4}}
end
)
end
);
{tuple, _, Elements} ->
gleam@result:'try'(
infer_each(Env, St, Elements),
fun(_use0@2) ->
{Elem_types, St@5} = _use0@2,
{ok, {{tuple, Elem_types}, St@5}}
end
);
{list, _, Elements@1, Rest} ->
{Elem, St@6} = fresh(St),
gleam@result:'try'(
gleam@list:try_fold(
Elements@1,
St@6,
fun(St@7, E) ->
gleam@result:'try'(
infer_expr(Env, St@7, E),
fun(_use0@3) ->
{T@2, St@8} = _use0@3,
unify(St@8, T@2, Elem)
end
)
end
),
fun(St@9) -> gleam@result:'try'(case Rest of
{some, R} ->
gleam@result:'try'(
infer_expr(Env, St@9, R),
fun(_use0@4) ->
{T@3, St@10} = _use0@4,
unify(
St@10,
T@3,
girard@internal@prelude:list(Elem)
)
end
);
none ->
{ok, St@9}
end, fun(St@11) ->
{ok, {girard@internal@prelude:list(Elem), St@11}}
end) end
);
{fn, _, Params, Return_annotation, Body} ->
infer_fn(Env, St, Params, Return_annotation, Body);
{call, Span, Function, Arguments} ->
infer_call(Env, St, Span, Function, Arguments);
{fn_capture, Span@1, Label, Function@1, Before, After} ->
infer_capture(Env, St, Span@1, Label, Function@1, Before, After);
{binary_operator, Span@2, Op, Left, Right} ->
infer_binop(Env, St, Span@2, Op, Left, Right);
{block, _, Statements} ->
infer_statements(Env, St, Statements);
{'case', _, Subjects, Clauses} ->
infer_case(Env, St, Subjects, Clauses);
{tuple_index, _, Tuple, Index} ->
gleam@result:'try'(
infer_expr(Env, St, Tuple),
fun(_use0@5) ->
{T@4, St@12} = _use0@5,
case resolve(St@12, T@4) of
{tuple, Elements@2} ->
case list_at(Elements@2, Index) of
{ok, Element} ->
{ok, {Element, St@12}};
{error, _} ->
{error, {tuple_index_out_of_range, Index}}
end;
{var, _} ->
{Element@1, St@13} = fresh(St@12),
St@14 = {state,
erlang:element(2, St@13),
erlang:element(3, St@13),
erlang:element(4, St@13),
[{pending_index, T@4, Index, Element@1} |
erlang:element(5, St@13)],
erlang:element(6, St@13)},
{ok, {Element@1, St@14}};
_ ->
{error, not_a_tuple}
end
end
);
{todo, _, _} ->
{ok, fresh(St)};
{panic, _, _} ->
{ok, fresh(St)};
{echo, _, Expression, _} ->
case Expression of
{some, E@1} ->
infer_expr(Env, St, E@1);
none ->
{ok, {girard@internal@prelude:nil(), St}}
end;
{field_access, _, Container, Label@1} ->
infer_field_access(Env, St, Container, Label@1);
{record_update, _, Module, Constructor, Record, Fields} ->
infer_record_update(Env, St, Module, Constructor, Record, Fields);
{bit_string, _, Segments} ->
gleam@result:'try'(
gleam@list:try_fold(
Segments,
St,
fun(St@15, Segment) ->
infer_bit_segment(Env, St@15, Segment)
end
),
fun(St@16) ->
{ok, {girard@internal@prelude:bit_array(), St@16}}
end
)
end.
-file("src/girard/internal/infer.gleam", 819).
?DOC(false).
-spec infer_expr(env(), state(), glance:expression()) -> {ok,
{girard@types:type(), state()}} |
{error, girard@types:error()}.
infer_expr(Env, St, Expr) ->
gleam@result:'try'(
infer_expr_inner(Env, St, Expr),
fun(_use0) ->
{Type_, St@1} = _use0,
{ok, {Type_, record(St@1, span(Expr), Type_)}}
end
).
-file("src/girard/internal/infer.gleam", 2601).
?DOC(false).
-spec function_annotation_var_names(glance:function_()) -> list(binary()).
function_annotation_var_names(Function) ->
From_params = gleam@list:flat_map(
erlang:element(5, Function),
fun(P) -> case erlang:element(4, P) of
{some, T} ->
type_var_names(T);
none ->
[]
end end
),
case erlang:element(6, Function) of
{some, T@1} ->
lists:append(From_params, type_var_names(T@1));
none ->
From_params
end.
-file("src/girard/internal/infer.gleam", 2597).
?DOC(false).
-spec has_annotation_vars(glance:function_()) -> boolean().
has_annotation_vars(Function) ->
function_annotation_var_names(Function) /= [].
-file("src/girard/internal/infer.gleam", 2620).
?DOC(false).
-spec signature_skeleton(env(), state(), glance:function_()) -> {list(girard@types:type()),
girard@types:type(),
list(integer()),
state()}.
signature_skeleton(Env, St, Function) ->
{Names@1, Rigid_ids, St@3} = gleam@list:fold(
gleam@list:unique(function_annotation_var_names(Function)),
{maps:new(), [], St},
fun(Acc, Name) ->
{Names, Ids, St@1} = Acc,
{Id, St@2} = fresh_id(St@1),
{gleam@dict:insert(Names, Name, {var, Id}), [Id | Ids], St@2}
end
),
St@4 = mark_rigid(St@3, Rigid_ids),
{Rev_param_types, St@7} = gleam@list:fold(
erlang:element(5, Function),
{[], St@4},
fun(Acc@1, Param) ->
{Types_, St@5} = Acc@1,
{T, St@6} = case erlang:element(4, Param) of
{some, Ann} ->
hydrate_in(Env, Names@1, St@5, Ann);
none ->
fresh(St@5)
end,
{[T | Types_], St@6}
end
),
{Return_type, St@8} = case erlang:element(6, Function) of
{some, Ann@1} ->
hydrate_in(Env, Names@1, St@7, Ann@1);
none ->
fresh(St@7)
end,
{lists:reverse(Rev_param_types), Return_type, Rigid_ids, St@8}.
-file("src/girard/internal/infer.gleam", 2655).
?DOC(false).
-spec bind_params(env(), glance:function_(), list(girard@types:type())) -> env().
bind_params(Env, Function, Param_types) ->
gleam@list:fold(
gleam@list:zip(erlang:element(5, Function), Param_types),
Env,
fun(Env@1, Pair) ->
{Param, T} = Pair,
case erlang:element(3, Param) of
{named, Name} ->
bind_value(Env@1, Name, {scheme, [], T});
{discarded, _} ->
Env@1
end
end
).
-file("src/girard/internal/infer.gleam", 2671).
?DOC(false).
-spec check_body(env(), state(), glance:function_(), girard@types:type()) -> {ok,
state()} |
{error, girard@types:error()}.
check_body(Env, St, Function, Return_type) ->
case erlang:element(7, Function) of
[] ->
{ok, St};
_ ->
gleam@result:'try'(
infer_statements(Env, St, erlang:element(7, Function)),
fun(_use0) ->
{Body_type, St@1} = _use0,
unify(St@1, Body_type, Return_type)
end
)
end.
-file("src/girard/internal/infer.gleam", 2694).
?DOC(false).
-spec rigid_scheme(
list(integer()),
list(girard@types:type()),
girard@types:type()
) -> girard@types:scheme().
rigid_scheme(Rigid_ids, Param_types, Return_type) ->
{scheme, Rigid_ids, {fn, Param_types, Return_type}}.
-file("src/girard/internal/infer.gleam", 2704).
?DOC(false).
-spec function_scheme(
env(),
state(),
list(girard@types:type()),
girard@types:type()
) -> girard@types:scheme().
function_scheme(Env, St, Param_types, Return_type) ->
generalize(St, Env, {fn, Param_types, Return_type}).
-file("src/girard/internal/infer.gleam", 2718).
?DOC(false).
-spec rigid_self_scheme(list(girard@types:type()), girard@types:type()) -> girard@types:scheme().
rigid_self_scheme(Param_types, Return_type) ->
{scheme, [], {fn, Param_types, Return_type}}.
-file("src/girard/internal/infer.gleam", 3031).
?DOC(false).
-spec hydrate_threaded(
env(),
gleam@dict:dict(binary(), girard@types:type()),
state(),
glance:type()
) -> {girard@types:type(),
state(),
gleam@dict:dict(binary(), girard@types:type())}.
hydrate_threaded(Env, Names, St, Ast) ->
{{T, St@1}, Names@1} = hydrate_with(Env, Names, St, Ast),
{T, St@1, Names@1}.
-file("src/girard/internal/infer.gleam", 2723).
?DOC(false).
-spec infer_function(env(), state(), glance:function_()) -> {ok,
{girard@types:type(), state()}} |
{error, girard@types:error()}.
infer_function(Env, St, Function) ->
{Rev_param_types, Body_env, St@4, Names@2} = gleam@list:fold(
erlang:element(5, Function),
{[], Env, St, maps:new()},
fun(Acc, Param) ->
{Types_, Env@1, St@1, Names} = Acc,
{T@1, St@3, Names@1} = case erlang:element(4, Param) of
{some, Ann} ->
hydrate_threaded(Env@1, Names, St@1, Ann);
none ->
{T, St@2} = fresh(St@1),
{T, St@2, Names}
end,
Env@2 = case erlang:element(3, Param) of
{named, Name} ->
bind_value(Env@1, Name, {scheme, [], T@1});
{discarded, _} ->
Env@1
end,
{[T@1 | Types_], Env@2, St@3, Names@1}
end
),
Param_types = lists:reverse(Rev_param_types),
case erlang:element(7, Function) of
[] ->
{Return_type, St@6} = case erlang:element(6, Function) of
{some, Ann@1} ->
{T@2, St@5, _} = hydrate_threaded(Env, Names@2, St@4, Ann@1),
{T@2, St@5};
none ->
fresh(St@4)
end,
{ok, {{fn, Param_types, Return_type}, St@6}};
_ ->
gleam@result:'try'(
infer_statements(Body_env, St@4, erlang:element(7, Function)),
fun(_use0) ->
{Body_type, St@7} = _use0,
gleam@result:'try'(case erlang:element(6, Function) of
{some, Ann@2} ->
{T@3, St@8, _} = hydrate_threaded(
Env,
Names@2,
St@7,
Ann@2
),
unify(St@8, Body_type, T@3);
none ->
{ok, St@7}
end, fun(St@9) ->
{ok, {{fn, Param_types, Body_type}, St@9}}
end)
end
)
end.
-file("src/girard/internal/infer.gleam", 2780).
?DOC(false).
-spec infer_constant(env(), state(), glance:constant()) -> {ok,
{girard@types:type(), state()}} |
{error, girard@types:error()}.
infer_constant(Env, St, Constant) ->
gleam@result:'try'(
infer_expr(Env, St, erlang:element(6, Constant)),
fun(_use0) ->
{Value_type, St@1} = _use0,
case erlang:element(5, Constant) of
{some, Ann} ->
{T, St@2} = hydrate(Env, St@1, Ann),
gleam@result:'try'(
unify(St@2, Value_type, T),
fun(St@3) -> {ok, {Value_type, St@3}} end
);
none ->
{ok, {Value_type, St@1}}
end
end
).
-file("src/girard/internal/infer.gleam", 2867).
?DOC(false).
-spec shared_accessors(
list(gleam@dict:dict(binary(), girard@types:type())),
list(integer()),
girard@types:type()
) -> gleam@dict:dict(binary(), girard@types:scheme()).
shared_accessors(Variants, Param_ids, Return_type) ->
case Variants of
[] ->
maps:new();
[First | Rest] ->
gleam@dict:fold(
First,
maps:new(),
fun(Accessors, Label, Field_type) ->
Shared = gleam@list:all(
Rest,
fun(Variant) ->
gleam_stdlib:map_get(Variant, Label) =:= {ok,
Field_type}
end
),
case Shared of
true ->
gleam@dict:insert(
Accessors,
Label,
{scheme,
Param_ids,
{fn, [Return_type], Field_type}}
);
false ->
Accessors
end
end
)
end.
-file("src/girard/internal/infer.gleam", 3012).
?DOC(false).
-spec variant_field_type(glance:variant_field()) -> glance:type().
variant_field_type(Field) ->
case Field of
{labelled_variant_field, Item, _} ->
Item;
{unlabelled_variant_field, Item@1} ->
Item@1
end.
-file("src/girard/internal/infer.gleam", 2798).
?DOC(false).
-spec register_custom_type(env(), state(), glance:custom_type()) -> {env(),
state()}.
register_custom_type(Env, St, Custom_type) ->
Env@1 = declare_type(
Env,
erlang:element(3, Custom_type),
erlang:length(erlang:element(6, Custom_type))
),
{Rev_param_ids, St@3} = gleam@list:fold(
erlang:element(6, Custom_type),
{[], St},
fun(Acc, _) ->
{Ids, St@1} = Acc,
{Id, St@2} = fresh_id(St@1),
{[Id | Ids], St@2}
end
),
Param_ids = lists:reverse(Rev_param_ids),
Param_vars = gleam@list:map(Param_ids, fun(Field@0) -> {var, Field@0} end),
Names = maps:from_list(
gleam@list:zip(erlang:element(6, Custom_type), Param_vars)
),
Return_type = {named,
erlang:element(10, Env@1),
erlang:element(3, Custom_type),
Param_vars},
{Env@5, St@8, Rev_variant_labels} = gleam@list:fold(
erlang:element(7, Custom_type),
{Env@1, St@3, []},
fun(Acc@1, Variant) ->
{Env@2, St@4, Variant_labels} = Acc@1,
{Rev_field_types, Labelled@2, St@7} = gleam@list:fold(
erlang:element(3, Variant),
{[], maps:new(), St@4},
fun(Acc@2, Field) ->
{Types_, Labelled, St@5} = Acc@2,
{T, St@6} = hydrate_in(
Env@2,
Names,
St@5,
variant_field_type(Field)
),
Labelled@1 = case Field of
{labelled_variant_field, _, Label} ->
gleam@dict:insert(Labelled, Label, T);
{unlabelled_variant_field, _} ->
Labelled
end,
{[T | Types_], Labelled@1, St@6}
end
),
Field_types = lists:reverse(Rev_field_types),
Ctor_type = case Field_types of
[] ->
Return_type;
_ ->
{fn, Field_types, Return_type}
end,
Env@3 = register_field_map(
Env@2,
erlang:element(2, Variant),
gleam@list:map(erlang:element(3, Variant), fun(F) -> case F of
{labelled_variant_field, _, Label@1} ->
{some, Label@1};
{unlabelled_variant_field, _} ->
none
end end)
),
Env@4 = bind_value(
Env@3,
erlang:element(2, Variant),
{scheme, Param_ids, Ctor_type}
),
{Env@4, St@7, [Labelled@2 | Variant_labels]}
end
),
Accessors = shared_accessors(
lists:reverse(Rev_variant_labels),
Param_ids,
Return_type
),
Env@6 = {env,
erlang:element(2, Env@5),
erlang:element(3, Env@5),
erlang:element(4, Env@5),
erlang:element(5, Env@5),
gleam@dict:insert(
erlang:element(6, Env@5),
erlang:element(3, Custom_type),
Accessors
),
erlang:element(7, Env@5),
erlang:element(8, Env@5),
erlang:element(9, Env@5),
erlang:element(10, Env@5),
erlang:element(11, Env@5),
erlang:element(12, Env@5),
erlang:element(13, Env@5)},
{Env@6, St@8}.
-file("src/girard/internal/infer.gleam", 2979).
?DOC(false).
-spec resolve_one(env(), state(), pending()) -> {ok, {state(), boolean()}} |
{error, girard@types:error()}.
resolve_one(Env, St, Item) ->
case Item of
{pending_field, Container, Label, Field} ->
case resolve(St, Container) of
{named, _, _, _} = Record ->
gleam@result:'try'(
accessor(Env, Record, Label),
fun(Scheme) ->
{Accessor_type, St@1} = instantiate(St, Scheme),
gleam@result:'try'(
unify(
St@1,
Accessor_type,
{fn, [Container], Field}
),
fun(St@2) -> {ok, {St@2, true}} end
)
end
);
{var, _} ->
{ok, {St, false}};
_ ->
{error, not_a_record}
end;
{pending_index, Container@1, Index, Result} ->
case resolve(St, Container@1) of
{tuple, Elements} ->
case list_at(Elements, Index) of
{ok, Element} ->
gleam@result:'try'(
unify(St, Element, Result),
fun(St@3) -> {ok, {St@3, true}} end
);
{error, _} ->
{error, {tuple_index_out_of_range, Index}}
end;
{var, _} ->
{ok, {St, false}};
_ ->
{error, not_a_tuple}
end
end.
-file("src/girard/internal/infer.gleam", 2948).
?DOC(false).
-spec resolve_pending_loop(env(), state(), list(pending()), integer()) -> {ok,
state()} |
{error, girard@types:error()}.
resolve_pending_loop(Env, St, Pending, Fuel) ->
case {Pending, Fuel =< 0} of
{[], _} ->
{ok, St};
{[_ | _], true} ->
{error, not_a_record};
{_, false} ->
gleam@result:'try'(
gleam@list:try_fold(
Pending,
{St, [], false},
fun(Acc, Item) ->
{St@1, Remaining, Progressed} = Acc,
gleam@result:'try'(
resolve_one(Env, St@1, Item),
fun(_use0) ->
{St@2, Resolved} = _use0,
case Resolved of
true ->
{ok, {St@2, Remaining, true}};
false ->
{ok,
{St@2,
[Item | Remaining],
Progressed}}
end
end
)
end
),
fun(_use0@1) ->
{St@3, Remaining@1, Progressed@1} = _use0@1,
case Progressed@1 of
true ->
resolve_pending_loop(
Env,
St@3,
lists:reverse(Remaining@1),
Fuel - 1
);
false ->
{error, not_a_record}
end
end
)
end.
-file("src/girard/internal/infer.gleam", 2935).
?DOC(false).
-spec resolve_pending(env(), state()) -> {ok, state()} |
{error, girard@types:error()}.
resolve_pending(Env, St) ->
Pending = lists:reverse(erlang:element(5, St)),
resolve_pending_loop(
Env,
{state,
erlang:element(2, St),
erlang:element(3, St),
erlang:element(4, St),
[],
erlang:element(6, St)},
Pending,
erlang:length(Pending)
).