Change the map key parsing precedence from PREC_PRIMARY to PREC_UNARY in
wren_compiler.c, enabling method calls (e.g., name.count), subscript
access (name[0]), and unary operators (-1, ~3) as valid map keys.
Add two test files: precedence.wren verifying the new key types work
correctly, and bad_key_precedence.wren confirming that binary operators
like addition still produce a parse error.
- Fix debug dump to print human-readable instruction names instead of internal enum names (e.g., "RETURN" instead of "CODE_RETURN")
- Remove `ClassCompiler*` parameter from `method()` function, accessing class state through `compiler->enclosingClass` instead
- Change `ClassCompiler.fields` from pointer to embedded struct, updating field lookup to use address-of operator
Add `numSlots` and `maxSlots` fields to `Compiler` struct to track current and maximum stack usage during compilation. Introduce `stackEffects` array mapping each opcode to its net stack delta, defined via updated `OPCODE` macro in `wren_opcodes.h` now taking a second argument. Modify `initCompiler` to initialize slot tracking from `numLocals`, update `emitByte` and related emit functions to adjust `numSlots` and update `maxSlots` when a new peak is reached. Extend `ObjFn` with `maxSlots` field, pass it through `wrenNewFunction` calls (including `makeCallStub`), and fix a null-check in `wrenDumpCode` for core module name.
Add calls to ignoreNewlines in the import compiler function to allow
newlines between the import keyword and the module string, and between
the module string and the for clause. Create a new test case
test/language/module/newlines/ that verifies multiline import syntax
works correctly with both bare imports and imports with variable
bindings.
The error message for a missing '(' after '%' in string interpolation
contained an unescaped '%' character, which could be misinterpreted
by format string functions. Changed the literal '%' to '%%' to ensure
proper display of the percent sign in the error output.
Remove the deferred function compilation for interpolation parts and instead evaluate them directly during string parsing. This simplifies the compiler by eliminating the need for String.interpolate_() and the associated closure creation, replacing it with a direct list construction and join() call.
Add lexer support for `TOKEN_INTERPOLATION` to split string literals at interpolation points, introduce `MAX_INTERPOLATION_NESTING` limit of 8, and compile interpolated strings by emitting calls to `String.interpolate_()`. Optimize list and map literal construction with new `addCore_` primitives to reduce stack churn. Update `String`, `List`, and `Map` `toString` methods in core library to use interpolation syntax, and migrate all benchmark and test files from explicit concatenation to interpolated strings.
Rename `wrenMarkValue` to `wrenGrayValue`, `wrenMarkBuffer` to `wrenGrayBuffer`, and `wrenDarkenObjs` to `wrenBlackenObjects` to make the tri-color garbage collection abstraction explicit. Introduce `wrenGrayObj` as a new helper that handles adding objects to the gray stack with cycle detection via the `isDark` flag. Update all call sites in the compiler, value, and VM modules to use the new names. Fix a typo in the VM header comment ("garbace" → "garbage").
Extend the compiler's string parser to handle `\U` escapes with 8 hex digits
for codepoints above U+FFFF, replacing the previous TODO comment. The
`readUnicodeEscape` helper now accepts a variable digit count (4 or 8) and
the `readString` function dispatches `\u` with length 4 and `\U` with length 8.
New test cases verify correct encoding of emoji and ancient scripts, plus
error handling for incomplete long escapes and values that fit in 4 digits.
Add fallback empty UNREACHABLE() definition for GCC < 4.5 and non-MSVC compilers, and insert return/break statements after all UNREACHABLE() calls to prevent -Wreturn-type warnings when the macro expands to nothing. Also cast malloc result to char* in io.c to suppress C++ compilation warning.
The sourcePath field on ObjModule was redundant since it always matched the module name except for the main script. This change removes the parameter from wrenInterpret, wrenInterpretInModule, and wrenNewModule, and replaces all references to module->sourcePath with module->name in error reporting and debug output.
Remove the `sourcePath` field from `FnDebug` struct and the `Parser` struct, and instead store it directly in `ObjModule`. This eliminates duplication of the debug path across all functions in a module and simplifies the compiler interface by removing the `sourcePath` parameter from `wrenCompile()` and `wrenNewFunction()`. Update all call sites to reference `module->sourcePath` instead, including stack trace printing, code dumping, and the `meta_eval` primitive.
When a method references a name that exists as a local variable outside the method boundary, the compiler now correctly treats it as a self send rather than closing over the outer local. This fixes the closure resolution logic in `findUpvalue` to stop searching for upvalues when hitting a method boundary, unless the name starts with '_' indicating a static field access. The change removes two incorrect test cases that expected outer local closure behavior and adds a new test verifying that both instance and static methods resolve local names to their own methods.
Remove the compiler check that prevented 'super' from being used inside static methods, and fix the runtime binding logic in bindMethod to correctly resolve the superclass for static method dispatch. The key change moves the metaclass lookup (classObj->obj.classObj) to occur before wrenBindMethodCode so that bytecode patching uses the actual class rather than the metaclass, while preserving the original class name for foreign method resolution.
Introduce a Keyword struct and static keywords array mapping reserved word strings to their TokenType, replacing the previous isKeyword() function that performed repeated strncmp comparisons. The new table-driven approach simplifies lexing by enabling direct binary search or linear scan over known identifiers, reducing per-token branching and making the set of keywords explicit and easier to maintain.
Previously, inheriting from null would silently fall back to Object superclass. Now validates superclass and raises runtime error if null is provided. Refactored defineClass to remove implicit null-to-Object fallback, added loadCoreVariable helper for module-level core imports, and updated CLASS/FOREIGN_CLASS opcode comments to reflect that null is no longer a valid superclass. Added test case for inherit_from_null.
Refactor emitConstant to accept a Value parameter, removing the implicit dependency on compiler->parser->value. Update all call sites to pass the value explicitly, improving encapsulation and making the function's data flow clearer.
Add wrenNewStringFromRange function to wren_value.c that decodes UTF-8 code points from source string and re-encodes them into result, enabling correct range subscripts on multi-byte characters. Rename wrenUtf8NumBytes to wrenUtf8EncodeNumBytes and make wrenUtf8Encode return written byte count for use in range construction. Add wrenUtf8DecodeNumBytes utility to skip continuation bytes when iterating by byte index. Remove all skip directives from test files and add UTF-8 specific test cases verifying correct slicing across code point boundaries.
The compiler no longer auto-generates a default `new()` constructor for classes. All classes must now explicitly define `construct new() {}` to be instantiable. This change removes the `createDefaultConstructor` function from the compiler, eliminates the `return_this` primitive used by Object's default initializer, and adds explicit constructors to all test and example classes. Core metaclasses (Bool, Class, Null, Num, Object, Range, Sequence) now correctly reject `new()` calls with runtime errors.
The ignoreNewlines() call following list instantiation via callMethod(compiler, 0, "new()", 5) was redundant because the subsequent do-while loop for compiling list elements already handles newline skipping internally. Removing this duplicate call eliminates unnecessary parser state manipulation without affecting list compilation behavior.
- Convert list() and map() compiler functions from if/do-while to do-while loops
- Remove redundant empty literal handling by breaking on right bracket/brace
- Add new test files for duplicate comma, duplicate trailing comma, and empty list/map with comma
- Expand newlines test to cover trailing comma and empty list/map cases
- Simplify trailing_comma tests by removing inline syntax error checks
- Update Test.fail() to handle variable arguments without kwargs
Add support for trailing commas in list literals by checking for TOKEN_RIGHT_BRACKET
after parsing the last element in the list() function. When a trailing comma is
followed by the closing bracket, the loop breaks immediately instead of attempting
to parse another element.
Include a test case verifying that lists with trailing commas parse correctly and
elements are accessible by index.
Add a check in the map parsing function to break when encountering a closing brace after a comma, enabling trailing commas in map literals. Include a test case verifying that maps with trailing commas parse and execute correctly.
Replace the separate `string` ByteBuffer and `number` double fields in the Parser struct with a single `value` field of type Value. This unifies literal storage, simplifies the parser's state, and eliminates the need for separate buffers and conversion logic for different literal types.
The change modifies `makeNumber` to store parsed numbers as `NUM_VAL` directly into `parser->value`, and adds a guard in `addConstant` to return -1 early if the parser has encountered an error.
Rename the constructor initializer signature prefix from "this " to "init " in
wren_common.h's MAX_METHOD_SIGNATURE calculation, wren_compiler.c's
signatureToString and createDefaultConstructor functions, and wren_core.c's
default Object constructor primitive registration. This changes the syntactic
keyword used to define initializer methods in the Wren language.
- Changed error message in `constructorSignature` from "Expect constructor name after 'this'." to "Expect constructor name after 'construct'."
- Updated comment in `createDefaultConstructor` from "It just invokes 'this new()' on the instance" to "It just invokes 'construct new()' on the instance"
Implement the initial infrastructure for foreign classes in the Wren VM, including new opcodes (FOREIGN_CONSTRUCT, FOREIGN_CLASS), a WrenBindForeignClassFn callback type in the public API, and updated CLI vm.c to store and forward foreign binding callbacks via setForeignCallbacks(). The compiler now tracks whether a class is foreign via a new isForeign flag in ClassCompiler, emits CODE_FOREIGN_CONSTRUCT instead of CODE_CONSTRUCT for foreign class constructors, and errors on field definitions inside foreign classes. The debug dump and opcode header gain entries for the new opcodes, and wrenBindSuperclass handles the -1 numFields sentinel for foreign classes to prevent field inheritance from superclasses.
Add TOKEN_CONSTRUCT as a new reserved word in the Wren compiler lexer and parser, and update the grammar rule table so that 'construct' triggers a constructor signature instead of 'this'. Modify all built-in class definitions in core.wren, wren_core.c, benchmark files, and test fixtures to use 'construct new(...)' and 'construct named(...)' syntax. Update documentation in classes.markdown and syntax.markdown to reflect the new keyword, and remove the deprecated test files for 'new' and infix class expressions.
- Switch Travis CI from sudo-based apt-get to addons.apt.packages for gcc-multilib
- Enable container-based builds with `sudo: false`
- Update README.md call-to-action links to point to getting-started and browser playground
- Replace `printList_` with `printAll` in IO class and remove redundant `IO.` prefixes
- Add IO.read() method documentation and update IO.print docs for up to 16 arguments
- Reorganize community page with Libraries, Language bindings, and Tools sections
- Add wrenjs JavaScript binding and Sublime Text syntax highlighting
- Fix typo "no where" to "nowhere" in fibers documentation
- Add indentation to preprocessor defines in wren_common.h for consistency
- Remove unreachable `return 0` after UNREACHABLE() in wren_compiler.c
- Fix Windows color output by wrapping text in str() in test script
Replace all uses of the `new` reserved word with explicit `this new()` constructor definitions and `ClassName.new()` instantiation calls in builtin/core.wren. Update all documentation files (classes.markdown, fiber.markdown, fn.markdown, sequence.markdown, error-handling.markdown, expressions.markdown, fibers.markdown, functions.markdown) to reflect the new constructor syntax, removing `new` keyword examples and replacing them with `ClassName.new()` patterns and `this new()` definitions.
Add support for parsing scientific notation (e.g., 2.55e2, -2.55e-2) in the
readNumber function of wren_compiler.c. The implementation handles optional
negative exponents, validates that exponent digits follow 'e'/'E', and emits
a lex error for unterminated scientific notation. Also adds comprehensive
test cases covering valid scientific literals, missing exponents, floating
exponents, missing fractional parts, and multiple exponents.
When a block is passed as an argument to a method call, the generated
function's debug name now includes the method's signature followed by
" block argument" instead of the generic "(fn)" placeholder. This
improves debugging by showing which method the block belongs to.
The wrenMarkObj function already handles null pointers internally, making the explicit
`if (x != NULL)` guards unnecessary. This change removes three such checks in
wrenMarkCompiler, markFn, and collectGarbage, simplifying the code without changing
behavior.
The constants buffer was not being cleared when the compiler finished,
causing a memory leak since ownership of constants is transferred to
the new function via wrenNewFunction. Added wrenValueBufferClear calls
in both freeCompiler and endCompiler to properly release the buffer.
The super() call resolution is changed from dynamic runtime lookup (walking the receiver's class hierarchy) to static binding at class definition time. This ensures correct method dispatch when a method containing a super call is inherited by another subclass.
Key changes:
- In `callSignature()`, when compiling a `CODE_SUPER_0` instruction, a constant slot is created and filled with NULL, to be populated with the superclass reference when the method is bound.
- In `getNumArguments()`, the `CODE_SUPER_0` through `CODE_SUPER_16` cases are moved after the newly added 2-argument opcodes (`CODE_JUMP`, `CODE_LOOP`, etc.) to maintain correct ordering.
- In `dumpInstruction()`, the debug output now prints the superclass constant index alongside the method symbol.
- In `runInterpreter()`, the super call execution reads the superclass directly from the function's constant table instead of deriving it from the receiver's class at runtime.
Replace the loop-based single-element writes in readUnicodeEscape and wrenBindMethod with a new BufferFill macro that grows the buffer by a specified count in one allocation. The macro doubles capacity until it fits the requested count, then fills the new slots with the given data. The existing BufferWrite is reimplemented as a call to BufferFill with count=1.
When a compile error occurs, the compiler's code is freed but the parent compiler
was not restored as the active compiler. This could cause the garbage collector
to operate on a dangling compiler pointer if a collection happens after the error.
The fix calls wrenSetCompiler to restore the parent compiler before freeing,
ensuring the GC always sees a valid compiler state.