* Fix#690: Apply clang-format consistently with CI
Applied clang-format-19 to all source files to enforce consistent
formatting according to the existing .clang-format configuration.
Added auto-clang-format GitHub Actions workflow (from
cpp-best-practices/cmake_template) that runs on pull requests to
automatically format and commit any style violations going forward.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a customizable file reader callback to ChaiScript_Basic, following
the same pattern as set_print_handler. When set, the callback is invoked
instead of the default filesystem read, enabling use cases like encrypted
files, in-memory virtual filesystems, or platform-specific file access
(e.g., Android assets). The callback is settable from both C++ and
ChaiScript.
Co-authored-by: leftibot <leftibot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix#552: Support nested namespaces via dotted names
Namespaces can now be nested using dotted name syntax, both from C++
(register_namespace(gen, "constants.si")) and from script
(namespace("constants.si")). Parent namespaces are auto-registered when
absent, and child namespaces are automatically nested into their parent
on import. This allows clean hierarchical organization like
constants.si.mu_B instead of flat names like constants_si.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Address review: use :: instead of . as nested namespace separator
Switch from dotted names (e.g. "constants.si") to C++-style ::
separator (e.g. "constants::si") for nested namespace declarations,
both in the C++ API (register_namespace) and in script (namespace()).
The original implementation used . because namespace members are
accessed via dot notation at runtime (constants.si.mu_B), making the
declaration separator match the access syntax. However, :: is more
consistent with C++ namespace conventions and aligns with ChaiScript's
existing use of :: for method (def Class::method) and attribute
(attr Class::attr) declarations.
Member access in scripts remains dot-based (constants.si.mu_B) since
that is ChaiScript's member access operator.
Requested by @lefticus in PR #675 review.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Address review: C++-style namespace scoping and block declarations
Add :: scope resolution operator for member access (ns::func works
like ns.func). Add block namespace declarations:
namespace x::y { def func() { ... } }
Functions and variables declared inside a namespace block are added
as members of the namespace, accessible via :: or dot notation.
Namespaces can be reopened to add more members, matching C++ behavior.
Requested by @lefticus in PR #675 review.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Address review: extract shared make_proxy_function from Def_AST_Node
Namespace_Block_AST_Node was duplicating the entire proxy function
creation logic from Def_AST_Node::eval_internal. Extract a static
make_proxy_function helper so both nodes share the same code path,
eliminating fragile duplication that would drift if Def handling changes.
Requested by @lefticus in PR #675 review.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Address review: reject non-declaration statements inside namespace blocks
Only def, var, auto, and global declarations are now allowed inside
namespace { } blocks. Arbitrary expressions, assignments, and function
calls are rejected with an eval_error. Added compiled tests verifying
that expressions, function calls, and assignments are rejected.
Requested by @lefticus in PR #675 review.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Address review: remove -j parameter from unix builds
Ninja handles parallelism intelligently on its own; the explicit -j flag
was causing memory pressure on sanitizer builds. Windows (non-Ninja)
build retains -j.
Requested by @lefticus in PR #675 review.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: leftibot <leftibot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The operator functions in chaiscript::bootstrap::operators (equal, not_equal,
assign, etc.) hardcoded Module& as their first parameter, preventing
chaiscript::utility::add_class for enum types from working when passed a
ChaiScript& reference directly. Added a second template parameter ModuleType
to all operator functions so they accept any type that provides an add()
method, matching the already-templatized add_class functions in utility.hpp.
Co-authored-by: leftibot <leftibot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When all typed catch blocks failed to match a thrown exception's type,
handle_exception() would silently discard the exception and return a
default-constructed Boxed_Value instead of propagating it. This meant
code like `try { throw(42) } catch(string e) { }` would swallow the
int exception rather than letting it propagate to an outer handler.
The fix adds an explicit re-throw when no catch block matches, and
restructures eval_internal() with a nested try/catch to ensure the
finally block still executes before the unhandled exception propagates.
Co-authored-by: leftibot <leftibot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix#571: Add per-instance IO redirection via set_print_handler/set_println_handler
The print_string and println_string functions were previously registered as static
functions writing directly to stdout, making it impossible to redirect ChaiScript
output to custom destinations (e.g., GUI windows, loggers, or buffers). This moves
their registration from Bootstrap::bootstrap() to ChaiScript_Basic::build_eval_system()
as lambdas that dispatch through configurable std::function handlers, allowing each
ChaiScript instance to independently redirect its output via set_print_handler() and
set_println_handler().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Address review: add IO redirection section to cheatsheet
Documents set_print_handler() and set_println_handler() with usage
examples for GUI embedding and output capture.
Requested by @lefticus in PR #657 review.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Address review: define println in terms of print, expose set_print_handler to ChaiScript
Remove separate println_handler — println_string now dispatches through the
single print handler with a newline appended. Only set_print_handler is
needed to redirect all output. The set_print_handler function is also
registered in the ChaiScript engine, so scripts can capture and redirect
their own output.
Requested by @lefticus in PR #657 review.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* 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>
---------
Co-authored-by: leftibot <leftibot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix#146: Add configuration options to selectively disable built-in functions
Add new Options enum values (No_Stdlib, No_IO, No_Prelude, No_JSON) that
allow users to control which parts of the standard library are registered.
Std_Lib::library() now accepts an options vector, and the ChaiScript
convenience class forwards its options to the library builder. This enables
use cases where only custom functions should be exposed to script users.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* 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>
* Add cheatsheet documentation for Options and Library_Options
Documents the two-enum configuration system: Options (engine-level:
load_module, use, eval_file) and Library_Options (stdlib-level:
No_Stdlib, No_IO, No_Prelude, No_JSON), with usage examples for
both ChaiScript and ChaiScript_Basic constructors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: leftibot <leftibot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Several STL bootstrap functions unconditionally instantiated copy-dependent
operations (copy constructor, assignment, push_back/push_front by const ref,
insert_at, and resize with fill value), causing compilation failures when
registering containers of move-only types like std::unique_ptr. Guard these
operations with if constexpr(std::is_copy_constructible_v<value_type>) so they
are only compiled when the element type supports copying.
Co-authored-by: leftibot <leftibot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Jason Turner <jason@emptycrate.com>
The function_less_than comparator used by std::stable_sort violated the
strict-weak ordering requirement in two ways: (1) functions with different
arities but matching overlapping parameters were treated as equivalent,
breaking transitivity, and (2) the dynamic_object_type_name comparison
silently fell through when one side had an empty type name. Fixed by
ordering by arity when overlapping parameters match, and imposing a total
order on dynamic object type names.
Co-authored-by: leftibot <leftibot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Jason Turner <jason@emptycrate.com>
* Fix#405: push_back() on script-created vector has no effect with vector_conversion
When both vector_type<T> and vector_conversion<T> are registered, the
dispatch scoring treats all parameter mismatches equally. This causes
the C++ push_back (for the converted type) to be selected over the
built-in one when both have the same number of type differences. The
converted function operates on a temporary copy of the vector, silently
discarding the mutation. The fix deprioritizes overloads that require
type conversion on the first parameter (the object/receiver), ensuring
functions matching the receiver type exactly are always tried first.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Address review: remove issue references from comments, add round-trip conversion tests
Requested by @lefticus in PR #663 review.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: leftibot <leftibot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The forward declarations of AST_Node_Trace and eval_error at the top of
chaiscript_common.hpp introduced these types as incomplete before the standard
library headers were fully processed. On clang/libc++ in C++20 mode, this
caused compilation errors because std::vector<AST_Node_Trace> was instantiated
while the type was still incomplete. Since the full definitions of both types
appear later in the same file (and nothing between the forward declarations
and the definitions references them), these forward declarations are unnecessary
and removing them prevents the incomplete type issue.
Co-authored-by: leftibot <leftibot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix#256: Expose get_function_objects() and get_scripting_objects() in public API
The ChaiScript_Basic public API only exposed get_locals() for inspecting
runtime state from C++, requiring users to work around this via
chai.eval("get_functions()") to access function objects. Added
get_function_objects() and get_scripting_objects() as public methods on
ChaiScript_Basic, delegating to the existing Dispatch_Engine methods,
matching the pattern already used by get_locals().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Address review: add tests for get_scripting_objects()
Requested by @lefticus in PR #640 review.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: leftibot <leftibot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add both a compiled C++ test (with registered type_conversion) and a
pure ChaiScript test (with dynamic objects and custom == operator) to
verify that switch case comparisons properly manage object lifetimes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
I initially tried to use the existing .clang-format file,
but it does not match the code style (at least with clang-format 11)
and the formatting is not consistent across files.
Therefore, I decided to rewrite the .clang-format with some personal
preferences.
Used command
find . -iname "*.hpp" -o -iname "*.cpp" | xargs clang-format -i -style=file
Implemented unit test which is validating whether a lambda from
Chaiscript could return a boolean value without throwing any exception.
The same test case is checking whether lambda with boolean return value
could be called peacefully from Chaiscript.