X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fbasic.cpp;h=66e6c90182cdfef57bc2ccec12ec55c3caa0b43d;hp=daac085617d01cb8d1c3d66077a3a82e4317c8e2;hb=052d42fd9eb8b7e59eff497da98e1f58cde413a4;hpb=44ec54892fdadceeb95e78e786f0411860f342ad diff --git a/ginac/basic.cpp b/ginac/basic.cpp index daac0856..66e6c901 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -36,13 +36,15 @@ #include "relational.h" #include "operators.h" #include "wildcard.h" -#include "print.h" #include "archive.h" #include "utils.h" namespace GiNaC { -GINAC_IMPLEMENT_REGISTERED_CLASS(basic, void) +GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(basic, void, + print_func(&basic::do_print). + print_func(&basic::do_print_tree). + print_func(&basic::do_print_python_repr)) ////////// // default constructor, destructor, copy constructor and assignment operator @@ -116,23 +118,74 @@ void basic::archive(archive_node &n) const // public -/** Output to stream. +/** Output to stream. This performs double dispatch on the dynamic type of + * *this and the dynamic type of the supplied print context. * @param c print context object that describes the output formatting * @param level value that is used to identify the precedence or indentation * level for placing parentheses and formatting */ void basic::print(const print_context & c, unsigned level) const { - if (is_a(c)) { + // Double dispatch on object type and print_context type + const registered_class_info * reg_info = &get_class_info(); + const print_context_class_info * pc_info = &c.get_class_info(); - c.s << std::string(level, ' ') << class_name() - << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec - << ", nops=" << nops() - << std::endl; - for (size_t i=0; i(c).delta_indent); +next_class: + const std::vector & pdt = reg_info->options.get_print_dispatch_table(); - } else - c.s << "[" << class_name() << " object]"; +next_context: + unsigned id = pc_info->options.get_id(); + if (id >= pdt.size() || !(pdt[id].is_valid())) { + + // Method not found, try parent print_context class + const print_context_class_info * parent_pc_info = pc_info->get_parent(); + if (parent_pc_info) { + pc_info = parent_pc_info; + goto next_context; + } + + // Method still not found, try parent class + const registered_class_info * parent_reg_info = reg_info->get_parent(); + if (parent_reg_info) { + reg_info = parent_reg_info; + pc_info = &c.get_class_info(); + goto next_class; + } + + // Method still not found. This shouldn't happen because basic (the + // base class of the algebraic hierarchy) registers a method for + // print_context (the base class of the print context hierarchy), + // so if we end up here, there's something wrong with the class + // registry. + throw (std::runtime_error(std::string("basic::print(): method for ") + class_name() + "/" + c.class_name() + " not found")); + + } else { + + // Call method + pdt[id](*this, c, level); + } +} + +/** Default output to stream. */ +void basic::do_print(const print_context & c, unsigned level) const +{ + c.s << "[" << class_name() << " object]"; +} + +/** Tree output to stream. */ +void basic::do_print_tree(const print_tree & c, unsigned level) const +{ + c.s << std::string(level, ' ') << class_name() + << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << ", nops=" << nops() + << std::endl; + for (size_t i=0; iprint(print_tree(std::cerr)); } -/** Return relative operator precedence (for parenthizing output). */ +/** Return relative operator precedence (for parenthezing output). */ unsigned basic::precedence() const { return 70;