-module(prequel@pretty_printer). -compile([no_auto_import, nowarn_unused_vars]). -export([format/1]). -spec entity_has_empty_body(prequel@ast:entity()) -> boolean(). entity_has_empty_body(Entity) -> {entity, _, _, Keys, Attributes, Inner_relationships, Children} = Entity, case {Keys, Attributes, Inner_relationships, Children} of {[], [], [], none} -> true; {_, _, _, _} -> false end. -spec pretty_cardinality(prequel@ast:cardinality()) -> gleam@string_builder:string_builder(). pretty_cardinality(Cardinality) -> case Cardinality of {bounded, _, Min, Max} -> gleam@string_builder:from_strings( [<<"("/utf8>>, gleam@int:to_string(Min), <<"-"/utf8>>, gleam@int:to_string(Max), <<")"/utf8>>] ); {unbounded, _, Min@1} -> gleam@string_builder:from_strings( [<<"("/utf8>>, gleam@int:to_string(Min@1), <<"-N)"/utf8>>] ) end. -spec indent(gleam@string_builder:string_builder(), integer()) -> gleam@string_builder:string_builder(). indent(Builder, Indentation) -> Spaces = gleam@string_builder:from_strings( gleam@list:repeat(<<" "/utf8>>, Indentation) ), gleam@string_builder:append_builder(Spaces, Builder). -spec indent_string(binary(), integer()) -> gleam@string_builder:string_builder(). indent_string(String, Indentation) -> indent(gleam@string_builder:from_string(String), Indentation). -spec pretty_key(prequel@ast:key(), integer()) -> gleam@string_builder:string_builder(). pretty_key(Key, Indentation) -> case Key of {single_key, _, Key@1, _} -> _pipe = indent_string(<<"-* "/utf8>>, Indentation), gleam@string_builder:append(_pipe, Key@1); {composed_key, _, Keys} -> _pipe@1 = Keys, _pipe@2 = non_empty_list:to_list(_pipe@1), _pipe@3 = gleam@list:intersperse(_pipe@2, <<" & "/utf8>>), _pipe@4 = gleam@string_builder:from_strings(_pipe@3), gleam@string_builder:prepend_builder( _pipe@4, indent_string(<<"-* "/utf8>>, Indentation) ) end. -spec pretty_attribute(prequel@ast:attribute(), integer()) -> gleam@string_builder:string_builder(). pretty_attribute(Attribute, Indentation) -> Lollipop = indent_string(<<"-o "/utf8>>, Indentation), case erlang:element(4, Attribute) of {bounded, _, 1, 1} -> gleam@string_builder:append(Lollipop, erlang:element(3, Attribute)); _ -> _pipe = Lollipop, _pipe@1 = gleam@string_builder:append( _pipe, erlang:element(3, Attribute) ), _pipe@2 = gleam@string_builder:append(_pipe@1, <<" : "/utf8>>), gleam@string_builder:append_builder( _pipe@2, pretty_cardinality(erlang:element(4, Attribute)) ) end. -spec pretty_inner_relationship(prequel@ast:relationship(), binary(), integer()) -> gleam@string_builder:string_builder(). pretty_inner_relationship(Inner_relationship, Entity_name, Indentation) -> _assert_subject = begin _pipe = erlang:element(5, Inner_relationship), _pipe@1 = non_empty_list:prepend( _pipe, erlang:element(4, Inner_relationship) ), _pipe@2 = non_empty_list:to_list(_pipe@1), gleam@list:partition( _pipe@2, fun(Entity) -> erlang:element(3, Entity) =:= Entity_name end ) end, {[Outer_entity], [Inner_entity]} = case _assert_subject of {[_], [_]} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"prequel/pretty_printer"/utf8>>, function => <<"pretty_inner_relationship"/utf8>>, line => 107}) end, Inner_relationship_head = begin _pipe@3 = indent_string(<<"-> "/utf8>>, Indentation), _pipe@4 = gleam@string_builder:append( _pipe@3, erlang:element(3, Inner_relationship) ), _pipe@5 = gleam@string_builder:append(_pipe@4, <<" : "/utf8>>), _pipe@6 = gleam@string_builder:append_builder( _pipe@5, pretty_cardinality(erlang:element(4, Outer_entity)) ), _pipe@7 = gleam@string_builder:append(_pipe@6, <<" "/utf8>>), _pipe@8 = gleam@string_builder:append( _pipe@7, erlang:element(3, Inner_entity) ), _pipe@9 = gleam@string_builder:append(_pipe@8, <<" "/utf8>>), gleam@string_builder:append_builder( _pipe@9, pretty_cardinality(erlang:element(4, Inner_entity)) ) end, case erlang:element(6, Inner_relationship) of [] -> Inner_relationship_head; _ -> _pipe@10 = Inner_relationship_head, _pipe@11 = gleam@string_builder:append(_pipe@10, <<" {\n"/utf8>>), _pipe@15 = gleam@string_builder:append_builder( _pipe@11, begin _pipe@12 = erlang:element(6, Inner_relationship), _pipe@13 = gleam@list:map( _pipe@12, fun(_capture) -> pretty_attribute(_capture, Indentation + 2) end ), _pipe@14 = gleam@string_builder:join( _pipe@13, <<"\n"/utf8>> ), gleam@string_builder:append(_pipe@14, <<"\n"/utf8>>) end ), gleam@string_builder:append_builder( _pipe@15, indent_string(<<"}"/utf8>>, Indentation) ) end. -spec pretty_relationship_entity(prequel@ast:relationship_entity()) -> gleam@string_builder:string_builder(). pretty_relationship_entity(Entity) -> _pipe = [<<"-> "/utf8>>, erlang:element(3, Entity), <<" : "/utf8>>], _pipe@1 = gleam@string_builder:from_strings(_pipe), gleam@string_builder:append_builder( _pipe@1, pretty_cardinality(erlang:element(4, Entity)) ). -spec pretty_relationship_body(prequel@ast:relationship()) -> gleam@string_builder:string_builder(). pretty_relationship_body(Relationship) -> Entities = begin _pipe = erlang:element(5, Relationship), _pipe@1 = non_empty_list:prepend(_pipe, erlang:element(4, Relationship)), _pipe@2 = non_empty_list:to_list(_pipe@1), _pipe@3 = gleam@list:map(_pipe@2, fun pretty_relationship_entity/1), _pipe@4 = gleam@list:map( _pipe@3, fun(_capture) -> indent(_capture, 2) end ), gleam@string_builder:join(_pipe@4, <<"\n"/utf8>>) end, Attributes = begin _pipe@5 = erlang:element(6, Relationship), _pipe@6 = gleam@list:map( _pipe@5, fun(_capture@1) -> pretty_attribute(_capture@1, 2) end ), gleam@string_builder:join(_pipe@6, <<"\n"/utf8>>) end, _pipe@7 = [Entities, Attributes], _pipe@8 = gleam@list:filter( _pipe@7, fun(Builder) -> not gleam@string_builder:is_empty(Builder) end ), _pipe@9 = gleam@string_builder:join(_pipe@8, <<"\n\n"/utf8>>), gleam@string_builder:append(_pipe@9, <<"\n"/utf8>>). -spec pretty_relationship(prequel@ast:relationship()) -> gleam@string_builder:string_builder(). pretty_relationship(Relationship) -> _pipe = gleam@string_builder:new(), _pipe@1 = gleam@string_builder:append(_pipe, <<"relationship "/utf8>>), _pipe@2 = gleam@string_builder:append( _pipe@1, erlang:element(3, Relationship) ), _pipe@3 = gleam@string_builder:append(_pipe@2, <<" {\n"/utf8>>), _pipe@4 = gleam@string_builder:append_builder( _pipe@3, pretty_relationship_body(Relationship) ), gleam@string_builder:append(_pipe@4, <<"}"/utf8>>). -spec pretty_hierarchy(prequel@ast:hierarchy(), integer()) -> gleam@string_builder:string_builder(). pretty_hierarchy(Hierarchy, Indentation) -> Totality = case erlang:element(4, Hierarchy) of total -> <<"total"/utf8>>; partial -> <<"partial"/utf8>> end, Overlapping = case erlang:element(3, Hierarchy) of overlapped -> <<"overlapped"/utf8>>; disjoint -> <<"disjoint"/utf8>> end, Entities = begin _pipe = erlang:element(5, Hierarchy), _pipe@1 = non_empty_list:to_list(_pipe), _pipe@2 = gleam@list:map( _pipe@1, fun(_capture) -> pretty_entity(_capture, Indentation + 2) end ), gleam@string_builder:join(_pipe@2, <<"\n\n"/utf8>>) end, _pipe@3 = indent_string(Totality, Indentation), _pipe@4 = gleam@string_builder:append(_pipe@3, <<" "/utf8>>), _pipe@5 = gleam@string_builder:append(_pipe@4, Overlapping), _pipe@6 = gleam@string_builder:append(_pipe@5, <<" hierarchy {\n"/utf8>>), _pipe@7 = gleam@string_builder:append_builder(_pipe@6, Entities), _pipe@8 = gleam@string_builder:append(_pipe@7, <<"\n"/utf8>>), gleam@string_builder:append_builder( _pipe@8, indent_string(<<"}"/utf8>>, Indentation) ). -spec pretty_entity(prequel@ast:entity(), integer()) -> gleam@string_builder:string_builder(). pretty_entity(Entity, Indentation) -> Entity_head = begin _pipe = gleam@string_builder:from_strings( [<<"entity "/utf8>>, erlang:element(3, Entity)] ), indent(_pipe, Indentation) end, gleam@bool:guard( entity_has_empty_body(Entity), Entity_head, fun() -> _pipe@1 = Entity_head, _pipe@2 = gleam@string_builder:append(_pipe@1, <<" {\n"/utf8>>), _pipe@3 = gleam@string_builder:append_builder( _pipe@2, pretty_entity_body(Entity, Indentation + 2) ), gleam@string_builder:append_builder( _pipe@3, indent_string(<<"}"/utf8>>, Indentation) ) end ). -spec pretty_entity_body(prequel@ast:entity(), integer()) -> gleam@string_builder:string_builder(). pretty_entity_body(Entity, Indentation) -> Keys = begin _pipe = erlang:element(4, Entity), _pipe@1 = gleam@list:map( _pipe, fun(_capture) -> pretty_key(_capture, Indentation) end ), gleam@string_builder:join(_pipe@1, <<"\n"/utf8>>) end, Attributes = begin _pipe@2 = erlang:element(5, Entity), _pipe@3 = gleam@list:map( _pipe@2, fun(_capture@1) -> pretty_attribute(_capture@1, Indentation) end ), gleam@string_builder:join(_pipe@3, <<"\n"/utf8>>) end, Inner_relationships = begin _pipe@4 = erlang:element(6, Entity), _pipe@5 = gleam@list:map( _pipe@4, fun(_capture@2) -> pretty_inner_relationship( _capture@2, erlang:element(3, Entity), Indentation ) end ), gleam@string_builder:join(_pipe@5, <<"\n"/utf8>>) end, Hierarchy = begin _pipe@6 = erlang:element(7, Entity), _pipe@7 = gleam@option:map( _pipe@6, fun(_capture@3) -> pretty_hierarchy(_capture@3, Indentation) end ), gleam@option:unwrap(_pipe@7, gleam@string_builder:new()) end, _pipe@8 = [Keys, Attributes, Inner_relationships, Hierarchy], _pipe@9 = gleam@list:filter( _pipe@8, fun(Builder) -> not gleam@string_builder:is_empty(Builder) end ), _pipe@10 = gleam@string_builder:join(_pipe@9, <<"\n\n"/utf8>>), gleam@string_builder:append(_pipe@10, <<"\n"/utf8>>). -spec format(prequel@ast:module_()) -> gleam@string_builder:string_builder(). format(Module) -> Entities = begin _pipe = erlang:element(2, Module), _pipe@1 = gleam@list:map( _pipe, fun(_capture) -> pretty_entity(_capture, 0) end ), gleam@string_builder:join(_pipe@1, <<"\n\n"/utf8>>) end, Relationships = begin _pipe@2 = erlang:element(3, Module), _pipe@3 = gleam@list:map(_pipe@2, fun pretty_relationship/1), gleam@string_builder:join(_pipe@3, <<"\n\n"/utf8>>) end, _pipe@4 = [Entities, Relationships], _pipe@5 = gleam@list:filter( _pipe@4, fun(Builder) -> not gleam@string_builder:is_empty(Builder) end ), gleam@string_builder:join(_pipe@5, <<"\n\n"/utf8>>).