Simplify the VM by ensuring all called objects are closures, removing the need for runtime checks between bare functions and closures. This eliminates the `IS_FN`/`IS_CLOSURE` branching in `validateFn`, `checkArity`, `bindMethod`, and `wrenNewFiber`, and changes `CallFrame.fn` from `Obj*` to `ObjClosure*`. The compiler now emits `CODE_CLOSURE` for all function declarations, even those without upvalues, trading a small allocation cost at declaration time for faster and more uniform invocation. Benchmarks show performance is neutral to slightly improved across all tested workloads.
Consolidate repetitive `vm->fiber->error = wrenStringFormat(...)` and `return false` patterns into two new macros defined in wren_primitive.h, reducing code duplication and improving consistency in error reporting for fiber operations, number parsing, and type validation helpers.
Add a `verb` string parameter to the `runFiber` helper function so that
`Fiber.try()` produces consistent error messages like "Cannot try a finished
fiber." instead of the previous generic fallback. Update all call sites
(`fiber_call`, `fiber_call1`, `fiber_transfer`, `fiber_transfer1`) to pass
the appropriate verb string, and add a new test case `try_error.wren`
verifying the error message for trying an aborted fiber.
Remove CODE_LOAD_MODULE and CODE_IMPORT_VARIABLE opcodes, replacing them with calls to System.importModule(_) and System.getModuleVariable(_,_) primitives. This simplifies the interpreter loop, improves performance by reducing bytecode dispatch, and prepares for moving module loading logic into Wren source code for embedder flexibility.
Refactor the C API for invoking Wren methods from C code. Remove the old
wrenGetMethod and wrenCallVarArgs functions that used a type-string-based
argument marshalling system. Introduce a new slot-based approach where
callers first call wrenEnsureSlots to reserve space, then use wrenSetSlot___
functions to place the receiver and arguments on the stack, and finally call
wrenCall with a handle created by wrenMakeCallHandle. Results are retrieved
via wrenGetSlot___. This change simplifies the VM internals, eliminates
varargs parsing overhead, and yields a 185% speed improvement in the call
benchmark. Update all internal modules (scheduler, io, timer) and test files
to use the new API. Also fix fiber suspension to clear the API stack pointer
and adjust the interpreter to store the final fiber result at stack[0] for
C API access.
Add lexer support for `TOKEN_INTERPOLATION` to split string literals at interpolation points, introduce `MAX_INTERPOLATION_NESTING` limit of 8, and compile interpolated strings by emitting calls to `String.interpolate_()`. Optimize list and map literal construction with new `addCore_` primitives to reduce stack churn. Update `String`, `List`, and `Map` `toString` methods in core library to use interpolation syntax, and migrate all benchmark and test files from explicit concatenation to interpolated strings.
Add a new `System.gc()` primitive that calls `wrenCollectGarbage` to allow
scripts to trigger garbage collection. Document the method in the core
System page. Remove the test-only `Api.gc()` foreign method and update
the foreign_class test to use `System.gc()` instead.
Update three inline comments in wren_core.c (defineClass docstring and wrenInitializeCore bootstrap note) and one in wren_core.h (module-level description) to consistently refer to the "core module" instead of "core library", aligning terminology with the actual module-based architecture.
The sourcePath field on ObjModule was redundant since it always matched the module name except for the main script. This change removes the parameter from wrenInterpret, wrenInterpretInModule, and wrenNewModule, and replaces all references to module->sourcePath with module->name in error reporting and debug output.
The PrimitiveResult enum (PRIM_VALUE/PRIM_FIBER) is removed and replaced with a simple bool return value where `true` indicates a normal value return and `false` signals a fiber switch or runtime error. This simplifies the interpreter dispatch in `runInterpreter` by converting the switch on enum cases into a single if/else branch, and reduces branching in the common value-returning path. All primitive function signatures, the `RETURN_VAL`/`RETURN_ERROR` macros, and the `runFiber` helper are updated accordingly.
Replace the special "call" primitive result type (PRIM_CALL) with a new METHOD_FN_CALL method type that marks function call methods. Add checkArity helper to validate argument count before invoking function closures, and update the interpreter dispatch to handle the new method type instead of relying on the removed PRIM_CALL result.
Replace the `ObjFiber* fiber` parameter in `DEF_PRIMITIVE` macro and `Primitive` typedef with direct access to `vm->fiber` inside each primitive implementation. Update all call sites in `fiber_current`, `fiber_try`, `fiber_yield`, `fiber_yield1`, `meta_eval`, and the interpreter dispatch to use `vm->fiber` or a local `current` variable instead of the passed-in `fiber` argument.
Implements two new methods on the Num class: isInfinity checks if a number is positive or negative infinity using isinf(), and isInteger checks if a number has no fractional component, returning false for NaN and infinity. Includes C primitives, documentation, and test files.
Replace separate PRIM_ERROR and PRIM_RUN_FIBER return codes with a unified PRIM_FIBER in PrimitiveResult enum, updating all primitive implementations and the interpreter switch case to use the new combined value.
Refactor runtime error handling to store errors directly in the fiber's error field instead of on the stack, enabling any object (except null) as an error value. Add Fiber.transferError(_) primitive for transferring errors between fibers. Update validation helpers to accept Value arguments directly and modify RETURN_ERROR macro to set fiber error. Adjust GC marking to use wrenMarkValue for the error field. Add tests for aborting with non-string errors and null abort behavior.
Add a `WrenWriteFn` callback to `WrenConfiguration` that allows host applications to control how text from `System.print()` and related functions is displayed. When set, the VM invokes this callback instead of directly calling `printf`. If the callback is NULL, printed text is silently discarded. The CLI's `initVM()` now registers a simple `write` function that prints to stdout, while the core `system_writeString` primitive checks for the callback before outputting. This change also refactors `wrenInitConfiguration` to set `defaultReallocate` as the default reallocation function and consolidates configuration fields into a single `WrenConfiguration` struct stored directly in `WrenVM`, removing separate member fields for reallocate, bindForeignMethod, bindForeignClass, loadModule, minNextGC, and heapScalePercent.
- Delete wren_io.c, wren_io.h, and io.wren source files
- Remove multi-arity print overloads and IO.read/IO.time methods
- Add System class with print, printAll, write, writeAll methods to core.wren
- Update all documentation examples and README to use System.print instead of IO.print
Replace the manually embedded C string constants for builtin Wren modules with
a new build system that automatically generates `.wren.inc` header files from
`.wren` source files. The old `script/generate_builtins.py` is removed and
replaced by `script/wren_to_c_string.py`, which produces standalone include
files with a `PREAMBLE` containing the module name and source path. The Makefile
gains pattern rules to rebuild these `.wren.inc` files whenever the
corresponding `.wren` source changes, and the `builtin` phony target is removed
since the generation is now automatic. The `wren.mk` wildcard lists are updated
to include the new `.wren.inc` files as dependencies. The `timer.c` and
`wren_core.c` source files now `#include` their respective `.wren.inc` headers
instead of defining the string literals inline, and the `timer.wren` trailing
newline is removed.
The string class is now documented as an immutable byte array rather than a
sequence of Unicode code points. The .count getter is removed from the string
primitive and replaced by .codePoints.count on the code point sequence
interface, making the O(n) cost explicit. Updated the doc site and test files
accordingly.
Extract codePointAt() logic into a dedicated StringCodePointSequence class that wraps a string and implements the Sequence interface, enabling iteration over code points. Add a `codePoints` getter to String that returns a new instance of this sequence. Refactor the underlying C implementation of `codePointAt_` to decode UTF-8 into actual code point integers (returning raw bytes for invalid sequences) and rename the primitive to use trailing underscore convention. Update all related tests to reflect the new behavior where mid-sequence byte indices return the raw byte string instead of an empty string, and add new test files for the code point sequence iteration.
Remove the public `byteAt(_)` method from String and its ByteSequence wrapper, renaming it to the private `byteAt_(_)` to eliminate redundancy with `.bytes[_]`. Add a native `byteCount_` primitive on String and expose it as `count` on StringByteSequence, enabling O(1) byte length queries. Update all test files to use the new `.bytes` subscript API and add a dedicated `count.wren` test for the new functionality.
Add wrenNewStringFromRange function to wren_value.c that decodes UTF-8 code points from source string and re-encodes them into result, enabling correct range subscripts on multi-byte characters. Rename wrenUtf8NumBytes to wrenUtf8EncodeNumBytes and make wrenUtf8Encode return written byte count for use in range construction. Add wrenUtf8DecodeNumBytes utility to skip continuation bytes when iterating by byte index. Remove all skip directives from test files and add UTF-8 specific test cases verifying correct slicing across code point boundaries.
The compiler no longer auto-generates a default `new()` constructor for classes. All classes must now explicitly define `construct new() {}` to be instantiable. This change removes the `createDefaultConstructor` function from the compiler, eliminates the `return_this` primitive used by Object's default initializer, and adds explicit constructors to all test and example classes. Core metaclasses (Bool, Class, Null, Num, Object, Range, Sequence) now correctly reject `new()` calls with runtime errors.
Remove the run() method from fibers and introduce transfer() for non-stack-based fiber switching, along with suspend() to pause the interpreter and return control to the host application. Update Timer.sleep() to use runNextScheduled_() instead of Fiber.yield(), and add Timer.schedule() for creating independently scheduled fibers. Refactor the core fiber runtime to support transfer semantics, including proper error handling for aborted fibers and self-transfer edge cases. Fix a missing quote in test.py's runtime error validation string.
Rename the constructor initializer signature prefix from "this " to "init " in
wren_common.h's MAX_METHOD_SIGNATURE calculation, wren_compiler.c's
signatureToString and createDefaultConstructor functions, and wren_core.c's
default Object constructor primitive registration. This changes the syntactic
keyword used to define initializer methods in the Wren language.
Refactor wrenFindVariable to accept an explicit ObjModule* parameter instead of
implicitly using the main module. Promote the internal getCoreModule helper to
a public wrenGetCoreModule function declared in wren_vm.h. Update all call sites
in wren_core.c and wren_meta.c to pass the core module when looking up core
variables, and replace inline getCoreModule calls in wren_vm.c with the new
public function. Remove the NULL-module fallback documentation from
wrenDeclareVariable and wrenDefineVariable.
Add TOKEN_CONSTRUCT as a new reserved word in the Wren compiler lexer and parser, and update the grammar rule table so that 'construct' triggers a constructor signature instead of 'this'. Modify all built-in class definitions in core.wren, wren_core.c, benchmark files, and test fixtures to use 'construct new(...)' and 'construct named(...)' syntax. Update documentation in classes.markdown and syntax.markdown to reflect the new keyword, and remove the deprecated test files for 'new' and infix class expressions.
Replace all uses of the `new` reserved word with explicit `this new()` constructor definitions and `ClassName.new()` instantiation calls in builtin/core.wren. Update all documentation files (classes.markdown, fiber.markdown, fn.markdown, sequence.markdown, error-handling.markdown, expressions.markdown, fibers.markdown, functions.markdown) to reflect the new constructor syntax, removing `new` keyword examples and replacing them with `ClassName.new()` patterns and `this new()` definitions.
Extract the common pattern of returning the receiver argument into a single
DEF_PRIMITIVE(return_this) function, and refactor fiber_instantiate,
fn_instantiate, and the default Object constructor to use it instead of
inline RETURN_VAL(args[0]) calls. Also fix trailing whitespace on isEmpty
and class_toString lines in the core library source string.
Extract class name retrieval from object_toString into a new class_toString primitive, registered on the Class metaclass. This removes the IS_CLASS branch from object_toString, which now only handles instances and falls back to "<object>". The change ensures Class objects return their own name directly via toString rather than relying on the generic object handler.
The safeToString_ mechanism introduced in 40897f33 used per-fiber maps and lists to detect recursive toString calls, but leaked memory when runtime errors occurred before cleanup. This reverts to direct toString implementations for List and Map, removing the recursive detection logic and updating tests to mark self-referencing containers as TODO.
Add `String.safeToString_` static method that tracks objects currently being
converted to string per fiber, returning "..." when recursion is detected.
Wrap List.toString and Map.toString with this guard to handle self-referential
and mutually recursive structures without crashing.
Introduce a new static method `Object.same(obj1, obj2)` that exposes the VM's
built-in equality semantics (`wrenValuesEqual`) directly, bypassing any
user-defined `==` overrides. This required creating a dedicated metaclass for
Object (subclass of Class) to host the static method without polluting every
class with a `same` method. The implementation wires up a new `Object metaclass`
in the core initialization sequence, adjusts the class hierarchy setup order,
and adds comprehensive tests covering value types, identity comparison, and
verification that `Object.same` ignores custom `==` operators.
The static helper `callFunction` in wren_core.c was renamed to `callFn` to prevent symbol conflicts with the public `wrenCallFunction` API, ensuring unique linkage and clearer separation between internal and external call paths.
The `.list` method on Sequence was renamed to `.toList` to better reflect its
purpose of converting a sequence into a List object. This change updates the
method definition in `builtin/core.wren` and `src/vm/wren_core.c`, along with
all test files that called `.list` on sequences, maps, ranges, and custom
sequence implementations. The test file `test/core/sequence/list.wren` was also
renamed to `test/core/sequence/to_list.wren` to match the new method name.
Move the definitions of Bool, Fiber, Fn, Null, and Num classes from hardcoded C code in wren_core.c into the core.wren library source, allowing them to be parsed and created during library initialization. Simplify defineClass to always use wrenNewSingleClass, remove redundant root pushing in wrenNewClass, and adjust the class creation in the interpreter to use a Value instead of ObjClass*.
Consolidate the refactoring branch changes from patriciomacadden's fork into the main repository, incorporating the updated class definition logic in wren_core.c that replaces the separate defineSingleClass function with a unified defineClass function capable of handling both raw and subclassed class creation.
Refactor Sequence.map and Sequence.where to return lazy MapSequence and WhereSequence wrappers instead of eagerly building a List. Add new MapSequence and WhereSequence classes that delegate iteration and apply the transformation or predicate on-the-fly. Update documentation to reflect lazy semantics and the need to call .list to materialize results. Adjust all existing tests to call .list on map/where results. Add new tests in test/core/sequence/ verifying lazy behavior with infinite Fibonacci iterators.
Add a new `each` method to the Sequence class in the Wren programming language,
allowing iteration over sequence elements by passing each element to a provided
function. This replaces the previous pattern of using `map` with `Fiber.yield`
in examples, providing a more direct and idiomatic way to perform side effects
per element. The implementation includes a core library method in `core.wren`,
a C source string in `wren_core.c`, documentation in the Sequence markdown file,
and three test cases covering normal iteration, empty sequences, and non-function
argument error handling.