def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the exponentiation of all the arguments:
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute pow " + safe_str_convert(self.arg))
            return reduce(
                lambda x, y: pow(x, y),
                vba_conversion.coerce_args(evaluated_args,
                                           preferred_type="int"))
        except (TypeError, ValueError):
            # Try converting strings to ints.
            # TODO: Need to handle floats in strings.
            try:
                return reduce(lambda x, y: pow(int(x), int(y)), evaluated_args)
            except Exception as e:
                log.error(
                    'Impossible to do exponentiation with arguments of different types. '
                    + safe_str_convert(e))
                return 0
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the floor division of all the arguments:
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute floor div " + safe_str_convert(self.arg))
            return reduce(
                lambda x, y: x // y,
                vba_conversion.coerce_args(evaluated_args,
                                           preferred_type="int"))
        except (TypeError, ValueError):
            # Try converting strings to ints.
            # TODO: Need to handle floats in strings.
            try:
                return reduce(lambda x, y: int(x) // int(y), evaluated_args)
            except Exception as e:
                if (safe_str_convert(e).strip() != "division by zero"):
                    log.error(
                        'Impossible to divide arguments of different types. ' +
                        safe_str_convert(e))
                # TODO
                return 0
        except ZeroDivisionError as e:
            context.set_error(safe_str_convert(e))
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the xor of all the arguments:
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute xor " + safe_str_convert(self.arg))
            return reduce(
                lambda x, y: x ^ y,
                vba_conversion.coerce_args(evaluated_args,
                                           preferred_type="int"))
        except (TypeError, ValueError):
            # Try converting strings to ints.
            # TODO: Need to handle floats in strings.
            try:
                return reduce(lambda x, y: int(x) ^ int(y), evaluated_args)
            except Exception as e:
                log.error(
                    'Impossible to xor arguments of different types. Arg list = '
                    + safe_str_convert(self.arg) + ". " + safe_str_convert(e))
                return 0
        except RuntimeError as e:
            log.error("overflow trying eval xor: %r" % self.arg)
            raise e
    def eval(self, context, params=None):

        # We are emulating some string or numeric
        # expression. Therefore any boolean operators we find in the
        # expression are actually bitwise operators.
        # Track that in the context.
        set_flag = False
        if (not context.in_bitwise_expression):
            context.in_bitwise_expression = True
            set_flag = True

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            if set_flag:
                context.in_bitwise_expression = False
            return "**MATCH ANY**"

        try:
            args = vba_conversion.coerce_args(evaluated_args)
            ret = args[0]
            for op, arg in zip(self.operators, args[1:]):
                try:
                    ret = self.operator_map[op](ret, arg)
                except OverflowError:
                    log.error("overflow trying eval: %r" %
                              safe_str_convert(self))
            if set_flag:
                context.in_bitwise_expression = False
            return ret
        except (TypeError, ValueError):
            # Try converting strings to numbers.
            # TODO: Need to handle floats in strings.
            try:
                args = map(vba_conversion.coerce_to_num, evaluated_args)
                ret = args[0]
                for op, arg in zip(self.operators, args[1:]):
                    ret = self.operator_map[op](ret, arg)
                if set_flag:
                    context.in_bitwise_expression = False
                return ret
            except ZeroDivisionError:
                context.set_error("Division by 0 error. Returning 'NULL'.")
                if set_flag:
                    context.in_bitwise_expression = False
                return 'NULL'
            except Exception as e:
                log.error(
                    'Impossible to operate on arguments of different types. ' +
                    safe_str_convert(e))
                if set_flag:
                    context.in_bitwise_expression = False
                return 0
        except ZeroDivisionError:
            context.set_error("Division by 0 error. Returning 'NULL'.")
            if set_flag:
                context.in_bitwise_expression = False
            return 'NULL'
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the subtraction of all the arguments:
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute subract " + safe_str_convert(self.arg))
            return reduce(
                lambda x, y: x - y,
                vba_conversion.coerce_args(evaluated_args,
                                           preferred_type="int"))
        except (TypeError, ValueError):
            # Try converting strings to ints.
            # TODO: Need to handle floats in strings.
            try:
                return reduce(
                    lambda x, y: vba_conversion.coerce_to_int(x) -
                    vba_conversion.coerce_to_int(y), evaluated_args)
            except Exception as e:

                # Are we doing math on character ordinals?
                l1 = []
                orig = evaluated_args
                for v in orig:
                    if (isinstance(v, int)):
                        l1.append(v)
                        continue
                    if (isinstance(v, str) and (len(v) == 1)):
                        l1.append(ord(v))
                        continue

                # Do we have something that we can do math on?
                if (len(orig) != len(l1)):
                    log.error(
                        'Impossible to subtract arguments of different types. '
                        + safe_str_convert(e))
                    return 0

                # Try subtracting based on character ordinals.
                return reduce(lambda x, y: int(x) - int(y), l1)
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the and of all the arguments:
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute not " + safe_str_convert(self.arg))
            val = self.arg
            if (isinstance(val, VBA_Object)):
                val = val.eval(context)
            return (~int(val))
        except Exception as e:
            log.error("Cannot compute Not " + safe_str_convert(self.arg) +
                      ". " + safe_str_convert(e))
            return "NULL"
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the sum of all the arguments:
        # (Note: sum() is not applicable here, because it does not work for strings)
        # see https://docs.python.org/2/library/functions.html#reduce
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute sum (1) " + safe_str_convert(self.arg))
            r = reduce(
                lambda x, y: x + y,
                vba_conversion.coerce_args(evaluated_args,
                                           preferred_type="int"))
            return r
        except (TypeError, ValueError):
            # NOTE: In VB you are not supposed to be able to add integers and strings.
            # However, there are maldocs that do this. If the strings are integer strings,
            # integer addition is performed.
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug(
                    'Impossible to sum arguments of different types. Try converting strings to common type.'
                )
            try:
                r = reduce(lambda x, y: int(x) + int(y), evaluated_args)
                return r
            except (TypeError, ValueError):
                # Punt and sum all arguments as strings.
                if (log.getEffectiveLevel() == logging.DEBUG):
                    log.debug("Compute sum (2) " + safe_str_convert(self.arg))
                r = reduce(
                    lambda x, y: safe_str_convert(x) + safe_str_convert(y),
                    vba_conversion.coerce_args_to_str(evaluated_args))
                return r
        except RuntimeError as e:
            log.error("overflow trying eval sum: %r" % self.arg)
            raise e
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the eqv of all the arguments:
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute eqv " + safe_str_convert(self.arg))
            return reduce(
                lambda a, b: (a & b) | ~(a | b),
                vba_conversion.coerce_args(evaluated_args,
                                           preferred_type="int"))
        except (TypeError, ValueError):
            log.error('Impossible to Eqv arguments of different types.')
            return 0
        except RuntimeError as e:
            log.error("overflow trying eval Eqv: %r" % self.arg)
            raise e
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the concatenation of all the arguments:
        # TODO: handle non-string args
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug('Concatenation before eval: %r' % params)
        try:
            eval_params = evaluated_args
            eval_params = vba_conversion.coerce_args_to_str(eval_params)
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('Concatenation after eval: %r' % eval_params)
            return ''.join(eval_params)
        except (TypeError, ValueError) as e:
            log.exception('Impossible to concatenate non-string arguments. ' +
                          safe_str_convert(e))
            # TODO
            return ''
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the sum of all the arguments:
        # see https://docs.python.org/2/library/functions.html#reduce
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute mod " + safe_str_convert(self.arg))
            return reduce(
                lambda x, y: int(x) % int(y),
                vba_conversion.coerce_args(evaluated_args,
                                           preferred_type="int"))
        except (TypeError, ValueError) as e:
            log.error('Impossible to mod arguments of different types. ' +
                      safe_str_convert(e))
            return ''
        except ZeroDivisionError:
            log.error('Mod division by zero error.')
            return ''