Current section

Files

Jump to
glance src glance.erl
Raw

src/glance.erl

-module(glance).
-compile([no_auto_import, nowarn_unused_vars]).
-export([module/1]).
-export_type([module_/0, external_function/0, import/0, constant_expression/0, constant/0, unqualified_import/0, publicity/0, type_alias/0, custom_type/0, external_type/0, variant/0, field/1, type/0, error/0]).
-type module_() :: {module,
list(import()),
list(custom_type()),
list(type_alias()),
list(constant()),
list(external_type()),
list(external_function())}.
-type external_function() :: {external_function,
binary(),
publicity(),
list(field(type())),
type(),
binary(),
binary()}.
-type import() :: {import,
binary(),
gleam@option:option(binary()),
list(unqualified_import())}.
-type constant_expression() :: constant_bit_string |
{constant_int, binary()} |
{constant_float, binary()} |
{constant_string, binary()} |
{constant_variable, binary()} |
{constant_tuple, list(constant_expression())} |
{constant_list, list(constant_expression())} |
{constant_constructor,
binary(),
gleam@option:option(binary()),
list(field(constant_expression()))}.
-type constant() :: {constant,
binary(),
publicity(),
gleam@option:option(type()),
constant_expression()}.
-type unqualified_import() :: {unqualified_import,
binary(),
gleam@option:option(binary())}.
-type publicity() :: public | private.
-type type_alias() :: {type_alias,
binary(),
publicity(),
list(binary()),
type()}.
-type custom_type() :: {custom_type,
binary(),
publicity(),
list(binary()),
list(variant())}.
-type external_type() :: {external_type, binary(), publicity(), list(binary())}.
-type variant() :: {variant, binary(), list(field(type()))}.
-type field(EZM) :: {field, gleam@option:option(binary()), EZM}.
-type type() :: {named_type,
binary(),
gleam@option:option(binary()),
list(type())} |
{tuple_type, list(type())} |
{function_type, list(type()), type()} |
{variable_type, binary()}.
-type error() :: unexpected_end_of_input |
{unexpected_token, glexer@token:token(), glexer:position()}.
-spec push_constant(module_(), constant()) -> module_().
push_constant(Module, Constant) ->
erlang:setelement(5, Module, [Constant | erlang:element(5, Module)]).
-spec push_external_function(module_(), external_function()) -> module_().
push_external_function(Module, External_function) ->
erlang:setelement(
7,
Module,
[External_function | erlang:element(7, Module)]
).
-spec push_external_type(module_(), external_type()) -> module_().
push_external_type(Module, External_type) ->
erlang:setelement(6, Module, [External_type | erlang:element(6, Module)]).
-spec push_custom_type(module_(), custom_type()) -> module_().
push_custom_type(Module, Custom_type) ->
Custom_type@1 = erlang:setelement(
5,
Custom_type,
gleam@list:reverse(erlang:element(5, Custom_type))
),
erlang:setelement(3, Module, [Custom_type@1 | erlang:element(3, Module)]).
-spec push_type_alias(module_(), type_alias()) -> module_().
push_type_alias(Module, Type_alias) ->
erlang:setelement(4, Module, [Type_alias | erlang:element(4, Module)]).
-spec push_variant(custom_type(), variant()) -> custom_type().
push_variant(Custom_type, Variant) ->
erlang:setelement(
5,
Custom_type,
[Variant | erlang:element(5, Custom_type)]
).
-spec expect(
glexer@token:token(),
list({glexer@token:token(), glexer:position()}),
fun((glexer:position(), list({glexer@token:token(), glexer:position()})) -> {ok,
EZQ} |
{error, error()})
) -> {ok, EZQ} | {error, error()}.
expect(Expected, Tokens, Next) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{Token, Position} | Tokens@1] when Token =:= Expected ->
Next(Position, Tokens@1);
[{Other, Position@1} | _] ->
{error, {unexpected_token, Other, Position@1}}
end.
-spec expect_upper_name(
list({glexer@token:token(), glexer:position()}),
fun((binary(), list({glexer@token:token(), glexer:position()})) -> {ok, EZV} |
{error, error()})
) -> {ok, EZV} | {error, error()}.
expect_upper_name(Tokens, Next) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{{upper_name, Name}, _} | Tokens@1] ->
Next(Name, Tokens@1);
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}}
end.
-spec expect_name(
list({glexer@token:token(), glexer:position()}),
fun((binary(), list({glexer@token:token(), glexer:position()})) -> {ok, FAA} |
{error, error()})
) -> {ok, FAA} | {error, error()}.
expect_name(Tokens, Next) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{{name, Name}, _} | Tokens@1] ->
Next(Name, Tokens@1);
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}}
end.
-spec expect_string(
list({glexer@token:token(), glexer:position()}),
fun((binary(), list({glexer@token:token(), glexer:position()})) -> {ok, FAF} |
{error, error()})
) -> {ok, FAF} | {error, error()}.
expect_string(Tokens, Next) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{{string, S}, _} | Tokens@1] ->
Next(S, Tokens@1);
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}}
end.
-spec optional_module_alias(list({glexer@token:token(), glexer:position()})) -> {gleam@option:option(binary()),
list({glexer@token:token(), glexer:position()})}.
optional_module_alias(Tokens) ->
case Tokens of
[{as, _}, {{name, Alias}, _} | Tokens@1] ->
{{some, Alias}, Tokens@1};
_ ->
{none, Tokens}
end.
-spec name(list({glexer@token:token(), glexer:position()})) -> {ok,
{binary(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
name(Tokens) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{{name, Name}, _} | Tokens@1] ->
{ok, {Name, Tokens@1}};
[{Token, Position} | _] ->
{error, {unexpected_token, Token, Position}}
end.
-spec field(
list({glexer@token:token(), glexer:position()}),
fun((list({glexer@token:token(), glexer:position()})) -> {ok,
{FDD, list({glexer@token:token(), glexer:position()})}} |
{error, error()})
) -> {ok, {field(FDD), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
field(Tokens, Parser) ->
case Tokens of
[{{name, Name}, _}, {colon, _} | Tokens@1] ->
gleam@result:'try'(
Parser(Tokens@1),
fun(_use0) ->
{T, Tokens@2} = _use0,
{ok, {{field, {some, Name}, T}, Tokens@2}}
end
);
_ ->
gleam@result:'try'(
Parser(Tokens),
fun(_use0@1) ->
{T@1, Tokens@3} = _use0@1,
{ok, {{field, none, T@1}, Tokens@3}}
end
)
end.
-spec slurp(module_(), list({glexer@token:token(), glexer:position()})) -> {ok,
module_()} |
{error, error()}.
slurp(Module, Tokens) ->
case Tokens of
[] ->
{ok, Module};
[{import, _} | Tokens@1] ->
import_statement(Module, Tokens@1);
[{pub, _}, {type, _} | Tokens@2] ->
type_definition(Module, public, Tokens@2);
[{type, _} | Tokens@3] ->
type_definition(Module, private, Tokens@3);
[{pub, _}, {const, _} | Tokens@4] ->
const_definition(Module, public, Tokens@4);
[{const, _} | Tokens@5] ->
const_definition(Module, private, Tokens@5);
[{pub, _}, {external, _}, {fn, _} | Tokens@6] ->
external_fn_definition(Module, public, Tokens@6);
[{external, _}, {fn, _} | Tokens@7] ->
external_fn_definition(Module, private, Tokens@7);
[{pub, _}, {external, _}, {type, _} | Tokens@8] ->
external_type_definition(Module, public, Tokens@8);
[{external, _}, {type, _} | Tokens@9] ->
external_type_definition(Module, private, Tokens@9);
[_ | Tokens@10] ->
slurp(Module, Tokens@10)
end.
-spec module(binary()) -> {ok, module_()} | {error, error()}.
module(Src) ->
_pipe = glexer:new(Src),
_pipe@1 = glexer:lex(_pipe),
_pipe@2 = gleam@list:filter(
_pipe@1,
fun(Pair) -> erlang:element(1, Pair) /= comment_normal end
),
slurp({module, [], [], [], [], [], []}, _pipe@2).
-spec until(
glexer@token:token(),
FAK,
list({glexer@token:token(), glexer:position()}),
fun((FAK, list({glexer@token:token(), glexer:position()})) -> {ok,
{FAK, list({glexer@token:token(), glexer:position()})}} |
{error, error()})
) -> {ok, {FAK, list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
until(Limit, Acc, Tokens, Callback) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{Token, _} | Tokens@1] when Token =:= Limit ->
{ok, {Acc, Tokens@1}};
[_ | _] ->
case Callback(Acc, Tokens) of
{ok, {Acc@1, Tokens@2}} ->
until(Limit, Acc@1, Tokens@2, Callback);
{error, Error} ->
{error, Error}
end
end.
-spec module_name(binary(), list({glexer@token:token(), glexer:position()})) -> {ok,
{binary(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
module_name(Name, Tokens) ->
case Tokens of
[{slash, _}, {{name, S}, _} | Tokens@1] when Name =/= <<""/utf8>> ->
module_name(
<<<<Name/binary, "/"/utf8>>/binary, S/binary>>,
Tokens@1
);
[{{name, S@1}, _} | Tokens@2] when Name =:= <<""/utf8>> ->
module_name(S@1, Tokens@2);
[] when Name =:= <<""/utf8>> ->
{error, unexpected_end_of_input};
[{Other, Position} | _] when Name =:= <<""/utf8>> ->
{error, {unexpected_token, Other, Position}};
_ ->
{ok, {Name, Tokens}}
end.
-spec unqualified_imports(
list(unqualified_import()),
list({glexer@token:token(), glexer:position()})
) -> {ok,
{list(unqualified_import()),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
unqualified_imports(Items, Tokens) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{right_brace, _} | Tokens@1] ->
{ok, {gleam@list:reverse(Items), Tokens@1}};
[{{upper_name, Name}, _},
{as, _},
{{upper_name, Alias}, _},
{comma, _} |
Tokens@2] ->
Import_ = {unqualified_import, Name, {some, Alias}},
unqualified_imports([Import_ | Items], Tokens@2);
[{{name, Name}, _}, {as, _}, {{name, Alias}, _}, {comma, _} | Tokens@2] ->
Import_ = {unqualified_import, Name, {some, Alias}},
unqualified_imports([Import_ | Items], Tokens@2);
[{{upper_name, Name@1}, _},
{as, _},
{{upper_name, Alias@1}, _},
{right_brace, _} |
Tokens@3] ->
Import_@1 = {unqualified_import, Name@1, {some, Alias@1}},
{ok, {gleam@list:reverse([Import_@1 | Items]), Tokens@3}};
[{{name, Name@1}, _},
{as, _},
{{name, Alias@1}, _},
{right_brace, _} |
Tokens@3] ->
Import_@1 = {unqualified_import, Name@1, {some, Alias@1}},
{ok, {gleam@list:reverse([Import_@1 | Items]), Tokens@3}};
[{{upper_name, Name@2}, _}, {comma, _} | Tokens@4] ->
Import_@2 = {unqualified_import, Name@2, none},
unqualified_imports([Import_@2 | Items], Tokens@4);
[{{name, Name@2}, _}, {comma, _} | Tokens@4] ->
Import_@2 = {unqualified_import, Name@2, none},
unqualified_imports([Import_@2 | Items], Tokens@4);
[{{upper_name, Name@3}, _}, {right_brace, _} | Tokens@5] ->
Import_@3 = {unqualified_import, Name@3, none},
{ok, {gleam@list:reverse([Import_@3 | Items]), Tokens@5}};
[{{name, Name@3}, _}, {right_brace, _} | Tokens@5] ->
Import_@3 = {unqualified_import, Name@3, none},
{ok, {gleam@list:reverse([Import_@3 | Items]), Tokens@5}};
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}}
end.
-spec optional_unqualified_imports(
list({glexer@token:token(), glexer:position()})
) -> {ok,
{list(unqualified_import()),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
optional_unqualified_imports(Tokens) ->
case Tokens of
[{dot, _}, {left_brace, _} | Tokens@1] ->
unqualified_imports([], Tokens@1);
_ ->
{ok, {[], Tokens}}
end.
-spec import_statement(
module_(),
list({glexer@token:token(), glexer:position()})
) -> {ok, module_()} | {error, error()}.
import_statement(Module, Tokens) ->
gleam@result:'try'(
module_name(<<""/utf8>>, Tokens),
fun(_use0) ->
{Module_name, Tokens@1} = _use0,
gleam@result:'try'(
optional_unqualified_imports(Tokens@1),
fun(_use0@1) ->
{Unqualified, Tokens@2} = _use0@1,
{Alias, Tokens@3} = optional_module_alias(Tokens@2),
Import_ = {import, Module_name, Alias, Unqualified},
slurp(
erlang:setelement(
2,
Module,
[Import_ | erlang:element(2, Module)]
),
Tokens@3
)
end
)
end
).
-spec comma_delimited(
list(FBQ),
list({glexer@token:token(), glexer:position()}),
fun((list({glexer@token:token(), glexer:position()})) -> {ok,
{FBQ, list({glexer@token:token(), glexer:position()})}} |
{error, error()}),
glexer@token:token()
) -> {ok, {list(FBQ), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
comma_delimited(Items, Tokens, Parser, Final) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{Token, _} | Tokens@1] when Token =:= Final ->
{ok, {gleam@list:reverse(Items), Tokens@1}};
_ ->
gleam@result:'try'(
Parser(Tokens),
fun(_use0) ->
{Element, Tokens@2} = _use0,
case Tokens@2 of
[{comma, _} | Tokens@3] ->
comma_delimited(
[Element | Items],
Tokens@3,
Parser,
Final
);
[{Token@1, _} | Tokens@4] when Token@1 =:= Final ->
{ok,
{gleam@list:reverse([Element | Items]),
Tokens@4}};
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}}
end
end
)
end.
-spec optional_type_parameters(list({glexer@token:token(), glexer:position()})) -> {ok,
{list(binary()), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
optional_type_parameters(Tokens) ->
case Tokens of
[{left_paren, _} | Tokens@1] ->
comma_delimited([], Tokens@1, fun name/1, right_paren);
_ ->
{ok, {[], Tokens}}
end.
-spec external_type_definition(
module_(),
publicity(),
list({glexer@token:token(), glexer:position()})
) -> {ok, module_()} | {error, error()}.
external_type_definition(Module, Publicity, Tokens) ->
expect_upper_name(
Tokens,
fun(Name, Tokens@1) ->
gleam@result:'try'(
optional_type_parameters(Tokens@1),
fun(_use0) ->
{Parameters, Tokens@2} = _use0,
_pipe = Module,
_pipe@1 = push_external_type(
_pipe,
{external_type, Name, Publicity, Parameters}
),
slurp(_pipe@1, Tokens@2)
end
)
end
).
-spec constant_bit_string(list({glexer@token:token(), glexer:position()})) -> {ok,
{constant_expression(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
constant_bit_string(Tokens) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{greater_greater, _} | Tokens@1] ->
{ok, {constant_bit_string, Tokens@1}};
[_ | Tokens@2] ->
constant_bit_string(Tokens@2)
end.
-spec constant_constructor(
binary(),
gleam@option:option(binary()),
list({glexer@token:token(), glexer:position()})
) -> {ok,
{constant_expression(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
constant_constructor(Name, Module, Tokens) ->
case Tokens of
[{left_paren, _} | Tokens@1] ->
Parser = fun(_capture) ->
field(_capture, fun constant_expression/1)
end,
Result = comma_delimited([], Tokens@1, Parser, right_paren),
gleam@result:'try'(
Result,
fun(_use0) ->
{Arguments, Tokens@2} = _use0,
{ok,
{{constant_constructor, Name, Module, Arguments},
Tokens@2}}
end
);
_ ->
{ok, {{constant_constructor, Name, Module, []}, Tokens}}
end.
-spec constant_expression(list({glexer@token:token(), glexer:position()})) -> {ok,
{constant_expression(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
constant_expression(Tokens) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{{name, Module}, _}, {dot, _}, {{upper_name, Name}, _} | Tokens@1] ->
constant_constructor(Name, {some, Module}, Tokens@1);
[{{upper_name, Name@1}, _} | Tokens@2] ->
constant_constructor(Name@1, none, Tokens@2);
[{{int, I}, _} | Tokens@3] ->
{ok, {{constant_int, I}, Tokens@3}};
[{{name, N}, _} | Tokens@4] ->
{ok, {{constant_variable, N}, Tokens@4}};
[{{float, I@1}, _} | Tokens@5] ->
{ok, {{constant_float, I@1}, Tokens@5}};
[{{string, I@2}, _} | Tokens@6] ->
{ok, {{constant_string, I@2}, Tokens@6}};
[{left_square, _} | Tokens@7] ->
constant_list(Tokens@7);
[{hash, _}, {left_paren, _} | Tokens@8] ->
constant_tuple(Tokens@8);
[{less_less, _} | Tokens@9] ->
constant_bit_string(Tokens@9);
[{Token, Position} | _] ->
{error, {unexpected_token, Token, Position}}
end.
-spec constant_tuple(list({glexer@token:token(), glexer:position()})) -> {ok,
{constant_expression(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
constant_tuple(Tokens) ->
Result = comma_delimited([], Tokens, fun constant_expression/1, right_paren),
gleam@result:'try'(
Result,
fun(_use0) ->
{Elements, Tokens@1} = _use0,
{ok, {{constant_tuple, Elements}, Tokens@1}}
end
).
-spec constant_list(list({glexer@token:token(), glexer:position()})) -> {ok,
{constant_expression(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
constant_list(Tokens) ->
Result = comma_delimited(
[],
Tokens,
fun constant_expression/1,
right_square
),
gleam@result:'try'(
Result,
fun(_use0) ->
{Elements, Tokens@1} = _use0,
{ok, {{constant_list, Elements}, Tokens@1}}
end
).
-spec named_type(
binary(),
gleam@option:option(binary()),
list({glexer@token:token(), glexer:position()})
) -> {ok, {type(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
named_type(Name, Module, Tokens) ->
gleam@result:'try'(case Tokens of
[{left_paren, _} | Tokens@1] ->
comma_delimited([], Tokens@1, fun type_/1, right_paren);
_ ->
{ok, {[], Tokens}}
end, fun(_use0) ->
{Parameters, Tokens@2} = _use0,
T = {named_type, Name, Module, Parameters},
{ok, {T, Tokens@2}}
end).
-spec type_(list({glexer@token:token(), glexer:position()})) -> {ok,
{type(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
type_(Tokens) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{fn, _}, {left_paren, _} | Tokens@1] ->
fn_type(Tokens@1);
[{hash, _}, {left_paren, _} | Tokens@2] ->
tuple_type(Tokens@2);
[{{name, Module}, _}, {dot, _}, {{upper_name, Name}, _} | Tokens@3] ->
named_type(Name, {some, Module}, Tokens@3);
[{{upper_name, Name@1}, _} | Tokens@4] ->
named_type(Name@1, none, Tokens@4);
[{{name, Name@2}, _} | Tokens@5] ->
{ok, {{variable_type, Name@2}, Tokens@5}};
[{Token, Position} | _] ->
{error, {unexpected_token, Token, Position}}
end.
-spec external_fn_definition(
module_(),
publicity(),
list({glexer@token:token(), glexer:position()})
) -> {ok, module_()} | {error, error()}.
external_fn_definition(Module, Publicity, Tokens) ->
expect_name(
Tokens,
fun(Name, Tokens@1) ->
expect(
left_paren,
Tokens@1,
fun(_, Tokens@2) ->
Parser = fun(_capture) -> field(_capture, fun type_/1) end,
Result = comma_delimited([], Tokens@2, Parser, right_paren),
gleam@result:'try'(
Result,
fun(_use0) ->
{Parameters, Tokens@3} = _use0,
expect(
right_arrow,
Tokens@3,
fun(_, Tokens@4) ->
gleam@result:'try'(
type_(Tokens@4),
fun(_use0@1) ->
{Return_type, Tokens@5} = _use0@1,
expect(
equal,
Tokens@5,
fun(_, Tokens@6) ->
expect_string(
Tokens@6,
fun(Mod, Tokens@7) ->
expect_string(
Tokens@7,
fun(F, Tokens@8) ->
Extern = {external_function,
Name,
Publicity,
Parameters,
Return_type,
Mod,
F},
_pipe = Module,
_pipe@1 = push_external_function(
_pipe,
Extern
),
slurp(
_pipe@1,
Tokens@8
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-spec const_definition(
module_(),
publicity(),
list({glexer@token:token(), glexer:position()})
) -> {ok, module_()} | {error, error()}.
const_definition(Module, Publicity, Tokens) ->
expect_name(
Tokens,
fun(Name, Tokens@1) -> gleam@result:'try'(case Tokens@1 of
[{colon, _} | Tokens@2] ->
gleam@result:map(
type_(Tokens@2),
fun(_use0) ->
{Annotation, Tokens@3} = _use0,
{{some, Annotation}, Tokens@3}
end
);
_ ->
{ok, {none, Tokens@1}}
end, fun(_use0@1) ->
{Annotation@1, Tokens@4} = _use0@1,
expect(
equal,
Tokens@4,
fun(_, Tokens@5) ->
gleam@result:'try'(
constant_expression(Tokens@5),
fun(_use0@2) ->
{Expression, Tokens@6} = _use0@2,
_pipe = Module,
_pipe@1 = push_constant(
_pipe,
{constant,
Name,
Publicity,
Annotation@1,
Expression}
),
slurp(_pipe@1, Tokens@6)
end
)
end
)
end) end
).
-spec type_alias(
module_(),
binary(),
list(binary()),
publicity(),
list({glexer@token:token(), glexer:position()})
) -> {ok, module_()} | {error, error()}.
type_alias(Module, Name, Parameters, Publicity, Tokens) ->
gleam@result:'try'(
type_(Tokens),
fun(_use0) ->
{Type_, Tokens@1} = _use0,
_pipe = Module,
_pipe@1 = push_type_alias(
_pipe,
{type_alias, Name, Publicity, Parameters, Type_}
),
slurp(_pipe@1, Tokens@1)
end
).
-spec fn_type(list({glexer@token:token(), glexer:position()})) -> {ok,
{type(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
fn_type(Tokens) ->
Result = comma_delimited([], Tokens, fun type_/1, right_paren),
gleam@result:'try'(
Result,
fun(_use0) ->
{Parameters, Tokens@1} = _use0,
expect(
right_arrow,
Tokens@1,
fun(_, Tokens@2) ->
gleam@result:'try'(
type_(Tokens@2),
fun(_use0@1) ->
{Return, Tokens@3} = _use0@1,
{ok,
{{function_type, Parameters, Return}, Tokens@3}}
end
)
end
)
end
).
-spec tuple_type(list({glexer@token:token(), glexer:position()})) -> {ok,
{type(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
tuple_type(Tokens) ->
Result = comma_delimited([], Tokens, fun type_/1, right_paren),
gleam@result:'try'(
Result,
fun(_use0) ->
{Types, Tokens@1} = _use0,
{ok, {{tuple_type, Types}, Tokens@1}}
end
).
-spec optional_variant_fields(list({glexer@token:token(), glexer:position()})) -> {ok,
{list(field(type())), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
optional_variant_fields(Tokens) ->
case Tokens of
[{left_paren, _}, {right_paren, _} | Tokens@1] ->
{ok, {[], Tokens@1}};
[{left_paren, _} | Tokens@2] ->
comma_delimited(
[],
Tokens@2,
fun(_capture) -> field(_capture, fun type_/1) end,
right_paren
);
_ ->
{ok, {[], Tokens}}
end.
-spec variants(custom_type(), list({glexer@token:token(), glexer:position()})) -> {ok,
{custom_type(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
variants(Ct, Tokens) ->
until(
right_brace,
Ct,
Tokens,
fun(Ct@1, Tokens@1) ->
expect_upper_name(
Tokens@1,
fun(Name, Tokens@2) ->
gleam@result:'try'(
optional_variant_fields(Tokens@2),
fun(_use0) ->
{Parameters, Tokens@3} = _use0,
Ct@2 = push_variant(
Ct@1,
{variant, Name, Parameters}
),
{ok, {Ct@2, Tokens@3}}
end
)
end
)
end
).
-spec custom_type(
module_(),
binary(),
list(binary()),
publicity(),
list({glexer@token:token(), glexer:position()})
) -> {ok, module_()} | {error, error()}.
custom_type(Module, Name, Parameters, Publicity, Tokens) ->
Ct = {custom_type, Name, Publicity, Parameters, []},
gleam@result:'try'(
variants(Ct, Tokens),
fun(_use0) ->
{Ct@1, Tokens@1} = _use0,
Module@1 = push_custom_type(Module, Ct@1),
slurp(Module@1, Tokens@1)
end
).
-spec type_definition(
module_(),
publicity(),
list({glexer@token:token(), glexer:position()})
) -> {ok, module_()} | {error, error()}.
type_definition(Module, Publicity, Tokens) ->
expect_upper_name(
Tokens,
fun(Name, Tokens@1) ->
gleam@result:'try'(
optional_type_parameters(Tokens@1),
fun(_use0) ->
{Parameters, Tokens@2} = _use0,
case Tokens@2 of
[] ->
{error, unexpected_end_of_input};
[{equal, _} | Tokens@3] ->
type_alias(
Module,
Name,
Parameters,
Publicity,
Tokens@3
);
[{left_brace, _} | Tokens@4] ->
custom_type(
Module,
Name,
Parameters,
Publicity,
Tokens@4
)
end
end
)
end
).