uw-switch-semantics #53
48
src/gmser_dyn_types.erl
Normal file
48
src/gmser_dyn_types.erl
Normal file
@ -0,0 +1,48 @@
|
||||
-module(gmser_dyn_types).
|
||||
|
||||
-export([ from_list/2 ]).
|
||||
-export([ next_code/1 ]).
|
||||
|
||||
next_code(#{codes := Codes}) ->
|
||||
lists:max(maps:keys(Codes)) + 1.
|
||||
|
||||
add_type(Tag, Code, Template, Types) ->
|
||||
elem_to_type({Tag, Code, Template}, Types).
|
||||
|
||||
from_list(L, Types) ->
|
||||
lists:foldl(fun elem_to_type/2, Types, L).
|
||||
|
||||
elem_to_type({Tag, Code, Template}, Acc) when is_atom(Tag), is_integer(Code) ->
|
||||
#{codes := Codes, rev := Rev, templates := Temps} = Acc,
|
||||
case {is_map_key(Tag, Rev), is_map_key(Code, Codes)} of
|
||||
{false, false} ->
|
||||
Acc#{ codes := Codes#{Code => Tag}
|
||||
, rev := Rev#{Tag => Code}
|
||||
, templates => Temps#{Tag => Template}
|
||||
};
|
||||
{true, _} -> error({duplicate_tag, Tag});
|
||||
{_, true} -> error({duplicate_code, Code})
|
||||
end;
|
||||
elem_to_type({modify, {Tag, Template}}, Acc) ->
|
||||
#{codes := _, rev := Rev, templates := Templates} = Acc,
|
||||
_ = maps:get(Tag, Rev),
|
||||
Templates1 = Templates#{Tag := Template},
|
||||
Acc#{templates := Templates1};
|
||||
elem_to_type({labels, Lbls}, Acc) ->
|
||||
lists:foldl(fun add_label/2, Acc, Lbls);
|
||||
elem_to_type({vsn, V}, Acc) ->
|
||||
Acc#{vsn => V};
|
||||
elem_to_type(Elem, _) ->
|
||||
error({invalid_type, Elem}).
|
||||
|
||||
add_label({L, Code}, #{labels := Lbls, rev_labels := RevLbls} = Acc)
|
||||
when is_atom(L), is_integer(Code), Code > 0 ->
|
||||
case {is_map_key(L, Lbls), is_map_key(Code, RevLbls)} of
|
||||
{false, false} ->
|
||||
Acc#{labels := Lbls#{L => Code},
|
||||
rev_labels := RevLbls#{Code => L}};
|
||||
{true, _} -> error({duplicate_label, L});
|
||||
{_, true} -> error({duplicate_label_code, Code})
|
||||
end;
|
||||
add_label(Elem, _) ->
|
||||
error({invalid_label, Elem}).
|
Loading…
x
Reference in New Issue
Block a user