Commit Graph

73 Commits

Author SHA1 Message Date
Bob Nystrom
e83296ea53 feat: add class name storage and expose via name method on class objects
Store the class name string in `ObjClass` during compilation and class creation, and expose it through a new `class_name` native method. Also update `object_toString` to return the class name for class instances and "instance of <name>" for regular instances.
2014-01-28 23:31:11 +00:00
Bob Nystrom
74b67eae67 refactor: remove separate CODE_SUBCLASS instruction, unify class creation with null sentinel
Eliminate the dedicated CODE_SUBCLASS opcode and instead push a null value to indicate implicit inheritance from Object. This simplifies the bytecode interpreter by using a single CODE_CLASS instruction that checks the top of stack for a null sentinel to determine whether to use the implicit Object superclass or a user-provided superclass. The change also consolidates argument counting and debug printing logic, removing the now-unnecessary case branches for CODE_SUBCLASS across the compiler, VM, and debug modules.
2014-01-27 01:25:38 +00:00
Bob Nystrom
4aa851cb64 fix: correct upvalue argument count calculation in bytecode patching loop
The getNumArguments function was incorrectly returning the number of upvalues
as a direct count instead of accounting for the two bytes consumed per upvalue
in the bytecode stream. This caused the patching loop to exit prematurely when
processing closures with multiple upvalues, leading to corrupted bytecode offsets
and runtime crashes.
2014-01-27 01:24:59 +00:00
Bob Nystrom
7ad96755f4 feat: implement static methods as local variables in implicit class scope
Refactor the compiler to treat static methods as local variables defined in an implicit scope surrounding the class, eliminating the need for VM-level static method support. This changes `declareVariable` to use the previously consumed token, adds `declareNamedVariable` for explicit token consumption, and updates `parameterList` to use the new function. Adjusts VM bytecode ordering for `CODE_METHOD_INSTANCE` and `CODE_METHOD_STATIC` to pop the class before the function body. Adds comprehensive test coverage for static fields including closures, nested classes, default null values, instance method access, and error cases for field usage outside classes or in static methods.
2014-01-19 21:01:51 +00:00
Bob Nystrom
9d71e765c8 refactor: extract class compilation state into dedicated ClassCompiler struct
Move fields, isStaticMethod, methodName, and methodLength from Compiler struct into a new ClassCompiler struct, replacing them with a single enclosingClass pointer. This consolidates class-level bookkeeping and simplifies the Compiler struct by grouping related fields.
2014-01-18 22:03:52 +00:00
Bob Nystrom
f2bf1104af feat: add TOKEN_STATIC_FIELD token for double-underscore prefixed identifiers
Add a new token type TOKEN_STATIC_FIELD to the compiler's token enum and
update the lexer to distinguish between single underscore (TOKEN_FIELD)
and double underscore (TOKEN_STATIC_FIELD) prefixed names. The new token
is registered in the grammar rules table as UNUSED with a TODO comment
for future implementation.
2014-01-18 17:33:18 +00:00
Bob Nystrom
15d9dc229c feat: prevent metaclass inheritance and disallow super in static methods
Remove the metaclass inheritance chain that mirrored the class hierarchy, instead always binding metaclasses directly to Class. This prevents static methods from being inherited by subclasses. Also add a compile-time error when `super` is used inside a static method, since it would always delegate to Class without useful effect. Update the `isInsideMethod` check to use `compiler->fields` instead of walking the parent chain for correctness. Add test cases for the new restrictions and remove the old test that verified static method inheritance.
2014-01-18 01:29:10 +00:00
Bob Nystrom
3663af8a27 fix: prevent instance field access inside static methods in wren compiler
Add isStaticMethod flag to Compiler struct to track whether the current method is static. When compiling a field access, check this flag and emit a compile error if an instance field is used inside a static method. Initialize the flag to false for top-level code and propagate it from parent to child compilers for nested functions and methods.
2014-01-16 15:09:43 +00:00
Bob Nystrom
7e196d9781 feat: add MAX_FIELDS constant and runtime overflow checks for class field limit of 255
Add a MAX_FIELDS constant (255) to wren_common.h and implement field overflow
validation in the compiler and VM. The compiler now emits an error when a class
declares more than 255 fields, and the VM checks for inherited field overflow
at class creation time, producing a descriptive runtime error. Also add four
test files (many_fields, many_inherited_fields, too_many_fields,
too_many_inherited_fields) to verify both valid and invalid field counts.
2014-01-15 15:59:10 +00:00
Bob Nystrom
b4437d5723 fix: recursively bind inherited field references inside nested closures in wrenBindMethodCode 2014-01-15 15:03:24 +00:00
b01dface
d15c36ee89 fix: correct error message token from '}' to '{' in class definition parser
The error message emitted when a left brace is expected after a class body
incorrectly referenced a closing brace '}' instead of the required opening
brace '{'. This fix updates the error string in the `classDefinition` function
within `src/wren_compiler.c` to accurately describe the expected token.
2014-01-14 01:21:25 +00:00
Bob Nystrom
08c38f92cb feat: allow implicit null return when return statement has no value
In the compiler, when a `return` token is followed by a newline or right brace, emit CODE_NULL instead of parsing an expression. This enables bare `return` statements to implicitly return null. Also removes a stale TODO comment about setter parameters and fixes a typo in a comment in wren_core.c. Adds three test cases: one for explicit return in a function, one for bare return before a brace, and one for bare return before a newline.
2014-01-13 03:37:11 +00:00
Bob Nystrom
2e34a5c42b feat: add support for escape sequences \a, \b, \f, \r, \v in string parsing
Implement the remaining standard C escape codes in the readString function
of the Wren compiler, removing the TODO comment about missing escapes.
Adds handling for alert (a), backspace (b), form feed (f), carriage return (r),
and vertical tab (v) escape sequences.
2014-01-13 03:24:30 +00:00
Bob Nystrom
33b0fae6f6 feat: extend jump offsets from 8-bit to 16-bit in compiler and VM
Replace single-byte jump offset emission and reading with two-byte (uint16) handling across all jump instructions (JUMP, LOOP, JUMP_IF, AND, OR). Add new emitJump helper that reserves a 16-bit placeholder, update patchJump to write the offset as big-endian short, and change VM opcode handlers to use READ_SHORT instead of READ_BYTE for jump offsets. This increases maximum jump distance from 255 to 65535 bytes, supporting larger generated bytecode.
2014-01-08 07:03:38 +00:00
Bob Nystrom
0ba6456214 fix: properly dispose loop-scoped variables and exit scopes on break
Replace the single `loopBody` index with a `Loop` struct that tracks scope depth, enabling the compiler to emit correct scope-exit code when a `break` statement is encountered inside nested blocks. Also add `WREN_DUMP_COMPILED_CODE` debug flag and new test cases for closures capturing loop variables after break, return inside loops, and nested loop scoping.
2014-01-06 16:01:04 +00:00
Bob Nystrom
c72db7d594 feat: rename IO.write to IO.print and add Unicode escape support in strings
Rename the IO.write method to IO.print, which now prints without a trailing newline, and add a new IO.print method that appends a newline after output. Update all benchmark, example, and test files to use IO.print instead of IO.write. Additionally, implement Unicode escape sequence parsing in the compiler's string tokenizer, supporting \uXXXX and \u{...} syntax with proper UTF-8 encoding for code points up to U+10FFFF.
2014-01-05 20:27:12 +00:00
Bob Nystrom
e23e0ce6a3 feat: remove hardcoded 256 symbol limit and switch to dynamic symbol table with 16-bit instruction arguments
Replace the fixed-size MAX_SYMBOLS array with a dynamically growing StringBuffer for symbol names, update all instruction encodings to use 16-bit operands for constants and method symbols, and refactor method binding to use a dynamic MethodBuffer per class. Remove the constant deduplication logic in addConstant and the commented-out struct fields in initCompiler.
2014-01-04 19:08:31 +00:00
Bob Nystrom
003d4f77f4 refactor: reorder and document fields in Compiler struct for clarity
Move bytecode and debug source line buffers out of Compiler struct to
simplify initialization, and add inline comments for source path, source
code, constants, locals, upvalues, and fields to improve readability of
the compiler's internal state layout.
2014-01-02 15:31:31 +00:00
Bob Nystrom
720b1b5d76 refactor: replace monolithic Buffer struct with generic macro-generated ByteBuffer and IntBuffer types
Remove the single-purpose Buffer struct from wren_compiler.c and replace it with type-specific ByteBuffer and IntBuffer types generated via a DECLARE_BUFFER macro in wren_utils.h, with shared buffer logic implemented in wren_utils.c using a void* Buffer helper struct. This enables a growable line-number buffer for debug source lines.
2014-01-02 06:23:03 +00:00
Bob Nystrom
b93bd62623 refactor: extract SymbolTable into dedicated wren_utils module with prefixed API
Move SymbolTable struct and its associated functions (initSymbolTable, clearSymbolTable, addSymbol, findSymbol, ensureSymbol, getSymbolName) from wren_vm.c and wren_value.h into new wren_utils.c and wren_utils.h files. Rename all functions with wrenSymbolTable prefix for consistent naming convention, update all call sites across compiler, core, debug, and VM files, and relocate MAX_SYMBOLS constant to wren_common.h.
2014-01-02 04:57:58 +00:00
Bob Nystrom
547107a086 feat: add runtime error support with source paths, line info, and stack traces
Introduce primitive error signaling, runtime error handling with callstack printing, and fiber termination on error. Add source file path and method name tracking to functions, along with debug line number information. Update arithmetic operators to error on non-numeric operands and implement proper "method not found" runtime errors. Refactor the test runner to expect runtime errors with exit code 70 (EX_SOFTWARE) and update the C API to accept source paths in wrenInterpret and wrenCompile. Rename WrenNativeMethodFn to WrenForeignMethodFn and adjust related typedefs. Add debug source line arrays to compilers and functions, and replace the old debug dump functions with new print-based variants that display line numbers.
2014-01-01 21:25:24 +00:00
Bob Nystrom
8a09c03cdd fix: reorder symbol table insertion before object allocation to prevent GC crashes
In `wren_core.c`, `defineClass` and `wrenInitializeCore` now call `addSymbol` before allocating new class objects (`wrenNewClass`, `wrenNewSingleClass`), ensuring unpinned objects are not live when a GC-triggering symbol insertion occurs. In `wren_compiler.c`, `freeBuffer` now passes zero capacity to `wrenReallocate` and reuses `initBuffer` instead of manually zeroing fields, fixing a potential double-free or stale pointer on buffer reuse.
2013-12-30 15:30:50 +00:00
Bob Nystrom
4f215f6531 feat: allow empty blocks in parser and fix native call slot assertion
Add support for empty block bodies in the Wren compiler by early-returning
from `finishBlock` when a right brace is immediately matched. This permits
syntactically valid constructs like `{}`, `if (true) {}`, and empty function
or method bodies.

