/* Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Gabriel Ebner */ #include #include "kernel/kernel_exception.h" #include "library/message_builder.h" #include "library/type_context.h" #include "library/error_msgs.h" namespace lean { message_builder::message_builder(std::shared_ptr const & tc, environment const & env, io_state const & ios, std::string const & file_name, const pos_info & pos, message_severity severity) : m_tc(tc), m_file_name(file_name), m_pos(pos), m_severity(severity), m_caption(), m_text(std::make_shared()), m_text_stream(env, ios.get_formatter_factory()(env, ios.get_options(), *tc), m_text) {} message_builder::message_builder(environment const & env, io_state const & ios, std::string const & file_name, pos_info const & pos, message_severity severity) : message_builder(std::make_shared(env, ios.get_options()), env, ios, file_name, pos, severity) {} message message_builder::build() { auto text = m_text->str(); if (!text.empty() && *text.rbegin() == '\n') text = text.substr(0, text.size() - 1); return message(m_file_name, m_pos, m_end_pos, m_severity, m_caption, text); } message_builder & message_builder::set_exception(std::exception const & ex, bool use_pos) { if (auto pos_ex = dynamic_cast(&ex)) { if (use_pos && pos_ex->get_pos()) { m_pos = *pos_ex->get_pos(); } } if (auto f_ex = dynamic_cast(&ex)) { *this << f_ex->pp(); } else if (auto nex = dynamic_cast(&ex)) { // reimplement nested_exception::pp to handle nested kernel_exceptions *this << nex->generic_exception::pp(get_formatter()) << "\nnested exception message:\n"; try { std::rethrow_exception(nex->get_exception()); } catch (std::exception & ex) { set_exception(ex, false); } catch (...) { } } else if (auto ext_ex = dynamic_cast(&ex)) { *this << *ext_ex; } else if (auto kex = dynamic_cast(&ex)) { *this << "unknown declaration '" << kex->get_name() << "'"; } else if (auto kex = dynamic_cast(&ex)) { *this << "invalid declaration, a declaration named '" << kex->get_name() << "' has already been declared"; } else if (auto kex = dynamic_cast(&ex)) { type_context_old ctx(kex->get_environment()); auto fmt = get_global_ios().get_formatter_factory()(kex->get_environment(), get_global_ios().get_options(), ctx); if (kex->get_declaration().is_definition()) { auto def = kex->get_declaration().to_definition_val(); *this << pp_def_type_mismatch(fmt, def.get_name(), kex->get_given_type(), def.get_type()); } else if (kex->get_declaration().is_theorem()) { auto def = kex->get_declaration().to_theorem_val(); *this << pp_def_type_mismatch(fmt, def.get_name(), kex->get_given_type(), def.get_type()); } else { lean_unreachable(); } } else if (auto kex = dynamic_cast(&ex)) { type_context_old ctx(kex->get_environment(), get_global_ios().get_options()); auto fmt = get_global_ios().get_formatter_factory()(kex->get_environment(), get_global_ios().get_options(), ctx); *this << pp_decl_has_metavars(fmt, kex->get_decl_name(), kex->get_expr(), /* is_type */ false); } else if (dynamic_cast(&ex)) { *this << "invalid declaration, it contains free variables"; } else if (auto kex = dynamic_cast(&ex)) { // TODO(Leo) FIX #if 0 type_context_old ctx(kex->get_environment(), get_global_ios().get_options(), metavar_context(), local_context(kex->get_local_ctx())); auto fmt = get_global_ios().get_formatter_factory()(kex->get_environment(), get_global_ios().get_options(), ctx); if (auto kex = dynamic_cast(&ex)) { *this << pp_function_expected(fmt, kex->get_fn()); } else if (auto kex = dynamic_cast(&ex)) { *this << pp_type_expected(fmt, kex->get_type()); } else if (auto kex = dynamic_cast(&ex)) { *this << pp_def_type_mismatch(fmt, kex->get_name(), kex->get_given_type(), kex->get_expected_type()); } else if (auto kex = dynamic_cast(&ex)) { *this << pp_type_mismatch(fmt, kex->get_given_type(), kex->get_expected_type()); } else if (auto kex = dynamic_cast(&ex)) { *this << pp_type_mismatch(fmt, kex->get_expr(), kex->get_expected_type()); } else if (auto kex = dynamic_cast(&ex)) { *this << pp_app_type_mismatch(fmt, kex->get_app(), kex->get_function_type(), app_arg(kex->get_app()), kex->get_arg_type()); } else if (auto kex = dynamic_cast(&ex)) { *this << "invalid projection " << pp_indent_expr(fmt, kex->get_proj()); } else { lean_unreachable(); } #endif } else { *this << ex.what(); } return *this; } void message_builder::report() { report_message(build()); } }