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 Dec 9, 2020
1 parent b23a0d9 commit e091720
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 @@ -52,7 +52,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 @@ -61,17 +61,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 e091720

Please sign in to comment.