Fix a copy-paste error in `wrenGetArgumentDouble` where the assertion
checked `nativeCallSlot` and `nativeCallNumArgs` instead of the correct
`foreignCallSlot` and `foreignCallNumArgs` fields.

Add test cases covering standalone empty blocks, empty blocks in if/else
statements, and empty function and method bodies returning null.
2013-12-29 18:46:21 +00:00
Bob Nystrom
b1e8d3f81e feat: add foreign method interface with native call support and argument passing
Introduce the `WrenNativeMethodFn` callback type and `METHOD_FOREIGN` enum value to allow host applications to define C-implemented methods on Wren classes. Add `wrenDefineMethod`, `wrenGetArgumentDouble`, and `wrenReturnDouble` API functions, along with `nativeCallSlot` and `nativeCallNumArgs` VM fields to manage foreign call state. Implement `callForeign` in the interpreter loop to invoke native methods and handle stack cleanup. Move `MAX_PARAMETERS`, `MAX_METHOD_NAME`, and `MAX_METHOD_SIGNATURE` constants from `wren_compiler.c` to `wren_common.h` for shared use across the VM.
2013-12-29 18:06:35 +00:00
Bob Nystrom
6dd270d7ef refactor: replace explicit free/malloc calls with wrenReallocate in symbol table functions
Pass WrenVM pointer to addSymbol, ensureSymbol, and clearSymbolTable to use
wrenReallocate for memory management instead of raw free/malloc, and remove
truncateSymbolTable and MAX_STRING constant as part of the cleanup.
2013-12-27 17:07:35 +00:00
Bob Nystrom
08f043caba feat: replace fixed-size arrays with growable Buffer struct for bytecode and string storage
Replace the static MAX_STRING-sized char array and fixed bytecode array in the compiler with a dynamic Buffer type that supports reallocation via wrenReallocate. Add initBuffer, ensureBufferCapacity, writeBuffer, and freeBuffer helpers to manage memory. This allows the compiler to handle arbitrarily long string literals and large function bodies without hitting hard-coded limits. Add test/long_function.wren (1013 lines) and test/long_string.wren to verify the fix.
2013-12-27 15:22:43 +00:00
Bob Nystrom
e055360616 refactor: pass constants and bytecode directly to wrenNewFunction instead of post-assignment
Refactor ObjFn creation in endCompiler to pass all data (constants, bytecode, upvalues) directly to wrenNewFunction, eliminating the temporary post-construction assignment loop and memcpy. Update wrenNewFunction signature to accept these parameters, copy constants into a new owned array, and take ownership of the bytecode buffer. Adjust ObjFn struct to use dynamic bytecode pointer and bytecodeLength field instead of fixed-size array. Update memory tracking in markFn and cleanup in freeObj to handle the new dynamic bytecode allocation.
2013-12-27 01:28:33 +00:00
Bob Nystrom
ce60209fcc refactor: replace hardcoded ObjFn arrays with growable buffers in compiler
Restructure Compiler to use dynamic bytecode and constant buffers instead of
relying on ObjFn's fixed-size arrays. Move ObjFn creation to the end of
compilation, add wrenListAdd/Insert/RemoveAt helpers to wren_value, relocate
list capacity macros and ensureListCapacity into wren_value.c, and store a
Compiler pointer in WrenVM for GC safety during compilation.
2013-12-27 00:58:03 +00:00
Bob Nystrom
6c61df3ed7 feat: add range operators and iterator protocol for numeric for loops
Implement `..` and `...` infix operators on Num returning Range objects that support the iterator protocol, enabling concise numeric for loops like `for (i in 1..10)`. Add Range class with min/max properties and iterate/iteratorValue methods. Introduce TOKEN_DOTDOT and TOKEN_DOTDOTDOT lexer tokens with PREC_RANGE precedence in the compiler. Unroll method_call benchmark loops across all languages to stress dynamic dispatch instead of loop overhead, reducing iteration count from 1M to 100K with 10x unrolling. Update Wren benchmarks (binary_trees, fib, for) to use new range syntax. Add benchmark/README.md documenting each benchmark's purpose.
2013-12-25 23:01:45 +00:00
Bob Nystrom
b72a42eedd refactor: replace manual instruction argument counting with getNumArguments() in wrenBindMethod
Remove the large switch statement that manually handled instruction argument counts for each opcode in wrenBindMethod(). Instead, use the existing getNumArguments() helper function to determine how many bytes each instruction consumes, reducing code duplication and making the method more maintainable when new instructions are added.
2013-12-25 06:10:30 +00:00
Bob Nystrom
ad559eabd3 feat: implement for-in loop syntax with iterate/iteratorValue protocol and break support
Add `for (variable in sequence)` syntax to the Wren language, introducing the `in` keyword token and compiler support for iterating over sequences using `iterate` and `iteratorValue` methods. Includes new benchmark files for Lua, Python, Ruby, and Wren, plus test cases covering single-expression bodies, block bodies, closures over loop variables, and break statements. Also fixes a missing POP() in CLOSE_UPVALUE and moves the while test file to a subdirectory.
2013-12-25 05:04:11 +00:00
Bob Nystrom
c58f15fc87 feat: allow statement bodies for flow control in compiler and add return tests
Replace the block() function's expression-only body with a call to definition(), enabling flow control statements like `if (foo) return bar` and `if (i > 2) break` without requiring curly braces. Add new test files for return statements after if, else, while, and inside functions/methods, and update existing break tests to use the simplified syntax.
2013-12-24 18:27:48 +00:00
Bob Nystrom
1a456738f6 feat: add break statement support with loop tracking and error handling
Add TOKEN_BREAK keyword recognition and a loopBody field to the compiler
to track the innermost loop's first instruction index. The break
statement emits a jump to the end of the current loop, and compile-time
errors are reported when break appears outside a loop body, inside a
function defined within a loop, or inside a method defined within a
loop. New test files verify correct behavior for break in while loops,
nested loops, and error cases for invalid break usage.
2013-12-24 18:15:50 +00:00
Bob Nystrom
b081f2622d chore: remove resolved TODO comments and fix buffer size in num_toString
- Remove two TODO comments in wren_compiler.c about parameter length overflow check and assignment in named call
- Remove TODO about interning bool_toString and null_toString strings in wren_core.c
- Replace oversized 100-char temp buffer with precise 21-char buffer in num_toString, referencing Lua implementation
- Rename io_write native to io_writeString and remove TODO about calling toString on argument
2013-12-23 23:38:00 +00:00
Bob Nystrom
f8e5351cf3 feat: add MAX_CONSTANTS limit and overflow check with deduplication in wren_compiler.c 2013-12-23 23:08:47 +00:00
Bob Nystrom
4fc948f2ca fix: add lexError function and fix line counting for unterminated block comments
Add a dedicated lexError function that marks compilation as failed and formats
error messages consistently with a trailing newline. Move line counting from
readRawToken into nextChar so that newlines are tracked during all lexer phases,
including block comment scanning. Replace the TODO placeholder in
skipBlockComment with a proper lexError call for unterminated block comments,
and add test cases for unterminated block and nested block comments.
2013-12-23 22:51:06 +00:00
Bob Nystrom
0067070804 refactor: remove unused CODE_DUP instruction and clean up interpreter dispatch
Remove the CODE_DUP opcode from the compiler, debug printer, VM dispatch table, and enum definition. Also simplify several case blocks in the computed-goto interpreter by removing unnecessary braces and consolidating local variable declarations, and add a critical ordering comment to the dispatch table.
2013-12-23 19:37:47 +00:00
Bob Nystrom
64fdc1876a feat: add optimized field load/store instructions for direct method access
Introduce CODE_LOAD_FIELD_THIS and CODE_STORE_FIELD_THIS opcodes that bypass receiver stack operations when field access occurs directly within a method body. Refactor field() compiler to emit these faster instructions when compiler->methodName is set, and extract loadThis() helper to correctly resolve 'this' in nested functions. Update VM interpreter with dedicated dispatch cases that read receiver from frame->stackStart instead of popping, and add debug disassembly support. Add test cases for field closure capture and nested class field isolation, removing related TODO comments.
2013-12-23 19:17:40 +00:00
Bob Nystrom
a7e29fc967 refactor: replace ResolvedName enum with direct Code instruction in resolveName
Remove the ResolvedName enum and its typedef, replacing the resolved parameter with a Code* loadInstruction pointer that directly returns the appropriate load instruction (CODE_LOAD_LOCAL, CODE_LOAD_UPVALUE, or CODE_LOAD_GLOBAL). This eliminates the intermediate enum and the TODO comment about ditching it, simplifying the variable resolution logic in the compiler.
2013-12-23 04:53:35 +00:00
Bob Nystrom
634e9fbb11 feat: add superclass call support inside closures in wren compiler
Add a new test case `test/super/closure.wren` verifying that `super.toString` correctly resolves to the base class method when called from within a closure defined in a derived class. Refactor `resolveLocal` and `resolveUpvalue` to accept explicit name and length parameters instead of relying on the previously consumed token, enabling proper name resolution in nested closure scopes during superclass method dispatch.
2013-12-23 04:46:12 +00:00
Bob Nystrom
75d9a39040 feat: allow variable declarations without explicit initializers
In the compiler, when parsing a variable declaration, the `=` token is now optional. If present, the initializer expression is compiled as before. If absent, the variable is implicitly initialized to `null` via a call to `null(compiler, false)`. This change removes the previous `TODO` comment and the unconditional `consume` of `TOKEN_EQ`.

