Skip to content

Commit

Permalink
Infer type for struct update syntax. Fixes gyson#32.
Browse files Browse the repository at this point in the history
  • Loading branch information
Manuel Bärenz committed Mar 24, 2023
1 parent 91eaf12 commit 0f86666
Showing 1 changed file with 12 additions and 3 deletions.
15 changes: 12 additions & 3 deletions lib/ex_type/checker.ex
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ defmodule ExType.Checker do
{context, %Type.BitString{}}
end

def eval(context, {:%, meta, [struct, {:%{}, _, args}]}) when is_atom(struct) do
def eval(context, {:%, meta, [struct, {:%{}, _, [{:|, _, [old_struct, args]}]}]}) when is_atom(struct) do
if not Helper.is_struct(struct) do
Helper.throw(
message: "#{struct} is not struct",
Expand All @@ -70,17 +70,26 @@ defmodule ExType.Checker do
)
end

{_, %Type.Struct{struct: ^struct, types: old_types}} = eval(context, old_struct)

types =
args
|> Enum.map(fn {key, value} ->
{_, value_type} = eval(context, value)
{key, value_type}
end)
|> Enum.into(%{})

# TODO: check if all types match with typespec

{context, %Type.Struct{struct: struct, types: types}}
# %{some_struct | foo: bar} overwrites key foo, thus also its type
new_types = Map.merge(old_types, types)

{context, %Type.Struct{struct: struct, types: new_types}}
end

# %{foo => bar} is equivalent to %{%{} | foo => bar}
def eval(context, {:%, meta, [struct, {:%{}, meta, args}]}) do
eval(context, {:%, meta, [struct, {:%{}, meta, [{:|, meta, [%{}, args]}]}]})
end

# atom literal
Expand Down

0 comments on commit 0f86666

Please sign in to comment.