Address review: split Options into Options and Library_Options enums

Separate system-level options (No_Load_Modules, Load_Modules, No_External_Scripts,
External_Scripts) from library-level options (No_Stdlib, No_IO, No_Prelude, No_JSON)
into two distinct enum types. Add Library_Options as a parameter to the ChaiScript
constructor. Update tests to demonstrate both ChaiScript_Basic (explicit Std_Lib::library
call) and ChaiScript (library options via constructor parameter) usage.

Requested by @lefticus in PR #642 review.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
leftibot 2026-04-10 19:26:52 -06:00
parent c3aa9ee6d5
commit a25778c323
4 changed files with 80 additions and 40 deletions

View File

@ -824,8 +824,9 @@ namespace chaiscript {
public:
ChaiScript(std::vector<std::string> t_modulepaths = {},
std::vector<std::string> t_usepaths = {},
std::vector<Options> t_opts = chaiscript::default_options())
: ChaiScript_Basic(chaiscript::Std_Lib::library(t_opts),
std::vector<Options> t_opts = chaiscript::default_options(),
std::vector<Library_Options> t_lib_opts = {})
: ChaiScript_Basic(chaiscript::Std_Lib::library(t_lib_opts),
std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer_Default>>(),
std::move(t_modulepaths),
std::move(t_usepaths),

View File

@ -208,7 +208,10 @@ namespace chaiscript {
No_Load_Modules,
Load_Modules,
No_External_Scripts,
External_Scripts,
External_Scripts
};
enum class Library_Options {
No_Stdlib,
No_IO,
No_Prelude,

View File

@ -38,16 +38,16 @@
namespace chaiscript {
class Std_Lib {
public:
[[nodiscard]] static ModulePtr library(const std::vector<Options> &t_opts = {}) {
if (std::find(t_opts.begin(), t_opts.end(), Options::No_Stdlib) != t_opts.end()) {
[[nodiscard]] static ModulePtr library(const std::vector<Library_Options> &t_opts = {}) {
if (std::find(t_opts.begin(), t_opts.end(), Library_Options::No_Stdlib) != t_opts.end()) {
return std::make_shared<Module>();
}
auto lib = std::make_shared<Module>();
const bool no_io = std::find(t_opts.begin(), t_opts.end(), Options::No_IO) != t_opts.end();
const bool no_prelude = std::find(t_opts.begin(), t_opts.end(), Options::No_Prelude) != t_opts.end();
const bool no_json = std::find(t_opts.begin(), t_opts.end(), Options::No_JSON) != t_opts.end();
const bool no_io = std::find(t_opts.begin(), t_opts.end(), Library_Options::No_IO) != t_opts.end();
const bool no_prelude = std::find(t_opts.begin(), t_opts.end(), Library_Options::No_Prelude) != t_opts.end();
const bool no_json = std::find(t_opts.begin(), t_opts.end(), Library_Options::No_JSON) != t_opts.end();
bootstrap::Bootstrap::bootstrap(*lib, no_io);

View File

@ -1285,89 +1285,125 @@ TEST_CASE("Test if non copyable/movable types can be registered") {
}
// Tests for issue #146: configuration to bypass registering built-in functions
// Tests through ChaiScript_Basic (library options passed explicitly to Std_Lib::library)
TEST_CASE("No_Stdlib option disables all standard library functions") {
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library({chaiscript::Options::No_Stdlib}),
TEST_CASE("ChaiScript_Basic No_Stdlib option disables all standard library functions") {
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library({chaiscript::Library_Options::No_Stdlib}),
create_chaiscript_parser(),
{},
{},
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts});
// Core types should still work (they are part of bootstrap)
CHECK_NOTHROW(chai.eval("var x = 5"));
// print should not exist
CHECK_THROWS(chai.eval("print(\"hello\")"));
// Vector should not exist
CHECK_THROWS(chai.eval("var v = Vector()"));
// String methods from prelude should not exist
CHECK_THROWS(chai.eval("\"hello\".trim()"));
// JSON should not exist
CHECK_THROWS(chai.eval("from_json(\"[1,2,3]\")"));
}
TEST_CASE("No_IO option disables print functions") {
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library({chaiscript::Options::No_IO}),
TEST_CASE("ChaiScript_Basic No_IO option disables print functions") {
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});
// print_string and println_string should not exist
CHECK_THROWS(chai.eval("print_string(\"hello\")"));
CHECK_THROWS(chai.eval("println_string(\"hello\")"));
// Other functionality should still work
CHECK(chai.eval<int>("5 + 3") == 8);
CHECK_NOTHROW(chai.eval("var v = Vector()"));
}
TEST_CASE("No_Prelude option disables prelude functions") {
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library({chaiscript::Options::No_Prelude}),
TEST_CASE("ChaiScript_Basic No_Prelude option disables prelude functions") {
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library({chaiscript::Library_Options::No_Prelude}),
create_chaiscript_parser(),
{},
{},
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts});
// print (from prelude) should not exist
CHECK_THROWS(chai.eval("print(\"hello\")"));
// But print_string (from bootstrap) should still work
CHECK_NOTHROW(chai.eval("print_string(\"hello\")"));
// Prelude utility functions should not exist
CHECK_THROWS(chai.eval("filter([1,2,3], fun(x) { x > 1 })"));
// Core arithmetic should still work
CHECK(chai.eval<int>("5 + 3") == 8);
}
TEST_CASE("No_JSON option disables JSON support") {
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library({chaiscript::Options::No_JSON}),
TEST_CASE("ChaiScript_Basic No_JSON option disables JSON support") {
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library({chaiscript::Library_Options::No_JSON}),
create_chaiscript_parser(),
{},
{},
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts});
// JSON functions should not exist
CHECK_THROWS(chai.eval("from_json(\"[1,2,3]\")"));
// Other functionality should still work
CHECK(chai.eval<int>("5 + 3") == 8);
CHECK_NOTHROW(chai.eval("print(\"hello\")"));
}
TEST_CASE("Default library has all functions") {
TEST_CASE("ChaiScript_Basic default library has all functions") {
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library(),
create_chaiscript_parser(),
{},
{},
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts});
// Everything should work with default options
CHECK_NOTHROW(chai.eval("print(\"hello\")"));
CHECK_NOTHROW(chai.eval("print_string(\"hello\")"));
CHECK_NOTHROW(chai.eval("var v = Vector()"));
CHECK(chai.eval<int>("5 + 3") == 8);
}
// Tests through ChaiScript (library options passed as constructor parameter)
TEST_CASE("ChaiScript No_Stdlib option via library options parameter") {
chaiscript::ChaiScript chai({},
{},
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts},
{chaiscript::Library_Options::No_Stdlib});
CHECK_NOTHROW(chai.eval("var x = 5"));
CHECK_THROWS(chai.eval("print(\"hello\")"));
CHECK_THROWS(chai.eval("var v = Vector()"));
CHECK_THROWS(chai.eval("from_json(\"[1,2,3]\")"));
}
TEST_CASE("ChaiScript No_IO option via library options parameter") {
chaiscript::ChaiScript chai({},
{},
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts},
{chaiscript::Library_Options::No_IO});
CHECK_THROWS(chai.eval("print_string(\"hello\")"));
CHECK_THROWS(chai.eval("println_string(\"hello\")"));
CHECK(chai.eval<int>("5 + 3") == 8);
CHECK_NOTHROW(chai.eval("var v = Vector()"));
}
TEST_CASE("ChaiScript No_Prelude option via library options parameter") {
chaiscript::ChaiScript chai({},
{},
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts},
{chaiscript::Library_Options::No_Prelude});
CHECK_THROWS(chai.eval("print(\"hello\")"));
CHECK_NOTHROW(chai.eval("print_string(\"hello\")"));
CHECK_THROWS(chai.eval("filter([1,2,3], fun(x) { x > 1 })"));
CHECK(chai.eval<int>("5 + 3") == 8);
}
TEST_CASE("ChaiScript No_JSON option via library options parameter") {
chaiscript::ChaiScript chai({},
{},
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts},
{chaiscript::Library_Options::No_JSON});
CHECK_THROWS(chai.eval("from_json(\"[1,2,3]\")"));
CHECK(chai.eval<int>("5 + 3") == 8);
CHECK_NOTHROW(chai.eval("print(\"hello\")"));
}
TEST_CASE("ChaiScript default has all functions") {
chaiscript::ChaiScript chai;
CHECK_NOTHROW(chai.eval("print(\"hello\")"));
CHECK_NOTHROW(chai.eval("print_string(\"hello\")"));
CHECK_NOTHROW(chai.eval("var v = Vector()"));