
// This file is generated by GenerateCSSMathFunctions.cpp

#include <LibWeb/CSS/Enums.h>
#include <LibWeb/CSS/MathFunctions.h>
#include <LibWeb/CSS/Parser/ErrorReporter.h>
#include <LibWeb/CSS/Parser/Parser.h>
#include <LibWeb/CSS/StyleValues/CalculatedStyleValue.h>
#include <LibWeb/CSS/StyleValues/RandomValueSharingStyleValue.h>

namespace Web::CSS {

Optional<MathFunction> math_function_from_string(StringView name)
{
    if (name.equals_ignoring_ascii_case("calc"sv))
        return MathFunction::Calc;

    if (name.equals_ignoring_ascii_case("abs"sv))
        return MathFunction::Abs;

    if (name.equals_ignoring_ascii_case("acos"sv))
        return MathFunction::Acos;

    if (name.equals_ignoring_ascii_case("asin"sv))
        return MathFunction::Asin;

    if (name.equals_ignoring_ascii_case("atan"sv))
        return MathFunction::Atan;

    if (name.equals_ignoring_ascii_case("atan2"sv))
        return MathFunction::Atan2;

    if (name.equals_ignoring_ascii_case("clamp"sv))
        return MathFunction::Clamp;

    if (name.equals_ignoring_ascii_case("cos"sv))
        return MathFunction::Cos;

    if (name.equals_ignoring_ascii_case("exp"sv))
        return MathFunction::Exp;

    if (name.equals_ignoring_ascii_case("hypot"sv))
        return MathFunction::Hypot;

    if (name.equals_ignoring_ascii_case("log"sv))
        return MathFunction::Log;

    if (name.equals_ignoring_ascii_case("max"sv))
        return MathFunction::Max;

    if (name.equals_ignoring_ascii_case("min"sv))
        return MathFunction::Min;

    if (name.equals_ignoring_ascii_case("mod"sv))
        return MathFunction::Mod;

    if (name.equals_ignoring_ascii_case("pow"sv))
        return MathFunction::Pow;

    if (name.equals_ignoring_ascii_case("random"sv))
        return MathFunction::Random;

    if (name.equals_ignoring_ascii_case("rem"sv))
        return MathFunction::Rem;

    if (name.equals_ignoring_ascii_case("round"sv))
        return MathFunction::Round;

    if (name.equals_ignoring_ascii_case("sign"sv))
        return MathFunction::Sign;

    if (name.equals_ignoring_ascii_case("sin"sv))
        return MathFunction::Sin;

    if (name.equals_ignoring_ascii_case("sqrt"sv))
        return MathFunction::Sqrt;

    if (name.equals_ignoring_ascii_case("tan"sv))
        return MathFunction::Tan;

    return {};
}

}

namespace Web::CSS::Parser {

static Optional<RoundingStrategy> parse_rounding_strategy(TokenStream<ComponentValue>& stream)
{
    stream.discard_whitespace();
    if (!stream.has_next_token())
        return {};

    auto& ident = stream.consume_a_token();
    if (!ident.is(Token::Type::Ident))
        return {};

    stream.discard_whitespace();
    if (stream.has_next_token())
        return {};

    auto maybe_keyword = keyword_from_string(ident.token().ident());
    if (!maybe_keyword.has_value())
        return {};

    return keyword_to_rounding_strategy(maybe_keyword.value());
}

RefPtr<CalculationNode const> Parser::parse_math_function(Function const& function, CalculationContext const& context)
{
    TokenStream stream { function.value };
    auto arguments = parse_a_comma_separated_list_of_component_values(stream);
    auto const& percentages_resolve_as = context.percentages_resolve_as;
    if (function.name.equals_ignoring_ascii_case("abs"sv)) {

        if (arguments.size() < 1 || arguments.size() > 1) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "abs()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 1 and 1 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "abs()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "abs()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "abs()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as) || argument_type_0.matches_dimension() || argument_type_0.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "abs()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (determined_argument_type != argument_type_0) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "abs()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) doesn't match type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return AbsCalculationNode::create(parameter_0.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("acos"sv)) {

