def invoke_function(self, ctx, name, arguments):
        """
        Invokes the given function
        :param ctx: the evaluation context
        :param name: the function name (case insensitive)
        :param arguments: the arguments to be passed to the function
        :return: the function return value
        """
        from temba_expressions import EvaluationError, conversions

        # find function with given name
        func = self.get_function(name)
        if func is None:
            raise EvaluationError("Undefined function: %s" % name)

        args, varargs, defaults = self._get_arg_spec(func)

        call_args = []
        passed_args = list(arguments)

        for arg in args:
            if arg == 'ctx':
                call_args.append(ctx)
            elif passed_args:
                call_args.append(passed_args.pop(0))
            elif arg in defaults:
                call_args.append(defaults[arg])
            else:
                raise EvaluationError("Too few arguments provided for function %s" % name)

        if varargs is not None:
            call_args.extend(passed_args)
            passed_args = []

        # any unused arguments?
        if passed_args:
            raise EvaluationError("Too many arguments provided for function %s" % name)

        try:
            return func(*call_args)
        except Exception as e:
            pretty_args = []
            for arg in arguments:
                if isinstance(arg, str):
                    pretty = '"%s"' % arg
                else:
                    try:
                        pretty = conversions.to_string(arg, ctx)
                    except EvaluationError:
                        pretty = str(arg)
                pretty_args.append(pretty)

            raise EvaluationError("Error calling function %s with arguments %s" % (name, ', '.join(pretty_args)), e)