Remove the List.new(_) primitive that initialized a list with null elements, merging its functionality into List.filled(_,_) which now accepts both size and default value. Add validation for negative size with a clear error message, and introduce comprehensive test coverage for filled list creation including edge cases for negative size, non-integer size, and non-numeric size arguments.
Add two new list constructors to the Wren VM: `List.new(size)` creates a list of given size with null elements, and `List.filled(size, value)` creates a list with all elements initialized to a specified default value. Includes corresponding C primitives `list_newWithSize` and `list_newWithSizeDefault`, registration in `wrenInitializeCore`, and a test file verifying both constructors produce correct counts and element values. Also adds Max Ferguson to AUTHORS.
Simplify arithmetic in wrenStringFind by removing startIndex offset from loop range and using start directly as the initial index. Rename internal primitives to string_indexOf1 and string_indexOf2 for clarity. Add validateIndex helper to clamp negative start values and reject out-of-bounds indices. Update documentation to describe the new start parameter behavior. Add comprehensive test suite for indexOf with start, including negative offsets, edge cases, and error conditions.
Add a new `indexOf(_,_)` primitive that accepts a start index for searching within strings, and modify the existing `wrenStringFind` function to accept and use a start index parameter. The existing `indexOf(_)` and `contains(_)` methods now pass 0 as the start index to maintain backward compatibility. The Boyer-Moore-Horspool search algorithm is updated to offset comparisons by the start index and return the absolute position in the original string. New test cases verify correct behavior with various start index values including edge cases where the start index exceeds string length.
The `DEBUG_TRACE` macro was using `fn->bytecode` instead of `fn->code.data` to compute the instruction offset for `wrenDumpInstruction`. This caused incorrect offset values when dumping bytecode during interpreter tracing, as the bytecode pointer is stored in the `code.data` field of the function object.
- Rename wrenGetSlotListSize to wrenGetListCount and wrenGetSlotListValue to wrenGetListElement
- Change wrenGetListElement to move element directly to another slot instead of returning WrenValue
- Update all test bindings and calls to match new API signatures
Add two new C API functions to the Wren VM that allow foreign methods to query the size of a list stored in a slot and retrieve individual values from it by index. The implementation validates the slot holds a list, extracts the internal ValueBuffer, and returns the count or a captured WrenValue respectively. Corresponding test bindings (getListSize, getListValue) and Wren test cases are included to verify the new functionality.
The two-argument constructor `List.new(size, element)` was renamed to
`List.filled(size, element)` to better convey its purpose of creating a
list filled with a default value. The underlying primitive
`list_newWithSizeDefault` remains unchanged. The test file
`test/core/list/new_extra_args.wren` was updated to use the new name.
Implement two new List constructors: `List.new(size)` creates a list of given size initialized to null, and `List.new(size, default)` creates a list with all elements set to the provided default value. Add corresponding C primitives `list_newWithSize` and `list_newWithSizeDefault` in wren_core.c, register them in the core initialization, and include test coverage for both constructors. Also add Max Ferguson to AUTHORS.
Add a new primitive `string_indexOf_with_startIndex` that accepts a second integer argument to specify the starting position for the search. Modify the existing `wrenStringFind` function to accept a `startIndex` parameter, updating its Boyer-Moore-Horspool algorithm to begin scanning from the given offset. Update the `string_contains` primitive to pass `0` as the start index. Register the new overloaded method as `indexOf(_,_)` on the string class and add test cases covering boundary conditions and out-of-range start indices.
The debug dump macro in runInterpreter was computing instruction offsets
by subtracting fn->bytecode from ip, but the bytecode field was renamed
to code.data during a prior refactoring. This caused incorrect offset
values in debug output when Wren_DEBUG_DUMP_OBJECTS is enabled.
Add three new static primitives to the Num class: `highest` returning `DBL_MAX`, `lowest` returning `-DBL_MAX`, and `epsilon` returning `DBL_EPSILON`. Include `<float.h>` header for the floating-point limit constants. Register the new primitives in `wrenInitializeCore` alongside the existing `pi` static property.
Add MapEntry class to expose key-value pairs during map iteration, and make Map extend Sequence so maps can be directly iterated with `for` loops. Rename the internal `iterate_` primitive to `iterate` and update error messages for invalid map iterators.
The raw XOR of double's 32-bit halves causes small integers to have zero low bits,
mapping all small integer keys to entry zero in the hash map. This introduces a
bit-mixing function inspired by Java's HashMap that sloshes high bits downward,
eliminating the pathological collision pattern. The map_numeric benchmark improves
by ~18%, and a contrived benchmark with keys up to 1000 becomes 52x faster.
Previously, when inserting a key that already existed in the map but was
located after a tombstone in the probe sequence, the insertion would stop
at the first tombstone and add the key there, resulting in duplicate
entries for the same key. This fix introduces a `findEntry` function that
tracks the first encountered tombstone during probing and reuses it for
insertion only when the key is not found elsewhere in the sequence.
Previously, wrenImportModule unconditionally called vm->config.loadModuleFn,
causing a crash when the host did not set that function pointer. Now the
call is guarded by a NULL check, so hosts without a module loader can still
load built-in optional modules like "random" or "meta".
Add executeInput() method to REPL that lexes input, determines if it's a statement or expression based on the first token, and evaluates accordingly using Meta.eval for statements or the new Meta.compileExpression for expressions. Extend Meta.compile_ foreign method with isExpression and printErrors parameters, update wrenCompile signature to support expression compilation mode, and add newline handling after equals in variable definitions.
Add a new public API function `wrenAbortFiber()` that allows foreign methods to abort the currently executing fiber with a custom runtime error object. The function validates the API slot, then sets the fiber's error field to the value in the specified slot. The interpreter loop is updated to check for a non-null fiber error after calling a foreign method, triggering a runtime error if set. New test files (error.c, error.h, error.wren) demonstrate usage via a static Error.runtimeError foreign method, verifying that the error is propagated through Fiber.try() and that the fiber's isDone and error properties are correctly set. Xcode project updated to include the new error.c source file.
Rename the `WrenValue` type to `WrenHandle` in the public C header, update all
function signatures (`wrenMakeCallHandle`, `wrenCall`, `wrenReleaseHandle`),
and rename the documentation page from "Slots and Values" to "Slots and Handles"
with corresponding link updates throughout the embedding guide and module source
files.
Implement two new C API functions to retrieve list metadata and values from Wren slots: wrenGetSlotListSize returns the element count of a list in a slot, and wrenGetSlotListValue returns a captured WrenValue pointer for a specific index. Add corresponding foreign method bindings in test/api/slots.c and test cases in test/api/slots.wren that verify size retrieval and indexed value access on a three-element list. Also add Damien Radtke to AUTHORS.
Add missing loop to count underscore parameters in subscript operator signatures
starting with '['. Previously only counted parameters in parenthesized signatures,
causing incorrect arity for methods like `[_,_]` and `[_,_]=(_)`. Also adds
validation assertions for null and empty signatures, and extends test coverage
with unary, binary, subscript, and subscript-set operator call handles.
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.
Replace direct fprintf(stderr) calls in wrenDebugPrintStackTrace with invocations of the host-provided errorFn callback, passing WREN_ERROR_RUNTIME for the error message and WREN_ERROR_STACK_TRACE for each stack frame. Introduce the WrenErrorType enum in wren.h with WREN_ERROR_COMPILE, WREN_ERROR_RUNTIME, and WREN_ERROR_STACK_TRACE values, update the WrenErrorFn typedef to accept a type parameter, and modify reportError in cli/vm.c to switch on the error type for formatted output. Adjust wrenDebugPrintStackTrace signature to take WrenVM* instead of ObjFiber* to access the config, and update all call sites accordingly.
- Add `WrenErrorFn` typedef in wren.h accepting module, line, and message parameters
- Include `errorFn` slot in `WrenConfiguration` struct with documentation comment
- Initialize `errorFn` to NULL in `wrenInitConfiguration()` in wren_vm.c
- Replace direct `fprintf(stderr, ...)` in wren_compiler.c with call to `parser->vm->config.errorFn()`
- Add guard in wren_compiler.c to skip error reporting when `errorFn` is NULL
- Implement `reportError()` in cli/vm.c that writes formatted errors to stderr
- Wire `reportError` into config during `initVM()` in cli/vm.c
Store the line number of first use in implicitly declared variables as a numeric value, then synthesize a token at that line when reporting the error, ensuring bounded error message length even for pathologically long variable names.
Add tracking of static and instance method names during class compilation to detect and report duplicate method definitions. Introduce `hasMethod` helper function and `staticMethods`/`instanceMethods` buffers in the `ClassCompiler` struct, along with a `name` field for identification. Include a new test case `duplicate_methods.wren` verifying error generation for duplicate instance and static methods, while allowing same-named methods across static/instance boundaries.
Replace the generic `wrenIntBufferFind` function with a specialized `hasMethod` helper that performs exact method symbol matching in the compiler. This change removes the generic `BufferFind` macro from the buffer utility system and introduces a focused implementation in `wren_compiler.c` that directly compares method symbols using `memcmp`. The error message for duplicate methods is also simplified to exclude the module name. Additionally, a new test file `duplicate_methods.wren` is added to verify error handling for duplicate instance and static method definitions.
Replace multiple fprintf calls in lexError and compileError with a unified printError function that formats the entire error message into a fixed-size buffer before outputting it as a single fprintf call. This centralizes error formatting logic and prepares for future integration of a host-provided error callback by eliminating scattered fprintf invocations.
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.
When wrenNewVM is called with a NULL config pointer, the previous code
dereferenced it without checking, causing a crash. This commit adds a
NULL guard: if config is NULL, the VM is allocated using the default
reallocator and initialized with default configuration via
wrenInitConfiguration. The gray array allocation and nextGC field now
correctly reference vm->config instead of the potentially NULL config
parameter.
Fix the misspelled function name `wrenUpwrapClosure` to the correct `wrenUnwrapClosure` in wren_debug.c, wren_value.c, wren_value.h, and wren_vm.c. Also fix a minor grammar typo in wren_vm.c comment changing 'arguments' to 'argument'.
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.
The block() function duplicated the curly-block parsing logic that statement() already handled for single-expression bodies. By removing block() and replacing its single call site in loopBody() with statement(), the compiler eliminates unnecessary indirection and simplifies the control flow parsing. The statement() comment is updated to clarify that it excludes variable binding statements like "var" and "class" which are not allowed in if-branch positions.
Add `*(count)` method to both String and List classes in wren_core.wren, enabling eager repetition of string characters or list elements. The operator validates that count is a non-negative integer, aborting with a clear error message otherwise. For strings, concatenates the original string count times; for lists, builds a new list by adding all elements count times. Includes comprehensive test cases for normal, zero, and edge-case inputs, plus error tests for negative, non-integer, and non-numeric counts. Also refactors existing list plus tests to use inline expressions and adds a plus_not_iterable error test.
- Add missing `:::wren` code block marker before the `removeAt` example in the list documentation to ensure proper syntax highlighting.
- Simplify the `parens` array increment in `readString` by combining the assignment and post-increment into a single expression.
Introduce a `methods` symbol table and `name` field to `ClassCompiler` struct to track method signatures during compilation. When a method is defined, check for existing entries in the table and emit a compile error if a duplicate is found, preventing silent method overrides. Initialize the class name string before class definition processing to support error messages referencing the class name.