Extract the inline character processing logic from the REPL's main loop into a dedicated `handleChar()` method that returns a boolean to indicate whether the loop should exit. Add `_allowAnsi` flag and corresponding getter/setters for cursor and line to support a simpler fallback REPL when ANSI escape sequences are unavailable.
Add tab-completion support to the interactive REPL by introducing a new `Meta.getModuleVariables` foreign method that returns all top-level variable names from a given module. The REPL's `run()` method now handles the tab key to append completions, and the `refreshLine` method accepts a boolean parameter to control whether completion hints are shown. Also fix the Ctrl-D exit logic (inverted condition) and remove the unused `EscapeBracket` class.
Implement cursor movement (ctrl-b left, ctrl-f right), line clearing (ctrl-k kill after cursor, ctrl-u clear entire line, ctrl-l clear screen), and history navigation (ctrl-n next, ctrl-p previous) in the repl module, along with updated TODO comments for future shortcuts.
Implement a history buffer in the REPL class that stores previously entered commands and allows cycling through them using the up and down arrow keys. The `_history` list and `_historyIndex` track the current position, with `previousHistory()` and `nextHistory()` methods restoring lines from the buffer or clearing the input when reaching the end. The `executeInput()` method now appends the current line to history before resetting, and the Ctrl-D exit condition is fixed to check `_line.isEmpty` instead of `_line == ""`.
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.
Replace the simple fgets-based REPL loop with a full-featured interactive Wren REPL module. The new implementation supports cursor movement via arrow keys, Ctrl-A/E for line start/end, Ctrl-C/D for exit/delete, character insertion/deletion, and syntax highlighting of the current input line. The C side now imports the "repl" Wren module and runs the libuv event loop instead of blocking on stdin reads.
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.
The link to the iterator protocol section in control-flow.html was incorrectly
pointing to `../control-flow.html` instead of `../../control-flow.html`, which
is the correct relative path from the `doc/site/modules/core/` directory.
Add a new `isWindows` static method to the `Platform` class that returns `true` when the host operating system name equals "Windows". This provides a less stringly-typed API compared to checking `Platform.name` directly. The implementation is a simple delegation to the existing `name` foreign method, comparing it against the "Windows" string. Includes a test that verifies `Platform.isWindows` is equivalent to `Platform.name == "Windows"`.
Add a new `isTerminal` static method to the Stdin class that returns `true` when
stdin is connected to a TTY (interactive terminal) and `false` when input comes
from a pipe. Implementation uses libuv's `uv_guess_handle` to check the stdin
descriptor. Includes documentation, foreign method declaration, module
registration, and a test expecting `false` since tests run non-interactively.
Rename the "process" module to "os" across all source files, documentation, tests, and build configuration. Add a new Platform class to the os module with static methods `name` (returns OS string like "Windows", "Linux", "OS X", "iOS", "Unix", "POSIX", or "Unknown") and `isPosix` (returns bool indicating POSIX compliance). Update all import paths from "process" to "os" in test files and module registrations. Move process.c/h to os.c/h, rename processSetArguments to osSetArguments, and regenerate the os.wren.inc bytecode source. Add documentation pages for the os module and Platform class.
Define WREN_VERSION_MAJOR, WREN_VERSION_MINOR, WREN_VERSION_PATCH macros,
WREN_VERSION_STRING "0.1.0", and WREN_VERSION_NUMBER for monotonic checks.
Update REPL banner to use WREN_VERSION_STRING instead of hardcoded "v0.0.0".
Create CHANGELOG.md documenting the first declared version.
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.
Add foreign static getter `isRaw` and setter `isRaw=(value)` to the Stdin class, backed by a new `isStdinRaw` boolean flag and `uv_tty_set_mode` calls. The getter returns the current raw mode state, while the setter initializes the stdin stream if needed and applies raw or normal mode only when stdin is a TTY. Also includes a test file verifying default false, reading bytes in normal mode, enabling raw mode, and reading subsequent bytes.
Implement a new `readByte()` static method on the `Stdin` class that reads one byte from standard input, blocking the current fiber until a byte is received. The method returns the byte value as a number or `null` if stdin is closed.
Refactor the internal buffering mechanism by introducing a shared `read_()` helper method that both `readByte()` and `readLine()` use, replacing the previous per-method buffering logic. The `readByte()` implementation peels off the first byte from the internal `__buffered` string using `bytes[0]` and slicing.
Add two test files: `read_byte.wren` verifying byte-by-byte reading of "first" and "second" input lines, and `read_byte_eof.wren` confirming that reading after stdin is closed returns the expected error message.
Replace placeholder TODO with full documentation covering method invocation via wrenCall(), including method signature lookup, receiver specification, and argument passing mechanics.
The overflow:auto on pre elements caused horizontal scrollbars in Firefox
when code lines exceeded container width. Adding white-space:pre-wrap
enables natural line wrapping while preserving whitespace formatting,
eliminating the need for horizontal scrolling in narrow viewports.
The phrase "most two common" was inverted to "two most common" in the
error-handling.markdown documentation file to fix a grammatical error
in the description of runtime error types.
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.
Fix a spelling error in the doc/site/values.markdown file where the word
"intpolations" was missing the letter 'e' in the section describing nested
string interpolation within interpolated expressions.
Fix the typo "exectuable" to "executable" in the project structure description within the src/README.md file, specifically in the section documenting the cli directory's purpose.
Corrected "You can is use as a static" to "You can use it as a static"
in the virtual machine description paragraph of the getting-started
markdown file.
The example call `list.insert("item", 3)` was swapped to match the actual API signature where the index comes first, changing it to `list.insert(3, "item")` in the doc/site/method-calls.markdown file.
The example code snippet for method call syntax previously showed `list.insert("item", 3)` which incorrectly placed the value before the index. Updated to `list.insert(3, "item")` to match Wren's actual List.insert method signature where the index parameter comes first.
Add a test case to equality.wren that creates two closures from the same
function literal inside a loop and asserts they are not equal, confirming
that each closure invocation produces a distinct object.
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 inline comments clarifying the purpose of Windows-specific permission and mode flag
definitions in the platform compatibility block. Also remove the conditional `#ifdef O_SYNC`
guard around the O_SYNC flag assignment in `mapFileFlags`, since O_SYNC is now always
defined (as 0) on Windows.
Add conditional preprocessor definitions for Windows builds (WIN32/WIN64) to handle
platform-specific differences in file mode constants (S_IRUSR, S_IWUSR), sync flag
(O_SYNC), and stat macros (S_ISREG, S_ISDIR). Also fix a minor typo in the comment
describing file flag mapping logic.
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 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.
Add `from __future__ import print_function` import for Python 2/3 compatibility and introduce `C_FORMAT_LINE` and `WREN_FORMAT_LINE` format strings to produce aligned columnar output for C source and Wren test file metrics respectively, replacing the previous unstructured print statements.
- Rename `acc` to `account` in Lua and Wren examples for consistency
- Fix Wren constructor syntax from `this new` to `construct new`
- Remove hyphen from "one-byte" to match standard phrasing
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.
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'.
Implement a new static method `File.realPath(path)` that resolves the given path by traversing symlinks and removing redundant `./` and `../` components, returning the canonical absolute path. The implementation uses libuv's `uv_fs_realpath` via an asynchronous callback pattern consistent with other File operations. Includes documentation, foreign method declarations, and two error-case tests for nonexistent paths and wrong argument types.
The precedence table in doc/site/syntax.markdown had several operators listed at wrong priority levels. This commit reorders the table so that comparison operators (<, <=, >, >=) are at level 10, equality operators (==, !=) at level 12, and bitwise operators (&, ^, |) at levels 7-9, aligning with the true precedence hierarchy.
Update the LIB_UV_VERSION constant in the build dependency script to point to the
newer v1.8.0 release tag, which includes bug fixes and performance improvements
for the event loop backend.
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.
- Remove erroneous iterate() and iteratorValue() method docs from map.markdown
since Map does not expose those methods directly
- Fix remove(key) parameter formatting from [key] to `key` for consistency
- Correct File.read encoding description from "The encoding or decoding is done"
to "No encoding or decoding is done" to accurately reflect behavior
Add four new file system checking functions: Stat.isFile and Stat.isDirectory for querying entry type from a Stat object, and File.exists and Directory.exists static methods that return booleans by attempting to stat the path and checking the appropriate type. Also bump MAX_METHODS_PER_CLASS from 12 to 14 to accommodate the new Stat foreign methods, and clean up unused Scheduler imports in existing stat tests.
Replace the Wren-implemented Stat class that stored stat fields in a list with a foreign class backed by the raw uv_fs_stat struct, enabling direct C-level access to stat data for future methods like isDirectory() using S_ISDIR().
Implement `File.stat` method that performs an asynchronous `fstat` call on the open file descriptor, returning a `Stat` object populated with file metadata (device, inode, mode, link count, user, group, size, block size, block count). Refactor the existing `statPathCallback` into a generic `statCallback` shared by both `statPath` and the new `fileStat` function. Bump `MAX_METHODS_PER_CLASS` from 11 to 12 to accommodate the new foreign method slot. Add comprehensive test coverage including successful stat retrieval and error handling when called on a closed file.
Implement File.create() and File.delete() static methods with async libuv operations, add writeBytes() instance method for writing at offsets, introduce FileFlags constants class mirroring POSIX open() flags, refactor File.open() to accept flag parameters via openWithFlags(), and update documentation and module registration accordingly.
Introduce `shared` and `static` make targets to allow building only the shared library (`libwren.so`/`.dylib`) or only the static library (`libwren.a`), respectively. The existing `vm` target now depends on both new targets, preserving backward compatibility while enabling selective builds. This addresses issue #322 by providing finer-grained build control.
Introduce a new public C API function wrenGetSlotType() that returns the
underlying representation type (bool, num, foreign, list, null, string,
or unknown) of the object stored in a given VM slot. This allows C
extensions to inspect slot contents without needing to call individual
type-checking functions or handle errors from mismatched accessors.
The implementation in wren_vm.c uses the existing IS_* macros to
determine the type and returns the corresponding WrenType enum value.
A new WrenType enum is added to wren.h with WREN_TYPE_BOOL,
WREN_TYPE_NUM, WREN_TYPE_FOREIGN, WREN_TYPE_LIST, WREN_TYPE_NULL,
WREN_TYPE_STRING, and WREN_TYPE_UNKNOWN.
Test coverage is added in test/api/slots.c with a slotTypes() foreign
method that verifies all seven type values, and a ForeignType foreign
class is introduced in slots.wren to provide a foreign object for
testing WREN_TYPE_FOREIGN. The test harness in main.c is updated to
support binding foreign class allocate methods via slotsBindClass().
Add a MAX_JUMP constant set to 2^16 and validate jump distance in patchJump to prevent silent overflow when bytecode exceeds the maximum representable offset. Also remove the TODO comment in endLoop since the forward jump error will be caught by patchJump. Include test cases jump_too_far.wren and loop_too_far.wren to verify the compiler correctly reports "Too much code to jump over." for both conditional and loop constructs.
Add early return for "skynet" path in run_example function to avoid
executing the skynet example during test runs, as it is too slow and
causes timeouts on Travis CI bots. Also reduce the kill timer from 5
to 2 seconds in the Test class to fail faster on hanging processes.
The test runner's per-test timeout was raised to 5 seconds to prevent flaky
timeouts on slower systems. A new example file (example/skynet.wren) was added
demonstrating a million-fiber microbenchmark based on the skynet algorithm,
showcasing Wren's fiber concurrency model. Additionally, the shuffle test's
tolerance threshold was relaxed from 0.2 to 0.21 to reduce false positives
in the random distribution check.
- Add explicit `construct new() {}` to Foo class in error-handling doc to clarify method dispatch behavior
- Fix `(-123).abs` syntax in num.markdown to use parentheses for unary minus precedence
Replace the integer `classSlot` parameter with a `Variable` struct in both `defineMethod()` and `method()` functions, removing duplicate code that handled top-level vs local class loading by delegating to the new `loadVariable()` helper.
In both declareVariable and resolveLocal functions within wren_compiler.c,
the string comparison using strncmp is replaced with memcmp since the
length parameter is already known and null-termination checking is
unnecessary for these fixed-length identifier comparisons. This avoids
the overhead of scanning for null terminators when comparing local
variable names against token or parameter strings.
Replace the ad-hoc output parameter pattern in resolveNonmodule with a proper Variable struct that bundles the variable's index and scope (local, upvalue, or module). This makes variable references a first-class concept in the compiler, eliminating the need to pass around a separate Code pointer for load instructions and improving code clarity throughout the compilation pipeline.
Implement in-place shuffle for lists on the Random class, using the Fisher-Yates algorithm to ensure uniform permutation distribution. Includes documentation with usage examples, Wren source implementation, and a test suite covering empty lists, single-element lists, and verification that all 24 permutations of a 4-element list are reachable.
The community.markdown file is deleted entirely. Its content about mailing list, libraries, bindings, editor integrations, and tools is migrated into the contributing.markdown page, which now directs users to add such resources to the wiki instead of maintaining them inline. The site navigation template also removes the community link from both the sidebar and footer.
The old wrenAllocateForeign was limited to slot 0 and the class at the top of the API stack. The new wrenSetSlotNewForeign takes explicit slot and classSlot parameters, allowing foreign objects to be created in any slot from any class. All internal and test call sites updated to use the new API.
- Introduce new 'process' module exposing a Process class with foreign static methods for accessing command-line arguments.
- Implement processSetArguments in main.c to store argc/argv, and processAllArguments in process.c to return them as a Wren list.
- Add --help flag support to CLI, printing usage with optional arguments.
- Include documentation for Process.arguments and Process.allArguments, plus module index and template updates.
- Register process module in modules.c and add Xcode project references for new source files.
- Add test scripts for allArguments and arguments, verifying list type, count, and expected values.
- Add System.print() wrapper to all list subscript and count examples in lists.markdown
- Reformat map literal alignment and reword description in maps.markdown
- Remove paragraph about fibers as map keys from maps.markdown
- Change method-calls example from "hello" to "Heyoo!" and reword VM execution description
- Update performance benchmark timings and bar widths across all test cases
Add `-flto` to `C_OPTIONS` and replace the CLI linker invocation with `-fwhole-program`, yielding 5-45% performance improvements across benchmarks (e.g., api_call +30%, binary_trees +12%, fib +20%).
Replace hardcoded expected values for linkCount and size with range checks
(>=1 and >0 respectively) so the test passes across different filesystems
that may report varying directory metadata.
Add a new `File.stat(path)` static method that returns a `Stat` object with low-level file system metadata for both files and directories. Include a test file `stat_static_directory.wren` that validates the returned `Stat` object's type and field types (device, inode, mode, linkCount, user, group, specialDevice, size, blockSize, blockCount) against a known test directory.
Implement asynchronous stat() on File class returning a new Stat object with device, inode, mode, linkCount, user, group, specialDevice, size, blockSize, and blockCount fields populated from libuv uv_fs_stat callback. Register foreign method statPath_ in module registry, bump MAX_METHODS_PER_CLASS to 10, add Stat class to io.wren with indexed field accessors, update documentation index with Stat page, and include test coverage for stat on existing file and nonexistent path.
Extend File.readBytes with a second overload accepting an offset argument, allowing reads to start at any byte position from the beginning of the file. The existing single-argument variant now delegates to the new two-argument version with offset 0. Validation for the offset parameter mirrors the existing count checks, aborting on non-numeric, non-integer, or negative values. The underlying C implementation passes the offset directly to uv_fs_read, replacing the previous hardcoded zero. Documentation in the io module markdown is updated with usage examples for both signatures, and the old TODO comment about missing offset support is removed. New test files cover offset-based reads, edge cases (zero offset, past-end offset, zero count with offset), and error conditions for invalid offset arguments.
The documentation for `System.print` and `System.printAll` used square brackets
(e.g., `[object]`, `[sequence]`) to denote parameters, which is inconsistent
with the project's standard backtick formatting. This change updates both
descriptions to use backtick-wrapped parameter names (`object`, `sequence`).
- Fix missing article "a" in "expose some stored or computed property"
- Fix missing relative pronoun "that" in "a method doesn't need any parameters"
- Replace incorrect example `list.clear` with `[1, 2, 3].clear` in getter/setter distinction section
- Simplify phrasing "without any collision" to "without a collision" in setters section