Implement hexadecimal number literal support in the Wren compiler by adding a `number` field to the Parser struct, a `readHexDigit` helper that returns -1 for invalid hex chars, and a `readHexNumber` function that skips the 'x' prefix, accumulates hex digits, converts via strtol, and emits a TOKEN_NUMBER. Update `readNumber` to remove the TODO placeholder for hex support. Include test cases for valid hex literals (0xFF, 0x09, negative -0xFF) and an invalid hex literal (2xFF) that triggers a lex error.
Remove the TOKEN_HEXADECIMAL token type and isHexDigit helper, replacing them with a readHexDigit function and readHexNumber parser that directly converts hex literals to numeric values during lexing. Add a `number` field to the Parser struct to hold the parsed value, and include a test for invalid hex literal error handling.
Add support for map literals using `{}` syntax in the compiler, replacing the previous `new Map` constructor pattern. This introduces a new `map()` grammar function that loads the Map class, instantiates it, and compiles key-value pairs using subscript setter calls. A new `CODE_DUP` bytecode is added to duplicate the map reference on the stack for each element insertion. The change includes updated test files to use literal syntax and new error tests for edge cases like EOF after colon, comma, key, or value.
Add TOKEN_HEXADECIMAL token type and isHexDigit helper function to lexer.
Modify readNumber to detect 'x' prefix after '0' and lex hex digits.
Implement emitNumericConstant for hex values in compiler.
Add test file test/number/hex_literals.wren verifying basic hex parsing,
arithmetic, type checks, and negative hex literals.
Add Visual Studio 2013 solution and project files under project/msvc2013/ directory, enabling native Windows builds without MinGW. Include Marco Lizza in AUTHORS for the contribution. Fix C89 compatibility issues for MSVC: disable computed goto via _MSC_VER check, define inline as _inline for non-C++ mode, change flexible array members from empty brackets to [0] syntax, and fix char to int type for readHexDigit return value. Refactor single-line if/while/for bodies in wren_compiler.c to use braces to satisfy MSVC stricter parsing.
The diff reorders includes across multiple source files to place standard library headers before project headers, removes the `_CRT_SECURE_NO_WARNINGS` define from `wren_common.h`, and adds it as a preprocessor definition in both Debug and Release configurations of the MSVC 2013 project file.
The modulo operator was incorrectly assigned PREC_TERM precedence, making it
evaluate at the same level as + and -. This caused expressions like "13 + 1 % 7"
to parse as "(13 + 1) % 7" instead of the correct "13 + (1 % 7)".
Changed the grammar rule for TOKEN_PERCENT to use PREC_FACTOR, matching the
precedence of * and / operators. Added a precedence test case in mod.wren to
verify the fix.
Enforce a consistent include ordering convention across the codebase: wren_common.h (as configuration header) first, followed by the module's own header, then other wren_*.h headers in lexicographic order, and finally standard library includes. Also add missing wren_common.h include to main.c and wren_io.c, and add _CRT_SECURE_NO_WARNINGS define for MSVC in wren_common.h.
Refactor parameter list parsing to support bracket-delimited parameters for
subscript operators. Extract finishParameterList from parameterList to handle
the common closing logic, and add TOKEN_RIGHT_BRACKET case for error messages.
Add comprehensive test suite for subscript getters and setters with 1-3
parameters in test/method/subscript_operators.wren.
The consume() function previously returned a pointer to the consumed token,
and consumeLine() returned a boolean indicating success. Both return values
were never used by any callers. This change converts both functions to void,
eliminating dead code and simplifying the interface.
The `is` operator was placed at `PREC_IS` which had lower precedence than `PREC_EQUALITY`, causing expressions like `true == 10 is Num` to parse incorrectly. Moved `PREC_IS` above `PREC_EQUALITY` in the precedence enum to give `is` higher binding power than `==` and `!=`. Added precedence tests in new `test/precedence.wren` file and removed TODO comments about precedence from `test/is/is.wren`.
- 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
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 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.
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.
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.
Previously, when `super` was used at the top level or outside any method, the compiler would error but still attempt to read `enclosingClass->methodLength` and `enclosingClass->methodName` from a NULL pointer, leading to undefined behavior. This restructures the error handling in `super_()` to always call `loadThis()` and guard the unnamed super call path with a NULL check on `enclosingClass`, setting an empty method signature when no enclosing class exists. Two additional test cases for `super.foo("bar")` and `super("foo")` are added to verify the compiler continues past the error without crashing.
When `super` is called at top-level with no arguments, `enclosingClass` is null, causing a segfault when trying to access its method name. This fix wraps the unnamed super call logic inside an else branch that only executes when `enclosingClass` is non-null, and adds a test case for the unnamed `super` call at top-level.
Previously, the lexer greedily consumed a `-` followed by a digit as a single negative number token, causing "1 -1" to be lexed as two number tokens instead of a minus operator and a positive literal. This broke parsing of subtraction expressions without spaces.
Now `-` always emits a TOKEN_MINUS, and the parser handles unary negation. This is a breaking change: `-16.sqrt` is now parsed as `-(16.sqrt)` instead of `(-16).sqrt`, requiring parentheses for negative method receivers. All number method tests (abs, ceil, floor, sqrt, toString) are updated to use explicit parentheses for negative receivers.
- Open source files in binary mode to prevent OS-level newline translation
- Treat '\r' character as equivalent to '\n' in the tokenizer
- Handle '\r' followed by '\n' as a single line break via twoCharToken
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.
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.
Add explicit case for '\t' alongside space character in the nextToken function's whitespace-skipping logic. Previously, only spaces were consumed during whitespace skipping, causing tab characters to be incorrectly treated as unexpected tokens. The fix ensures tabs are properly skipped by first matching the tab case and then falling through to the existing space-handling loop.
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%.
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.
Add -lm flag to both debug and release linker commands in Makefile to resolve
undefined math library references. Define _GNU_SOURCE in main.c to make getline()
available under GCC. Add default cases to switch statements in runFile and
getNumArguments to suppress -Wswitch warnings. Fix u_int8_t to uint8_t type in
wrenNewFunction declaration and definition for POSIX compliance.
Add a 64-character maximum identifier length with compile-time error reporting, and enhance the runtime field overflow error to include the class name and remove the TODO comment. Update test expectations for both limit scenarios.
Add a new test case `shadow_closure_with_local.wren` that verifies a closed-over
variable can be shadowed by a local variable in an inner scope within the same
closure. The test ensures that the outer closure variable retains its value
outside the inner scope after the shadowing local goes out of scope.
Also remove an incomplete TODO comment from `reuse_closure_slot.wren` and add
a detailed TODO comment in `wren_compiler.c` discussing the design trade-off
between treating capitalized names as globals versus implicit `this` calls
when walking the scope chain.
Add a static `print` method with no arguments that writes only a newline, enabling blank-line output. Remove the `ignoreNewlines` calls before closing parentheses in parameter lists and method calls, tightening syntax rules. Add a `strlen` TODO comment in symbol table lookup for future optimization. Move the `Foo.toString` test from `test/io/write.wren` to `test/io/print.wren` and delete the old write test file.
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.
Rename boolean defines from `true`/`false` to `1`/`0` for consistency, prefix debug flags with `WREN_DEBUG_`, add `WREN_USE_LIB_IO` flag to guard IO library loading, and wrap IO module includes and function declarations in conditional compilation blocks.