from __future__ import print_function, division

from sympy.core import Add, Mul, Pow, S, sympify
from sympy.core.basic import Basic
from sympy.core.containers import Tuple
from sympy.core.compatibility import default_sort_key, string_types
from sympy.core.function import Lambda
from sympy.core.mul import _keep_coeff
from sympy.core.symbol import Symbol
from sympy.printing.str import StrPrinter
from sympy.printing.precedence import precedence

# Backwards compatibility
from sympy.codegen.ast import Assignment


class AssignmentError(Exception):
    """
    Raised if an assignment variable for a loop is missing.
    """
    pass

class CodePrinter(StrPrinter):
    """
    The base class for code-printing subclasses.
    """

    _operators = {
        'and': '&&',
        'or': '||',
        'not': '!',
    }

    _default_settings = {'order': None,
                         'full_prec': 'auto',
                         'error_on_reserved': False,
                         'reserved_word_suffix': '_'}

    def __init__(self, settings=None):

        super(CodePrinter, self).__init__(settings=settings)

        self.reserved_words = set()

    def doprint(self, expr, assign_to=None):
        """
        Print the expression as code.

        Parameters
        ----------
        expr : Expression
            The expression to be printed.

        assign_to : Symbol, MatrixSymbol, or string (optional)
            If provided, the printed code will set the expression to a
            variable with name ``assign_to``.