Commit Graph

95 Commits

Author SHA1 Message Date
Bob Nystrom
ffb15081f0 refactor: extract if-statement compilation into dedicated ifStatement helper 2017-10-08 17:47:31 +00:00
Bob Nystrom
bd31425b5f fix: detect missing closing brace in block parsing to prevent crash
The compiler previously relied on `match(TOKEN_RIGHT_BRACE)` in the while loop condition, which consumed the brace and made it impossible to detect a missing one. Changed to peek-based loop termination and added explicit `consume` call for the closing brace, ensuring proper error reporting when '}' is absent. Added regression test for issue #429.
2017-10-08 17:03:42 +00:00
Bob Nystrom
184126372c fix: set token type to TOKEN_ERROR after invalid character to prevent compiler loop
When the lexer encounters an invalid character, it now explicitly sets the
current token's type to TOKEN_ERROR and its length to 0. Previously, the
token retained the previous token's type, which could cause the compiler
to get stuck in an infinite loop in certain code paths.

Also improves the error message for non-ASCII invalid bytes by showing
the raw hex value instead of attempting to display the character, since
the lexer operates on raw bytes without UTF-8 decoding.

Adds regression test for issue #428 that was crashing the compiler with
an out-of-bounds memory access due to this loop.
2017-03-24 04:19:20 +00:00
Bob Nystrom
9b0d2aefb6 feat: add user_data API test and reorder WrenErrorFn vm parameter to first position
Add a new test suite for user data get/set operations on WrenVM, including
a Wren script that validates default NULL userData, retrieval after VM
creation, and mutation via wrenSetUserData. Also reorder the vm parameter
in WrenErrorFn callback signature and all its call sites to match the
convention used by other callback types, updating the typedef, the
reportError implementation, and all invocations in the compiler and
debug modules. Include the new source and header files in the Xcode
project build configuration.
2017-03-22 14:26:19 +00:00
scott
b2b187ab07 feat: add user-defined state data pointer and accessors to WrenVM
Add a `userData` void pointer field to `WrenConfiguration` and expose `wrenGetUserData`/`wrenSetUserData` functions for associating arbitrary state with a VM instance. Also update the `WrenErrorFn` signature to include the `WrenVM*` parameter, and propagate the VM pointer through all error callback invocations in the compiler, debug, and runtime paths.
2017-01-20 03:54:25 +00:00
Bob Nystrom
1b635d029a fix: replace strtol with strtoll for 64-bit hex literal parsing on 32-bit platforms
The previous implementation used strtol() for parsing hex literals, which only supports up to 32-bit values on 32-bit architectures. This caused hex literals larger than 0x7FFFFFFF to overflow or fail. Changed to strtoll() which guarantees 64-bit parsing regardless of platform word size.

