refactor(*): error messages
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
55aa4cbfa3
commit
ccb9faf065
39 changed files with 572 additions and 274 deletions
|
@ -304,7 +304,7 @@ print(o2)
|
||||||
-- An error is raised if the option is not known.
|
-- An error is raised if the option is not known.
|
||||||
local ok, ex = pcall(function() options({"pp", "foo"}, true) end)
|
local ok, ex = pcall(function() options({"pp", "foo"}, true) end)
|
||||||
assert(not ok)
|
assert(not ok)
|
||||||
assert(ex:what() == "unknown option 'pp::foo'")
|
assert(ex:what():find("unknown option 'pp::foo'"))
|
||||||
```
|
```
|
||||||
|
|
||||||
Options objects are non-mutable values. The method `update` returns a new
|
Options objects are non-mutable values. The method `update` returns a new
|
||||||
|
|
|
@ -223,6 +223,8 @@ add_subdirectory(library/elaborator)
|
||||||
set(LEAN_LIBS ${LEAN_LIBS} elaborator)
|
set(LEAN_LIBS ${LEAN_LIBS} elaborator)
|
||||||
add_subdirectory(library/tactic)
|
add_subdirectory(library/tactic)
|
||||||
set(LEAN_LIBS ${LEAN_LIBS} tactic)
|
set(LEAN_LIBS ${LEAN_LIBS} tactic)
|
||||||
|
add_subdirectory(library/error_handling)
|
||||||
|
set(LEAN_LIBS ${LEAN_LIBS} error_handling)
|
||||||
add_subdirectory(frontends/lean)
|
add_subdirectory(frontends/lean)
|
||||||
set(LEAN_LIBS ${LEAN_LIBS} lean_frontend)
|
set(LEAN_LIBS ${LEAN_LIBS} lean_frontend)
|
||||||
add_subdirectory(frontends/lua)
|
add_subdirectory(frontends/lua)
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace lean {
|
||||||
parser::parser(environment const & env, io_state const & ios, std::istream & in, char const * strm_name, script_state * S, bool use_exceptions, bool interactive) {
|
parser::parser(environment const & env, io_state const & ios, std::istream & in, char const * strm_name, script_state * S, bool use_exceptions, bool interactive) {
|
||||||
parser_imp::show_prompt(interactive, ios);
|
parser_imp::show_prompt(interactive, ios);
|
||||||
m_ptr.reset(new parser_imp(env, ios, in, strm_name, S, use_exceptions, interactive));
|
m_ptr.reset(new parser_imp(env, ios, in, strm_name, S, use_exceptions, interactive));
|
||||||
|
m_ptr->m_this = m_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser::~parser() {
|
parser::~parser() {
|
||||||
|
|
|
@ -16,7 +16,7 @@ class parser_imp;
|
||||||
/** \brief Functional object for parsing commands and expressions */
|
/** \brief Functional object for parsing commands and expressions */
|
||||||
class parser {
|
class parser {
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<parser_imp> m_ptr;
|
std::shared_ptr<parser_imp> m_ptr;
|
||||||
public:
|
public:
|
||||||
parser(environment const & env, io_state const & st, std::istream & in, char const * strm_name, script_state * S, bool use_exceptions = true, bool interactive = false);
|
parser(environment const & env, io_state const & st, std::istream & in, char const * strm_name, script_state * S, bool use_exceptions = true, bool interactive = false);
|
||||||
~parser();
|
~parser();
|
||||||
|
|
|
@ -83,7 +83,7 @@ void parser_imp::register_implicit_arguments(name const & n, parameter_buffer &
|
||||||
|
|
||||||
|
|
||||||
/** \brief Throw an exception if \c e contains a metavariable */
|
/** \brief Throw an exception if \c e contains a metavariable */
|
||||||
void parser_imp::check_no_metavar(expr const & e, metavar_env const & menv, char const * msg) {
|
void parser_imp::check_no_metavar(expr const & e, metavar_env const &, char const * msg) {
|
||||||
if (has_metavar(e))
|
if (has_metavar(e))
|
||||||
throw unsolved_metavar_exception(msg, e);
|
throw unsolved_metavar_exception(msg, e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
||||||
Author: Leonardo de Moura
|
Author: Leonardo de Moura
|
||||||
*/
|
*/
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "kernel/kernel_exception.h"
|
|
||||||
#include "kernel/for_each_fn.h"
|
#include "kernel/for_each_fn.h"
|
||||||
#include "library/io_state_stream.h"
|
#include "library/io_state_stream.h"
|
||||||
#include "library/elaborator/elaborator_justification.h"
|
#include "library/parser_nested_exception.h"
|
||||||
|
#include "library/error_handling/error_handling.h"
|
||||||
#include "frontends/lean/parser_imp.h"
|
#include "frontends/lean/parser_imp.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
|
@ -21,94 +21,21 @@ void parser_imp::display_error_pos(unsigned line, unsigned pos) {
|
||||||
|
|
||||||
void parser_imp::display_error_pos(pos_info const & p) { display_error_pos(p.first, p.second); }
|
void parser_imp::display_error_pos(pos_info const & p) { display_error_pos(p.first, p.second); }
|
||||||
|
|
||||||
void parser_imp::display_error_pos(optional<expr> const & e) {
|
|
||||||
if (e) {
|
|
||||||
auto it = m_expr_pos_info.find(*e);
|
|
||||||
if (it == m_expr_pos_info.end())
|
|
||||||
return display_error_pos(m_last_cmd_pos);
|
|
||||||
else
|
|
||||||
return display_error_pos(it->second);
|
|
||||||
} else {
|
|
||||||
return display_error_pos(m_last_cmd_pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void parser_imp::display_error(char const * msg, unsigned line, unsigned pos) {
|
void parser_imp::display_error(char const * msg, unsigned line, unsigned pos) {
|
||||||
display_error_pos(line, pos);
|
display_error_pos(line, pos);
|
||||||
regular(m_io_state) << " " << msg << endl;
|
regular(m_io_state) << " " << msg << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parser_imp::display_error(char const * msg) {
|
|
||||||
display_error(msg, m_scanner.get_line(), m_scanner.get_pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
void parser_imp::display_error(kernel_exception const & ex) {
|
|
||||||
optional<expr> main_expr = ex.get_main_expr();
|
|
||||||
if (main_expr)
|
|
||||||
display_error_pos(some_expr(m_elaborator.get_original(*main_expr)));
|
|
||||||
else
|
|
||||||
display_error_pos(main_expr);
|
|
||||||
regular(m_io_state) << " " << ex << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void parser_imp::display_error(unsolved_metavar_exception const & ex) {
|
|
||||||
display_error_pos(some_expr(m_elaborator.get_original(ex.get_expr())));
|
|
||||||
formatter fmt = m_io_state.get_formatter();
|
|
||||||
options opts = m_io_state.get_options();
|
|
||||||
unsigned indent = get_pp_indent(opts);
|
|
||||||
format r = nest(indent, compose(line(), fmt(ex.get_expr(), opts)));
|
|
||||||
regular(m_io_state) << " " << ex.what() << mk_pair(r, opts) << endl;
|
|
||||||
name_set already_displayed;
|
|
||||||
for_each(ex.get_expr(), [&](expr const & e, unsigned) -> bool {
|
|
||||||
if (is_metavar(e)) {
|
|
||||||
name const & m = metavar_name(e);
|
|
||||||
if (already_displayed.find(m) == already_displayed.end()) {
|
|
||||||
already_displayed.insert(m);
|
|
||||||
for (unsigned i = 0; i < indent; i++) regular(m_io_state) << " ";
|
|
||||||
display_error_pos(some_expr(m_elaborator.get_original(e)));
|
|
||||||
regular(m_io_state) << " unsolved metavar " << m << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<unsigned, unsigned> parser_imp::lean_pos_info_provider::get_pos_info(expr const & e) const {
|
std::pair<unsigned, unsigned> parser_imp::lean_pos_info_provider::get_pos_info(expr const & e) const {
|
||||||
expr const & o = m_ref.m_elaborator.get_original(e);
|
expr const & o = m_parser->m_elaborator.get_original(e);
|
||||||
auto it = m_ref.m_expr_pos_info.find(o);
|
auto it = m_parser->m_expr_pos_info.find(o);
|
||||||
if (it == m_ref.m_expr_pos_info.end())
|
if (it == m_parser->m_expr_pos_info.end())
|
||||||
throw exception("position is not available"); // information is not available
|
return m_pos;
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const * parser_imp::lean_pos_info_provider::get_file_name(expr const & ) const {
|
char const * parser_imp::lean_pos_info_provider::get_file_name() const {
|
||||||
return m_ref.m_strm_name.c_str();
|
return m_parser->m_strm_name.c_str();
|
||||||
}
|
|
||||||
|
|
||||||
void parser_imp::display_error(elaborator_exception const & ex) {
|
|
||||||
formatter fmt = m_io_state.get_formatter();
|
|
||||||
options opts = m_io_state.get_options();
|
|
||||||
lean_pos_info_provider pos_provider(*this);
|
|
||||||
auto j = ex.get_justification();
|
|
||||||
j = remove_detail(j);
|
|
||||||
regular(m_io_state) << mk_pair(j.pp(fmt, opts, &pos_provider, true), opts) << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void parser_imp::display_error(script_exception const & ex) {
|
|
||||||
switch (ex.get_source()) {
|
|
||||||
case script_exception::source::String:
|
|
||||||
display_error_pos(ex.get_line() + m_last_script_pos.first - 1, static_cast<unsigned>(-1));
|
|
||||||
regular(m_io_state) << " executing script," << ex.get_msg() << endl;
|
|
||||||
break;
|
|
||||||
case script_exception::source::File:
|
|
||||||
display_error_pos(m_last_script_pos);
|
|
||||||
regular(m_io_state) << " executing external script (" << ex.get_filename() << ":" << ex.get_line() << ")," << ex.get_msg() << endl;
|
|
||||||
break;
|
|
||||||
case script_exception::source::Unknown:
|
|
||||||
display_error_pos(m_last_script_pos);
|
|
||||||
regular(m_io_state) << " executing script, exact error position is not available, " << ex.what() << endl;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void parser_imp::display_error(tactic_cmd_error const & ex) {
|
void parser_imp::display_error(tactic_cmd_error const & ex) {
|
||||||
|
@ -116,13 +43,21 @@ void parser_imp::display_error(tactic_cmd_error const & ex) {
|
||||||
display_proof_state(ex.m_state);
|
display_proof_state(ex.m_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CATCH_CORE(ShowError, ThrowError) \
|
void parser_imp::display_error(exception const & ex) {
|
||||||
m_found_errors = true; \
|
lean_pos_info_provider pos_provider(m_this.lock(), m_last_cmd_pos);
|
||||||
if (m_show_errors) { ShowError ; } \
|
::lean::display_error(m_io_state, &pos_provider, ex);
|
||||||
sync(); \
|
}
|
||||||
if (m_use_exceptions) { ThrowError ; }
|
|
||||||
|
|
||||||
#define CATCH(ShowError) CATCH_CORE(ShowError, throw;)
|
void parser_imp::display_error(script_exception const & ex) {
|
||||||
|
lean_pos_info_provider pos_provider(m_this.lock(), m_last_script_pos);
|
||||||
|
::lean::display_error(m_io_state, &pos_provider, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CATCH(ShowError, ThrowError) \
|
||||||
|
m_found_errors = true; \
|
||||||
|
if (!m_use_exceptions && m_show_errors) { ShowError ; } \
|
||||||
|
sync(); \
|
||||||
|
if (m_use_exceptions) { ThrowError ; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Execute the given function \c f, and handle exceptions occurring
|
\brief Execute the given function \c f, and handle exceptions occurring
|
||||||
|
@ -133,21 +68,14 @@ void parser_imp::protected_call(std::function<void()> && f, std::function<void()
|
||||||
try {
|
try {
|
||||||
f();
|
f();
|
||||||
} catch (tactic_cmd_error & ex) {
|
} catch (tactic_cmd_error & ex) {
|
||||||
CATCH(display_error(ex));
|
CATCH(display_error(ex),
|
||||||
|
throw parser_exception(ex.what(), m_strm_name.c_str(), ex.m_pos.first, ex.m_pos.second));
|
||||||
} catch (parser_exception & ex) {
|
} catch (parser_exception & ex) {
|
||||||
CATCH(regular(m_io_state) << ex.what() << endl;);
|
CATCH(regular(m_io_state) << ex.what() << endl,
|
||||||
|
throw);
|
||||||
} catch (parser_error & ex) {
|
} catch (parser_error & ex) {
|
||||||
CATCH_CORE(display_error(ex.what(), ex.m_pos.first, ex.m_pos.second),
|
CATCH(display_error(ex.what(), ex.m_pos.first, ex.m_pos.second),
|
||||||
throw parser_exception(ex.what(), m_strm_name.c_str(), ex.m_pos.first, ex.m_pos.second));
|
throw parser_exception(ex.what(), m_strm_name.c_str(), ex.m_pos.first, ex.m_pos.second));
|
||||||
} catch (kernel_exception & ex) {
|
|
||||||
CATCH(display_error(ex));
|
|
||||||
} catch (elaborator_exception & ex) {
|
|
||||||
CATCH(display_error(ex));
|
|
||||||
} catch (unsolved_metavar_exception & ex) {
|
|
||||||
CATCH(display_error(ex));
|
|
||||||
} catch (script_exception & ex) {
|
|
||||||
reset_interrupt();
|
|
||||||
CATCH(display_error(ex));
|
|
||||||
} catch (interrupted & ex) {
|
} catch (interrupted & ex) {
|
||||||
reset_interrupt();
|
reset_interrupt();
|
||||||
if (m_verbose)
|
if (m_verbose)
|
||||||
|
@ -155,8 +83,16 @@ void parser_imp::protected_call(std::function<void()> && f, std::function<void()
|
||||||
sync();
|
sync();
|
||||||
if (m_use_exceptions)
|
if (m_use_exceptions)
|
||||||
throw;
|
throw;
|
||||||
|
} catch (script_exception & ex) {
|
||||||
|
reset_interrupt();
|
||||||
|
CATCH(display_error(ex),
|
||||||
|
throw parser_nested_exception(std::shared_ptr<exception>(ex.clone()),
|
||||||
|
std::shared_ptr<pos_info_provider>(new lean_pos_info_provider(m_this.lock(), m_last_script_pos))));
|
||||||
} catch (exception & ex) {
|
} catch (exception & ex) {
|
||||||
CATCH(display_error(ex.what()););
|
reset_interrupt();
|
||||||
|
CATCH(display_error(ex),
|
||||||
|
throw parser_nested_exception(std::shared_ptr<exception>(ex.clone()),
|
||||||
|
std::shared_ptr<pos_info_provider>(new lean_pos_info_provider(m_this.lock(), m_last_cmd_pos))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ Author: Leonardo de Moura
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "library/io_state_stream.h"
|
#include "library/io_state_stream.h"
|
||||||
|
#include "library/parser_nested_exception.h"
|
||||||
#include "frontends/lean/parser_imp.h"
|
#include "frontends/lean/parser_imp.h"
|
||||||
#include "frontends/lean/parser_macros.h"
|
#include "frontends/lean/parser_macros.h"
|
||||||
#include "frontends/lean/parser_calc.h"
|
#include "frontends/lean/parser_calc.h"
|
||||||
|
@ -217,6 +218,9 @@ expr parser_imp::parse_expr_main() {
|
||||||
return p.first;
|
return p.first;
|
||||||
} catch (parser_error & ex) {
|
} catch (parser_error & ex) {
|
||||||
throw parser_exception(ex.what(), m_strm_name.c_str(), ex.m_pos.first, ex.m_pos.second);
|
throw parser_exception(ex.what(), m_strm_name.c_str(), ex.m_pos.first, ex.m_pos.second);
|
||||||
|
} catch (exception & ex) {
|
||||||
|
throw parser_nested_exception(std::shared_ptr<exception>(ex.clone()),
|
||||||
|
std::shared_ptr<pos_info_provider>(new lean_pos_info_provider(m_this.lock(), m_last_cmd_pos)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,7 +34,7 @@ bool get_parser_show_errors(options const & opts);
|
||||||
|
|
||||||
/** \brief Auxiliary object that stores a reference to the parser object inside the Lua State */
|
/** \brief Auxiliary object that stores a reference to the parser object inside the Lua State */
|
||||||
struct set_parser {
|
struct set_parser {
|
||||||
script_state * m_state;
|
script_state::weak_ref m_state;
|
||||||
parser_imp * m_prev;
|
parser_imp * m_prev;
|
||||||
set_parser(script_state * S, parser_imp * ptr);
|
set_parser(script_state * S, parser_imp * ptr);
|
||||||
~set_parser();
|
~set_parser();
|
||||||
|
@ -57,29 +57,30 @@ class parser_imp {
|
||||||
typedef expr_map<pos_info> expr_pos_info;
|
typedef expr_map<pos_info> expr_pos_info;
|
||||||
typedef expr_map<tactic> tactic_hints; // a mapping from placeholder to tactic
|
typedef expr_map<tactic> tactic_hints; // a mapping from placeholder to tactic
|
||||||
typedef scoped_map<name, expr, name_hash, name_eq> using_decls;
|
typedef scoped_map<name, expr, name_hash, name_eq> using_decls;
|
||||||
environment m_env;
|
|
||||||
io_state m_io_state;
|
|
||||||
scanner m_scanner;
|
|
||||||
std::string m_strm_name; // input stream name
|
|
||||||
frontend_elaborator m_elaborator;
|
|
||||||
macros const * m_expr_macros;
|
|
||||||
macros const * m_cmd_macros;
|
|
||||||
macros const * m_tactic_macros;
|
|
||||||
scanner::token m_curr;
|
|
||||||
bool m_use_exceptions;
|
|
||||||
bool m_interactive;
|
|
||||||
bool m_found_errors;
|
|
||||||
local_decls m_local_decls;
|
|
||||||
unsigned m_num_local_decls;
|
|
||||||
expr_pos_info m_expr_pos_info;
|
|
||||||
pos_info m_last_cmd_pos;
|
|
||||||
pos_info m_last_script_pos;
|
|
||||||
tactic_hints m_tactic_hints;
|
|
||||||
using_decls m_using_decls;
|
|
||||||
std::vector<name> m_namespace_prefixes;
|
|
||||||
enum class scope_kind { Scope, Namespace };
|
enum class scope_kind { Scope, Namespace };
|
||||||
std::vector<scope_kind> m_scope_kinds;
|
|
||||||
|
|
||||||
|
std::weak_ptr<parser_imp> m_this;
|
||||||
|
environment m_env;
|
||||||
|
io_state m_io_state;
|
||||||
|
scanner m_scanner;
|
||||||
|
std::string m_strm_name; // input stream name
|
||||||
|
frontend_elaborator m_elaborator;
|
||||||
|
macros const * m_expr_macros;
|
||||||
|
macros const * m_cmd_macros;
|
||||||
|
macros const * m_tactic_macros;
|
||||||
|
scanner::token m_curr;
|
||||||
|
bool m_use_exceptions;
|
||||||
|
bool m_interactive;
|
||||||
|
bool m_found_errors;
|
||||||
|
local_decls m_local_decls;
|
||||||
|
unsigned m_num_local_decls;
|
||||||
|
expr_pos_info m_expr_pos_info;
|
||||||
|
pos_info m_last_cmd_pos;
|
||||||
|
pos_info m_last_script_pos;
|
||||||
|
tactic_hints m_tactic_hints;
|
||||||
|
using_decls m_using_decls;
|
||||||
|
std::vector<name> m_namespace_prefixes;
|
||||||
|
std::vector<scope_kind> m_scope_kinds;
|
||||||
std::unique_ptr<calc_proof_parser> m_calc_proof_parser;
|
std::unique_ptr<calc_proof_parser> m_calc_proof_parser;
|
||||||
|
|
||||||
|
|
||||||
|
@ -202,22 +203,20 @@ public:
|
||||||
private:
|
private:
|
||||||
void display_error_pos(unsigned line, unsigned pos);
|
void display_error_pos(unsigned line, unsigned pos);
|
||||||
void display_error_pos(pos_info const & p);
|
void display_error_pos(pos_info const & p);
|
||||||
void display_error_pos(optional<expr> const & e);
|
|
||||||
void display_error(char const * msg, unsigned line, unsigned pos);
|
void display_error(char const * msg, unsigned line, unsigned pos);
|
||||||
void display_error(char const * msg);
|
|
||||||
void display_error(kernel_exception const & ex);
|
|
||||||
void display_error(unsolved_metavar_exception const & ex);
|
|
||||||
|
|
||||||
struct lean_pos_info_provider : public pos_info_provider {
|
struct lean_pos_info_provider : public pos_info_provider {
|
||||||
parser_imp const & m_ref;
|
std::shared_ptr<parser_imp> m_parser;
|
||||||
lean_pos_info_provider(parser_imp const & r):m_ref(r) {}
|
pos_info m_pos;
|
||||||
|
lean_pos_info_provider(std::shared_ptr<parser_imp> const & p, pos_info const & pos):m_parser(p), m_pos(pos) {}
|
||||||
virtual std::pair<unsigned, unsigned> get_pos_info(expr const & e) const;
|
virtual std::pair<unsigned, unsigned> get_pos_info(expr const & e) const;
|
||||||
virtual char const * get_file_name(expr const & e) const;
|
virtual std::pair<unsigned, unsigned> get_some_pos() const { return m_pos; }
|
||||||
|
virtual char const * get_file_name() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
void display_error(elaborator_exception const & ex);
|
|
||||||
void display_error(script_exception const & ex);
|
|
||||||
void display_error(tactic_cmd_error const & ex);
|
void display_error(tactic_cmd_error const & ex);
|
||||||
|
void display_error(script_exception const & ex);
|
||||||
|
void display_error(exception const & ex);
|
||||||
public:
|
public:
|
||||||
void protected_call(std::function<void()> && f, std::function<void()> && sync);
|
void protected_call(std::function<void()> && f, std::function<void()> && sync);
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
|
@ -24,9 +24,9 @@ parser_imp * get_parser(lua_State * L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
set_parser::set_parser(script_state * S, parser_imp * ptr) {
|
set_parser::set_parser(script_state * S, parser_imp * ptr) {
|
||||||
m_state = S;
|
if (S) {
|
||||||
if (m_state) {
|
m_state = S->to_weak_ref();
|
||||||
m_state->apply([&](lua_State * L) {
|
S->apply([&](lua_State * L) {
|
||||||
m_prev = get_parser(L);
|
m_prev = get_parser(L);
|
||||||
lua_pushlightuserdata(L, static_cast<void *>(&g_set_parser_key));
|
lua_pushlightuserdata(L, static_cast<void *>(&g_set_parser_key));
|
||||||
lua_pushlightuserdata(L, ptr);
|
lua_pushlightuserdata(L, ptr);
|
||||||
|
@ -35,8 +35,9 @@ set_parser::set_parser(script_state * S, parser_imp * ptr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_parser::~set_parser() {
|
set_parser::~set_parser() {
|
||||||
if (m_state) {
|
if (!m_state.expired()) {
|
||||||
m_state->apply([&](lua_State * L) {
|
script_state S(m_state);
|
||||||
|
S.apply([&](lua_State * L) {
|
||||||
lua_pushlightuserdata(L, static_cast<void *>(&g_set_parser_key));
|
lua_pushlightuserdata(L, static_cast<void *>(&g_set_parser_key));
|
||||||
lua_pushlightuserdata(L, m_prev);
|
lua_pushlightuserdata(L, m_prev);
|
||||||
lua_settable(L, LUA_REGISTRYINDEX);
|
lua_settable(L, LUA_REGISTRYINDEX);
|
||||||
|
|
|
@ -101,9 +101,9 @@ bool shell::operator()() {
|
||||||
#ifdef LEAN_USE_READLINE
|
#ifdef LEAN_USE_READLINE
|
||||||
readline_streambuf buf;
|
readline_streambuf buf;
|
||||||
std::istream is(&buf);
|
std::istream is(&buf);
|
||||||
parser p(m_env, m_io_state, is, "stdin", m_script_state, false, true);
|
parser p(m_env, m_io_state, is, "[stdin]", m_script_state, false, true);
|
||||||
#else
|
#else
|
||||||
parser p(m_env, m_io_state, std::cin, "stdin", m_script_state, false, true);
|
parser p(m_env, m_io_state, std::cin, "[stdin]", m_script_state, false, true);
|
||||||
#endif
|
#endif
|
||||||
return p();
|
return p();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,13 @@ Author: Leonardo de Moura
|
||||||
#include "kernel/pos_info_provider.h"
|
#include "kernel/pos_info_provider.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
char const * pos_info_provider::get_file_name(expr const & ) const {
|
char const * pos_info_provider::get_file_name() const {
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
format pos_info_provider::pp(expr const & e) const {
|
format pos_info_provider::pp(expr const & e) const {
|
||||||
try {
|
try {
|
||||||
auto p = get_pos_info(e);
|
auto p = get_pos_info(e);
|
||||||
return format{format(get_file_name(e)), colon(), format(p.first), colon(), format(p.second), colon()};
|
return format{format(get_file_name()), colon(), format(p.first), colon(), format(p.second), colon()};
|
||||||
} catch (exception &) {
|
} catch (exception &) {
|
||||||
return format();
|
return format();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
||||||
|
|
||||||
Author: Leonardo de Moura
|
Author: Leonardo de Moura
|
||||||
*/
|
*/
|
||||||
|
#pragma once
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "util/sexpr/format.h"
|
#include "util/sexpr/format.h"
|
||||||
#include "kernel/expr.h"
|
#include "kernel/expr.h"
|
||||||
|
@ -20,7 +21,9 @@ public:
|
||||||
Throws an exception if the given expression does not have this kind of information associated with it.
|
Throws an exception if the given expression does not have this kind of information associated with it.
|
||||||
*/
|
*/
|
||||||
virtual std::pair<unsigned, unsigned> get_pos_info(expr const & e) const = 0;
|
virtual std::pair<unsigned, unsigned> get_pos_info(expr const & e) const = 0;
|
||||||
virtual char const * get_file_name(expr const & e) const;
|
virtual char const * get_file_name() const;
|
||||||
|
virtual std::pair<unsigned, unsigned> get_some_pos() const = 0;
|
||||||
|
|
||||||
unsigned get_line(expr const & e) const { return get_pos_info(e).first; }
|
unsigned get_line(expr const & e) const { return get_pos_info(e).first; }
|
||||||
unsigned get_pos(expr const & e) const { return get_pos_info(e).second; }
|
unsigned get_pos(expr const & e) const { return get_pos_info(e).second; }
|
||||||
/**
|
/**
|
||||||
|
|
2
src/library/error_handling/CMakeLists.txt
Normal file
2
src/library/error_handling/CMakeLists.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
add_library(error_handling error_handling.cpp)
|
||||||
|
target_link_libraries(error_handling ${LEAN_LIBS})
|
183
src/library/error_handling/error_handling.cpp
Normal file
183
src/library/error_handling/error_handling.cpp
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||||
|
Released under Apache 2.0 license as described in the file LICENSE.
|
||||||
|
|
||||||
|
Author: Leonardo de Moura
|
||||||
|
*/
|
||||||
|
#include <utility>
|
||||||
|
#include <string>
|
||||||
|
#include "util/script_exception.h"
|
||||||
|
#include "util/name_set.h"
|
||||||
|
#include "kernel/kernel_exception.h"
|
||||||
|
#include "kernel/for_each_fn.h"
|
||||||
|
#include "library/io_state_stream.h"
|
||||||
|
#include "library/elaborator/elaborator_justification.h"
|
||||||
|
#include "library/elaborator/elaborator_exception.h"
|
||||||
|
#include "library/parser_nested_exception.h"
|
||||||
|
#include "library/unsolved_metavar_exception.h"
|
||||||
|
|
||||||
|
namespace lean {
|
||||||
|
void display_error_pos(io_state const & ios, char const * strm_name, unsigned line, unsigned pos) {
|
||||||
|
regular(ios) << strm_name << ":" << line << ":";
|
||||||
|
if (pos != static_cast<unsigned>(-1))
|
||||||
|
regular(ios) << pos << ":";
|
||||||
|
regular(ios) << " error:";
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_error_pos(io_state const & ios, pos_info_provider const * p, expr const & e) {
|
||||||
|
if (p) {
|
||||||
|
auto pos = p->get_pos_info(e);
|
||||||
|
display_error_pos(ios, p->get_file_name(), pos.first, pos.second);
|
||||||
|
} else {
|
||||||
|
regular(ios) << "error:";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_error_pos(io_state const & ios, pos_info_provider const * p, optional<expr> const & e) {
|
||||||
|
if (e) {
|
||||||
|
display_error_pos(ios, p, *e);
|
||||||
|
} else if (p) {
|
||||||
|
auto pos = p->get_some_pos();
|
||||||
|
display_error_pos(ios, p->get_file_name(), pos.first, pos.second);
|
||||||
|
} else {
|
||||||
|
regular(ios) << "error:";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_error(io_state const & ios, pos_info_provider const * p, exception const & ex);
|
||||||
|
|
||||||
|
static void display_error(io_state const & ios, pos_info_provider const * p, kernel_exception const & ex) {
|
||||||
|
display_error_pos(ios, p, ex.get_main_expr());
|
||||||
|
regular(ios) << " " << ex << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void display_error(io_state const & ios, pos_info_provider const * p, elaborator_exception const & ex) {
|
||||||
|
formatter fmt = ios.get_formatter();
|
||||||
|
options opts = ios.get_options();
|
||||||
|
auto j = ex.get_justification();
|
||||||
|
j = remove_detail(j);
|
||||||
|
regular(ios) << mk_pair(j.pp(fmt, opts, p, true), opts) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct delta_pos_info_provider : public pos_info_provider {
|
||||||
|
unsigned m_delta;
|
||||||
|
std::string m_file_name;
|
||||||
|
pos_info_provider const & m_provider;
|
||||||
|
delta_pos_info_provider(unsigned d, char const * fname, pos_info_provider const & p):m_delta(d), m_file_name(fname), m_provider(p) {}
|
||||||
|
virtual std::pair<unsigned, unsigned> get_pos_info(expr const & e) const {
|
||||||
|
auto r = m_provider.get_pos_info(e);
|
||||||
|
return mk_pair(r.first + m_delta, r.second);
|
||||||
|
}
|
||||||
|
virtual char const * get_file_name() const { return m_file_name.c_str(); }
|
||||||
|
virtual std::pair<unsigned, unsigned> get_some_pos() const {
|
||||||
|
auto r = m_provider.get_some_pos();
|
||||||
|
return mk_pair(r.first + m_delta, r.second);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void display_error(io_state const & ios, pos_info_provider const * p, script_exception const & ex) {
|
||||||
|
if (p) {
|
||||||
|
char const * msg = ex.get_msg();
|
||||||
|
char const * space = msg && *msg == ' ' ? "" : " ";
|
||||||
|
switch (ex.get_source()) {
|
||||||
|
case script_exception::source::String:
|
||||||
|
display_error_pos(ios, p->get_file_name(), ex.get_line() + p->get_some_pos().first - 1, static_cast<unsigned>(-1));
|
||||||
|
regular(ios) << " executing script," << space << msg << endl;
|
||||||
|
break;
|
||||||
|
case script_exception::source::File:
|
||||||
|
display_error_pos(ios, p->get_file_name(), p->get_some_pos().first, p->get_some_pos().second);
|
||||||
|
regular(ios) << " executing external script (" << ex.get_file_name() << ":" << ex.get_line() << ")," << space << msg << endl;
|
||||||
|
break;
|
||||||
|
case script_exception::source::Unknown:
|
||||||
|
display_error_pos(ios, p->get_file_name(), p->get_some_pos().first, p->get_some_pos().second);
|
||||||
|
regular(ios) << " executing script, exact error position is not available, " << ex.what() << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
regular(ios) << ex.what() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void display_error(io_state const & ios, pos_info_provider const * p, script_nested_exception const & ex) {
|
||||||
|
switch (ex.get_source()) {
|
||||||
|
case script_exception::source::String:
|
||||||
|
if (p) {
|
||||||
|
display_error_pos(ios, p->get_file_name(), ex.get_line() + p->get_some_pos().first - 1, static_cast<unsigned>(-1));
|
||||||
|
regular(ios) << " executing script" << endl;
|
||||||
|
}
|
||||||
|
display_error(ios, nullptr, ex.get_exception());
|
||||||
|
break;
|
||||||
|
case script_exception::source::File:
|
||||||
|
if (p) {
|
||||||
|
display_error_pos(ios, p->get_file_name(), p->get_some_pos().first, p->get_some_pos().second);
|
||||||
|
regular(ios) << " executing external script (" << ex.get_file_name() << ":" << ex.get_line() << ")" << endl;
|
||||||
|
} else {
|
||||||
|
display_error_pos(ios, ex.get_file_name(), ex.get_line(), -1);
|
||||||
|
regular(ios) << " executing script" << endl;
|
||||||
|
}
|
||||||
|
display_error(ios, nullptr, ex.get_exception());
|
||||||
|
break;
|
||||||
|
case script_exception::source::Unknown:
|
||||||
|
display_error(ios, nullptr, ex.get_exception());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void display_error(io_state const & ios, pos_info_provider const *, parser_nested_exception const & ex) {
|
||||||
|
display_error(ios, &(ex.get_provider()), ex.get_exception());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void display_error(io_state const & ios, pos_info_provider const *, parser_exception const & ex) {
|
||||||
|
regular(ios) << ex.what() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void display_error(io_state const & ios, pos_info_provider const * p, unsolved_metavar_exception const & ex) {
|
||||||
|
display_error_pos(ios, p, ex.get_expr());
|
||||||
|
formatter fmt = ios.get_formatter();
|
||||||
|
options opts = ios.get_options();
|
||||||
|
unsigned indent = get_pp_indent(opts);
|
||||||
|
format r = nest(indent, compose(line(), fmt(ex.get_expr(), opts)));
|
||||||
|
regular(ios) << " " << ex.what() << mk_pair(r, opts) << endl;
|
||||||
|
if (p) {
|
||||||
|
name_set already_displayed;
|
||||||
|
for_each(ex.get_expr(), [&](expr const & e, unsigned) -> bool {
|
||||||
|
if (is_metavar(e)) {
|
||||||
|
name const & m = metavar_name(e);
|
||||||
|
if (already_displayed.find(m) == already_displayed.end()) {
|
||||||
|
already_displayed.insert(m);
|
||||||
|
for (unsigned i = 0; i < indent; i++) regular(ios) << " ";
|
||||||
|
display_error_pos(ios, p, e);
|
||||||
|
regular(ios) << " unsolved metavar " << m << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_error(io_state const & ios, pos_info_provider const * p, exception const & ex) {
|
||||||
|
if (auto k_ex = dynamic_cast<kernel_exception const *>(&ex)) {
|
||||||
|
display_error(ios, p, *k_ex);
|
||||||
|
} else if (auto e_ex = dynamic_cast<elaborator_exception const *>(&ex)) {
|
||||||
|
display_error(ios, p, *e_ex);
|
||||||
|
} else if (auto m_ex = dynamic_cast<unsolved_metavar_exception const *>(&ex)) {
|
||||||
|
display_error(ios, p, *m_ex);
|
||||||
|
} else if (auto ls_ex = dynamic_cast<script_nested_exception const *>(&ex)) {
|
||||||
|
display_error(ios, p, *ls_ex);
|
||||||
|
} else if (auto s_ex = dynamic_cast<script_exception const *>(&ex)) {
|
||||||
|
display_error(ios, p, *s_ex);
|
||||||
|
} else if (auto n_ex = dynamic_cast<parser_nested_exception const *>(&ex)) {
|
||||||
|
display_error(ios, p, *n_ex);
|
||||||
|
} else if (auto n_ex = dynamic_cast<parser_exception const *>(&ex)) {
|
||||||
|
display_error(ios, p, *n_ex);
|
||||||
|
} else if (p) {
|
||||||
|
display_error_pos(ios, p->get_file_name(), p->get_some_pos().first, p->get_some_pos().second);
|
||||||
|
regular(ios) << " " << ex.what() << endl;
|
||||||
|
} else {
|
||||||
|
regular(ios) << "error: " << ex.what() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
18
src/library/error_handling/error_handling.h
Normal file
18
src/library/error_handling/error_handling.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||||
|
Released under Apache 2.0 license as described in the file LICENSE.
|
||||||
|
|
||||||
|
Author: Leonardo de Moura
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "util/exception.h"
|
||||||
|
#include "kernel/pos_info_provider.h"
|
||||||
|
#include "kernel/io_state.h"
|
||||||
|
|
||||||
|
namespace lean {
|
||||||
|
/**
|
||||||
|
\brief Display exception in the regular stream of \c ios, using the configuration options and formatter from \c ios.
|
||||||
|
Exceptions that contain expressions use the given \c pos_info_provider (if available) to retrieve line number information.
|
||||||
|
*/
|
||||||
|
void display_error(io_state const & ios, pos_info_provider const * p, exception const & ex);
|
||||||
|
}
|
|
@ -1205,11 +1205,15 @@ static const struct luaL_Reg environment_m[] = {
|
||||||
|
|
||||||
static char g_set_environment_key;
|
static char g_set_environment_key;
|
||||||
|
|
||||||
|
void set_global_environment(lua_State * L, environment const & env) {
|
||||||
|
lua_pushlightuserdata(L, static_cast<void *>(&g_set_environment_key));
|
||||||
|
push_environment(L, env);
|
||||||
|
lua_settable(L, LUA_REGISTRYINDEX);
|
||||||
|
}
|
||||||
|
|
||||||
set_environment::set_environment(lua_State * L, environment const & env) {
|
set_environment::set_environment(lua_State * L, environment const & env) {
|
||||||
m_state = L;
|
m_state = L;
|
||||||
lua_pushlightuserdata(m_state, static_cast<void *>(&g_set_environment_key));
|
set_global_environment(L, env);
|
||||||
push_environment(m_state, env);
|
|
||||||
lua_settable(m_state, LUA_REGISTRYINDEX);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_environment::~set_environment() {
|
set_environment::~set_environment() {
|
||||||
|
@ -1832,6 +1836,13 @@ void open_io_state(lua_State * L) {
|
||||||
|
|
||||||
static char g_set_state_key;
|
static char g_set_state_key;
|
||||||
|
|
||||||
|
void set_global_io_state(lua_State * L, io_state & ios) {
|
||||||
|
lua_pushlightuserdata(L, static_cast<void *>(&g_set_state_key));
|
||||||
|
lua_pushlightuserdata(L, &ios);
|
||||||
|
lua_settable(L, LUA_REGISTRYINDEX);
|
||||||
|
set_global_options(L, ios.get_options());
|
||||||
|
}
|
||||||
|
|
||||||
set_io_state::set_io_state(lua_State * L, io_state & st) {
|
set_io_state::set_io_state(lua_State * L, io_state & st) {
|
||||||
m_state = L;
|
m_state = L;
|
||||||
m_prev = get_io_state(L);
|
m_prev = get_io_state(L);
|
||||||
|
|
|
@ -44,8 +44,11 @@ formatter get_global_formatter(lua_State * L);
|
||||||
Otherwise, we update the registry of \c L.
|
Otherwise, we update the registry of \c L.
|
||||||
*/
|
*/
|
||||||
void set_global_formatter(lua_State * L, formatter const & fmt);
|
void set_global_formatter(lua_State * L, formatter const & fmt);
|
||||||
|
|
||||||
|
/** \brief Set the Lua registry of a Lua state with an environment object. */
|
||||||
|
void set_global_environment(lua_State * L, environment const & env);
|
||||||
/**
|
/**
|
||||||
\brief Auxiliary class for setting the Lua registry of a Lua state
|
\brief Auxiliary class for temporarily setting the Lua registry of a Lua state
|
||||||
with an environment object.
|
with an environment object.
|
||||||
*/
|
*/
|
||||||
class set_environment {
|
class set_environment {
|
||||||
|
@ -74,6 +77,9 @@ public:
|
||||||
rw_shared_environment(lua_State * L, int idx);
|
rw_shared_environment(lua_State * L, int idx);
|
||||||
rw_shared_environment(lua_State * L);
|
rw_shared_environment(lua_State * L);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \brief Set the Lua registry of a Lua state with an io_state object. */
|
||||||
|
void set_global_io_state(lua_State * L, io_state & ios);
|
||||||
/**
|
/**
|
||||||
\brief Auxiliary class for temporarily setting the Lua registry of a Lua state
|
\brief Auxiliary class for temporarily setting the Lua registry of a Lua state
|
||||||
with a Lean io_state object.
|
with a Lean io_state object.
|
||||||
|
|
25
src/library/parser_nested_exception.h
Normal file
25
src/library/parser_nested_exception.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||||
|
Released under Apache 2.0 license as described in the file LICENSE.
|
||||||
|
|
||||||
|
Author: Leonardo de Moura
|
||||||
|
*/
|
||||||
|
#include <memory>
|
||||||
|
#include "util/exception.h"
|
||||||
|
#include "kernel/pos_info_provider.h"
|
||||||
|
|
||||||
|
namespace lean {
|
||||||
|
/** \brief Lean exception occurred when parsing file. */
|
||||||
|
class parser_nested_exception : public exception {
|
||||||
|
std::shared_ptr<exception> m_exception;
|
||||||
|
std::shared_ptr<pos_info_provider> m_provider;
|
||||||
|
public:
|
||||||
|
parser_nested_exception(std::shared_ptr<exception> const & ex, std::shared_ptr<pos_info_provider> const & pr):exception("parser exception"), m_exception(ex), m_provider(pr) {}
|
||||||
|
virtual ~parser_nested_exception() {}
|
||||||
|
virtual exception * clone() const { return new parser_nested_exception(m_exception, m_provider); }
|
||||||
|
virtual void rethrow() const { throw *this; }
|
||||||
|
virtual char const * what() const noexcept { return m_exception->what(); }
|
||||||
|
exception const & get_exception() const { return *(m_exception.get()); }
|
||||||
|
pos_info_provider const & get_provider() const { return *(m_provider.get()); }
|
||||||
|
};
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ Author: Leonardo de Moura
|
||||||
#include "library/printer.h"
|
#include "library/printer.h"
|
||||||
#include "library/kernel_bindings.h"
|
#include "library/kernel_bindings.h"
|
||||||
#include "library/io_state_stream.h"
|
#include "library/io_state_stream.h"
|
||||||
|
#include "library/error_handling/error_handling.h"
|
||||||
#include "frontends/lean/parser.h"
|
#include "frontends/lean/parser.h"
|
||||||
#include "frontends/lean/shell.h"
|
#include "frontends/lean/shell.h"
|
||||||
#include "frontends/lean/frontend.h"
|
#include "frontends/lean/frontend.h"
|
||||||
|
@ -108,67 +109,77 @@ static struct option g_long_options[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char ** argv) {
|
int main(int argc, char ** argv) {
|
||||||
try {
|
lean::save_stack_info();
|
||||||
lean::save_stack_info();
|
lean::register_modules();
|
||||||
lean::register_modules();
|
bool no_kernel = false;
|
||||||
bool no_kernel = false;
|
bool export_objects = false;
|
||||||
bool export_objects = false;
|
bool trust_imported = false;
|
||||||
bool trust_imported = false;
|
bool quiet = false;
|
||||||
bool quiet = false;
|
std::string output;
|
||||||
std::string output;
|
input_kind default_k = input_kind::Lean; // default
|
||||||
input_kind default_k = input_kind::Lean; // default
|
while (true) {
|
||||||
while (true) {
|
int c = getopt_long(argc, argv, "qtnlupgvhc:012s:012o:", g_long_options, NULL);
|
||||||
int c = getopt_long(argc, argv, "qtnlupgvhc:012s:012o:", g_long_options, NULL);
|
if (c == -1)
|
||||||
if (c == -1)
|
break; // end of command line
|
||||||
break; // end of command line
|
switch (c) {
|
||||||
switch (c) {
|
case 'v':
|
||||||
case 'v':
|
display_header(std::cout);
|
||||||
display_header(std::cout);
|
return 0;
|
||||||
return 0;
|
case 'g':
|
||||||
case 'g':
|
std::cout << g_githash << "\n";
|
||||||
std::cout << g_githash << "\n";
|
return 0;
|
||||||
return 0;
|
case 'h':
|
||||||
case 'h':
|
display_help(std::cout);
|
||||||
display_help(std::cout);
|
return 0;
|
||||||
return 0;
|
case 'l':
|
||||||
case 'l':
|
default_k = input_kind::Lean;
|
||||||
default_k = input_kind::Lean;
|
break;
|
||||||
break;
|
case 'u':
|
||||||
case 'u':
|
default_k = input_kind::Lua;
|
||||||
default_k = input_kind::Lua;
|
break;
|
||||||
break;
|
case 'b':
|
||||||
case 'b':
|
default_k = input_kind::OLean;
|
||||||
default_k = input_kind::OLean;
|
break;
|
||||||
break;
|
case 'c':
|
||||||
case 'c':
|
script_state::set_check_interrupt_freq(atoi(optarg));
|
||||||
script_state::set_check_interrupt_freq(atoi(optarg));
|
break;
|
||||||
break;
|
case 'p':
|
||||||
case 'p':
|
std::cout << lean::get_lean_path() << "\n";
|
||||||
std::cout << lean::get_lean_path() << "\n";
|
return 0;
|
||||||
return 0;
|
case 's':
|
||||||
case 's':
|
lean::set_thread_stack_size(atoi(optarg)*1024);
|
||||||
lean::set_thread_stack_size(atoi(optarg)*1024);
|
break;
|
||||||
break;
|
case 'n':
|
||||||
case 'n':
|
no_kernel = true;
|
||||||
no_kernel = true;
|
break;
|
||||||
break;
|
case 'o':
|
||||||
case 'o':
|
output = optarg;
|
||||||
output = optarg;
|
export_objects = true;
|
||||||
export_objects = true;
|
break;
|
||||||
break;
|
case 't':
|
||||||
case 't':
|
trust_imported = true;
|
||||||
trust_imported = true;
|
lean::set_default_trust_imported_for_lua(true);
|
||||||
lean::set_default_trust_imported_for_lua(true);
|
break;
|
||||||
break;
|
case 'q':
|
||||||
case 'q':
|
quiet = true;
|
||||||
quiet = true;
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
std::cerr << "Unknown command line option\n";
|
||||||
std::cerr << "Unknown command line option\n";
|
display_help(std::cerr);
|
||||||
display_help(std::cerr);
|
return 1;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
environment env;
|
||||||
|
env->set_trusted_imported(trust_imported);
|
||||||
|
io_state ios = init_frontend(env, no_kernel);
|
||||||
|
if (quiet)
|
||||||
|
ios.set_option("verbose", false);
|
||||||
|
script_state S;
|
||||||
|
S.apply([&](lua_State * L) {
|
||||||
|
set_global_environment(L, env);
|
||||||
|
set_global_io_state(L, ios);
|
||||||
|
});
|
||||||
|
try {
|
||||||
if (optind >= argc) {
|
if (optind >= argc) {
|
||||||
display_header(std::cout);
|
display_header(std::cout);
|
||||||
signal(SIGINT, on_ctrl_c);
|
signal(SIGINT, on_ctrl_c);
|
||||||
|
@ -178,12 +189,6 @@ int main(int argc, char ** argv) {
|
||||||
#else
|
#else
|
||||||
std::cout << "Type Ctrl-D or 'Exit.' to exit or 'Help.' for help."<< std::endl;
|
std::cout << "Type Ctrl-D or 'Exit.' to exit or 'Help.' for help."<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
environment env;
|
|
||||||
env->set_trusted_imported(trust_imported);
|
|
||||||
io_state ios = init_frontend(env, no_kernel);
|
|
||||||
if (quiet)
|
|
||||||
ios.set_option("verbose", false);
|
|
||||||
script_state S;
|
|
||||||
shell sh(env, &S);
|
shell sh(env, &S);
|
||||||
int status = sh() ? 0 : 1;
|
int status = sh() ? 0 : 1;
|
||||||
if (export_objects)
|
if (export_objects)
|
||||||
|
@ -191,17 +196,10 @@ int main(int argc, char ** argv) {
|
||||||
return status;
|
return status;
|
||||||
} else {
|
} else {
|
||||||
lean_assert(default_k == input_kind::Lua);
|
lean_assert(default_k == input_kind::Lua);
|
||||||
script_state S;
|
|
||||||
S.import("repl");
|
S.import("repl");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
environment env;
|
|
||||||
env->set_trusted_imported(trust_imported);
|
|
||||||
io_state ios = init_frontend(env, no_kernel);
|
|
||||||
if (quiet)
|
|
||||||
ios.set_option("verbose", false);
|
|
||||||
script_state S;
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
for (int i = optind; i < argc; i++) {
|
for (int i = optind; i < argc; i++) {
|
||||||
char const * ext = get_file_extension(argv[i]);
|
char const * ext = get_file_extension(argv[i]);
|
||||||
|
@ -227,15 +225,9 @@ int main(int argc, char ** argv) {
|
||||||
}
|
}
|
||||||
} else if (k == input_kind::Lua) {
|
} else if (k == input_kind::Lua) {
|
||||||
try {
|
try {
|
||||||
S.apply([&](lua_State * L) {
|
S.dofile(argv[i]);
|
||||||
lean::set_io_state set1(L, ios);
|
|
||||||
lean::set_environment set2(L, env);
|
|
||||||
S.exec_unprotected([&]() {
|
|
||||||
S.dofile(argv[i]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} catch (lean::exception & ex) {
|
} catch (lean::exception & ex) {
|
||||||
std::cerr << ex.what() << std::endl;
|
::lean::display_error(ios, nullptr, ex);
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -246,12 +238,8 @@ int main(int argc, char ** argv) {
|
||||||
env->export_objects(output);
|
env->export_objects(output);
|
||||||
return ok ? 0 : 1;
|
return ok ? 0 : 1;
|
||||||
}
|
}
|
||||||
} catch (lean::kernel_exception & ex) {
|
|
||||||
std::cerr << "Error: " << ex.pp(lean::mk_simple_formatter(), lean::options()) << "\n";
|
|
||||||
} catch (lean::parser_exception & ex) {
|
|
||||||
std::cerr << ex.what() << "\n";
|
|
||||||
} catch (lean::exception & ex) {
|
} catch (lean::exception & ex) {
|
||||||
std::cerr << "Error: " << ex.what() << "\n";
|
::lean::display_error(ios, nullptr, ex);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ Author: Leonardo de Moura
|
||||||
#include "util/lua.h"
|
#include "util/lua.h"
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
class sstream;
|
class sstream;
|
||||||
|
@ -39,9 +40,12 @@ public:
|
||||||
virtual char const * what() const noexcept;
|
virtual char const * what() const noexcept;
|
||||||
unsigned get_line() const { return m_line; }
|
unsigned get_line() const { return m_line; }
|
||||||
unsigned get_pos() const { return m_pos; }
|
unsigned get_pos() const { return m_pos; }
|
||||||
|
std::string const & get_file_name() const { return m_fname; }
|
||||||
virtual exception * clone() const { return new parser_exception(m_msg, m_fname.c_str(), m_line, m_pos); }
|
virtual exception * clone() const { return new parser_exception(m_msg, m_fname.c_str(), m_line, m_pos); }
|
||||||
virtual void rethrow() const { throw *this; }
|
virtual void rethrow() const { throw *this; }
|
||||||
|
parser_exception update_line(unsigned line_delta) const { return parser_exception(m_msg, m_fname.c_str(), m_line + line_delta, m_pos); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Exception used to sign that a computation was interrupted */
|
/** \brief Exception used to sign that a computation was interrupted */
|
||||||
class interrupted : public exception {
|
class interrupted : public exception {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -91,10 +91,11 @@ static void exec(lua_State * L) {
|
||||||
|
|
||||||
void check_result(lua_State * L, int result) {
|
void check_result(lua_State * L, int result) {
|
||||||
if (result) {
|
if (result) {
|
||||||
if (is_exception(L, -1))
|
if (is_exception(L, -1)) {
|
||||||
to_exception(L, -1).rethrow();
|
to_exception(L, -1).rethrow();
|
||||||
else
|
} else {
|
||||||
throw script_exception(lua_tostring(L, -1));
|
throw script_exception(lua_tostring(L, -1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,10 +138,16 @@ bool resume(lua_State * L, int nargs) {
|
||||||
int safe_function_wrapper(lua_State * L, lua_CFunction f) {
|
int safe_function_wrapper(lua_State * L, lua_CFunction f) {
|
||||||
try {
|
try {
|
||||||
return f(L);
|
return f(L);
|
||||||
} catch (script_exception & e) {
|
|
||||||
lua_pushstring(L, e.what());
|
|
||||||
} catch (exception & e) {
|
} catch (exception & e) {
|
||||||
push_exception(L, e);
|
lua_Debug ar;
|
||||||
|
lua_getstack(L, 1, &ar);
|
||||||
|
lua_getinfo(L, "Sl", &ar);
|
||||||
|
if (ar.source && *(ar.source) == '@')
|
||||||
|
push_exception(L, script_nested_exception(true, ar.source+1, ar.currentline, std::shared_ptr<exception>(e.clone())));
|
||||||
|
else if (ar.source)
|
||||||
|
push_exception(L, script_nested_exception(false, ar.source, ar.currentline, std::shared_ptr<exception>(e.clone())));
|
||||||
|
else
|
||||||
|
push_exception(L, e);
|
||||||
} catch (std::bad_alloc &) {
|
} catch (std::bad_alloc &) {
|
||||||
lua_pushstring(L, "out of memory");
|
lua_pushstring(L, "out of memory");
|
||||||
} catch (std::exception & e) {
|
} catch (std::exception & e) {
|
||||||
|
|
|
@ -55,7 +55,7 @@ script_exception::script_exception(char const * lua_error) {
|
||||||
script_exception::~script_exception() {
|
script_exception::~script_exception() {
|
||||||
}
|
}
|
||||||
|
|
||||||
char const * script_exception::get_filename() const {
|
char const * script_exception::get_file_name() const {
|
||||||
lean_assert(get_source() == source::File);
|
lean_assert(get_source() == source::File);
|
||||||
return m_file.c_str();
|
return m_file.c_str();
|
||||||
}
|
}
|
||||||
|
@ -72,12 +72,30 @@ char const * script_exception::get_msg() const noexcept {
|
||||||
char const * script_exception::what() const noexcept {
|
char const * script_exception::what() const noexcept {
|
||||||
static thread_local std::string buffer;
|
static thread_local std::string buffer;
|
||||||
std::ostringstream strm;
|
std::ostringstream strm;
|
||||||
|
char const * msg = get_msg();
|
||||||
|
char const * space = msg && *msg == ' ' ? "" : " ";
|
||||||
switch (get_source()) {
|
switch (get_source()) {
|
||||||
case source::String: strm << "[string]:" << get_line() << ":" << get_msg() << "\n"; break;
|
case source::String: strm << "[string]:" << get_line() << ":" << space << get_msg(); break;
|
||||||
case source::File: strm << get_filename() << ":" << get_line() << ":" << get_msg() << "\n"; break;
|
case source::File: strm << get_file_name() << ":" << get_line() << ":" << space << get_msg(); break;
|
||||||
case source::Unknown: return get_msg();
|
case source::Unknown: return get_msg();
|
||||||
}
|
}
|
||||||
buffer = strm.str();
|
buffer = strm.str();
|
||||||
return buffer.c_str();
|
return buffer.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
script_nested_exception::script_nested_exception(source s, std::string f, unsigned l, std::shared_ptr<exception> const & ex):
|
||||||
|
script_exception(s, f, l, "Lean exception"),
|
||||||
|
m_exception(ex) {
|
||||||
|
lean_assert(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
script_nested_exception::~script_nested_exception() {}
|
||||||
|
|
||||||
|
char const * script_nested_exception::what() const noexcept {
|
||||||
|
static thread_local std::string buffer;
|
||||||
|
std::ostringstream strm;
|
||||||
|
strm << script_exception::what() << "\n" << get_exception().what();
|
||||||
|
buffer = strm.str();
|
||||||
|
return buffer.c_str();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ Author: Leonardo de Moura
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
#include "util/exception.h"
|
#include "util/exception.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
|
@ -15,21 +16,36 @@ namespace lean {
|
||||||
class script_exception : public exception {
|
class script_exception : public exception {
|
||||||
public:
|
public:
|
||||||
enum class source { String, File, Unknown };
|
enum class source { String, File, Unknown };
|
||||||
private:
|
protected:
|
||||||
source m_source;
|
source m_source;
|
||||||
std::string m_file; // if source == File, then this field contains the filename that triggered the error.
|
std::string m_file; // if source == File, then this field contains the filename that triggered the error.
|
||||||
unsigned m_line; // line number
|
unsigned m_line; // line number
|
||||||
script_exception(source s, std::string f, unsigned l):m_source(s), m_file(f), m_line(l) {}
|
script_exception(source s, std::string f, unsigned l, std::string const & msg):exception(msg), m_source(s), m_file(f), m_line(l) {}
|
||||||
public:
|
public:
|
||||||
script_exception(char const * lua_error);
|
script_exception(char const * lua_error);
|
||||||
virtual ~script_exception();
|
virtual ~script_exception();
|
||||||
virtual char const * what() const noexcept;
|
virtual char const * what() const noexcept;
|
||||||
virtual source get_source() const { return m_source; }
|
virtual source get_source() const { return m_source; }
|
||||||
virtual char const * get_filename() const;
|
virtual char const * get_file_name() const;
|
||||||
virtual unsigned get_line() const;
|
virtual unsigned get_line() const;
|
||||||
/** \brief Return error message without position information */
|
/** \brief Return error message without position information */
|
||||||
virtual char const * get_msg() const noexcept;
|
virtual char const * get_msg() const noexcept;
|
||||||
virtual exception * clone() const { return new script_exception(m_source, m_file, m_line); }
|
virtual exception * clone() const { return new script_exception(m_source, m_file, m_line, m_msg); }
|
||||||
virtual void rethrow() const { throw *this; }
|
virtual void rethrow() const { throw *this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Lean exception occurred inside of a script
|
||||||
|
*/
|
||||||
|
class script_nested_exception : public script_exception {
|
||||||
|
std::shared_ptr<exception> m_exception;
|
||||||
|
script_nested_exception(source s, std::string f, unsigned l, std::shared_ptr<exception> const & ex);
|
||||||
|
public:
|
||||||
|
script_nested_exception(bool file, std::string f, unsigned l, std::shared_ptr<exception> const & ex):script_nested_exception(file ? source::File : source::String, f, l, ex) {}
|
||||||
|
virtual ~script_nested_exception();
|
||||||
|
virtual char const * what() const noexcept;
|
||||||
|
virtual exception * clone() const { return new script_nested_exception(m_source, m_file, m_line, m_exception); }
|
||||||
|
virtual void rethrow() const { throw *this; }
|
||||||
|
exception const & get_exception() const { return *(m_exception.get()); }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Set: pp::colors
|
Set: pp::colors
|
||||||
Set: pp::unicode
|
Set: pp::unicode
|
||||||
alias3.lean:2:13: error: alias 'A' was already defined
|
alias3.lean:2:0: error: alias 'A' was already defined
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
variable f : T → R
|
variable f : T → R
|
||||||
coercion f
|
coercion f
|
||||||
Assumed: g
|
Assumed: g
|
||||||
coercion1.lean:8:0: error: invalid coercion declaration, frontend already has a coercion for the given types
|
coercion1.lean:7:0: error: invalid coercion declaration, frontend already has a coercion for the given types
|
||||||
Assumed: h
|
Assumed: h
|
||||||
coercion1.lean:10:0: error: invalid coercion declaration, a coercion must have an arrow type (i.e., a non-dependent functional type)
|
coercion1.lean:9:0: error: invalid coercion declaration, a coercion must have an arrow type (i.e., a non-dependent functional type)
|
||||||
Defined: T2
|
Defined: T2
|
||||||
Defined: R2
|
Defined: R2
|
||||||
Assumed: f2
|
Assumed: f2
|
||||||
coercion1.lean:14:0: error: invalid coercion declaration, frontend already has a coercion for the given types
|
coercion1.lean:13:0: error: invalid coercion declaration, frontend already has a coercion for the given types
|
||||||
Assumed: id
|
Assumed: id
|
||||||
coercion1.lean:16:0: error: invalid coercion declaration, 'from' and 'to' types are the same
|
coercion1.lean:15:0: error: invalid coercion declaration, 'from' and 'to' types are the same
|
||||||
|
|
|
@ -3,10 +3,14 @@
|
||||||
Assumed: x
|
Assumed: x
|
||||||
env_errors.lean:3:0: error: set_opaque failed, 'x' is not a definition
|
env_errors.lean:3:0: error: set_opaque failed, 'x' is not a definition
|
||||||
before import
|
before import
|
||||||
env_errors.lean:11:0: error: file 'tstblafoo.lean' not found in the LEAN_PATH
|
env_errors.lean:8: error: executing script
|
||||||
|
error: file 'tstblafoo.lean' not found in the LEAN_PATH
|
||||||
before load1
|
before load1
|
||||||
env_errors.lean:17:0: error: failed to open file 'tstblafoo.lean'
|
env_errors.lean:14: error: executing script
|
||||||
|
error: failed to open file 'tstblafoo.lean'
|
||||||
before load2
|
before load2
|
||||||
env_errors.lean:23:0: error: corrupted binary file
|
env_errors.lean:20: error: executing script
|
||||||
|
error: corrupted binary file
|
||||||
before load3
|
before load3
|
||||||
env_errors.lean:28:0: error: file 'fake2.olean' does not seem to be a valid object Lean file
|
env_errors.lean:26: error: executing script
|
||||||
|
error: file 'fake2.olean' does not seem to be a valid object Lean file
|
||||||
|
|
|
@ -9,4 +9,4 @@ module::@g : ∀ (A : Type), A → A → A
|
||||||
h::1::explicit : ∀ (A B : Type), A → B → A
|
h::1::explicit : ∀ (A B : Type), A → B → A
|
||||||
Assumed: @h
|
Assumed: @h
|
||||||
Assumed: h
|
Assumed: h
|
||||||
explicit.lean:9:37: error: failed to mark implicit arguments for 'h', the frontend already has an object named '@h'
|
explicit.lean:9:0: error: failed to mark implicit arguments for 'h', the frontend already has an object named '@h'
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
Set: pp::unicode
|
Set: pp::unicode
|
||||||
Proof state:
|
Proof state:
|
||||||
a : Bool, b : Bool, H : a, H::1 : b ⊢ a ∧ b
|
a : Bool, b : Bool, H : a, H::1 : b ⊢ a ∧ b
|
||||||
## stdin:5:0: error: invalid 'done' command, proof cannot be produced from this state
|
## [stdin]:5:0: error: invalid 'done' command, proof cannot be produced from this state
|
||||||
Proof state:
|
Proof state:
|
||||||
a : Bool, b : Bool, H : a, H::1 : b ⊢ a ∧ b
|
a : Bool, b : Bool, H : a, H::1 : b ⊢ a ∧ b
|
||||||
## stdin:6:0: error: invalid 'done' command, proof cannot be produced from this state
|
## [stdin]:6:0: error: invalid 'done' command, proof cannot be produced from this state
|
||||||
Proof state:
|
Proof state:
|
||||||
a : Bool, b : Bool, H : a, H::1 : b ⊢ a ∧ b
|
a : Bool, b : Bool, H : a, H::1 : b ⊢ a ∧ b
|
||||||
## stdin:7:0: error: unknown tactic 'imp_tac2'
|
## [stdin]:7:0: error: unknown tactic 'imp_tac2'
|
||||||
## stdin:8:0: error: unknown tactic 'foo'
|
## [stdin]:8:0: error: unknown tactic 'foo'
|
||||||
## Proof state:
|
## Proof state:
|
||||||
a : Bool, b : Bool, H : a, H::1 : b ⊢ a
|
a : Bool, b : Bool, H : a, H::1 : b ⊢ a
|
||||||
a : Bool, b : Bool, H : a, H::1 : b ⊢ b
|
a : Bool, b : Bool, H : a, H::1 : b ⊢ b
|
||||||
## stdin:10:0: error: failed to backtrack
|
## [stdin]:10:0: error: failed to backtrack
|
||||||
Proof state:
|
Proof state:
|
||||||
a : Bool, b : Bool, H : a, H::1 : b ⊢ a
|
a : Bool, b : Bool, H : a, H::1 : b ⊢ a
|
||||||
a : Bool, b : Bool, H : a, H::1 : b ⊢ b
|
a : Bool, b : Bool, H : a, H::1 : b ⊢ b
|
||||||
|
|
|
@ -6,15 +6,15 @@ A : Bool, B : Bool, H : A ∧ B ⊢ A
|
||||||
no goals
|
no goals
|
||||||
## Proof state:
|
## Proof state:
|
||||||
A : Bool, B : Bool, H : A ∧ B, H1 : A ⊢ B
|
A : Bool, B : Bool, H : A ∧ B, H1 : A ⊢ B
|
||||||
## stdin:15:3: error: unknown tactic 'simple2_tac'
|
## [stdin]:15:3: error: unknown tactic 'simple2_tac'
|
||||||
## stdin:15:16: error: invalid 'done' command, proof cannot be produced from this state
|
## [stdin]:15:16: error: invalid 'done' command, proof cannot be produced from this state
|
||||||
Proof state:
|
Proof state:
|
||||||
A : Bool, B : Bool, H : A ∧ B, H1 : A ⊢ B
|
A : Bool, B : Bool, H : A ∧ B, H1 : A ⊢ B
|
||||||
## Proof state:
|
## Proof state:
|
||||||
no goals
|
no goals
|
||||||
## Proof state:
|
## Proof state:
|
||||||
A : Bool, B : Bool, H : A ∧ B, H1 : A, H2 : B ⊢ B ∧ A
|
A : Bool, B : Bool, H : A ∧ B, H1 : A, H2 : B ⊢ B ∧ A
|
||||||
## stdin:18:0: error: failed to prove theorem, proof has been aborted
|
## [stdin]:18:0: error: failed to prove theorem, proof has been aborted
|
||||||
Proof state:
|
Proof state:
|
||||||
A : Bool, B : Bool, H : A ∧ B, H1 : A, H2 : B ⊢ B ∧ A
|
A : Bool, B : Bool, H : A ∧ B, H1 : A, H2 : B ⊢ B ∧ A
|
||||||
# echo command after failure
|
# echo command after failure
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
Set: pp::unicode
|
Set: pp::unicode
|
||||||
Proof state:
|
Proof state:
|
||||||
a : Bool, b : Bool, H : a, H::1 : b ⊢ a ∧ b
|
a : Bool, b : Bool, H : a, H::1 : b ⊢ a ∧ b
|
||||||
## stdin:5:0: error: unknown tactic 'foo'
|
## [stdin]:5:0: error: unknown tactic 'foo'
|
||||||
## stdin:6:5: error: failed to prove theorem, proof has been aborted
|
## [stdin]:6:5: error: failed to prove theorem, proof has been aborted
|
||||||
Proof state:
|
Proof state:
|
||||||
a : Bool, b : Bool, H : a, H::1 : b ⊢ a ∧ b
|
a : Bool, b : Bool, H : a, H::1 : b ⊢ a ∧ b
|
||||||
# Assumed: a
|
# Assumed: a
|
||||||
|
|
|
@ -6,7 +6,7 @@ a : Bool, b : Bool, H : b ⊢ a ∨ b
|
||||||
a : Bool, b : Bool, H : b ⊢ a
|
a : Bool, b : Bool, H : b ⊢ a
|
||||||
## Proof state:
|
## Proof state:
|
||||||
a : Bool, b : Bool, H : b ⊢ b
|
a : Bool, b : Bool, H : b ⊢ b
|
||||||
## stdin:9:0: error: failed to backtrack
|
## [stdin]:9:0: error: failed to backtrack
|
||||||
Proof state:
|
Proof state:
|
||||||
a : Bool, b : Bool, H : b ⊢ b
|
a : Bool, b : Bool, H : b ⊢ b
|
||||||
## Proof state:
|
## Proof state:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Set: pp::colors
|
# Set: pp::colors
|
||||||
Set: pp::unicode
|
Set: pp::unicode
|
||||||
stdin:4:8: error: invalid definition, identifier expected
|
[stdin]:4:8: error: invalid definition, identifier expected
|
||||||
# done
|
# done
|
||||||
#
|
#
|
|
@ -4,21 +4,23 @@
|
||||||
Assumed: i
|
Assumed: i
|
||||||
Assumed: j
|
Assumed: j
|
||||||
Assumed: p
|
Assumed: p
|
||||||
|
[string]:5: Lean exception
|
||||||
elaborator exception
|
elaborator exception
|
||||||
|
lua15.lean:9: error: executing script
|
||||||
Failed to solve
|
Failed to solve
|
||||||
⊢ (?M::0 ≈ Nat::add) ⊕ (?M::0 ≈ Int::add)
|
⊢ (?M::0 ≈ Nat::add) ⊕ (?M::0 ≈ Int::add)
|
||||||
Overloading at
|
[string]:1:3: Overloading at
|
||||||
(Int::add | Nat::add) i p
|
(Int::add | Nat::add) i p
|
||||||
Failed to solve
|
Failed to solve
|
||||||
⊢ ℤ ≺ ℕ
|
⊢ ℤ ≺ ℕ
|
||||||
Type of argument 1 must be convertible to the expected type in the application of
|
[string]:1:3: Type of argument 1 must be convertible to the expected type in the application of
|
||||||
Nat::add
|
Nat::add
|
||||||
with arguments:
|
with arguments:
|
||||||
i
|
i
|
||||||
p
|
p
|
||||||
Failed to solve
|
Failed to solve
|
||||||
⊢ Bool ≺ ℤ
|
⊢ Bool ≺ ℤ
|
||||||
Type of argument 2 must be convertible to the expected type in the application of
|
[string]:1:3: Type of argument 2 must be convertible to the expected type in the application of
|
||||||
Int::add
|
Int::add
|
||||||
with arguments:
|
with arguments:
|
||||||
i
|
i
|
||||||
|
|
13
tests/lean/lua15b.lean
Normal file
13
tests/lean/lua15b.lean
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import Int.
|
||||||
|
variables i j : Int
|
||||||
|
variable p : Bool
|
||||||
|
|
||||||
|
(*
|
||||||
|
local env = get_environment()
|
||||||
|
|
||||||
|
parse_lean_cmds([[
|
||||||
|
print "hello"
|
||||||
|
eval i + j
|
||||||
|
check i + p
|
||||||
|
]])
|
||||||
|
*)
|
27
tests/lean/lua15b.lean.expected.out
Normal file
27
tests/lean/lua15b.lean.expected.out
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
Set: pp::colors
|
||||||
|
Set: pp::unicode
|
||||||
|
Imported 'Int'
|
||||||
|
Assumed: i
|
||||||
|
Assumed: j
|
||||||
|
Assumed: p
|
||||||
|
hello
|
||||||
|
i + j
|
||||||
|
lua15b.lean:8: error: executing script
|
||||||
|
Failed to solve
|
||||||
|
⊢ (?M::0 ≈ Nat::add) ⊕ (?M::0 ≈ Int::add)
|
||||||
|
[string]:3:12: Overloading at
|
||||||
|
(Int::add | Nat::add) i p
|
||||||
|
Failed to solve
|
||||||
|
⊢ ℤ ≺ ℕ
|
||||||
|
[string]:3:12: Type of argument 1 must be convertible to the expected type in the application of
|
||||||
|
Nat::add
|
||||||
|
with arguments:
|
||||||
|
i
|
||||||
|
p
|
||||||
|
Failed to solve
|
||||||
|
⊢ Bool ≺ ℤ
|
||||||
|
[string]:3:12: Type of argument 2 must be convertible to the expected type in the application of
|
||||||
|
Int::add
|
||||||
|
with arguments:
|
||||||
|
i
|
||||||
|
p
|
20
tests/lean/parser1.lean
Normal file
20
tests/lean/parser1.lean
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(*
|
||||||
|
|
||||||
|
foo(10)
|
||||||
|
|
||||||
|
*)
|
||||||
|
|
||||||
|
print "checkpoint"
|
||||||
|
|
||||||
|
(*
|
||||||
|
|
||||||
|
parse_lean_cmds("(" .. "*" .. [[
|
||||||
|
|
||||||
|
foo(20)
|
||||||
|
|
||||||
|
]] .. "*" .. ")")
|
||||||
|
|
||||||
|
*)
|
6
tests/lean/parser1.lean.expected.out
Normal file
6
tests/lean/parser1.lean.expected.out
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Set: pp::colors
|
||||||
|
Set: pp::unicode
|
||||||
|
parser1.lean:6: error: executing script, attempt to call global 'foo' (a nil value)
|
||||||
|
checkpoint
|
||||||
|
parser1.lean:14: error: executing script
|
||||||
|
[string]:2: error: executing script, attempt to call global 'foo' (a nil value)
|
|
@ -8,4 +8,4 @@ T:interrupt()
|
||||||
local ok, msg = pcall(function() T:wait() end)
|
local ok, msg = pcall(function() T:wait() end)
|
||||||
assert(not ok)
|
assert(not ok)
|
||||||
assert(is_exception(msg))
|
assert(is_exception(msg))
|
||||||
assert(msg:what() == "interrupted")
|
print(msg:what():find("interrupted"))
|
||||||
|
|
|
@ -31,6 +31,8 @@ assert(not pcall(function() S:eval([[ x = ]]) end))
|
||||||
local T2 = thread(S, [[ local x = ...; error("failed") ]], 10)
|
local T2 = thread(S, [[ local x = ...; error("failed") ]], 10)
|
||||||
local ok, msg = pcall(function() T2:wait() end)
|
local ok, msg = pcall(function() T2:wait() end)
|
||||||
assert(not ok)
|
assert(not ok)
|
||||||
assert(string.sub(msg, -7) == "failed\n")
|
assert(is_exception(msg))
|
||||||
|
print(msg:what())
|
||||||
|
assert(msg:what():find("failed"))
|
||||||
local T3 = thread(S, [[ local x = ...; return x + 10, x - 10 ]], 10)
|
local T3 = thread(S, [[ local x = ...; return x + 10, x - 10 ]], 10)
|
||||||
T3 = nil
|
T3 = nil
|
||||||
|
|
Loading…
Reference in a new issue