Current section

Files

Jump to
deriv src deriv@unify.erl
Raw

src/deriv@unify.erl

-module(deriv@unify).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([gen/5]).
-export_type([unify_func/0, field/0, unify_field_override/0]).
-type unify_func() :: {unify_func,
binary(),
binary(),
binary(),
binary(),
list(field())}.
-type field() :: {field, binary(), binary()}.
-type unify_field_override() :: {unify_field_override,
binary(),
binary(),
binary(),
binary(),
glance:custom_type()}.
-file("src/deriv/unify.gleam", 75).
-spec get_param_types_and_variants(
list(binary()),
fun((binary()) -> {ok, glance:module_()} |
{error, deriv@types:module_reader_err()})
) -> list({glance:definition(glance:custom_type()), glance:variant(), binary()}).
get_param_types_and_variants(Idents, Module_reader) ->
_pipe = Idents,
_pipe@1 = gleam@list:map(
_pipe,
fun(Ident) -> deriv@util:fetch_custom_type(Ident, Module_reader) end
),
_pipe@2 = gleam@result:all(_pipe@1),
_pipe@3 = (fun(X) -> case X of
{error, Err} ->
gleam@io:debug(Idents),
gleam@io:debug(Err),
erlang:error(#{gleam_error => panic,
message => <<"`unify` issue with the above `idents`"/utf8>>,
module => <<"deriv/unify"/utf8>>,
function => <<"get_param_types_and_variants"/utf8>>,
line => 89});
{ok, List} ->
List
end end)(_pipe@2),
gleam@list:map(
_pipe@3,
fun(X@1) ->
{Module_name, Type_} = X@1,
case erlang:element(6, erlang:element(3, Type_)) of
[Variant] ->
{Type_, Variant, Module_name};
_ ->
gleam@io:debug(Type_),
erlang:error(#{gleam_error => panic,
message => <<"`unify` derivation currently only supports invariant types"/utf8>>,
module => <<"deriv/unify"/utf8>>,
function => <<"get_param_types_and_variants"/utf8>>,
line => 105})
end
end
).
-file("src/deriv/unify.gleam", 205).
-spec build_field_override(
deriv@types:deriv_field_opt(),
deriv@types:deriv_field(),
fun((binary()) -> {ok, glance:module_()} |
{error, deriv@types:module_reader_err()})
) -> unify_field_override().
build_field_override(Field_opt, Deriv_field, Module_reader) ->
case Field_opt of
{deriv_field_opt, [<<"unify"/utf8>>, <<"field"/utf8>>, Ident, Override]} ->
{Module_name, Type_} = case deriv@util:fetch_custom_type(
Ident,
Module_reader
) of
{error, Err} ->
gleam@io:debug(Err),
erlang:error(#{gleam_error => panic,
message => <<"`panic` expression evaluated."/utf8>>,
module => <<"deriv/unify"/utf8>>,
function => <<"build_field_override"/utf8>>,
line => 216});
{ok, {M, Td}} ->
{M, erlang:element(3, Td)}
end,
Field = erlang:element(4, Deriv_field),
{unify_field_override, Ident, Field, Override, Module_name, Type_};
_ ->
gleam@io:debug(Field_opt),
erlang:error(#{gleam_error => panic,
message => <<"Invalid `unify` `DerivFieldOpt` (printed above)"/utf8>>,
module => <<"deriv/unify"/utf8>>,
function => <<"build_field_override"/utf8>>,
line => 235})
end.
-file("src/deriv/unify.gleam", 43).
-spec build_field_overrides(
gleam@dict:dict(deriv@types:deriv_field(), list(deriv@types:deriv_field_opt())),
fun((binary()) -> {ok, glance:module_()} |
{error, deriv@types:module_reader_err()})
) -> list({deriv@types:deriv_field(), list(unify_field_override())}).
build_field_overrides(Field_opts, Module_reader) ->
_pipe = Field_opts,
_pipe@2 = gleam@dict:map_values(_pipe, fun(Field, Opts) -> _pipe@1 = Opts,
gleam@list:map(
_pipe@1,
fun(_capture) ->
build_field_override(_capture, Field, Module_reader)
end
) end),
maps:to_list(_pipe@2).
-file("src/deriv/unify.gleam", 269).
-spec build_ident(binary(), glance:custom_type()) -> binary().
build_ident(Module_name, Type_) ->
<<<<Module_name/binary, "."/utf8>>/binary,
(erlang:element(2, Type_))/binary>>.
-file("src/deriv/unify.gleam", 363).
-spec fields(glance:variant()) -> list({binary(), binary()}).
fields(Variant) ->
_pipe = erlang:element(3, Variant),
gleam@list:map(_pipe, fun(Field) -> case Field of
{labelled_variant_field, {named_type, Name, _, _}, Label} ->
{Label, Name};
_ ->
gleam@io:debug(Variant),
gleam@io:debug(Field),
erlang:error(#{gleam_error => panic,
message => <<"Only the following field type is supported: `LabelledVariantField(item: NamedType(name:, ..), label:)`"/utf8>>,
module => <<"deriv/unify"/utf8>>,
function => <<"fields"/utf8>>,
line => 373})
end end).
-file("src/deriv/unify.gleam", 276).
-spec unify_func_fields(
binary(),
glance:custom_type(),
glance:variant(),
glance:custom_type(),
glance:variant(),
list({deriv@types:deriv_field(), list(unify_field_override())})
) -> list(field()).
unify_func_fields(
Param_type_module,
Param_type,
Param_variant,
Return_type,
Return_variant,
Overrides
) ->
Param_fields = fields(Param_variant),
Return_fields = fields(Return_variant),
_pipe = Return_fields,
gleam@list:map(
_pipe,
fun(R_field) ->
{Return_field, Result_field_type} = R_field,
Overrides@1 = begin
_pipe@1 = Overrides,
gleam@list:filter_map(
_pipe@1,
fun(X) ->
{Df, Os} = X,
case (erlang:element(2, Df) =:= erlang:element(
2,
Return_type
))
andalso (erlang:element(4, Df) =:= Return_field) of
false ->
{error, nil};
true ->
{ok, {erlang:element(4, Df), Os}}
end
end
)
end,
Override = begin
_pipe@2 = Overrides@1,
gleam@list:find_map(
_pipe@2,
fun(X@1) ->
{Param_field, Os@1} = X@1,
gleam@list:find_map(
Os@1,
fun(O) ->
Ident = build_ident(
Param_type_module,
Param_type
),
case (erlang:element(2, O) =:= Ident) andalso (erlang:element(
3,
O
)
=:= Return_field) of
false ->
{error, nil};
true ->
{ok, {Param_field, O}}
end
end
)
end
)
end,
{Param_field@1, _} = case Override of
{error, _} ->
{Return_field, nil};
{ok, {_, O@1}} ->
{erlang:element(4, O@1), nil}
end,
Param_field_type = gleam@list:find_map(
Param_fields,
fun(X@2) ->
{Name, Type_} = X@2,
case Param_field@1 =:= Name of
false ->
{error, nil};
true ->
{ok, Type_}
end
end
),
case Param_field_type of
{error, _} ->
gleam@io:debug(Param_type),
gleam@io:debug(Param_variant),
gleam@io:debug(Param_field@1),
erlang:error(#{gleam_error => panic,
message => <<"`unify` param field doesn't exist"/utf8>>,
module => <<"deriv/unify"/utf8>>,
function => <<"unify_func_fields"/utf8>>,
line => 336});
{ok, Param_field_type@1} when Param_field_type@1 =:= Result_field_type ->
Param_field_type@1;
_ ->
gleam_stdlib:println(<<"PARAM TYPE"/utf8>>),
gleam@io:debug(Param_type),
gleam@io:debug(Param_variant),
gleam@io:debug(Param_field@1),
gleam_stdlib:println(<<"RETURN TYPE"/utf8>>),
gleam@io:debug(Return_type),
gleam@io:debug(Return_variant),
gleam@io:debug(Return_field),
erlang:error(#{gleam_error => panic,
message => <<"`unify` param & return field types don't match"/utf8>>,
module => <<"deriv/unify"/utf8>>,
function => <<"unify_func_fields"/utf8>>,
line => 351})
end,
{field, Param_field@1, Return_field}
end
).
-file("src/deriv/unify.gleam", 142).
-spec unify_variant(
binary(),
glance:custom_type(),
glance:variant(),
glance:custom_type(),
glance:variant(),
list({deriv@types:deriv_field(), list(unify_field_override())})
) -> unify_func().
unify_variant(
Param_type_module,
Param_type,
Param_variant,
Return_type,
Return_variant,
Overrides
) ->
Fields = unify_func_fields(
Param_type_module,
Param_type,
Param_variant,
Return_type,
Return_variant,
Overrides
),
Func_name = deriv@util:snake_case(erlang:element(2, Param_type)),
Param_type@1 = erlang:element(2, Param_type),
Return_type@1 = erlang:element(2, Return_type),
Return_contr = erlang:element(2, Return_variant),
{unify_func, Func_name, Param_type@1, Return_type@1, Return_contr, Fields}.
-file("src/deriv/unify.gleam", 111).
-spec unify(
glance:custom_type(),
list(binary()),
list({deriv@types:deriv_field(), list(unify_field_override())}),
fun((binary()) -> {ok, glance:module_()} |
{error, deriv@types:module_reader_err()})
) -> list(unify_func()).
unify(Return_type, Idents, Overrides, Module_reader) ->
case erlang:element(6, Return_type) of
[Return_variant] ->
_pipe = Idents,
_pipe@1 = get_param_types_and_variants(_pipe, Module_reader),
gleam@list:map(
_pipe@1,
fun(X) ->
{Param_type_def, Param_variant, Param_type_module} = X,
Param_type = erlang:element(3, Param_type_def),
unify_variant(
Param_type_module,
Param_type,
Param_variant,
Return_type,
Return_variant,
Overrides
)
end
);
_ ->
gleam@io:debug(Return_type),
erlang:error(#{gleam_error => panic,
message => <<"`unify` derivation currently only supports invariant types"/utf8>>,
module => <<"deriv/unify"/utf8>>,
function => <<"unify"/utf8>>,
line => 137})
end.
-file("src/deriv/unify.gleam", 379).
-spec unify_func(unify_func()) -> glance:definition(glance:function_()).
unify_func(Uf) ->
{unify_func, Func_name, Param_type, Return_type, Return_contr, Fields} = Uf,
Dummy_span = {span, -1, -1},
{definition,
[],
{function,
Func_name,
public,
[{function_parameter,
none,
{named, <<"value"/utf8>>},
{some, {named_type, Param_type, none, []}}}],
{some, {named_type, Return_type, none, []}},
[{expression,
{call,
{variable, Return_contr},
gleam@list:map(
Fields,
fun(Field) ->
{labelled_field,
erlang:element(3, Field),
{field_access,
{variable, <<"value"/utf8>>},
erlang:element(2, Field)}}
end
)}}],
Dummy_span}}.
-file("src/deriv/unify.gleam", 13).
-spec gen(
glance:custom_type(),
deriv@types:derivation(),
gleam@dict:dict(deriv@types:deriv_field(), list(deriv@types:deriv_field_opt())),
deriv@types:file(),
fun((binary()) -> {ok, glance:module_()} |
{error, deriv@types:module_reader_err()})
) -> deriv@types:gen().
gen(Type_, Deriv, Field_opts, File, Module_reader) ->
Overrides = build_field_overrides(Field_opts, Module_reader),
Idents = erlang:element(3, Deriv),
Imports = [],
Funcs = begin
_pipe = unify(Type_, Idents, Overrides, Module_reader),
gleam@list:map(_pipe, fun unify_func/1)
end,
Src = begin
_pipe@1 = Funcs,
_pipe@2 = gleam@list:map(_pipe@1, fun deriv@util:func_str/1),
gleam@string:join(_pipe@2, <<"\n\n"/utf8>>)
end,
{gen, File, Deriv, Imports, Funcs, Src, maps:new()}.