Two new test files verify the behavior for both global and local variables without initializers, asserting that reading such a variable yields `null`.
2013-12-23 02:47:58 +00:00
Bob Nystrom
1a77a43fa0 feat: implement closure over "this" in methods and fix upvalue closing order
Add support for closing over "this" in function closures defined inside methods by naming the receiver local variable "this" in method compilers. Fix upvalue closing to copy the actual value instead of the stack top, and reorder return handling to close upvalues before storing the result. Add test cases for closure over "this", nested closures, and nested classes.
2013-12-21 23:55:08 +00:00
Bob Nystrom
b1243ac532 feat: add list subscript setter and refactor parameter validation
Implement list subscript setter (`[ ]=`) native method in wren_core.c, enabling assignment to list elements via bracket syntax. Extract duplicate parameter count validation logic into a shared `validateNumParameters` function in wren_compiler.c, replacing inline checks in both `parameterList` and `methodCall`. Add comprehensive test suite covering basic assignment, return value semantics, negative indices, and error cases for out-of-range and excessive arguments.
2013-12-21 17:37:59 +00:00
Bob Nystrom
d9255666f4 fix: add list newline handling and resolve multiple test TODOs across compiler and test suite
- Add TOKEN_LINE matching after list elements in compiler to allow newlines before commas or closing brackets
- Add tests for list newline handling, EOF after comma/element, and class name inside body
- Remove resolved TODOs for default constructors, inherited fields, metaclass is checks, zero comparison, and bitwise not behavior
2013-12-20 20:42:11 +00:00
Bob Nystrom
517844fbda feat: implement setter syntax and assignment in named method calls
Add support for setter methods in the compiler by detecting '=' after a method name in namedCall, compiling the assigned value, and emitting the setter instruction. Includes new test cases for instance setters, static setters, assignment associativity, grouping, operator precedence errors, setter result values, and same-name getter/setter methods. Also updates the super call test with a TODO for super setter calls.
2013-12-20 15:05:31 +00:00
Bob Nystrom
0e70d98169 refactor: replace Foo.new constructor syntax with new Foo and simplify superclass constructor calls
Remove the `this new` constructor declaration syntax in favor of a `new` keyword that creates instances directly. Superclass constructors are now invoked via bare `super(args)` instead of `super.new(args)`, eliminating the semantic weirdness of calling a constructor on a partially-constructed instance. Update the compiler to treat `new` as a keyword token, replace the `isMethod` flag with `methodName`/`methodLength` fields, and change the VM's `NEW` opcode to pop the class from the stack before creating the instance. Add a default `new` native method on Object that returns `this`. Update all benchmarks and tests to use the new syntax.
2013-12-19 15:02:27 +00:00
Bob Nystrom
f5a61e4241 fix: expand TODO comments for superclass constructor resolution edge cases
Add detailed TODO notes in wren_compiler.c's method() function to document two unresolved issues: the lack of validation for matching superclass constructors, and the problematic instance context during super() compilation where field access like _someField in super(_someField) expressions could cause undefined behavior since the receiver is still the class at that point.
2013-12-18 15:39:46 +00:00
Bob Nystrom
7ac04b9e3d feat: refactor method_call benchmark to use inheritance and fix constructor binding
Refactor the method_call benchmark across Lua, Python, Ruby, and Wren to use proper inheritance with super calls instead of direct state manipulation. This ensures all languages benchmark super method invocations consistently.

