+next_class:
+ const std::vector<print_functor> & pdt = reg_info->options.get_print_dispatch_table();
+
+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() << " @" << this
+ << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec;
+ if (nops())
+ c.s << ", nops=" << nops();
+ c.s << std::endl;
+ for (size_t i=0; i<nops(); ++i)
+ op(i).print(c, level + c.delta_indent);
+}
+
+/** Python parsable output to stream. */
+void basic::do_print_python_repr(const print_python_repr & c, unsigned level) const
+{
+ c.s << class_name() << "()";