mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-07-31 00:37:02 +08:00
Address review: populate null print handler when No_IO is set
When No_IO is active, the default m_print_handler is now a no-op instead of writing to stdout. The stdout handler is only installed when No_IO is not set. Users can still override the handler via set_print_handler() even with No_IO enabled. Requested by @lefticus in PR #657 review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
258eb63fd1
commit
66e945782e
@ -830,7 +830,8 @@ namespace chaiscript {
|
||||
std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer_Default>>(),
|
||||
std::move(t_modulepaths),
|
||||
std::move(t_usepaths),
|
||||
std::move(t_opts)) {
|
||||
std::move(t_opts),
|
||||
std::find(t_lib_opts.begin(), t_lib_opts.end(), Library_Options::No_IO) != t_lib_opts.end()) {
|
||||
}
|
||||
};
|
||||
} // namespace chaiscript
|
||||
|
||||
@ -439,8 +439,8 @@ namespace chaiscript::bootstrap {
|
||||
|
||||
// print_string and println_string are registered in ChaiScript_Basic::build_eval_system()
|
||||
// to support per-instance IO redirection via set_print_handler.
|
||||
// When No_IO is set, the handler-based functions are still registered there,
|
||||
// so users can provide their own print handlers even without built-in IO.
|
||||
// When No_IO is set, the functions are still registered but the default handler
|
||||
// is a no-op, so users can provide their own print handlers without any stdout output.
|
||||
|
||||
m.add(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
|
||||
|
||||
|
||||
@ -79,9 +79,7 @@ namespace chaiscript {
|
||||
|
||||
std::map<std::string, std::function<Namespace &()>> m_namespace_generators;
|
||||
|
||||
std::function<void(const std::string &)> m_print_handler = [](const std::string &s) noexcept {
|
||||
fwrite(s.c_str(), 1, s.size(), stdout);
|
||||
};
|
||||
std::function<void(const std::string &)> m_print_handler = [](const std::string &) noexcept {};
|
||||
|
||||
/// Evaluates the given string in by parsing it and running the results through the evaluator
|
||||
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false) {
|
||||
@ -123,11 +121,17 @@ namespace chaiscript {
|
||||
chaiscript::detail::Dispatch_Engine &get_eval_engine() noexcept { return m_engine; }
|
||||
|
||||
/// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
||||
void build_eval_system(const ModulePtr &t_lib, const std::vector<Options> &t_opts) {
|
||||
void build_eval_system(const ModulePtr &t_lib, const std::vector<Options> &t_opts, const bool t_no_io = false) {
|
||||
if (t_lib) {
|
||||
add(t_lib);
|
||||
}
|
||||
|
||||
if (!t_no_io) {
|
||||
m_print_handler = [](const std::string &s) noexcept {
|
||||
fwrite(s.c_str(), 1, s.size(), stdout);
|
||||
};
|
||||
}
|
||||
|
||||
m_engine.add(fun([this](const std::string &s) { m_print_handler(s); }), "print_string");
|
||||
m_engine.add(fun([this](const std::string &s) { m_print_handler(s + "\n"); }), "println_string");
|
||||
|
||||
@ -285,7 +289,8 @@ namespace chaiscript {
|
||||
std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
||||
std::vector<std::string> t_module_paths = {},
|
||||
std::vector<std::string> t_use_paths = {},
|
||||
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
|
||||
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options(),
|
||||
const bool t_no_io = false)
|
||||
: m_module_paths(ensure_minimum_path_vec(std::move(t_module_paths)))
|
||||
, m_use_paths(ensure_minimum_path_vec(std::move(t_use_paths)))
|
||||
, m_parser(std::move(parser))
|
||||
@ -320,7 +325,7 @@ namespace chaiscript {
|
||||
m_module_paths.insert(m_module_paths.begin(), dllpath + "/");
|
||||
}
|
||||
#endif
|
||||
build_eval_system(t_lib, t_opts);
|
||||
build_eval_system(t_lib, t_opts, t_no_io);
|
||||
}
|
||||
|
||||
#ifndef CHAISCRIPT_NO_DYNLOAD
|
||||
|
||||
@ -1360,14 +1360,16 @@ TEST_CASE("ChaiScript_Basic No_Stdlib option disables all standard library funct
|
||||
CHECK_THROWS(chai.eval("from_json(\"[1,2,3]\")"));
|
||||
}
|
||||
|
||||
TEST_CASE("ChaiScript_Basic No_IO option still allows print_handler registration") {
|
||||
TEST_CASE("ChaiScript_Basic No_IO option uses null handler by default") {
|
||||
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library({chaiscript::Library_Options::No_IO}),
|
||||
create_chaiscript_parser(),
|
||||
{},
|
||||
{},
|
||||
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts});
|
||||
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts},
|
||||
true);
|
||||
|
||||
// print_string and println_string should still be available via the handler mechanism
|
||||
// but the default handler is a no-op (no stdout output)
|
||||
CHECK_NOTHROW(chai.eval("print_string(\"hello\")"));
|
||||
CHECK_NOTHROW(chai.eval("println_string(\"hello\")"));
|
||||
CHECK(chai.eval<int>("5 + 3") == 8);
|
||||
@ -1439,10 +1441,17 @@ TEST_CASE("ChaiScript No_IO option via library options parameter") {
|
||||
{chaiscript::Library_Options::No_IO});
|
||||
|
||||
// print_string and println_string remain available via the handler mechanism
|
||||
// but the default handler is a no-op (no stdout output)
|
||||
CHECK_NOTHROW(chai.eval("print_string(\"hello\")"));
|
||||
CHECK_NOTHROW(chai.eval("println_string(\"hello\")"));
|
||||
CHECK(chai.eval<int>("5 + 3") == 8);
|
||||
CHECK_NOTHROW(chai.eval("var v = Vector()"));
|
||||
|
||||
// Users can override the null handler with their own
|
||||
std::string captured;
|
||||
chai.set_print_handler([&captured](const std::string &s) { captured += s; });
|
||||
chai.eval("print_string(\"redirected\")");
|
||||
CHECK(captured == "redirected");
|
||||
}
|
||||
|
||||
TEST_CASE("ChaiScript No_Prelude option via library options parameter") {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user