Fix a bug in the Wren compiler where constructors weren't being bound correctly by extracting method binding logic into a dedicated `bindMethod` function that properly handles both instance and static methods against the class object.

Optimize if-statement compilation by restructuring jump instruction emission to eliminate unnecessary CODE_JUMP instructions when no else branch exists, reducing bytecode size for conditional blocks.

Update the superclass constructor test to verify inherited field access through super constructor chains, confirming correct field initialization across multiple inheritance levels.
2013-12-18 15:37:41 +00:00
Bob Nystrom
656238f286 feat: implement superclass constructor calls and metaclass inheritance chain
Add support for explicit superclass constructor invocation in subclass constructors using `super.constructorName(args)` syntax before the opening brace. The metaclass inheritance hierarchy now mirrors the regular class chain, with `Class` as the root metaclass superclass instead of `Object`. Includes test cases for multi-level constructor delegation and static method inheritance.
2013-12-17 17:39:05 +00:00
Bob Nystrom
93cf4e6b87 feat: add compile-time error for 'super' used outside method context
Add isInsideMethod helper that walks the compiler's parent chain to detect
if the current compilation scope is within a method. Use it in super_()
to emit a compile error when 'super' is used at top level or inside a
top-level function, with corresponding test cases for both scenarios.
2013-12-16 06:08:40 +00:00