Register an expression resolver.

    Can be used such as a decorator.

    For example all remainding expressions are the same.

    .. code-block:: python

        @register('myresolver')
        def myresolver(**kwargs): pass

    .. code-block:: python

        def myresolver(**kwargs): pass

        register('myresolver', myresolver)

    .. code-block:: python

        @register('myresolver')
        class MyResolver():
            def __call__(**kwargs): pass

    .. code-block:: python

        class MyResolver():
            def __call__(**kwargs): pass

        register('myresolver', MyResolver)

    .. code-block:: python

        class MyResolver():
            def __call__(**kwargs): pass

        register('myresolver', MyResolver())


    :param str name: register name to use. Default is the function/class
        name.
    :param exprresolver: function able to resolve an expression.
    :param dict kwargs: parameters of resolver instanciation if exprresolver
        is a class and this function is used such as a decorator.
    :param ResolverRegistry reg: registry to use. Default is the global registry
    .

def register(name=None, exprresolver=None, params=None, reg=None):
    """Register an expression resolver.

    Can be used such as a decorator.

    For example all remainding expressions are the same.

    .. code-block:: python

        @register('myresolver')
        def myresolver(**kwargs): pass

    .. code-block:: python

        def myresolver(**kwargs): pass

        register('myresolver', myresolver)

    .. code-block:: python

        @register('myresolver')
        class MyResolver():
            def __call__(**kwargs): pass

    .. code-block:: python

        class MyResolver():
            def __call__(**kwargs): pass

        register('myresolver', MyResolver)

    .. code-block:: python

        class MyResolver():
            def __call__(**kwargs): pass

        register('myresolver', MyResolver())


    :param str name: register name to use. Default is the function/class
        name.
    :param exprresolver: function able to resolve an expression.
    :param dict kwargs: parameters of resolver instanciation if exprresolver
        is a class and this function is used such as a decorator.
    :param ResolverRegistry reg: registry to use. Default is the global registry
    .
    """

    def _register(exprresolver, _name=name, _params=params):
        """Local registration for better use in a decoration context.

        :param exprresolver: function/class able to resolve an expression.
        :param str _name: private parameter used to set the name.
        :param dict _params: private parameter used to set resolver class
            constructor parameters."""

        _exprresolver = exprresolver

        if isclass(exprresolver):  # try to instanciate exprresolver
            if _params is None:
                _params = {}

            _exprresolver = _exprresolver(**_params)

        if _name is None:
            _name = getname(exprresolver)

        reg[_name] = _exprresolver

        if reg.default is None:
            reg.default = _name

        return exprresolver

    if name is None:
        name = getname(exprresolver)

    if reg is None:
        reg = _RESOLVER_REGISTRY

    if exprresolver is None:
        result = _register

    else:
        result = name
        _register(exprresolver)

    return result