- Inserted a TODO comment before the toString native binding in the
function class initialization to remind about implementing an arity
getter for Wren functions.
Implements a new `Fiber.abort()` static method that allows a fiber to terminate with a custom error message string. The method validates that the argument is a string, then returns a PRIM_ERROR to abort the current fiber. Includes three test cases: basic abort with error message retrieval via `fiber.try`, aborting the main fiber with a runtime error, and type checking that non-string arguments produce an appropriate error message.
Consolidate the two separate conditional branches for empty range on zero-length list into a single expression using ternary on range->isInclusive, removing the TODO comment and reducing code duplication.
Migrate fiber stack management from an integer `stackSize` counter to a direct `Value* stackTop` pointer, eliminating repeated `stack[stackSize - 1]` calculations. Update all stack slot accesses, iteration loops, and the `CallFrame::stackStart` field to use pointer arithmetic, simplifying the code and reducing index arithmetic overhead.
Move the class pointer from ObjInstance into the base Obj struct and remove the separate metaclass field from ObjClass, allowing all heap objects to directly reference their class. Add an inlined wrenGetClassInline function in the header to eliminate function call overhead during method dispatch, yielding 10-43% performance gains across benchmarks.
Implement a new `Fiber.try()` method that allows a calling fiber to catch runtime errors from a called fiber. When a fiber is invoked with `try()` instead of `call()`, any runtime error that occurs in the called fiber is returned as a string to the caller rather than terminating the program with a stack trace. The `callerIsTrying` flag on `ObjFiber` tracks this state, and the `runtimeError` function now checks this flag to redirect the error to the caller's stack. Also adds `Fiber.error` getter to retrieve the error string from a failed fiber, changes `Fiber.isDone` to return `true` for errored fibers, and migrates the fiber error field from a raw `char*` to an `ObjString*` for proper memory management. Includes comprehensive test cases for try behavior, re-entry prevention, and error state queries.
Add new `fiber.call` method that remembers the calling fiber for symmetric transfer, while `fiber.run` now performs tail-call style switching without preserving the caller. Introduce re-entrancy guards preventing a fiber from being called multiple times, update all test fixtures to use the new API, and add comprehensive test coverage for call semantics including direct/indirect re-entrancy, value passing, and finished fiber errors.
- Replace silent null return with explicit string type check in string_plus native
- Remove outdated TODO comments about string coercion from both num_plus and string_plus
- Add test for basic string concatenation ("a" + "b")
- Add test verifying runtime error when concatenating string with non-string ("a" + 123)
Enforce syntactic requirement for parentheses in operator method signatures (e.g., `+(other)` instead of `+ other`) and setter definitions (e.g., `bar=(value)` instead of `bar = value`). Update the compiler's `infixSignature`, `mixedSignature`, and `namedSignature` functions to consume explicit `(` and `)` tokens around parameter names. Migrate all built-in core library operator definitions and test fixtures to the new parenthesized syntax.
Add `list_instantiate` native to create empty lists, bind it to List's metaclass for `new` support, and remove the related TODO. Also change three `inline` functions in `wren_value.h` to `static inline` to prevent linker errors. Include a new test `test/list/new.wren` verifying `new List` yields an empty list that supports `add`.
Replace the nested `SymbolTable` struct (containing a `StringBuffer names` field) with a direct `typedef StringBuffer SymbolTable`, updating all internal accesses from `symbols->names.data` to `symbols->data` and `symbols->names.count` to `symbols->count`. Rename `vm->methods` to `vm->methodNames` and `vm->globalSymbols` to `vm->globalNames` across the codebase, including debug printing, compiler symbol resolution, core initialization, and VM interpreter error messages. Remove the stale TODO comment about error codes in `wren.h` and adjust the `instantiate` method name to include a leading space to prevent direct user invocation.
Replace the static `Value globals[MAX_GLOBALS]` array in WrenVM with a dynamic `ValueBuffer` that grows on demand, removing the 256-global limit. Introduce `wrenDefineGlobal()` helper that adds a named global to the symbol table and stores its value in the buffer, returning -2 when the 65536 limit is reached. Update all global access sites (compiler emit, runtime interpreter, GC marking, debug disassembly, core class definition) to use the buffer's data pointer and short (16-bit) opcode arguments instead of byte-sized ones. Add a regression test `many_globals.wren` that defines 8200 globals to verify the new capacity.
Add `addAll(other)` method to the List class in both the Wren core library source and its embedded C string representation. The method iterates over the given `other` sequence, appends each element to the list using the existing `add()` method, and returns the original `other` argument to match the documented return behavior. Include a new test file `test/list/add_all.wren` covering basic appending, empty iterable, range input, and return value verification.
Refactor fiber creation from a static `Fiber.create` method to a constructor-based `new Fiber` pattern. This introduces a `fiber_instantiate` native that returns the Fiber class itself, allowing `new Fiber` to invoke `fiber_new` for validation and creation. A shared `validateFn` helper is added to centralize function argument checking, replacing inline validation in both `fiber_new` and `fn_new`. All test files are updated to use the new syntax, and the old `create_wrong_arg_type` test is replaced with `new_wrong_arg_type`.
Add type checking to the `fn_new` native function to ensure the argument
passed to `Fn.new` is either a function or closure. Previously, passing
an invalid type like an integer would silently succeed. Now it returns
a clear runtime error message: "Argument must be a function."
Also remove two stale TODO comments about newline handling in the
compiler that were no longer relevant to current parsing logic.
Refactor the 'new' operator compilation to emit a method call to 'instantiate' on the class instead of using a dedicated bytecode instruction. This allows built-in types like Fn to override instantiation behavior, enabling `new Fn { ... }` to return the block argument directly. Remove the CODE_NEW opcode from the VM, compiler, and debug printer, and add native methods `class_instantiate`, `fn_instantiate`, `fn_new`, and `object_instantiate` to handle the new dispatch. Update test files to reflect the renamed `Function` class to `Fn`.
Implement num_bitwiseAnd and num_bitwiseOr native methods that cast operands to uint32_t before applying bitwise operations, matching the existing bitwiseNot pattern. Register both operators on the number class and add test files covering basic cases, max u32 boundary, overflow behavior, and non-numeric operand error handling.
Extract the common `map` and `where` methods from `List` into a new `Sequence` base class, making `List is Sequence` and `Range is Sequence`. Remove duplicate native method registrations for Range in wren_core.c and add new test files for Range map/where operations.
Add TOKEN_QUESTION token type and implement conditional() parsing function in wren_compiler.c to support the ternary conditional operator (condition ? then : else). Register fn_toString native in wren_core.c to return "<fn>" string for function objects. Include comprehensive test suite covering precedence, short-circuit evaluation, and error cases for missing tokens.
Implement a `where` method on the List class that takes a function `f` and returns a new list containing only elements for which `f.call(element)` returns true. The implementation is added both in the builtin core.wren source and embedded in the C library source string in wren_core.c. Also includes a new test file `test/list/where.wren` verifying filtering with matching and non-matching predicates.
Implement a `where` method on the List class that takes a predicate function and returns a new list containing only elements for which the predicate returns true. The implementation iterates over the list, calls the predicate on each element, and collects matching elements into a new list. Includes test cases verifying filtering with both matching and non-matching predicates.
Implement a `map` method on the List class that applies a given function `f` to each element, returning a new list with the transformed values. Includes a test case verifying incrementing each element by 1.
Add special case in list_subscript native to return a new empty list when
the source list is empty and the requested range is [0..-1] (inclusive) or
[0...0] (exclusive). This enables using list[0..-1] as a universal copy
idiom that works even for empty lists. Update the List.+ operator to use
this idiom instead of manual iteration. Add test cases for both range
forms on empty lists.
The previous implementation of List.+ used conditional checks (`this.count > 0`, `that.count > 0`) before iterating, which caused the loop body to be skipped entirely for empty lists. This commit removes those guards, allowing the for-in loops to run unconditionally — the Wren VM's iterate/iterateValue protocol already handles the empty case correctly at the native level. Additionally, the `list_iterate` native in `wren_core.c` now returns `false` immediately when the list count is zero and the iterator argument is null, preventing an out-of-bounds index of 0 from being returned for empty lists. The test file `test/list/concat.wren` is renamed to `test/list/plus.wren` and extended with a check that the original list `a` remains unmodified after concatenation. A new test in `test/list/iterate.wren` verifies that iterating over an empty list returns `false`.
Add `+` method to List class in core.wren that creates a new list by concatenating elements from both operands. Supports concatenation with Range objects and handles empty lists on either side. Includes comprehensive test cases in test/list/concat.wren covering list-list, list-range, and empty list combinations.
In the compiler, when a bare name is encountered inside a class definition and it does not resolve to a local variable or global, emit an implicit `this.` load before the call, enabling getter, setter, and method calls without explicit receiver. Update all benchmark, builtin, and test files to remove redundant `this.` qualifiers, and add comprehensive test suites for implicit receiver behavior across instance, inherited, static, nested, and shadowing scenarios.
Add `numParams` field to `ObjFn` and `Compiler` structs to track expected parameter count. Refactor `parameterList` to return count and store it in compiler. Modify `endCompiler` to pass `numParams` to `wrenNewFunction`. Replace single `fn_call` native with 17 arity-specific `fn_call0` through `fn_call16` natives that validate argument count against `fn->numParams` via `callFunction` helper, returning error on missing args. Remove stale TODO comment in VM interpreter. Add test files `call_extra_arguments.wren` and `call_missing_arguments.wren`.
Migrate the clock timing functionality from the OS class to the IO class across all benchmark scripts and the core library. Remove the os_clock native function and its associated OS class definition from wren_core.c, while adding a new ioClock native in wren_io.c that uses the same clock()/CLOCKS_PER_SEC logic. Update all benchmark files (binary_trees, fib, for, method_call) to reference IO.clock instead of OS.clock for both start time and elapsed time calculations.
Replace monolithic corelib.wren with per-class builtin/*.wren files and generate_builtins.py script. Move IO class definition and its native writeString_ method from wren_core.c to new wren_io.c, adding wrenGetArgumentString and wrenDefineStaticMethod to the public API. Update Makefile target from corelib to builtin and remove generate_corelib.py.
Extend the list subscript operator to accept Range arguments in addition to plain numbers. When a Range is provided, the operator returns a new list containing the elements within that range, supporting inclusive (..) and exclusive (...) bounds, negative indices that count from the end, and automatic reversal for backwards ranges. Added validation functions for integer values and range bounds, with dedicated error messages for non-integer range endpoints and out-of-bounds conditions. Updated the test suite with comprehensive range subscript tests and removed the old test that only checked for non-numeric subscripts.
Store the class name string in `ObjClass` during compilation and class creation, and expose it through a new `class_name` native method. Also update `object_toString` to return the class name for class instances and "instance of <name>" for regular instances.
The for-in loop in Wren already increments the loop variable automatically, so the explicit `i = i + 1` inside the loop body was causing every other element to be skipped when building the string representation of a List. This fix removes the unnecessary increment from both the corelib.wren source and the embedded string in wren_core.c.
Replace silent RETURN_NULL for non-numeric right operands with explicit runtime error via validateNum in four comparison primitives (num_lt, num_gt, num_lte, num_gte). Also remove redundant IS_NUM check in num_mod. Add four new test files verifying runtime error messages for each comparison operator when given a boolean operand.
Add isInclusive boolean to ObjRange struct to distinguish between inclusive (..) and exclusive (...) ranges. Update wrenNewRange signature to accept isInclusive parameter. Implement correct iteration logic for both ascending and descending ranges, handling empty exclusive ranges and floating-point iteration. Add type validation for range RHS operands. Update min/max/to properties to return raw endpoint values instead of adjusted ones. Add comprehensive test coverage for inclusive/exclusive ranges, negative ranges, empty ranges, floating-point iteration, isInclusive property, toString, and type error cases.
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
Add a new `isDone` native method to the Fiber class that returns true when the fiber has no remaining frames. Replace TODO comments with proper runtime error handling in `fiber_run`, `fiber_run1`, `fiber_yield`, and `fiber_yield1` to prevent running finished fibers or yielding from the main fiber. Include test cases verifying the new property and error conditions.
In the compiler, when a `return` token is followed by a newline or right brace, emit CODE_NULL instead of parsing an expression. This enables bare `return` statements to implicitly return null. Also removes a stale TODO comment about setter parameters and fixes a typo in a comment in wren_core.c. Adds three test cases: one for explicit return in a function, one for bare return before a brace, and one for bare return before a newline.
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
Implement five new Num methods (ceil, cos, sin, sqrt, isNan) in wren_core.c and register them on the Num class. Add corresponding test files for ceil, floor, is_nan, and sqrt. Extend divide.wren with division-by-zero edge cases (inf, -inf, nan). Remove stale TODO comments from minus, multiply, and plus tests.
Implement the `floor` native method on the `Num` class in `wren_core.c`, which delegates to C's `floor()` function to round a number down to the nearest integer value. Register the new method in `wrenInitializeCore` alongside the existing `abs` method.
The previous buffer size of 21 bytes was insufficient to hold the longest possible
double representation formatted with "%.14g", which can reach 24 bytes including
the null terminator. Updated the buffer to 24 bytes and extracted the numeric
value into a local variable for clarity.
Rename the IO.write method to IO.print, which now prints without a trailing newline, and add a new IO.print method that appends a newline after output. Update all benchmark, example, and test files to use IO.print instead of IO.write. Additionally, implement Unicode escape sequence parsing in the compiler's string tokenizer, supporting \uXXXX and \u{...} syntax with proper UTF-8 encoding for code points up to U+10FFFF.
Replace the fixed-size MAX_SYMBOLS array with a dynamically growing StringBuffer for symbol names, update all instruction encodings to use 16-bit operands for constants and method symbols, and refactor method binding to use a dynamic MethodBuffer per class. Remove the constant deduplication logic in addConstant and the commented-out struct fields in initCompiler.
Remove the deprecated validateIndexOld function and migrate all callers to the new validateIndex that reports runtime errors. Add validateString helper for string argument checking. Introduce comprehensive runtime error tests for list and string subscript operations, removeAt, and contains methods, replacing old silent null returns with proper error halting.
Replace the old validateIndex function with validateNum and validateInt helpers that produce descriptive runtime error messages. Add new test files covering invalid index types, out-of-bounds indices, and iterator validation for list insert, iterate, and iteratorValue methods. Rename existing number operator error tests to use consistent "must be a number" phrasing.