From a25778c32387fe49d6838bcc11610f1b5f93d997 Mon Sep 17 00:00:00 2001 From: leftibot Date: Fri, 10 Apr 2026 19:26:52 -0600 Subject: [PATCH] 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) --- include/chaiscript/chaiscript.hpp | 5 +- include/chaiscript/chaiscript_defines.hpp | 5 +- include/chaiscript/chaiscript_stdlib.hpp | 10 +-- unittests/compiled_tests.cpp | 100 +++++++++++++++------- 4 files changed, 80 insertions(+), 40 deletions(-) diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index 647ed5b6..1be2f0b4 100644 --- a/include/chaiscript/chaiscript.hpp +++ b/include/chaiscript/chaiscript.hpp @@ -824,8 +824,9 @@ namespace chaiscript { public: ChaiScript(std::vector t_modulepaths = {}, std::vector t_usepaths = {}, - std::vector t_opts = chaiscript::default_options()) - : ChaiScript_Basic(chaiscript::Std_Lib::library(t_opts), + std::vector t_opts = chaiscript::default_options(), + std::vector t_lib_opts = {}) + : ChaiScript_Basic(chaiscript::Std_Lib::library(t_lib_opts), std::make_unique>(), std::move(t_modulepaths), std::move(t_usepaths), diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index fb07cf28..f50510f0 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -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, diff --git a/include/chaiscript/chaiscript_stdlib.hpp b/include/chaiscript/chaiscript_stdlib.hpp index bcdc3165..a499ddfc 100644 --- a/include/chaiscript/chaiscript_stdlib.hpp +++ b/include/chaiscript/chaiscript_stdlib.hpp @@ -38,16 +38,16 @@ namespace chaiscript { class Std_Lib { public: - [[nodiscard]] static ModulePtr library(const std::vector &t_opts = {}) { - if (std::find(t_opts.begin(), t_opts.end(), Options::No_Stdlib) != t_opts.end()) { + [[nodiscard]] static ModulePtr library(const std::vector &t_opts = {}) { + if (std::find(t_opts.begin(), t_opts.end(), Library_Options::No_Stdlib) != t_opts.end()) { return std::make_shared(); } auto lib = std::make_shared(); - 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); diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 8cda152c..cb443200 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -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("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("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("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("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("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("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("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()"));