Packages
localize
0.30.0
1.0.0-rc.6
1.0.0-rc.5
1.0.0-rc.4
1.0.0-rc.3
1.0.0-rc.2
1.0.0-rc.1
1.0.0-rc.0
0.50.0
0.49.0
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.41.3
0.41.2
0.41.1
0.41.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.0
0.32.0
0.31.0
0.30.1
0.30.0
retired
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
0.1.0-alpha.1
Localization (parsing, formatting) of numbers, dates/time/calendar, units of measure, messages and lists. Includes localized collation.
Retired package: Deprecated - deprecated
Current section
Files
Jump to
Current section
Files
lib/localize/number/plural_rules/transformer.ex
defmodule Localize.Number.PluralRule.Transformer do
@moduledoc false
# Transforms the parse tree returned from parsing plural rules
# into an AST representing a `cond` statement that implements
# the rule.
@doc """
Converts a map representing a set of plural rules into a
`cond` statement AST.
`rules` is a keyword list of `{category, definition}` pairs
where the definition is the parsed AST of the CLDR plural
rule for that category.
"""
def rules_to_condition_statement(rules, module) do
branches =
Enum.map(rules, fn {category, definition} ->
{new_ast, _} = set_operand_module(definition[:rule], module)
rule_to_cond_branch(new_ast, category)
end)
{:cond, [], [[do: move_true_branch_to_end(branches)]]}
end
# We can't assume the order of branches and we need the
# `true` branch at the end since it will always match
# and hence potentially shadow other branches.
defp move_true_branch_to_end(branches) do
Enum.sort(branches, fn {:->, [], [[ast], _category]}, _other_branch ->
not (ast == true)
end)
end
# Walk the AST and replace the variable context to that of the calling
# module. Also set the correct import context for `mod` and `within`
# functions which are provided by `Localize.Utils.Math`.
defp set_operand_module(ast, _module) do
Macro.prewalk(ast, [], fn expr, acc ->
new_expr =
case expr do
{var, [], Elixir} ->
{var, [], nil}
{:mod, _context, [operand, value]} ->
{:mod, [context: Elixir, import: Elixir.Localize.Utils.Math], [operand, value]}
{:within, _context, [operand, range]} ->
{:within, [context: Elixir, import: Elixir.Localize.Utils.Math], [operand, range]}
_ ->
expr
end
{new_expr, acc}
end)
end
# Transform the rule AST into a branch of a `cond` statement.
defp rule_to_cond_branch(nil, category) do
{:->, [], [[true], category]}
end
defp rule_to_cond_branch(rule_ast, category) do
{:->, [], [[rule_ast], category]}
end
end