Current section
Files
Jump to
Current section
Files
lib/zig.parser/function.ex
defmodule Zig.Parser.FnOptions do
defstruct [
:position,
:doc_comment,
:block,
:align,
:linksection,
:callconv,
extern: false,
export: false,
pub: false,
inline: :maybe
]
end
defmodule Zig.Parser.Function do
alias Zig.Parser
alias Zig.Parser.FnOptions
def post_traverse(rest, [{tag, [position = %{line: _} | args]} | rest_args], context, _, _, tag) do
fun =
args
|> parse([])
|> Parser.put_opt(:position, position)
{rest, [fun | rest_args], context}
end
def parse(what), do: parse(what, [])
defp parse([:export | rest], parts) do
rest
|> parse(parts)
|> Parser.put_opt(:export, true)
end
defp parse([:extern, extern_form | rest], parts) when is_binary(extern_form) do
rest
|> parse(parts)
|> Parser.put_opt(:extern, extern_form)
end
defp parse([:extern | rest], parts) do
rest
|> parse(parts)
|> Parser.put_opt(:extern, true)
end
defp parse([:inline | rest], parts) do
rest
|> parse(parts)
|> Parser.put_opt(:inline, true)
end
defp parse([:noinline | rest], parts) do
rest
|> parse(parts)
|> Parser.put_opt(:inline, false)
end
# identifiers are required in top level fn declarations.
defp parse([:fn, name, :LPAREN, {:ParamDeclList, params}, :RPAREN | rest], parts) do
parse(rest, Keyword.merge(parts, name: name, params: parse_params(params)))
end
defp parse([:fn, :LPAREN, {:ParamDeclList, params}, :RPAREN | rest], parts) do
parse(rest, Keyword.merge(parts, params: parse_params(params)))
end
defp parse([:align, :LPAREN, alignexpr, :RPAREN | rest], parts) do
rest
|> parse(parts)
|> Parser.put_opt(:align, alignexpr)
end
defp parse([:linksection, :LPAREN, linkexpr, :RPAREN | rest], parts) do
rest
|> parse(parts)
|> Parser.put_opt(:linksection, linkexpr)
end
defp parse([:callconv, :LPAREN, callconv, :RPAREN | rest], parts) do
rest
|> parse(parts)
|> Parser.put_opt(:callconv, callconv)
end
@enders [[], [:SEMICOLON]]
defp parse(ender, parts) when ender in @enders, do: {:fn, %FnOptions{}, parts}
defp parse([block = {:block, _, _}], parts),
do: {:fn, %FnOptions{}, Keyword.merge(parts, block: block)}
defp parse([expr | rest], parts) do
parse(rest, Keyword.merge(parts, type: expr))
end
# parameters should have commas filtered
defp parse_params(params) do
Enum.filter(params, &(&1 != :COMMA))
end
end