Also updated the error message to include the actual sizeof(long int) for debugging, uncommented the previously disabled 64-bit hex literal examples in syntax.wren, and added a test case for 0xdeadbeef to verify the fix works correctly.
2017-01-13 05:53:21 +00:00
Bob Nystrom
409873c382 perf: replace O(n) linear scan with O(1) map lookup for constant deduplication in compiler
Replace the linear scan of the function's constant table in `addConstant()` with a hash map lookup using a new `ObjMap* constants` field on the `Compiler` struct. This avoids O(n) performance degradation when compiling functions with many constants, such as large literal-heavy functions. The map stores constant values as keys and their index as numeric values, lazily initialized on first insertion. Also adds OBJ_FN hashing support in `hashObject()` to allow bare function objects as map keys internally, and includes a regression test with 65,550 constant entries to validate the fix.
2016-08-16 14:43:34 +00:00
Bob Nystrom
3ff11eb9f3 feat: deduplicate constants in addConstant to reuse existing values
Add linear scan in addConstant() to check for duplicate constant values before appending. This reduces memory usage for repeated constants and enables support for functions with large numbers of repeated entries. Includes TODO noting O(n) complexity for future optimization.
2016-08-16 14:24:04 +00:00
Bob Nystrom
c726845c42 feat: implement expression evaluation and statement detection in REPL with Meta.compileExpression
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.
2016-05-21 06:03:05 +00:00
Bob Nystrom
19fc5e7534 feat: always wrap functions in closures to simplify VM and improve invocation performance
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.
2016-03-26 21:00:17 +00:00
Bob Nystrom
7e72462d90 feat: add WrenErrorType enum and route runtime errors through config errorFn callback
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.
2016-03-17 14:17:03 +00:00
Bob Nystrom
63e462bb84 chore: remove unused stdarg.h, stdio.h, and stdlib.h includes from wren_compiler.c and wren_value.c 2016-03-17 14:04:09 +00:00
Bob Nystrom
d9ec3627cf feat: add WrenErrorFn callback to WrenConfiguration for custom error reporting
- 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
2016-03-16 15:04:03 +00:00
Bob Nystrom
f16e5c775f feat: report undefined variable errors on the line where they are used
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.
2016-03-16 15:00:28 +00:00
Bob Nystrom
5d42ce9ad6 refactor: extract duplicate method detection into declareMethod helper and rename instanceMethods buffer to methods 2016-03-15 14:15:55 +00:00
Bob Nystrom
1d546cf840 feat: prevent duplicate method definitions in class compilation
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.
2016-03-15 13:54:49 +00:00
Bob Nystrom
c33dc205c3 chore: remove unused DUP opcode from compiler, debug, opcodes, and VM interpreter 2016-03-14 05:11:21 +00:00
Stephen Belanger
7913424c1c feat: replace generic BufferFind with dedicated hasMethod for duplicate detection
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.
2016-03-13 03:14:19 +00:00
Bob Nystrom
c30ee8a297 refactor: consolidate compile error formatting into single printError helper
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.
2016-03-12 05:30:54 +00:00
Bob Nystrom
51d1bb6b3a refactor: move shebang detection into default case and remove separate '#' branch 2016-03-12 01:23:31 +00:00
Bob Nystrom
0f18db0097 refactor: move compiler function state directly into ObjFn to eliminate copying on completion 2016-03-04 15:49:34 +00:00
Bob Nystrom
53f4cb15c9 fix: remove wrenSetCompiler and fix compiler root not being popped on error 2016-03-04 01:48:47 +00:00
Bob Nystrom
1ef9b77842 refactor: rename allowAssignment to canAssign and simplify parsePrecedence signature in wren_compiler.c 2016-03-04 00:30:48 +00:00
Stephen Belanger
b9b9611a8c fix: replace SymbolTable with IntBuffer for per-scope duplicate method detection 2016-02-28 20:53:34 +00:00
Bob Nystrom
06dad18184 docs: fix grammar and formatting in Wren VM comments and code 2016-02-28 00:05:50 +00:00
Bob Nystrom
0fde331974 refactor: replace import opcodes with core method calls for module loading
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.
2016-02-27 06:43:54 +00:00
Bob Nystrom
aca69b34e6 refactor: merge block() into statement() and remove redundant curly-block parsing
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.
2016-02-25 15:04:48 +00:00
Bob Nystrom
c9390c624b fix: add missing code block marker in list docs and simplify parens increment in compiler
- 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.
2016-02-24 14:52:12 +00:00
Stephen Belanger
ed94957e91 feat: add duplicate method detection in class compiler with error reporting
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.
2016-02-24 06:07:08 +00:00
Bob Nystrom
5d04ed2aed fix: add overflow check for jump distance in patchJump and emit error on too much code
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.
2016-02-19 14:57:38 +00:00
Bob Nystrom
cdf3b64ab2 refactor: replace classSlot int with Variable struct in defineMethod and method
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.
2016-02-12 15:43:44 +00:00
Bob Nystrom
6367195722 perf: replace strncmp with memcmp in variable declaration and resolution
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.
2016-02-12 15:27:42 +00:00
Bob Nystrom
18bedf45e1 feat: introduce Variable struct to replace raw index and load instruction pair
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.
2016-02-12 15:16:41 +00:00
Bob Nystrom
a20ef8458b fix: correct spelling of 'upvalue' in comment for addUpvalue function 2015-12-27 04:12:35 +00:00
Bob Nystrom
dbd75f8905 feat: allow call and unary expressions as map keys in compiler
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.
2015-12-23 00:00:50 +00:00
Bob Nystrom
6de3d6aa30 fix: correct debug instruction output and remove ClassCompiler parameter from method
- 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
2015-12-15 01:10:10 +00:00
Bob Nystrom
9aee7ee94e feat: grow fiber stack dynamically and replace fixed-size stack with heap-allocated array 2015-12-14 16:00:22 +00:00
Bob Nystrom
83254bbde3 feat: track max stack slots per function for dynamic stack growth
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.
2015-12-14 06:57:40 +00:00
Bob Nystrom
9dcba9f8b6 feat: ignore newlines in import statements and add test for multiline imports
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.
2015-12-08 03:41:10 +00:00
Bob Nystrom
a5d08effea fix: escape percent sign in string interpolation error message
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.
2015-12-05 18:15:18 +00:00
Bob Nystrom
58d4dfc2db refactor: eagerly evaluate interpolated expressions in string compilation
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.
2015-11-23 15:08:14 +00:00
Bob Nystrom
920b3e2a32 feat: implement string interpolation with %(expr) syntax in compiler and core library
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.
2015-11-11 15:55:48 +00:00
Bob Nystrom
9fe0b2475e refactor: rename GC marking functions to tri-color terminology and add wrenGrayObj helper
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").
2015-10-28 14:55:04 +00:00
Will Speak
645296cbd8 feat: add \U style 8-hex-digit unicode escape support in string literals
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.
2015-10-03 16:28:25 +00:00
Bob Nystrom
0f932e1f3a fix: make UNREACHABLE() macro safe on compilers lacking __builtin_unreachable
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.
2015-10-17 04:51:30 +00:00
Bob Nystrom
8b70246acd refactor: remove sourcePath parameter from wrenInterpret and related module functions
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.
2015-10-16 01:17:42 +00:00
Bob Nystrom
419a5dfda0 refactor: move source path from FnDebug to ObjModule for centralized debug path storage
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.
2015-10-14 14:37:13 +00:00
Bob Nystrom
ddc3ec855e fix: resolve local names in methods as self sends instead of upvalues
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.
2015-10-05 14:44:51 +00:00
Bob Nystrom
3a8582af89 feat: allow super calls in static methods by removing compiler error and fixing metaclass binding
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.
2015-09-19 22:19:41 +00:00
Bob Nystrom
a4922635f2 refactor: replace ad-hoc isKeyword checks with static keyword lookup table in lexer
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.
2015-09-18 03:51:24 +00:00