        if (arguments.size() < 1 || arguments.size() > 1) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "acos()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 1 and 1 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "acos()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "acos()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "acos()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as))) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "acos()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (determined_argument_type != argument_type_0) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "acos()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) doesn't match type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return AcosCalculationNode::create(parameter_0.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("asin"sv)) {

        if (arguments.size() < 1 || arguments.size() > 1) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "asin()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 1 and 1 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "asin()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "asin()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "asin()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as))) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "asin()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (determined_argument_type != argument_type_0) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "asin()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) doesn't match type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return AsinCalculationNode::create(parameter_0.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("atan"sv)) {

        if (arguments.size() < 1 || arguments.size() > 1) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "atan()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 1 and 1 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "atan()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "atan()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "atan()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as))) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "atan()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (determined_argument_type != argument_type_0) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "atan()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) doesn't match type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return AtanCalculationNode::create(parameter_0.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("atan2"sv)) {

        if (arguments.size() < 2 || arguments.size() > 2) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "atan2()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 2 and 2 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "atan2()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'y'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "atan2()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'y'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "atan2()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'y' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as) || argument_type_0.matches_dimension() || argument_type_0.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "atan2()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'y' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type_0); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "atan2()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'y' type ({}) is not consistent with type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        RefPtr<CalculationNode const> parameter_1;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "atan2()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'x'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_1 { arguments[argument_index] };
            auto maybe_parsed_argument_1 = parse_a_calculation(tokens_1, context);
            if (maybe_parsed_argument_1 != nullptr) {
                parameter_1 = maybe_parsed_argument_1.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "atan2()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'x'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_1) {
            auto maybe_argument_type_1 = parameter_1->numeric_type();
            if (!maybe_argument_type_1.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "atan2()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'x' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_1 = maybe_argument_type_1.release_value();

            if (!(argument_type_1.matches_number(percentages_resolve_as) || argument_type_1.matches_dimension() || argument_type_1.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "atan2()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'x' type ({}) is not an accepted type.", argument_type_1.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_1;
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type_1); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "atan2()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'x' type ({}) is not consistent with type of previous arguments ({}).", argument_type_1.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return Atan2CalculationNode::create(parameter_0.release_nonnull(), parameter_1.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("clamp"sv)) {

        if (arguments.size() < 3 || arguments.size() > 3) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "clamp()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 3 and 3 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "clamp()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'min'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "clamp()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'min'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "clamp()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'min' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as) || argument_type_0.matches_dimension() || argument_type_0.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "clamp()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'min' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type_0); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "clamp()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'min' type ({}) is not consistent with type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        RefPtr<CalculationNode const> parameter_1;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "clamp()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'central'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_1 { arguments[argument_index] };
            auto maybe_parsed_argument_1 = parse_a_calculation(tokens_1, context);
            if (maybe_parsed_argument_1 != nullptr) {
                parameter_1 = maybe_parsed_argument_1.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "clamp()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'central'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_1) {
            auto maybe_argument_type_1 = parameter_1->numeric_type();
            if (!maybe_argument_type_1.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "clamp()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'central' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_1 = maybe_argument_type_1.release_value();

            if (!(argument_type_1.matches_number(percentages_resolve_as) || argument_type_1.matches_dimension() || argument_type_1.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "clamp()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'central' type ({}) is not an accepted type.", argument_type_1.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_1;
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type_1); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "clamp()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'central' type ({}) is not consistent with type of previous arguments ({}).", argument_type_1.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        RefPtr<CalculationNode const> parameter_2;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "clamp()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'max'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_2 { arguments[argument_index] };
            auto maybe_parsed_argument_2 = parse_a_calculation(tokens_2, context);
            if (maybe_parsed_argument_2 != nullptr) {
                parameter_2 = maybe_parsed_argument_2.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "clamp()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'max'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_2) {
            auto maybe_argument_type_2 = parameter_2->numeric_type();
            if (!maybe_argument_type_2.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "clamp()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'max' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_2 = maybe_argument_type_2.release_value();

            if (!(argument_type_2.matches_number(percentages_resolve_as) || argument_type_2.matches_dimension() || argument_type_2.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "clamp()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'max' type ({}) is not an accepted type.", argument_type_2.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_2;
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type_2); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "clamp()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'max' type ({}) is not consistent with type of previous arguments ({}).", argument_type_2.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return ClampCalculationNode::create(parameter_0.release_nonnull(), parameter_1.release_nonnull(), parameter_2.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("cos"sv)) {

        if (arguments.size() < 1 || arguments.size() > 1) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "cos()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 1 and 1 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "cos()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "cos()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "cos()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as) || argument_type_0.matches_angle(percentages_resolve_as))) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "cos()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (determined_argument_type != argument_type_0) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "cos()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) doesn't match type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return CosCalculationNode::create(parameter_0.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("exp"sv)) {

        if (arguments.size() < 1 || arguments.size() > 1) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "exp()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 1 and 1 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "exp()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "exp()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "exp()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as))) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "exp()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (determined_argument_type != argument_type_0) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "exp()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) doesn't match type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return ExpCalculationNode::create(parameter_0.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("hypot"sv)) {

        Optional<NumericType> determined_argument_type;
        Vector<NonnullRefPtr<CalculationNode const>> parsed_arguments;
        parsed_arguments.ensure_capacity(arguments.size());

        for (auto& argument : arguments) {
            TokenStream<ComponentValue> tokens { argument };
            auto calculation_node = parse_a_calculation(tokens, context);
            if (!calculation_node) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "hypot()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument #{} is not a valid calculation.", parsed_arguments.size())),
                });
                return nullptr;
            }

            auto maybe_argument_type = calculation_node->numeric_type();
            if (!maybe_argument_type.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "hypot()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument #{} couldn't determine its type.", parsed_arguments.size())),
                });
                return nullptr;
            }
            auto argument_type = maybe_argument_type.release_value();


            if (!(argument_type.matches_number(percentages_resolve_as) || argument_type.matches_dimension() || argument_type.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "hypot()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument #{} type ({}) is not an accepted type.", parsed_arguments.size(), argument_type.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = move(argument_type);
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "hypot()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument #{} type ({}) is not consistent with type of previous arguments ({}).", parsed_arguments.size(), argument_type.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }

            parsed_arguments.append(calculation_node.release_nonnull());
        }

        return HypotCalculationNode::create(move(parsed_arguments));
    }
    if (function.name.equals_ignoring_ascii_case("log"sv)) {

        if (arguments.size() < 1 || arguments.size() > 2) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "log()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 1 and 2 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "log()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "log()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "log()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as))) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "log()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (determined_argument_type != argument_type_0) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "log()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) doesn't match type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        RefPtr<CalculationNode const> parameter_1 = NumericCalculationNode::from_keyword(Keyword::E, context);

        if (argument_index < arguments.size()) {

            TokenStream tokens_1 { arguments[argument_index] };
            auto maybe_parsed_argument_1 = parse_a_calculation(tokens_1, context);
            if (maybe_parsed_argument_1 != nullptr) {
                parameter_1 = maybe_parsed_argument_1.release_nonnull();
                argument_index++;

            }
        }

        if (parameter_1) {
            auto maybe_argument_type_1 = parameter_1->numeric_type();
            if (!maybe_argument_type_1.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "log()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'base' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_1 = maybe_argument_type_1.release_value();

            if (!(argument_type_1.matches_number(percentages_resolve_as))) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "log()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'base' type ({}) is not an accepted type.", argument_type_1.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_1;
            } else {

                if (determined_argument_type != argument_type_1) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "log()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'base' type ({}) doesn't match type of previous arguments ({}).", argument_type_1.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return LogCalculationNode::create(parameter_0.release_nonnull(), parameter_1.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("max"sv)) {

        Optional<NumericType> determined_argument_type;
        Vector<NonnullRefPtr<CalculationNode const>> parsed_arguments;
        parsed_arguments.ensure_capacity(arguments.size());

        for (auto& argument : arguments) {
            TokenStream<ComponentValue> tokens { argument };
            auto calculation_node = parse_a_calculation(tokens, context);
            if (!calculation_node) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "max()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument #{} is not a valid calculation.", parsed_arguments.size())),
                });
                return nullptr;
            }

            auto maybe_argument_type = calculation_node->numeric_type();
            if (!maybe_argument_type.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "max()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument #{} couldn't determine its type.", parsed_arguments.size())),
                });
                return nullptr;
            }
            auto argument_type = maybe_argument_type.release_value();


            if (!(argument_type.matches_number(percentages_resolve_as) || argument_type.matches_dimension() || argument_type.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "max()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument #{} type ({}) is not an accepted type.", parsed_arguments.size(), argument_type.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = move(argument_type);
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "max()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument #{} type ({}) is not consistent with type of previous arguments ({}).", parsed_arguments.size(), argument_type.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }

            parsed_arguments.append(calculation_node.release_nonnull());
        }

        return MaxCalculationNode::create(move(parsed_arguments));
    }
    if (function.name.equals_ignoring_ascii_case("min"sv)) {

        Optional<NumericType> determined_argument_type;
        Vector<NonnullRefPtr<CalculationNode const>> parsed_arguments;
        parsed_arguments.ensure_capacity(arguments.size());

        for (auto& argument : arguments) {
            TokenStream<ComponentValue> tokens { argument };
            auto calculation_node = parse_a_calculation(tokens, context);
            if (!calculation_node) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "min()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument #{} is not a valid calculation.", parsed_arguments.size())),
                });
                return nullptr;
            }

            auto maybe_argument_type = calculation_node->numeric_type();
            if (!maybe_argument_type.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "min()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument #{} couldn't determine its type.", parsed_arguments.size())),
                });
                return nullptr;
            }
            auto argument_type = maybe_argument_type.release_value();


            if (!(argument_type.matches_number(percentages_resolve_as) || argument_type.matches_dimension() || argument_type.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "min()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument #{} type ({}) is not an accepted type.", parsed_arguments.size(), argument_type.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = move(argument_type);
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "min()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument #{} type ({}) is not consistent with type of previous arguments ({}).", parsed_arguments.size(), argument_type.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }

            parsed_arguments.append(calculation_node.release_nonnull());
        }

        return MinCalculationNode::create(move(parsed_arguments));
    }
    if (function.name.equals_ignoring_ascii_case("mod"sv)) {

        if (arguments.size() < 2 || arguments.size() > 2) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "mod()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 2 and 2 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "mod()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "mod()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "mod()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as) || argument_type_0.matches_dimension() || argument_type_0.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "mod()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (determined_argument_type != argument_type_0) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "mod()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) doesn't match type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        RefPtr<CalculationNode const> parameter_1;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "mod()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'divisor'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_1 { arguments[argument_index] };
            auto maybe_parsed_argument_1 = parse_a_calculation(tokens_1, context);
            if (maybe_parsed_argument_1 != nullptr) {
                parameter_1 = maybe_parsed_argument_1.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "mod()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'divisor'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_1) {
            auto maybe_argument_type_1 = parameter_1->numeric_type();
            if (!maybe_argument_type_1.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "mod()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'divisor' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_1 = maybe_argument_type_1.release_value();

            if (!(argument_type_1.matches_number(percentages_resolve_as) || argument_type_1.matches_dimension() || argument_type_1.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "mod()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'divisor' type ({}) is not an accepted type.", argument_type_1.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_1;
            } else {

                if (determined_argument_type != argument_type_1) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "mod()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'divisor' type ({}) doesn't match type of previous arguments ({}).", argument_type_1.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return ModCalculationNode::create(parameter_0.release_nonnull(), parameter_1.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("pow"sv)) {

        if (arguments.size() < 2 || arguments.size() > 2) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "pow()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 2 and 2 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "pow()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "pow()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "pow()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as))) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "pow()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type_0); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "pow()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) is not consistent with type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        RefPtr<CalculationNode const> parameter_1;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "pow()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'exponent'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_1 { arguments[argument_index] };
            auto maybe_parsed_argument_1 = parse_a_calculation(tokens_1, context);
            if (maybe_parsed_argument_1 != nullptr) {
                parameter_1 = maybe_parsed_argument_1.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "pow()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'exponent'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_1) {
            auto maybe_argument_type_1 = parameter_1->numeric_type();
            if (!maybe_argument_type_1.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "pow()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'exponent' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_1 = maybe_argument_type_1.release_value();

            if (!(argument_type_1.matches_number(percentages_resolve_as))) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "pow()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'exponent' type ({}) is not an accepted type.", argument_type_1.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_1;
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type_1); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "pow()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'exponent' type ({}) is not consistent with type of previous arguments ({}).", argument_type_1.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return PowCalculationNode::create(parameter_0.release_nonnull(), parameter_1.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("random"sv)) {

        if (!context_allows_random_functions())
            return nullptr;

        m_random_function_index++;

        if (arguments.size() < 2 || arguments.size() > 4) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "random()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 2 and 4 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<RandomValueSharingStyleValue const> parameter_0 = RandomValueSharingStyleValue::create_auto(random_value_sharing_auto_name(), false);

        if (argument_index < arguments.size()) {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_random_value_sharing(tokens_0);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            }
        }

        RefPtr<CalculationNode const> parameter_1;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "random()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'minimum'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_1 { arguments[argument_index] };
            auto maybe_parsed_argument_1 = parse_a_calculation(tokens_1, context);
            if (maybe_parsed_argument_1 != nullptr) {
                parameter_1 = maybe_parsed_argument_1.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "random()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'minimum'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_1) {
            auto maybe_argument_type_1 = parameter_1->numeric_type();
            if (!maybe_argument_type_1.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "random()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'minimum' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_1 = maybe_argument_type_1.release_value();

            if (!(argument_type_1.matches_number(percentages_resolve_as) || argument_type_1.matches_dimension() || argument_type_1.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "random()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'minimum' type ({}) is not an accepted type.", argument_type_1.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_1;
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type_1); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "random()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'minimum' type ({}) is not consistent with type of previous arguments ({}).", argument_type_1.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        RefPtr<CalculationNode const> parameter_2;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "random()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'maximum'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_2 { arguments[argument_index] };
            auto maybe_parsed_argument_2 = parse_a_calculation(tokens_2, context);
            if (maybe_parsed_argument_2 != nullptr) {
                parameter_2 = maybe_parsed_argument_2.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "random()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'maximum'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_2) {
            auto maybe_argument_type_2 = parameter_2->numeric_type();
            if (!maybe_argument_type_2.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "random()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'maximum' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_2 = maybe_argument_type_2.release_value();

            if (!(argument_type_2.matches_number(percentages_resolve_as) || argument_type_2.matches_dimension() || argument_type_2.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "random()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'maximum' type ({}) is not an accepted type.", argument_type_2.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_2;
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type_2); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "random()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'maximum' type ({}) is not consistent with type of previous arguments ({}).", argument_type_2.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        RefPtr<CalculationNode const> parameter_3;

        if (argument_index < arguments.size()) {

            TokenStream tokens_3 { arguments[argument_index] };
            auto maybe_parsed_argument_3 = parse_a_calculation(tokens_3, context);
            if (maybe_parsed_argument_3 != nullptr) {
                parameter_3 = maybe_parsed_argument_3.release_nonnull();
                argument_index++;

            }
        }

        if (parameter_3) {
            auto maybe_argument_type_3 = parameter_3->numeric_type();
            if (!maybe_argument_type_3.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "random()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'step' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_3 = maybe_argument_type_3.release_value();

            if (!(argument_type_3.matches_number(percentages_resolve_as) || argument_type_3.matches_dimension() || argument_type_3.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "random()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'step' type ({}) is not an accepted type.", argument_type_3.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_3;
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type_3); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "random()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'step' type ({}) is not consistent with type of previous arguments ({}).", argument_type_3.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return RandomCalculationNode::create(parameter_0.release_nonnull(), parameter_1.release_nonnull(), parameter_2.release_nonnull(), parameter_3);
    }
    if (function.name.equals_ignoring_ascii_case("rem"sv)) {

        if (arguments.size() < 2 || arguments.size() > 2) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "rem()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 2 and 2 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "rem()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "rem()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "rem()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as) || argument_type_0.matches_dimension() || argument_type_0.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "rem()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (determined_argument_type != argument_type_0) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "rem()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) doesn't match type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        RefPtr<CalculationNode const> parameter_1;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "rem()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'divisor'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_1 { arguments[argument_index] };
            auto maybe_parsed_argument_1 = parse_a_calculation(tokens_1, context);
            if (maybe_parsed_argument_1 != nullptr) {
                parameter_1 = maybe_parsed_argument_1.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "rem()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'divisor'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_1) {
            auto maybe_argument_type_1 = parameter_1->numeric_type();
            if (!maybe_argument_type_1.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "rem()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'divisor' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_1 = maybe_argument_type_1.release_value();

            if (!(argument_type_1.matches_number(percentages_resolve_as) || argument_type_1.matches_dimension() || argument_type_1.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "rem()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'divisor' type ({}) is not an accepted type.", argument_type_1.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_1;
            } else {

                if (determined_argument_type != argument_type_1) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "rem()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'divisor' type ({}) doesn't match type of previous arguments ({}).", argument_type_1.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return RemCalculationNode::create(parameter_0.release_nonnull(), parameter_1.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("round"sv)) {

        if (arguments.size() < 2 || arguments.size() > 3) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "round()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 2 and 3 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RoundingStrategy parameter_0 = RoundingStrategy::Nearest;

        if (argument_index < arguments.size()) {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_rounding_strategy(tokens_0);
            if (maybe_parsed_argument_0.has_value()) {
                parameter_0 = maybe_parsed_argument_0.release_value();
                argument_index++;

            }
        }

        RefPtr<CalculationNode const> parameter_1;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "round()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_1 { arguments[argument_index] };
            auto maybe_parsed_argument_1 = parse_a_calculation(tokens_1, context);
            if (maybe_parsed_argument_1 != nullptr) {
                parameter_1 = maybe_parsed_argument_1.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "round()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_1) {
            auto maybe_argument_type_1 = parameter_1->numeric_type();
            if (!maybe_argument_type_1.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "round()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_1 = maybe_argument_type_1.release_value();

            if (!(argument_type_1.matches_number(percentages_resolve_as) || argument_type_1.matches_dimension() || argument_type_1.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "round()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_1.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_1;
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type_1); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "round()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) is not consistent with type of previous arguments ({}).", argument_type_1.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        RefPtr<CalculationNode const> parameter_2;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "round()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'interval'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_2 { arguments[argument_index] };
            auto maybe_parsed_argument_2 = parse_a_calculation(tokens_2, context);
            if (maybe_parsed_argument_2 != nullptr) {
                parameter_2 = maybe_parsed_argument_2.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "round()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'interval'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_2) {
            auto maybe_argument_type_2 = parameter_2->numeric_type();
            if (!maybe_argument_type_2.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "round()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'interval' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_2 = maybe_argument_type_2.release_value();

            if (!(argument_type_2.matches_number(percentages_resolve_as) || argument_type_2.matches_dimension() || argument_type_2.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "round()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'interval' type ({}) is not an accepted type.", argument_type_2.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_2;
            } else {

                if (auto consistent_type = determined_argument_type->consistent_type(argument_type_2); consistent_type.has_value()) {
                    determined_argument_type = consistent_type.release_value();
                } else {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "round()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'interval' type ({}) is not consistent with type of previous arguments ({}).", argument_type_2.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return RoundCalculationNode::create(parameter_0, parameter_1.release_nonnull(), parameter_2.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("sign"sv)) {

        if (arguments.size() < 1 || arguments.size() > 1) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "sign()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 1 and 1 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "sign()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "sign()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "sign()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as) || argument_type_0.matches_dimension() || argument_type_0.matches_percentage())) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "sign()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (determined_argument_type != argument_type_0) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "sign()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) doesn't match type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return SignCalculationNode::create(parameter_0.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("sin"sv)) {

        if (arguments.size() < 1 || arguments.size() > 1) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "sin()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 1 and 1 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "sin()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "sin()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "sin()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as) || argument_type_0.matches_angle(percentages_resolve_as))) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "sin()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (determined_argument_type != argument_type_0) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "sin()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) doesn't match type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return SinCalculationNode::create(parameter_0.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("sqrt"sv)) {

        if (arguments.size() < 1 || arguments.size() > 1) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "sqrt()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 1 and 1 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "sqrt()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "sqrt()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "sqrt()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as))) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "sqrt()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (determined_argument_type != argument_type_0) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "sqrt()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) doesn't match type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return SqrtCalculationNode::create(parameter_0.release_nonnull());
    }
    if (function.name.equals_ignoring_ascii_case("tan"sv)) {

        if (arguments.size() < 1 || arguments.size() > 1) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "tan()"_fly_string,
                .value_string = stream.dump_string(),
                .description = MUST(String::formatted("Wrong number of arguments {}, expected between 1 and 1 inclusive.", arguments.size())),
            });
            return nullptr;
        }
        size_t argument_index = 0;
        Optional<NumericType> determined_argument_type;

        RefPtr<CalculationNode const> parameter_0;

        if (argument_index >= arguments.size()) {
            ErrorReporter::the().report(InvalidValueError {
                .value_type = "tan()"_fly_string,
                .value_string = stream.dump_string(),
                .description = "Missing required argument 'value'."_string,
            });
            return nullptr;
        } else {

            TokenStream tokens_0 { arguments[argument_index] };
            auto maybe_parsed_argument_0 = parse_a_calculation(tokens_0, context);
            if (maybe_parsed_argument_0 != nullptr) {
                parameter_0 = maybe_parsed_argument_0.release_nonnull();
                argument_index++;

            } else {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "tan()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Failed to parse required argument 'value'."_string,
                });
                return nullptr;

            }
        }

        if (parameter_0) {
            auto maybe_argument_type_0 = parameter_0->numeric_type();
            if (!maybe_argument_type_0.has_value()) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "tan()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = "Argument 'value' couldn't determine its type."_string,
                });
                return nullptr;
            }
            auto argument_type_0 = maybe_argument_type_0.release_value();

            if (!(argument_type_0.matches_number(percentages_resolve_as) || argument_type_0.matches_angle(percentages_resolve_as))) {
                ErrorReporter::the().report(InvalidValueError {
                    .value_type = "tan()"_fly_string,
                    .value_string = stream.dump_string(),
                    .description = MUST(String::formatted("Argument 'value' type ({}) is not an accepted type.", argument_type_0.dump())),
                });
                return nullptr;
            }

            if (!determined_argument_type.has_value()) {
                determined_argument_type = argument_type_0;
            } else {

                if (determined_argument_type != argument_type_0) {
                    ErrorReporter::the().report(InvalidValueError {
                        .value_type = "tan()"_fly_string,
                        .value_string = stream.dump_string(),
                        .description = MUST(String::formatted("Argument 'value' type ({}) doesn't match type of previous arguments ({}).", argument_type_0.dump(), determined_argument_type->dump())),
                    });
                    return nullptr;
                }

            }
        }

        if (argument_index < arguments.size())
            return nullptr;
        return TanCalculationNode::create(parameter_0.release_nonnull());
    }

    return nullptr;
}

}
