The prep target was missing from the .PHONY declaration, causing Make to skip
its execution when a file named 'prep' existed in the working directory. This
change ensures prep is always treated as a phony target and executed regardless
of file system state.
Add a new public API function `wrenReturnBool` to the Wren C API, allowing
foreign method implementations to return boolean values. The function
includes the necessary `stdbool.h` include in the public header and
implements the return logic by storing a BOOL_VAL in the foreign call slot,
following the same pattern as existing return functions like
`wrenReturnNull` and `wrenReturnString`.
Remove the Linux-specific `_GNU_SOURCE` macro and `getline()` usage in the REPL loop, replacing them with a fixed-size `fgets()` buffer of 1024 bytes. Also switch `snprintf` to `sprintf` in `wren_vm.c` for the field limit error message, eliminating the need for `_GNU_SOURCE` entirely.
The benchmark HTML output previously displayed abstract "score" values and scaled bars by the highest score. This change replaces scores with the actual minimum execution time in seconds (e.g., "0.15s") and scales bar widths proportionally to the highest time, making the charts directly interpretable as performance comparisons. The `run_bench` script now computes `time` from `min(result["times"])` instead of `get_score()`, and the static performance documentation is updated to reflect the new time-based values.
Update the Method Call and DeltaBlue benchmark tables with new Wren performance results (6748 and 7564 respectively), adjusting all other language scores and corresponding chart-bar width percentages to reflect the latest measurements.
Replace the C99 designated initializer syntax for `WrenConfiguration config` with explicit field assignments to avoid potential compiler compatibility issues. The change preserves the same configuration values: `reallocateFn` set to NULL, `heapGrowthPercent` and `minHeapSize` set to 0, and `initialHeapSize` set to 100 MB.
Add native `!` methods to Null, Object, Num, String, and List classes so that `!` works reliably on any value. Null returns `true`, all other types return `false` since they are considered truthy. Update documentation to describe the operator as returning the logical complement and add comprehensive tests for each type. Also fix the `all` method test to use a truthy string instead of expecting a runtime error.
Add C++98 compatibility by introducing explicit casts, replacing C99-specific constructs with macros, and updating the build system to produce C++ object files. Refactor the Value union to a plain uint64_t when WREN_NAN_TAGGING is enabled, adding helper functions for num-to-value and value-to-num conversions. Update the compiler to split emit into emit and emitShort for cleaner bytecode emission, and rename emitByte/emitShort to emitByteArg/emitShortArg.
- Replace Value union with plain uint64_t typedef under WREN_NAN_TAGGING, removing num/bits field access
- Add wrenValueToNum and wrenNumToValue helper functions for double conversion
- Remove wrenValuesEqual function from wren_value.c as bitwise comparison is now direct
- Update Makefile with CPPFLAGS for C++98 compilation and add release-cpp build target
- Add wren-cpp and libwren-cpp.a to .gitignore for C++ build artifacts
Remove the single-purpose `allocate` helper and introduce three type-safe allocation macros (`ALLOCATE`, `ALLOCATE_FLEX`, `ALLOCATE_ARRAY`) that directly invoke `wrenReallocate`. Update all call sites in `wren_value.c` — including `wrenNewSingleClass`, `wrenNewClosure`, `wrenNewFiber`, and `wrenNewFunction` — to use the appropriate macro, eliminating the need for manual sizeof calculations and improving compile-time type checking when compiling as C++.
Add explicit casts to `(Code)` in `debugPrintInstruction` for bytecode indexing, to `(char*)` in `wrenSymbolTableAdd` for heap string allocation, and to `(type*)` in the `DEFINE_BUFFER` macro's reallocation call to ensure C++ compilation compatibility without implicit conversion errors.
- Cast malloc return to char* in src/main.c to avoid C++ implicit void* conversion
- Rename emit to emitByteArg and emitShort to emitShortArg in src/wren_compiler.c to avoid conflict with new emit and emitShort helpers
- Add new emit function taking uint8_t byte and emitShort helper for 16-bit big-endian emission
- Remove stray semicolon in script/test.py
Implement `all(f)` method on Sequence class that returns true if all elements pass the predicate function. Add corresponding documentation entry for `forall(predicate)` in core-library.markdown. Include three test files covering basic functionality, non-boolean return handling, and non-function argument error cases.
Add a new singleton value `VAL_UNDEFINED` to represent globals that have been implicitly declared via forward reference but not yet explicitly defined. Introduce `wrenDeclareGlobal()` to create such entries in the global table, and modify `wrenDefineGlobal()` to check for and resolve undefined slots. Update the compiler's `findUpvalue()` to stop closure capture at method boundaries, preventing methods from closing over local variables. Refactor `wrenSymbolTableAdd()` to always add symbols without duplicate checking, moving that logic to callers. Adjust error messages in the compiler to handle EOF tokens and improve newline formatting. Fix the delta_blue benchmark by renaming the global `planner` variable to `ThePlanner` to avoid shadowing the forward-declared function.
Add support for forward references to top-level variables by implicitly
declaring unresolved capitalized names as globals during compilation.
If a real definition is not found later, a compile-time error is raised.
This enables mutual recursion at the top level and fixes issues #101 and #106.
Introduce an `UNDEFINED` singleton value to mark implicitly declared globals
that have not yet been explicitly defined. Update `wrenDeclareGlobal` to add
such entries, and modify `wrenDefineGlobal` to check for and replace undefined
placeholders. Adjust the symbol table API to allow duplicate additions for
implicit declarations. Add test cases for mutual recursion, forward references
in functions and methods, and undefined variable errors.
Replace the forward-declared `planner` variable with a capitalized `ThePlanner` name across all constraint methods and test functions, removing the TODO comment about forward declarations.
Replace sequential `if` statements with `else if` chains in `readName` so that once a keyword matches (e.g. "break"), the remaining keyword checks are skipped, fixing issue #110 where later keywords could incorrectly override an already-matched token type.
Modify `findUpvalue` in the compiler to return -1 when the enclosing function is a method, preventing closures from capturing outer local variables. Add a new `nonlocal` variable resolution path that treats capitalized identifiers as global variables rather than method receivers. Update existing test files to use capitalized global names and add new test cases for nonlocal assignment, duplicate nonlocal declarations, block scoping, and method-local variable shadowing.
Fix three typos across documentation files: 'unvalid' to 'invalid' in
doc/error-handling.txt, and 'bretheren' to 'brethren' in both
doc/site/expressions.markdown and doc/site/getting-started.markdown
Add the -g compiler flag to DEBUG_CFLAGS in the Makefile to enable
generation of debugging symbols during debug builds, allowing better
debugging with tools like GDB.
Add string type check for IO.read() prompt argument with Fiber.abort on non-string input. Implement stdin piping in test runner via // stdin: comments, allowing tests to provide input lines. Update stack trace filtering to omit built-in library frames with empty source paths. Add io/read.wren and io/read_arg_not_string.wren test cases.
Implement a new static `IO.read(prompt)` method in the IO class that writes a prompt string to stdout and reads a line from stdin into a fixed 1024-byte buffer. The C implementation adds a `MAX_READ_LEN` constant, an `ioRead` function using `fgets`, and registers the method via `wrenDefineStaticMethod`. The builtin source string is updated to include the new Wren method definition.
The nextToken function in wren_compiler.c previously only skipped spaces and carriage returns when advancing past whitespace, causing tab characters to be treated as non-whitespace tokens. This change adds '\t' to the whitespace check in both the initial case statement and the peekChar loop, ensuring tabs are properly skipped like other whitespace characters. A new test file test/whitespace.wren is added to verify correct handling of tabs in various indentation patterns and inline code positions.
Add a new test file `test/ignore_carriage_returns.wren` that sprinkles carriage
return characters (`\r`) in various positions within source code to confirm the
parser correctly ignores them as whitespace. The test includes a deliberate
compile error to validate that line numbering remains accurate despite the
presence of carriage returns.
Add a `contains(element)` method to the built-in `List` class in `builtin/core.wren` and its embedded source in `src/wren_core.c`, enabling linear search for an element. Introduce a new `Set` class example in `example/set.wren` implementing set operations (union, intersection, difference) using the new `contains` method. Update `doc/site/classes.markdown` with a warning against inheriting from built-in types due to internal bit representation constraints.
Change `fopen` mode from `"r"` to `"rb"` in `readFile()` to prevent CRLF-to-LF conversion on Windows, and add `'\r'` as a skipped whitespace character in `nextToken()` to handle carriage returns embedded in source files. This fixes parsing errors when Wren source files use Windows-style line endings.
Add a note to the classes documentation page explaining that inheriting from built-in types (Bool, Num, String, Range, List) is not supported due to internal bit representation conflicts that cause errors when invoking inherited methods on derived types.
Add a complete Set class implementation in example/set.wren with union, intersection, and set minus operations. Implement List.contains method in builtin/core.wren and its C source to support element existence checks via iteration.
When `super` is invoked at the top level without an explicit method name, the compiler previously dereferenced a NULL `enclosingClass` pointer while trying to copy the enclosing method's signature. This change adds a NULL check for `enclosingClass` in the `super_` function, setting an empty method name and zero length when the pointer is NULL, preventing the segmentation fault. Also extends the test file `super_at_top_level.wren` with additional cases for bare `super`, `super.foo("bar")`, and `super("foo")` to verify error handling for these top-level super invocations.
Rename indexOf.wren and startsWith.wren test files to index_of.wren and
starts_with.wren respectively, fix missing trailing newlines, update
string class documentation to clarify UTF-8 storage and move the
note about incorrect UTF-8 handling in the index operator, and
remove unnecessary parentheses in string_indexOf native return.
The font stylesheet link in doc/site/template.html used an explicit http:// scheme,
causing Firefox to block the request on HTTPS pages due to Mixed Content warnings.
Changed to a protocol-relative URL (//fonts.googleapis.com/...) so the browser
automatically uses the same protocol as the parent page.
The `string_subscript` native was allocating a 2-byte buffer for single-character
results, causing a one-byte over-allocation. Changed to allocate exactly 1 byte
for the character plus the null terminator handled by `wrenNewUninitializedString`.
Also fixed `wrenNewUninitializedString` to properly cast the `length` parameter
to `int` when assigning to `ObjString->length`, resolving a potential
truncation warning on 64-bit systems.
Added a test case to verify that subscript access returns a properly formed
string that compares equal to the expected character.
The lexer previously treated a leading minus sign followed by a digit as a single negative number token, which caused incorrect parsing of expressions like `1-1` and broke method calls on negative numbers. This change removes that special case, making the minus sign always a separate token, and updates all test expectations to use explicit parentheses for negative number method calls.
Introduce a `methodNotFound` helper in `wren_vm.c` that parses the symbol name to determine the number of arguments and generates a detailed error message including the argument count. Update all runtime error calls and test expectations across fiber, inheritance, method, and super test files to reflect the new format, and add new test cases for method-not-found with 1, 2, and 11 arguments.
Add a new FAQ entry explaining why Wren uses a stack-based bytecode VM
instead of a register-based one. The entry covers the trade-offs between
the two approaches, references Lua's switch to register-based VM, and
explains that Wren's operator-overloading design makes register-based
optimizations less beneficial.
Add writeObject_ helper that checks if obj.toString returns a String before
writing it, falling back to "[invalid toString]" otherwise. Update print,
write, and printList_ to use the new helper instead of calling toString
directly. Include test cases for both IO.print and IO.write with a class
whose toString returns an integer.
Use the integer length returned by sprintf directly instead of calling strlen on the buffer, eliminating redundant string length calculations in two native functions for number and range string conversion.
The length field in ObjString struct now uses int instead of size_t, saving memory
and aligning with other string length storage conventions throughout the VM.
This eliminates signed/unsigned conversion warnings and matches the type used
elsewhere for string lengths.
Replace strlen(buffer) calls with the length returned directly by sprintf in the
num_toString and range_toString native functions, eliminating unnecessary string
length calculations after formatting.
Replace all uses of `strlen()` and `strcmp()` on string values with the precomputed `length` field and `memcmp()` for equality checks. This eliminates repeated O(n) length calculations in `string_count`, `string_contains`, `string_eqeq`, `string_bangeq`, and `string_subscript`. Also fixes memory accounting in `markString` to use the stored length instead of recalculating it.
Extend the metrics script to walk the benchmark directory, counting benchmark files, TODOs, non-empty lines, and empty lines, and print these new benchmark statistics alongside existing source and test metrics.
Add Travis CI build status badge to README for continuous integration visibility.
Remove trailing semicolons from three assignment statements in delta_blue.wren
benchmark to maintain consistent coding style across the codebase.
Remove unnecessary semicolons from three assignment expressions in the
delta_blue.wren benchmark file to conform to Wren language style conventions,
where semicolons are optional and typically omitted.
Remove separate heap allocation for string text by converting ObjString.value from a char pointer to a C99 flexible array member. This eliminates the extra allocation in wrenNewUninitializedString and the corresponding free in wrenFreeObj, reducing memory fragmentation and pointer indirection for all string objects.
Insert a Markdown image link pointing to the Travis CI build status SVG for the munificent/wren repository, placed between the contribution call-to-action paragraph and the syntax reference link. Also fix the missing trailing newline on the contributing URL line.
The previous implementation relied on sprintf's "%.14g" format for NaN values,
which produces platform-dependent results (some libc versions add a sign prefix).
This change adds an explicit NaN check using the self-comparison idiom (value != value)
and returns a lowercase "nan" string directly, ensuring consistent behavior across
all platforms. The buffer size comment is also updated to remove the now-inaccurate
reference to NaN handling.
Append Paul Woolcock's name and email (paul@woolcock.us) to the list of contributors in the AUTHORS file, following the existing entry for Robert Nystrom.
- Create AUTHORS file listing Robert Nystrom as initial contributor
- Rewrite README to emphasize Wren as concurrent scripting language with fiber examples
- Expand contributing.markdown with structured sections for finding tasks and making changes
- Update index.markdown with call-to-action links for trying and contributing
The `error()` function in the compiler now returns early when the offending token
is of type `TOKEN_ERROR`, preventing the lexer's already-reported error from
being emitted a second time to stderr. This eliminates redundant error messages
for malformed tokens.
Add special handling in the lexer's nextToken function to detect a '#' character followed by '!' on the first line (currentLine == 1) and skip the entire line as a comment. If the shebang appears on any other line, or if a '#' is not followed by '!', emit a lex error for invalid character. Include test cases for valid shebang execution, shebang at EOF, shebang on a non-first line (expected error), and an invalid shebang pattern (expected error).
Remove the empty-line check in runRepl that skipped interpretation for blank input, and refactor the main compilation loop in wrenCompile to use a while loop with TOKEN_EOF matching instead of a for loop with redundant EOF break. This allows the compiler to process files containing only comments or whitespace without prematurely terminating, fixing issue #57. Add test fixtures for comment-only source files.
Add libwren.a and libwrend.a to .gitignore to prevent tracking of static library build outputs, and update the Makefile comment to explain that main.c is excluded from shared library object lists.
Add `libwren.a` and `libwrend.a` static library build targets using `ar rcu`, compile all object files with `-fPIC` for position-independent code, and exclude `main.o` from the shared library object lists via `subst` to allow linking the interpreter separately against the static archive.
Remove the `;` case from the `nextToken` function in `wren_compiler.c` so that semicolons are no longer lexed as `TOKEN_LINE`. Update the documentation in `doc/site/syntax.markdown` to describe newlines as the sole statement separator, and adjust all test files (`test/limit/many_constants.wren`, `test/limit/many_globals.wren`, `test/limit/too_many_constants.wren`, `test/semicolon.wren`) to reflect that semicolons now produce an error instead of being treated as line breaks.
The anonymous union inside the Method struct was previously unnamed, which is not allowed in strict C99 mode. This change names the union `fn` and updates all references to its members (`.primitive`, `.foreign`, `.obj`) to use the qualified syntax (`.fn.primitive`, `.fn.foreign`, `.fn.obj`). The NATIVE macro parameter was also renamed from `fn` to `function` to avoid shadowing the new union field name.
Add .travis.yml with gcc and clang compilers running make && make test.
Modify script/test.py to call sys.exit(1) when any tests fail, ensuring
CI build correctly reports failure status.
- Introduce Wren as a small, clean, fast class-based scripting language
- Include code example demonstrating class syntax with adjectives list
- List key features: small codebase under 4000 semicolons, clean C99 implementation, fast single-pass compiler, class-based object model, embedding-focused design
- Provide links to source code, NaN tagging implementation, performance benchmarks, class documentation, and embedding API
The link target for the embedding API reference was pointing to the wrong
filename (`embedding.html` instead of `embedding-api.html`), causing a 404
error when users clicked the link. This commit updates the href to match the
actual generated documentation file.
Add a new `gh-pages` make target that depends on the `docs` target and copies the generated documentation from `build/docs/` into a local `gh-pages/` directory. Also update `.gitignore` to exclude the `gh-pages/` directory, which is intended to be a separate checkout of the repository for pushing to GitHub Pages.
- 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.
Store the start of the current frame's stack in a local `stackStart` variable
during LOAD_FRAME() macro execution, replacing repeated calculations of
`fiber->stack[frame->stackStart + offset]` with `stackStart[offset]` across
LOAD_LOCAL and LOAD_FIELD opcodes. Also remove unused `upvalues` register
variable and its assignments from closure handling paths.
The performance numbers in the documentation's benchmark chart have been refreshed to reflect the latest measurements. Method call results now show wren at 5100 (up from 4930), luajit at 4441 (up from 4266), ruby at 2868 (up from 2752), lua at 1742 (up from 1728), python3 at 884 (up from 865), and python at 779 (up from 764). DeltaBlue results show wren at 7006 (up from 6662) and python3 at 2333 (down from 2336).
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.
Introduce nine new bytecode instructions (CODE_LOAD_LOCAL_0 through CODE_LOAD_LOCAL_8) that directly encode the local slot number in the opcode itself, eliminating the need to read and decode a separate argument byte for the most frequently accessed local variables. This optimization targets the hottest path in the interpreter, as LOAD_LOCAL is the most executed instruction across benchmarks (e.g., 3.75M times in delta_blue). The compiler's `loadLocal` helper emits the specialized opcode when the slot index is ≤8, falling back to the generic `CODE_LOAD_LOCAL` with an argument byte otherwise. The VM dispatch table and debug printer are updated accordingly. Benchmarks show consistent speedups: fib +7.3%, method_call +5.9%, binary_trees +1.9%, for +2.8%, delta_blue +1.0%.
Add a new test file `test/limit/too_many_constants.wren` containing a single function with 8195 integer literal constants to verify the compiler correctly rejects functions that exceed the maximum constant count limit.
In `getNumArguments`, add a `return 0` after the `UNREACHABLE()` default case to prevent
undefined behavior when assertions are disabled. In `wrenGetClass`, reorder the
`UNREACHABLE()` macro before the `return NULL` so the unreachable annotation is
always emitted. In `runInterpreter`, replace the `ASSERT(0, ...)` with an explicit
`UNREACHABLE()` and `return false` to guarantee a return value on all control paths
when the interpreter exits unexpectedly.