def print_expression(self, node: ASTExpressionNode) -> str:
     return self.__do_print(node)
     if node.get_implicit_conversion_factor() is not None:
         return str(node.get_implicit_conversion_factor()
                    ) + ' * (' + self.__do_print(node) + ')'
     else:
         return self.__do_print(node)
 def __do_print(self,
                node: ASTExpressionNode,
                prefix: str = '',
                with_origins=True) -> str:
     if isinstance(node, ASTSimpleExpression):
         if node.has_unit():
             # todo by kp: this should not be done in the typesPrinter, obsolete
             if isinstance(self.reference_converter,
                           NESTReferenceConverter):
                 # NESTReferenceConverter takes the extra with_origins parameter
                 # which is used in compartmental models
                 return self.types_printer.pretty_print(node.get_numeric_literal()) + '*' + \
                     self.reference_converter.convert_name_reference(node.get_variable(), prefix=prefix, with_origins = with_origins)
             else:
                 return self.types_printer.pretty_print(node.get_numeric_literal()) + '*' + \
                     self.reference_converter.convert_name_reference(node.get_variable(), prefix=prefix)
         elif node.is_numeric_literal():
             return str(node.get_numeric_literal())
         elif node.is_inf_literal:
             return self.reference_converter.convert_constant('inf')
         elif node.is_string():
             return self.types_printer.pretty_print(node.get_string())
         elif node.is_boolean_true:
             return self.types_printer.pretty_print(True)
         elif node.is_boolean_false:
             return self.types_printer.pretty_print(False)
         elif node.is_variable():
             # NESTReferenceConverter takes the extra with_origins parameter
             # which is used in cm models
             if isinstance(self.reference_converter,
                           NESTReferenceConverter):
                 return self.reference_converter.convert_name_reference\
                 (node.get_variable(), prefix=prefix, with_origins = with_origins)
             else:
                 return self.reference_converter.convert_name_reference(
                     node.get_variable(), prefix=prefix)
         elif node.is_function_call():
             return self.print_function_call(node.get_function_call(),
                                             prefix=prefix)
         raise Exception('Unknown node type')
     elif isinstance(node, ASTExpression):
         # a unary operator
         if node.is_unary_operator():
             op = self.reference_converter.convert_unary_op(
                 node.get_unary_operator())
             rhs = self.print_expression(node.get_expression(),
                                         prefix=prefix,
                                         with_origins=with_origins)
             return op % rhs
         # encapsulated in brackets
         elif node.is_encapsulated:
             return self.reference_converter.convert_encapsulated(
             ) % self.print_expression(node.get_expression(),
                                       prefix=prefix,
                                       with_origins=with_origins)
         # logical not
         elif node.is_logical_not:
             op = self.reference_converter.convert_logical_not()
             rhs = self.print_expression(node.get_expression(),
                                         prefix=prefix,
                                         with_origins=with_origins)
             return op % rhs
         # compound rhs with lhs + rhs
         elif node.is_compound_expression():
             lhs = self.print_expression(node.get_lhs(),
                                         prefix=prefix,
                                         with_origins=with_origins)
             op = self.reference_converter.convert_binary_op(
                 node.get_binary_operator())
             rhs = self.print_expression(node.get_rhs(),
                                         prefix=prefix,
                                         with_origins=with_origins)
             return op % (lhs, rhs)
         elif node.is_ternary_operator():
             condition = self.print_expression(node.get_condition(),
                                               prefix=prefix,
                                               with_origins=with_origins)
             if_true = self.print_expression(node.get_if_true(),
                                             prefix=prefix,
                                             with_origins=with_origins)
             if_not = self.print_expression(node.if_not,
                                            prefix=prefix,
                                            with_origins=with_origins)
             return self.reference_converter.convert_ternary_operator() % (
                 condition, if_true, if_not)
         raise Exception('Unknown node type')
     else:
         raise RuntimeError('Unsupported rhs in rhs pretty printer (%s)!' %
                            str(node))
 def __do_print(self, node: ASTExpressionNode) -> str:
     if isinstance(node, ASTVariable):
         return self.reference_converter.convert_name_reference(node)
     elif isinstance(node, ASTSimpleExpression):
         if node.has_unit():
             # todo by kp: this should not be done in the typesPrinter, obsolete
             s = ""
             if node.get_numeric_literal() != 1:
                 s += "{0:E}".format(node.get_numeric_literal())
                 s += r"\cdot"
             s += self.reference_converter.convert_name_reference(
                 node.get_variable())
             return s
         elif node.is_numeric_literal():
             return str(node.get_numeric_literal())
         elif node.is_inf_literal:
             return r"\infty"
         elif node.is_string():
             return self.types_printer.pretty_print(node.get_string())
         elif node.is_boolean_true:
             return self.types_printer.pretty_print(True)
         elif node.is_boolean_false:
             return self.types_printer.pretty_print(False)
         elif node.is_variable():
             return self.reference_converter.convert_name_reference(
                 node.get_variable())
         elif node.is_function_call():
             return self.print_function_call(node.get_function_call())
         raise Exception('Unknown node type')
     elif isinstance(node, ASTExpression):
         # a unary operator
         if node.is_unary_operator():
             op = self.reference_converter.convert_unary_op(
                 node.get_unary_operator())
             rhs = self.print_expression(node.get_expression())
             return op % rhs
         # encapsulated in brackets
         elif node.is_encapsulated:
             return self.reference_converter.convert_encapsulated(
             ) % self.print_expression(node.get_expression())
         # logical not
         elif node.is_logical_not:
             op = self.reference_converter.convert_logical_not()
             rhs = self.print_expression(node.get_expression())
             return op % rhs
         # compound rhs with lhs + rhs
         elif node.is_compound_expression():
             lhs = self.print_expression(node.get_lhs())
             rhs = self.print_expression(node.get_rhs())
             wide = False
             if node.get_binary_operator().is_div_op \
                     and len(lhs) > 3 * len(rhs):
                 # if lhs (numerator) is much wider than rhs (denominator), rewrite as a factor
                 wide = True
             op = self.reference_converter.convert_binary_op(
                 node.get_binary_operator(), wide=wide)
             return op % ({"lhs": lhs, "rhs": rhs})
         elif node.is_ternary_operator():
             condition = self.print_expression(node.get_condition())
             if_true = self.print_expression(node.get_if_true())
             if_not = self.print_expression(node.if_not)
             return self.reference_converter.convert_ternary_operator() % (
                 condition, if_true, if_not)
         raise Exception('Unknown node type')
     else:
         raise RuntimeError('Unsupported rhs in rhs pretty printer!')