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.
The defineSingleClass helper was only used for the initial Object and Class
definitions during core initialization. By inlining its logic into defineClass
with a check for vm->classClass being NULL, we eliminate a redundant function
while preserving the same behavior for those two special cases.
Introduce MapSequence and WhereSequence subclasses of Sequence that apply transformations lazily during iteration instead of building intermediate lists. Update Sequence.map and Sequence.where to return these deferred wrappers, modify all existing tests to call .list on results, and add new infinite-sequence tests verifying lazy behavior on Fibonacci iterators.
Add a new `each` method to the Sequence class that iterates over elements
calling a provided function for each, serving as a side-effect-only
alternative to `map` when the resulting list is not needed. This is
particularly important for the upcoming change where `map` will return a
new sequence instead of mutating in place, as demonstrated by updating
the README and index examples to use `each` with Fiber.yield. Includes
documentation in the Sequence API reference and three new test cases
covering normal iteration, empty sequences, and non-function argument
error handling.
Rewrite all() and any() to store and return the predicate's result directly, matching && and || semantics. Update documentation to describe the new behavior. Move tests from test/core/list/ to test/core/sequence/ and add cases verifying that the first falsey/truthy value is returned.
The return value of finishBlock() was inverted so that it now returns true
for expression bodies (value left on stack) and false for statement bodies
(no value left). All internal return points and the call site in finishBody()
were updated accordingly to maintain correct code generation behavior.
Implements a new `list` method on the Sequence class that iterates over all elements and returns them as a freshly created List object. Includes documentation with usage example and a test case using a custom TestSequence class to verify correct behavior.
Add `byteAt(index)`, `codePointAt(index)`, and `bytes` sequence to String,
enabling direct byte-level manipulation of UTF-8 encoded strings. Introduce
`\x` hex escape sequence in string literals for specifying raw byte values.
Refactor Unicode escape parsing into a generic `readHexEscape` function
supporting variable digit counts. Implement `wrenUtf8Decode` utility for
decoding UTF-8 sequences from byte buffers. Add comprehensive tests for
`byteAt` including boundary conditions and error cases.
Implements a new `list` method on the Sequence class that iterates over all elements and collects them into a new List instance. Includes documentation in the core sequence docs and a test case verifying correct behavior with a custom sequence implementation.
Implement the `String.fromCodePoint(_)` primitive that creates a string from a Unicode code point, with validation for integer range 0–0x10ffff. Extract inline UTF-8 encoding logic from `readUnicodeEscape` in the compiler into new `wrenUtf8NumBytes` and `wrenUtf8Encode` utility functions in `wren_utils`, and add `wrenStringFromCodePoint` helper in `wren_value`. Update documentation for core classes to add "Methods" and "Static Methods" section headers, and include `String.fromCodePoint` docs with example. Add a test file `from_code_point.wren` covering various code points.
The READ_BYTE and READ_SHORT macros are defined locally within functions
in wren_debug.c and wren_vm.c but were not being undefined after use,
causing potential redefinition warnings or errors when these macros
conflict with other definitions in the same translation unit. This
change adds #undef directives at the end of dumpInstruction in
wren_debug.c and runInterpreter in wren_vm.c to properly clean up
the macro definitions.
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.
Change bindMethod return type from void to Value to propagate error string when a foreign method's C function pointer is NULL. The call site in runInterpreter now checks for a string error and triggers a runtime error, preventing silent failures on missing foreign bindings.
Add three test cases: foreign method after static declaration, foreign method with a body, and unknown foreign method that expects the new runtime error message.
Add foreign static eval(source) method to Meta class in meta.wren and implement wrenBindMetaForeignMethod in wren_meta.c to handle its binding. Change the implicit module name from "main" to "core" in wren_vm.c and restrict foreign method lookup to only the "core" module, enabling Meta foreign methods to be resolved alongside IO methods. Relax the IO foreign method binder to return NULL instead of asserting for non-IO classes, allowing fallback to other library binders.
Add wren_meta.c and wren_meta.h file references to the Xcode project.pbxproj, including the wren_meta.c source in the PBXBuildFile section and both files in the PBXFileReference section. Also reformat indentation in metaEval function body and add a TODO comment for argument type checking.
Introduce a new Meta built-in class exposing a static eval(_) method for runtime code interpretation, guarded by the WREN_USE_LIB_META compile-time flag (default on). Include the meta.wren source, C implementation files, header, VM integration in wrenNewVM, test runner update to include the meta test directory, and an initial test for evaluating code that modifies an existing scoped variable.
Simplify the allocation API by dropping the unused `oldSize` argument from `WrenReallocateFn` typedef, its documentation, and all internal callers. Update `wrenReallocate` in `wren_vm.c` to pass only `newSize`, remove the `defaultReallocate` wrapper in favor of direct `realloc`, and adjust `generate_baseline` signature in benchmark script to match.
The wren_meta.h header included <stdio.h>, "wren_value.h", and "wren_vm.h"
which were not required for its declarations. These headers are already
included transitively through "wren.h" and "wren_common.h", making the
explicit includes redundant. Removing them reduces unnecessary
dependencies and potential circular inclusion issues.
Implement the `WrenBindForeignMethodFn` callback type and `bindForeignMethodFn` configuration field to allow host applications to resolve foreign method declarations at class definition time. Refactor the IO library to use this new binding mechanism instead of the previous `wrenDefineStaticMethod` approach, adding `foreign` keyword support to the lexer and compiler. Introduce `freeCompiler` helper for cleanup, store module names in `ObjModule`, and update the VM to call the binder when processing `CODE_METHOD_INSTANCE` and `CODE_METHOD_STATIC` opcodes for foreign methods.
Implement a new `count(f)` method on the Sequence class that iterates over elements and returns the number of items for which the given predicate function evaluates to true. Update the core library source, sequence documentation, and add three new test files covering normal usage, non-boolean return values, and non-function argument error handling. Also fix minor terminology in list docs (items → elements).
Rename the internal concept from "package" to "module directory" when loading
module.wren files from subdirectories. Update variable names (packageModule
to moduleDir, packageModulePath to moduleDirPath) and adjust early return
logic to free modulePath before checking contents. Add test for loading
module from a directory and remove old package module test.
Extract the module-to-filepath construction logic from readModule into a reusable wrenFilePath function. Modify readModule to first attempt loading the module with a ".wren" extension; if that fails, treat the module name as a package directory and try loading "module.wren" from within it. Add test fixtures for the new package module resolution behavior.
Rename the `Upvalue` struct and all related type references to `ObjUpvalue` across
wren_value.c, wren_value.h, and wren_vm.c. This aligns with the existing pattern
where Obj-derived types (like ObjModule, ObjClosure) use the Obj prefix even when
the type is not first-class in the language. The change touches function signatures,
variable declarations, pointer arithmetic in memory tracking, and the struct
definition itself.
Remove the `WrenVM* vm` parameter from `wrenValueBufferInit`, `wrenByteBufferInit`,
`wrenIntBufferInit`, `wrenStringBufferInit`, `wrenSymbolTableInit`,
`wrenMethodBufferInit`, `wrenStringFind`, and `wrenDebugPrintStackTrace`
functions across the compiler, core, debug, utils, value, and VM modules.
Update all call sites and macro definitions to match the simplified signatures,
eliminating dead parameters that were never used within the function bodies.
Replace the hand-rolled capacity/count/elements fields in ObjList with a
ValueBuffer struct, and update Compiler to use a ValueBuffer for its
constant pool instead of an ObjList. This eliminates the separate
ensureListCapacity and wrenListAdd functions, centralizing buffer growth
logic in wrenValueBufferWrite. Adjust all list primitives (add, clear,
count, iterate, iteratorValue) and the GC marking path to operate on the
embedded ValueBuffer. Add wrenMarkBuffer helper for marking buffer
contents during sweep.
Add CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES to both Debug and Release Xcode build configurations. Fix the resulting warnings by adding explicit casts in wren_compiler.c (readUnicodeEscape, emit, emitShort, emitByteArg) and wren_vm.c (READ_SHORT macro, makeCallStub bytecode assignment) to prevent unintended truncation or sign extension during implicit integer conversions.
The original REPL loop had an if-else structure where the else branch (handling fgets failure) contained a return statement, making the code after the if-else block unreachable. This commit restructures the loop by inverting the condition: when fgets fails, the loop breaks instead of returning, allowing the subsequent wrenFreeVM call to execute. Additionally, enables CLANG_WARN_UNREACHABLE_CODE in both Debug and Release Xcode build configurations to catch similar issues in the future.
Extract file path construction into `wrenFilePath` helper and modify `readModule` to first attempt loading the module as a `.wren` file. If that fails, treat the module name as a package directory and try to load `module.wren` from within it. Add test files `module_package/module.wren` and `package_module.wren` to verify the new package resolution behavior.
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
Add acos, asin, atan, atan2, tan methods to Num class and expose Num.pi constant with value π. Include corresponding C primitives in wren_core.c and test files for each new method.
Convert `validateIndexValue` and `validateIndex` return types to `uint32_t` with `UINT32_MAX` sentinel, update `wrenNewList`, `wrenListInsert`, `wrenListRemoveAt` signatures, and remove the TODO comment about type unification with `ObjMap`.
Add early return check in wrenFreeVM that validates the VM pointer is not NULL
and that the methodNames count is non-zero, preventing a crash when the VM
has already been freed or was never properly initialized.
Add a generic `contains(element)` method to the `Sequence` class that iterates over elements using the existing `for` loop protocol, removing the duplicate implementation from `List`. Include comprehensive test files for both `List.contains` and `Range.contains` covering ordered, backwards, and exclusive ranges. Also fix the `generate_builtins.py` script to write to the correct `src/vm/` directory path and add a `float:left` CSS rule to the main content area in the documentation stylesheet.
The contains method is promoted from List to the Sequence base class, making it available to all sequence types (including Range). Tests are added for both List.contains and Range.contains, covering ordered, backwards, and exclusive ranges.
Cache the FNV-1a hash code in the ObjString struct at creation time, replacing the
on-the-fly sampling hash in hashObject() and enabling constant-time string equality
checks. Refactor string allocation into allocateString() and hashString() helpers,
remove the old wrenNewUninitializedString() declaration, and add a CONST_STRING
macro. Disable the unimplemented subscript range operator with a runtime error and
skip the related UTF-8 tests. Add a string_equals benchmark to measure the speedup.
Swap the parameter order of `List.insert()` from `(item, index)` to `(index, item)`,
matching the convention used by most standard libraries. Update the C implementation
in `wren_core.c`, all documentation examples, and every test file to reflect the new
signature. Also restructure MSVC project files to match the new `src/cli/` and
`src/vm/` directory layout, add Visual Studio cache files to `.gitignore`, and fix
a trailing whitespace issue in `class_supertype`.
The `List.insert` method signature is changed from `insert(item, index)` to `insert(index, item)`, aligning with standard practice in most languages. All documentation, core implementation, and test files are updated to reflect the new parameter order. The `validateIndex` call now reads the index from slot 1 instead of slot 2, and the value is read from slot 2.
Move runFile() and VM configuration logic from main.c into new vm.c module,
exposing createVM() and runFile() functions. This decouples CLI script
execution from the REPL and main entry point, enabling reuse of the same
VM setup and file-running code for API tests.
Extract the static `readFile`, `readModule`, and `setRootDirectory` functions from main.c into a new io module, replacing the fixed-size `rootDirectory` array with a heap-allocated pointer and adding the corresponding header with public declarations.
The dumpObject function in wren_debug.c was incorrectly printing "[fn %p]" for
OBJ_RANGE objects instead of the correct "[range %p]" label. This fix ensures
that range objects are properly identified during debug output.
The two validation functions in wren_core.c were calling wrenStringFormat with a format
string containing a "$" placeholder but were not passing the argName argument, causing
the placeholder to remain unsubstituted in error messages. This commit adds the missing
argName parameter to both calls.
Additionally, the CONST_STRING macro in wren_value.h was changed from using strlen(text)
to sizeof(text) - 1, which allows the compiler to compute the string length at compile
time rather than at runtime, improving performance for string literal creation.
The previous implementation used `sizeof(text) - 1` to determine string length at compile time, which required the argument to be a bare string literal. The new approach uses `strlen(text)` instead, which allows most compilers to evaluate the string length at compile time when a string literal is passed, while also supporting non-literal string arguments. This change trades compile-time guarantee for broader compatibility and compiler optimization potential.
Replace ad-hoc string construction using wrenNewString, wrenStringConcat, and sprintf with the new wrenStringFormat helper. This centralizes string formatting logic, reduces code duplication, and eliminates manual length calculations in wren_compiler.c, wren_core.c, wren_value.c, and wren_vm.c. Also introduces CONST_STRING macro for compile-time string literals and changes wrenNewUninitializedString return type from Value to ObjString* for consistency.
The previous signature `insert(element, index)` was counter-intuitive and inconsistent with every major language's list API. This commit swaps the parameters to `insert(index, element)`, matching the convention used by Ruby, JavaScript, C++, Lua, C#, Java, and Python. All documentation, C implementation, and test files are updated to reflect the new order.
Adds a new `atan(_)` primitive method to the Num class that wraps the C
`atan2` function, allowing callers to compute the arc tangent of the
number divided by a given argument `x` while using the signs of both
numbers to determine the correct quadrant of the result. The
implementation registers the primitive `num_atan2` in the core VM
initialization and documents the new method in the core library
reference.
Add a generic `contains` implementation on the `Sequence` base class, removing the duplicate method from `List`. This allows all sequence types (including Range) to use the method without per-class redefinition. Include new test files for `List.contains` and `Range.contains` covering ordered, backwards, and exclusive ranges.
Separate Wren VM library sources from CLI tool sources by moving them into
src/vm/ and src/cli/ subdirectories respectively. Update the Makefile to use
separate wildcard patterns for each directory, generate distinct object file
paths under build/vm/ and build/cli/, and adjust include paths to src/include.
Also update the Xcode project file to reference the new file locations.
Implement a new `supertype` property on Class objects that returns the superclass of a given class. The primitive `class_supertype` checks if the class has a superclass (returning null for Object) and returns the superclass object. Includes documentation in the class reference and a test file verifying behavior for explicit superclasses, implicit Object inheritance, and Object's null supertype.
Remove explicit NULL and zero assignments for vm fields (methodHandles, foreignCallSlot, foreignCallNumArgs, bytesAllocated, compiler, fiber, first, numTempRoots, modules) and consolidate them into a single memset(vm, 0, sizeof(WrenVM)) call, simplifying the initialization logic.
Moves the debug trace instruction printing logic from inline DISPATCH() macro into a dedicated DEBUG_TRACE_INSTRUCTIONS macro with proper WREN_DEBUG_TRACE_INSTRUCTIONS guard, and adjusts RUNTIME_ERROR macro to use Allman brace style for consistency with surrounding code.
Add the missing `tan` method to the Num class, implementing the tangent
trigonometric function. This fills the gap between the existing `sin` and
`cos` methods, providing a complete set of basic trigonometric operations.
- Register `num_tan` primitive in the VM core initialization
- Implement `DEF_PRIMITIVE(num_tan)` using C's `tan()` math function
- Add documentation entry for `tan` in the core library reference
Implement a new `count(f)` method on the Sequence class that accepts a predicate function and returns the number of elements for which the predicate evaluates to true. The implementation iterates over the sequence, calling `f.call(element)` on each element and incrementing a counter when the result is truthy.
Also update the documentation for both Sequence and List classes: add full documentation for the new `count(predicate)` method on Sequence, and change the terminology in List docs from "items" to "elements" for consistency. Add three test files covering the basic predicate behavior, non-boolean return values from the predicate, and the error case when a non-function argument is passed.
Update the num_toString primitive in wren_core.c to return "infinity" and "-infinity"
instead of the platform-dependent "inf" and "-inf" for positive and negative infinity
values. This ensures consistent string output across different C compilers and
platforms that may format infinity differently. Update the corresponding test
expectations in test/number/divide.wren to match the new output format.
Remove the Xcode-generated file header comment with copyright notice
and author attribution from wren_debug.h. Also correct the include guard
macro from `wren_wren_debug_h` to `wren_debug_h` to match the actual
file path and naming convention used by other headers in the project.
- Fix misleading comment in `new_` function in `wren_compiler.c` to accurately describe angle brackets instead of leading space
- Fix typo "Uknown" to "Unknown" in assertion message in `wrenCall` function in `wren_vm.c`
- Remove trailing whitespace in `wren_vm.c`
In the variable undefined check within wrenCompile, the error() call was
receiving an ObjString struct instead of its underlying char* buffer,
causing a type mismatch. Changed the argument to access the .buffer field
of the variable name string.
The comment previously stated that a leading space prevents direct calls,
but the actual mechanism uses angle brackets in the method name "<instantiate>"
to make it inaccessible from user code.
Change the `capacity` and `count` fields in `ObjList` from `int` to `uint32_t` to match the
types used in `ObjMap`, ensuring consistency between the two structures. Update all loop
variables and index calculations in `wren_core.c` and `wren_value.c` that interact with
these fields to use `uint32_t` instead of `int`, and remove the now-unnecessary negative
bounds check in `list_iterate` since unsigned types cannot be negative.
- Delete TODO about nullary constructor handling in constructorSignature
- Remove TODO and commented-out code for making fibers iterable in wrenInitializeCore
- Eliminate TODO questioning elimination of OBJ_CLASS enum in favor of classObj pointers
- Drop TODO about moving WrenVM struct definition and using array for class fields
Previously, IO.read would return an empty string when stdin reached EOF because it always called wrenReturnString with the buffer, even when fgets returned NULL. Now it returns null by only calling wrenReturnString when fgets succeeds, and adds a test case verifying that IO.read returns null on EOF.
Refactor the internal Map API to replace the low-level `wrenMapFind` function
(which returned a raw entry index or UINT32_MAX) with a higher-level
`wrenMapGet` that directly returns the stored Value or UNDEFINED_VAL.
This change simplifies all call sites by eliminating manual index-based entry
lookups and direct access to the internal `entries` array. The old
`wrenMapFind` is made static and renamed to `findEntry`, returning a pointer
to the MapEntry struct instead of an index, which is used internally by
`wrenMapGet` and `wrenMapRemoveKey`.
Additionally, fix a bug in `loadModule` where a new module was always created
before checking if the module already existed; now the early return for
already-loaded modules correctly skips module creation and variable copying.
- Change Fiber.yield() to exit interpreter when no parent fiber exists instead of raising runtime error
- Add Fiber.current primitive to return the currently executing fiber object
- Update interpreter loop to stop execution when PRIM_RUN_FIBER receives null value
- Modify test expectations to reflect new yielding behavior from main fiber
Previously, IO.read would return an empty string when reading from stdin reached EOF. This changes the behavior to return null when fgets returns NULL, indicating end-of-file. The fix removes the unconditional wrenReturnString call and only returns the buffer when data was actually read. A new test case verifies that IO.read returns null on EOF.
Add five new numeric methods to the Wren core library: deg (convert radians to degrees), rad (convert degrees to radians), fraction (extract fractional part), sign (return -1, 0, or 1), and truncate (discard fractional part). Register all new primitives in wrenInitializeCore and include corresponding test files for fraction, sign, and truncate operations.
Implement a `count` method on the `Sequence` class that iterates over all elements and returns the total number. The method uses a simple for-loop to increment a counter for each element, providing a generic way to determine sequence length without requiring a separate length property. Includes a test sequence that yields values 1 through 10 to verify the count returns 10.
The `num_div` primitive performed integer division on two int32 values, but this
functionality is already covered by the existing `num_divide` primitive which
handles floating-point division. Removing this duplicate method eliminates
confusion and reduces code maintenance burden.
The previous implementation cast the number to int32_t, which incorrectly
truncated values outside the int32_t range and produced wrong results for
large doubles. The new implementation uses the standard C `modf` function
to correctly truncate the fractional part while preserving the full
double precision of the integer portion.
Replace the num_decimal primitive with num_fraction, changing the implementation from a simple subtraction of integer part to using the standard C modf function for more robust fractional part extraction. Update the method registration in wrenInitializeCore to bind the new name and function.
Implement DEF_PRIMITIVE(num_div) that casts both operands to int32_t
and performs integer division, returning the truncated quotient.
Register the new primitive as "div(_)" on the num class in
wrenInitializeCore, placed alphabetically between "deg" and "floor".
Remove the dedicated `setMarkedFlag`, `markString`, `markFn`, and `markClass` helper functions, replacing their calls with the new generic `wrenMarkObj` entry point. This eliminates duplicated marking logic and ensures all object types go through a single marking path that handles cycle detection and memory tracking consistently.
Implement the num_sign primitive that checks if the numeric argument is >= 0.0
and returns 1.0 for non-negative values or -1.0 for negative values. Register
the new primitive on the Number class in wrenInitializeCore.
The num_decimal primitive was incorrectly returning the integer part of a number
instead of the fractional part, while num_truncate was returning the fractional
part instead of truncating to the integer portion. This commit corrects both
functions by exchanging their logic bodies.