Commit Graph

960 Commits

Author SHA1 Message Date
Bob Nystrom
c4532102e8 feat: add minimal path manipulation C module for internal VM use
Introduce a new `Path` struct and associated functions in `src/cli/path.c` and `src/cli/path.h` for resolving relative imports within the VM. The module provides operations such as normalization, directory extraction, extension removal, joining, and absolute path detection. Additionally, add a lightweight unit test framework under `test/unit/` with a `test.h`/`test.c` harness and `path_test.c` covering normalization cases. Update the build system (`Makefile`, `util/wren.mk`) to separate API tests from unit tests, rename the test executables to `api_wren` and `unit_wren`, and adjust CI targets and Python test scripts accordingly.
2018-03-24 17:52:16 +00:00
Bob Nystrom
761032c0fc feat: add WrenResolveModuleFn callback and module name parameter to wrenInterpret for relative import resolution
This breaking API change introduces a new `WrenResolveModuleFn` callback in the configuration that allows the host to canonicalize import module names, enabling relative imports. The `wrenInterpret()` function now requires a `module` parameter to specify the module name for the code being interpreted. The `wrenInterpretInModule()` function is removed in favor of the updated `wrenInterpret()`. The `metaCompile` function now dynamically looks up the caller's module name instead of hardcoding "main". New test files `resolution.c`, `resolution.h`, and `resolution.wren` are added to verify resolver behavior including null default, NULL return error, string rewriting, shared module deduplication, and importer propagation.
2018-03-23 14:54:09 +00:00
Bob Nystrom
88ad0fc138 feat: replace module import string operand with direct ObjModule reference in IMPORT_VARIABLE
Add CODE_END_MODULE opcode to store the current ObjModule in vm->lastModule after module body execution. Modify IMPORT_VARIABLE to load variables from vm->lastModule instead of using a constant string operand for the module name. Update opcode definitions, debug dump, compiler import logic, and interpreter dispatch accordingly. Refactor variable lookup into getModuleVariable helper. Adjust formatting in wren_primitive.c and wren_opt_meta.c.
2018-03-20 13:54:51 +00:00
snocl
813bf5e90f fix: wrap Meta.compile result in Fiber.new to restore REPL execution 2018-03-19 20:39:35 +00:00
Bob Nystrom
cf05cd7c8c refactor: change wrenCompileSource to return ObjClosure instead of ObjFiber and inline import execution
The compileInModule function now returns a closure directly instead of wrapping it in a fiber, simplifying the compilation pipeline and removing unnecessary fiber overhead for module imports. The wrenImportModule function is moved into wren_vm.c and rewritten to execute the imported module's closure immediately rather than returning a fiber for deferred execution. This change also adds a test for yielding from an imported module to verify correct behavior with the new execution model.
2018-03-17 16:33:33 +00:00
Bob Nystrom
2bbd385f69 refactor: consolidate duplicate wrenPopRoot calls in wrenCompileSource
Remove redundant NULL-check branches for module parameter by merging the
wrenPopRoot call into a single conditional after compileInModule, eliminating
the early return path and simplifying control flow in the compilation entry point.
2018-03-17 16:13:51 +00:00
Marshall Bowers
512ba07c22 fix: correct assertion to validate variable name instead of module in wrenGetVariable
The assertion in `wrenGetVariable` was incorrectly checking `module != NULL` twice,
instead of checking `name != NULL` for the variable name parameter. This fix
ensures the second assertion validates the correct parameter, preventing
potential null pointer dereference when a NULL variable name is passed.
2018-01-18 05:46:58 +00:00
Michel Hermier
28b3234fa5 fix: correct opcode argument counts and field offset patching in wrenBindMethodCode
The getNumArguments function had CODE_IMPORT_MODULE incorrectly listed as a 1-argument
opcode and CODE_IMPORT_VARIABLE as a 2-argument opcode. This swap caused incorrect
bytecode parsing during method binding. Additionally, wrenBindMethodCode had two bugs:
the instruction fetch was incrementing ip before reading the opcode, and field offset
patching was using ip++ instead of ip+1, corrupting subsequent bytecode. The super
instruction handling also had an incorrect ip+=2 skip that removed the symbol offset
before reading the constant index.
2018-01-11 10:56:03 +00:00
Bob Nystrom
3a1d93e2a8 fix: add unreachable return after switch in getNumArguments to fix compiler warning
The switch statement in getNumArguments covers all opcode cases, but the compiler
cannot prove exhaustiveness. Adding UNREACHABLE() followed by return 0 eliminates
the "control reaches end of non-void function" warning on strict compiler settings.
2017-11-01 05:07:07 +00:00
Bob Nystrom
981ea50407 feat: replace core library import calls with dedicated bytecode instructions
Replace the previous approach of desugaring import statements into calls to System.importModule() and System.getModuleVariable() with two new bytecode instructions: CODE_IMPORT_MODULE and CODE_IMPORT_VARIABLE. This eliminates the need for the corresponding primitive methods in the core library, adds proper debug dump support for the new opcodes, and updates the compiler to emit these instructions directly. The getNumArguments function is also updated to handle the new opcodes and the unreachable default case is removed.
2017-10-31 22:58:59 +00:00
Bob Nystrom
1be81bde81 feat: allow passing initial value to fiber function parameter on first call
When a fiber is started for the first time via call() or transfer(), the value argument is now bound to the fiber's function parameter if it takes one. Previously, the first value was always ignored. Also adds runtime error for fibers created with functions taking more than one parameter, and updates documentation and tests accordingly.
2017-10-20 03:45:13 +00:00
Bob Nystrom
8bd5b85df5 fix: switch REPL eval to use fiber execution and add explicit stdout flush
Replace `Meta.eval()` to compile source into a fiber instead of a function, fixing issue #456 where top-level variable declarations failed in the REPL. Add `Stdout` import and flush stdout before reading stdin since `System.print()` no longer auto-flushes. Refactor token detection to use `lexFirst()` instead of full `lex()`, and add new `Meta.compile()` method returning a fiber. Internally rename `wrenNewString` to `wrenNewStringLength` with explicit length parameter, updating all call sites across compiler, core, and meta modules.
2017-10-13 14:58:57 +00:00
Bob Nystrom
5ab44d7203 fix: correct function name in comment for foreign allocate callback
The comment in the WrenForeignClassMethods struct incorrectly referenced
`wrenAllocateForeign` instead of the actual function `wrenSetSlotNewForeign()`.
This fixes the documentation to match the correct API function name that must
be called exactly once inside the allocate callback body.
2017-10-12 13:37:49 +00:00
Bob Nystrom
5098c37491 feat: add explicit Stdout.flush() and remove automatic flush on System.write()
Remove the automatic fflush(stdout) call from the write() function in vm.c, which was causing gratuitous performance overhead on every System.write() invocation. Introduce a new Stdout class with a foreign static flush() method that delegates to fflush(stdout), giving users explicit control over when output is flushed. Update the io module registration in modules.c to include the Stdout class and bump MAX_CLASSES_PER_MODULE from 5 to 6. Add documentation for Stdout in doc/site/modules/io/stdout.markdown, update the io index and template to list the new class, and add flush() usage notes to the Stdin readByte() and readLine() docs. Implement the stdoutFlush() foreign function in io.c.
2017-10-09 14:16:05 +00:00
Bob Nystrom
8b2994b6e4 fix: rename ClassCompiler typedef to ClassInfo across compiler source
Rename the internal `ClassCompiler` struct typedef to `ClassInfo` to better reflect its purpose as a descriptor for the enclosing class context during compilation. Update all variable declarations, function signatures, and references throughout `wren_compiler.c` to use the new type name, including in `getEnclosingClass`, `field`, `super_`, and `declareMethod` functions. This resolves issue #469 by eliminating the misleading "Compiler" suffix from a type that tracks class metadata rather than compilation state.
2017-10-09 13:47:42 +00:00
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
623cc454e5 fix: parenthesize count argument in ALLOCATE_FLEX and ALLOCATE_ARRAY macros
Add parentheses around the `count` parameter in both `ALLOCATE_FLEX` and
`ALLOCATE_ARRAY` macro definitions to prevent operator precedence bugs when
the argument is an expression. Without this fix, expressions like
`sizeof(type) * n + 1` would be evaluated incorrectly due to `*` having
higher precedence than `+`.
2017-10-08 16:45:06 +00:00
Bob Nystrom
381ef53e84 fix: avoid undefined pointer difference behavior in wrenEnsureStack
When the fiber's stack is reallocated, pointer subtraction between old and new stack
addresses is undefined behavior. Instead of computing an offset and adding it to each
pointer, recalculate each pointer relative to the new stack base using well-defined
arithmetic within the single array. This affects the apiStack, call frame stackStart
pointers, open upvalue values, and the stackTop pointer.
2017-10-08 16:42:35 +00:00
Bob Nystrom
168d6d75b5 feat: add Num.round method for rounding numbers to nearest integer
Implement the `round` method on the Num class in the Wren VM, which rounds a number to the nearest integer using standard rounding rules (away from zero for .5). The implementation adds a new `DEF_NUM_FN(round, round)` macro invocation in `wren_core.c`, registers the corresponding primitive `num_round`, and includes comprehensive documentation in the core module reference. A new test file `test/core/number/round.wren` validates behavior for positive, negative, zero, and fractional values. Also adds Kyle Charters to the AUTHORS file.
2017-10-06 14:51:55 +00:00
Bob Nystrom
eecc18244f fix: abort all fibers along call chain when one fiber errors
In runtimeError, walk the entire fiber call chain and set each fiber's error field to the same error value, unhooking callers as we go. Previously only the immediate caller was considered, leaving intermediate fibers in an inconsistent state. This ensures that when a fiber aborts, every fiber in the chain up to (but not including) the one that catches the error via try() is properly marked as errored.

Also remove the old nested fiber tests from try.wren and add a new comprehensive test (try_through_call.wren) that verifies the percolation behavior through multiple levels of fiber calls and confirms that intermediate fibers carry the error while the catching fiber and its callers remain clean.
2017-10-06 14:39:00 +00:00
Bob Nystrom
85c4e9aa57 fix: propagate aborted fiber error check before call and unwind caller chain in runtimeError
Move the aborted fiber check in runFiber to execute before the "already called" check, ensuring a clear error message for aborted fibers. In runtimeError, replace the single caller unhook with a loop that walks the fiber chain, preserving the callerIsTrying flag and only unhooking fibers until a try-catch boundary is found, enabling proper error propagation through nested fiber calls. Add test cases for one and two levels of nested fiber try calls.
2017-10-06 13:58:27 +00:00
Kyle Charters
884e6853d3 feat: add Num.round method for rounding numbers to nearest integer
Implement the `round` method on the Num class that rounds a number to the nearest integer using standard rounding rules (away from zero for .5). The implementation adds a new `num_round` primitive function in the VM core, registers it as a method on the Num class, includes documentation in the core module reference, and adds a comprehensive test file covering positive, negative, zero, and fractional cases.
2017-09-21 00:27:02 +00:00
Brian Slesinsky
de5802b6ad chore: remove obsolete comment block about foreign method return behavior in wren.h 2017-05-29 19:02:50 +00:00
Bob Nystrom
1f4c0975d0 fix: free dynamically allocated module source strings after compilation
When a module is loaded via the host's loadModuleFn callback, the source string is dynamically allocated and ownership is transferred to the VM. Previously, this memory was never freed after compilation, causing a leak. This change introduces an `allocatedSource` flag that tracks whether the source was dynamically allocated (host-provided) or a static constant (built-in modules like "random"). After `loadModule` completes, the source is freed if it was dynamically allocated, resolving the memory leak described in issue #430.
2017-04-08 19:38:36 +00:00
Andew Jones
3b448427fb fix: propagate error through nested fiber callers in try blocks
Move the aborted fiber check before the already-called check in runFiber to catch errors earlier. In runtimeError, walk the caller chain to find the nearest fiber with callerIsTrying set, properly propagating errors through nested fiber calls. Add test cases for two and three levels of nested fiber try blocks.
2017-03-31 01:57:29 +00:00
Bob Nystrom
5803c8bb58 feat: add wren.hpp convenience header for C++ users linking to C Wren library 2017-03-25 17:05:33 +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
Bob Nystrom
6c756c0c67 feat: add userData field and pass WrenVM* to error callback
Extend WrenConfiguration with a void* userData field for attaching arbitrary state to a VM instance. Add wrenGetUserData and wrenSetUserData accessor functions. Modify the WrenErrorFn typedef and all call sites (compiler, debug, VM) to pass the WrenVM pointer as the final argument, enabling error handlers to access VM context.
2017-03-22 14:12:26 +00:00
Bob Nystrom
dad494093e feat: add validation to skip/take and rename split parameter for clarity
Add type and range checks to Sequence.skip() and Sequence.take() methods, aborting with "Count must be a non-negative integer." when count is not a non-negative integer. Rename split() parameter from 'delim' to 'delimiter' and update its error message from "Argument must be a non-empty string." to "Delimiter must be a non-empty string." for consistency. Remove old behavior allowing negative counts and add new test files for skip/take validation errors.
2017-03-15 14:22:44 +00:00
Bob Nystrom
38b92435bf feat: add lazy skip and take methods to Sequence with SkipSequence and TakeSequence classes
Implement `skip(count)` and `take(count)` on the Sequence class, backed by new SkipSequence and TakeSequence wrapper classes that lazily skip or limit iteration. Includes documentation in the sequence module markdown, core source definitions, and unit tests for edge cases (zero, negative, and overflow counts).
2017-03-15 14:15:00 +00:00
Bob Nystrom
10928fb5de chore: replace C++-style comments with C-style in callForeign function 2017-03-15 14:10:23 +00:00
Bob Nystrom
cb2f45487b fix: restore apiStack after foreign method calls instead of setting to NULL 2017-03-15 14:09:31 +00:00
Bob Nystrom
f96d2e3b8b feat: add split and replace methods to String class with tests and docs
Implement String.split(delim) and String.replace(from, to) methods in the core Wren VM. split returns a list of substrings separated by the given delimiter, while replace returns a new string with all occurrences of the old substring replaced by the new one. Both methods validate arguments (must be non-empty strings) and abort the fiber on invalid input. Include comprehensive test suites covering basic usage, multiple matches, non-ASCII characters, 8-bit clean data, and error cases. Update the string.markdown documentation with usage examples for both methods.
2017-03-15 14:04:56 +00:00
Andew Jones
6fa769beeb feat: add split and replace methods to String class with tests and docs 2017-03-08 02:12:03 +00:00
Bob Nystrom
ecf3b7081b docs: replace placeholder TODO with full VM configuration documentation and fix typo in wren.h
Replace the stub "TODO: Write these docs." in configuring-the-vm.markdown with comprehensive documentation covering all WrenConfiguration fields including binding callbacks, memory management, and error handling. Also fix the typo "phyisically" to "physically" in the wren.h header comment and remove trailing whitespace on several lines.
2017-02-12 19:04:38 +00:00
Bob Nystrom
be7682a656 feat: add log and pow methods to Num class with tests
Adds `log` method to Num class via DEF_NUM_FN macro, and `pow(_)` method via a new DEF_PRIMITIVE that calls C's `pow()`. Registers both primitives in wrenInitializeCore. Includes new test files `test/core/number/log.wren` and `test/core/number/pow.wren` covering basic cases and edge values (negative input for log, zero exponent for pow). Also adds Sven Bergström to AUTHORS.
2017-01-20 15:20:55 +00:00
scott
bbc8f9c0d2 fix: add missing WrenVM* parameter to reportError signature in vm.c
The reportError function signature was missing the WrenVM* parameter required by the updated Wren API, causing a compilation error when the CLI attempted to register it as the error callback. Added the vm parameter to match the expected callback type.
2017-01-20 03:58:52 +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
2620b34c8e fix: replace fpclassify with isnan/isinf for C++98 compatibility in wrenNumToString
The fpclassify() macro is not available in C++98, causing build failures on older compilers. This commit replaces the switch on fpclassify with explicit isnan() and isinf() checks, handling NaN and infinity edge cases directly. The logic for signed infinity is preserved by comparing value > 0.0 instead of using signbit(), which is also not guaranteed in C++98. This aligns with the existing usage of isnan/isinf elsewhere in the Wren codebase.
2017-01-13 05:34:11 +00:00
Bob Nystrom
54bc22efc0 fix: replace decimal u32 overflow test values with hex literals and remove undefined-behavior tests
The bitwise operator tests used decimal literals exceeding u32 range, causing undefined behavior when converting double to u32 on some compilers. This replaces those values with hex equivalents that fit within u32, removes tests for values past max u32, and adds TODO comments for future handling. Also simplifies the `num_bitwiseNot` primitive by removing the intermediate `wideVal` variable, and fixes minor formatting in `util/test.py`.
2017-01-13 05:32:50 +00:00
underscorediscovery
a86e8158e4 feat: add natural logarithm method to Num class with C binding and test
Implement the `log` method on Num by adding a DEF_NUM_FN(log, log) macro invocation in wren_core.c, registering the corresponding primitive `num_log` on the numClass, and creating a new test file test/core/number/log.wren that validates positive and negative input behavior.
2016-10-31 19:52:32 +00:00
underscorediscovery
8b9f99663b feat: add pow(_) primitive to Num class for exponentiation
Implement the `num_pow` primitive that wraps C's `pow()` function, enabling
exponentiation on Num instances via the `pow(_)` method. Register the new
primitive in `wrenInitializeCore` and add a test file verifying basic cases:
2^4=16, 2^10=1024, and 1^0=1.
2016-10-31 19:52:13 +00:00
Daniel Larimer
651dd48128 fix: restore apiStack to saved value instead of NULL in callForeign and createForeign 2016-10-26 17:45:35 +00:00
Will Speak
2d578e0051 feat: add multi-arch CI matrix with nan-tagging toggle and 32-bit test suite
Add Travis CI configuration to build and test Wren on both Linux and macOS, for both 32-bit and 64-bit architectures, with and without WREN_NAN_TAGGING defined. Introduce `ci_32` and `ci_64` make targets that build debug/release and C/C++ variants, then run the test suite against each binary using a suffix parameter. Update `util/test.py` with argparse to accept `--suffix` and `suite` arguments, increase test timeout from 2 to 5 seconds, and fix handle leak in `test/api/slots.c` by moving `wrenReleaseHandle` after the conditional block. Replace `fpclassify`/`signbit` checks for infinity/nan in `wrenNumToString` to avoid GCC overflow warnings on 32-bit, double-cast `double` to `uint32_t` in `num_bitwiseNot` to prevent undefined behavior, and relax floating-point comparisons in `test/core/number/sin.wren` and `cos.wren` to use absolute tolerance. Comment out hex literals larger than `0x1000000` in `example/syntax.wren` since they exceed 32-bit range, and bump libuv from v1.8.0 to v1.10.0 for 32-bit build fixes.
2016-10-09 08:18:27 +00:00
Will Speak
ca3cbf9a88 fix: correct GC next threshold calculation to prevent infinite collections on 32-bit builds
The previous formula `vm->bytesAllocated * (100 + heapGrowthPercent) / 100` incorrectly computed the total heap size instead of the additional allocation threshold, causing the GC to trigger endlessly when `bytesAllocated` already exceeded the calculated `nextGC` value. The fix changes the calculation to `bytesAllocated + (bytesAllocated * heapGrowthPercent / 100)`, which properly represents the next collection point as the current allocation plus a growth allowance. This resolves the infinite GC loop observed in `test/language/deeply_nested_gc.wren` on 32-bit architectures.
2016-10-09 16:59:58 +00:00
Bob Nystrom
6e8a798959 fix: reset API stack to NULL when fiber is aborted in wrenCall to prevent broken state on reuse 2016-11-01 15:40:16 +00:00
Bob Nystrom
77f7f759ff fix: free libuv request data before resuming fiber on error in handleRequestError 2016-11-01 15:39:30 +00:00
Bob Nystrom
8d3a7eabb9 fix: reset apiStack to NULL after foreign constructor returns to prevent broken state on subsequent wrenCall 2016-08-28 15:23:27 +00:00
Bob Nystrom
a82c4d7263 fix: parenthesize macro parameter in BOOL_VAL to prevent operator precedence bugs 2016-08-28 04:44:39 +00:00
Bob Nystrom
17777ef0ce feat: add --version flag to CLI main entry point printing WREN_VERSION_STRING
When invoked with exactly two arguments where the second is "--version", the
main function now prints the version string (e.g. "wren 0.4.0") and exits
successfully before any other initialization occurs.
2016-08-28 00:38:14 +00:00
Bob Nystrom
c29f3e694f fix: replace DBL_EPSILON with DBL_MIN for Num.smallest in wren_core.c
Change the C implementation of `num_smallest` primitive to return `DBL_MIN` instead of `DBL_EPSILON`, correcting the value from the machine epsilon (difference between 1.0 and next representable value) to the smallest positive representable double. Update the documentation in `num.markdown` to describe `Num.smallest` as "the smallest positive representable numeric value" and `Num.largest` as "the largest representable numeric value". Add test files `largest.wren` and `smallest.wren` verifying the expected output values.
2016-08-28 00:25:32 +00:00
Bob Nystrom
5f6e06e1b5 feat: add Num.largest and Num.smallest static properties for float limits
Add two new static properties to the Num class: `Num.largest` returns `DBL_MAX`
and `Num.smallest` returns `DBL_EPSILON`. Include corresponding documentation
in the core module markdown and register the primitives in the VM core
initialization.
2016-08-28 00:18:21 +00:00
Bob Nystrom
53b1120f90 fix: add const qualifier to SymbolTable parameter in wrenSymbolTableFind
The function signature in both the declaration (wren_utils.h) and definition
(wren_utils.c) is updated to accept a const SymbolTable* instead of a
non-const pointer, enabling callers to pass const-qualified symbol tables
without casting away constness.
2016-08-16 14:43:54 +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
Johann Muszynski
f2077844b3 feat: rename Num highest/lowest/epsilon to largest/smallest and update primitives
Rename the static Num class properties from `highest`/`lowest`/`epsilon` to `largest`/`smallest` in wren_core.c, replacing the DBL_MAX/-DBL_MAX/DBL_EPSILON return values with updated DEF_PRIMITIVE implementations and corresponding PRIMITIVE registrations in wrenInitializeCore.
2016-08-04 18:15:55 +00:00
Bob Nystrom
bfb109473e feat: remove List.new(_) constructor and consolidate into List.filled(_,_)
Remove the List.new(_) primitive that initialized a list with null elements, merging its functionality into List.filled(_,_) which now accepts both size and default value. Add validation for negative size with a clear error message, and introduce comprehensive test coverage for filled list creation including edge cases for negative size, non-integer size, and non-numeric size arguments.
2016-08-04 05:42:31 +00:00
Bob Nystrom
85ab5d2aec feat: add List.new(_) and List.filled(_,_) constructors with size and default value
Add two new list constructors to the Wren VM: `List.new(size)` creates a list of given size with null elements, and `List.filled(size, value)` creates a list with all elements initialized to a specified default value. Includes corresponding C primitives `list_newWithSize` and `list_newWithSizeDefault`, registration in `wrenInitializeCore`, and a test file verifying both constructors produce correct counts and element values. Also adds Max Ferguson to AUTHORS.
2016-08-04 05:34:08 +00:00
Bob Nystrom
59a6fc1bcc feat: add negative start support and validate index in String.indexOf(_,_)
Simplify arithmetic in wrenStringFind by removing startIndex offset from loop range and using start directly as the initial index. Rename internal primitives to string_indexOf1 and string_indexOf2 for clarity. Add validateIndex helper to clamp negative start values and reject out-of-bounds indices. Update documentation to describe the new start parameter behavior. Add comprehensive test suite for indexOf with start, including negative offsets, edge cases, and error conditions.
2016-08-04 05:19:34 +00:00
Bob Nystrom
48b69a7c43 feat: add startIndex parameter to string indexOf and update internal find function
Add a new `indexOf(_,_)` primitive that accepts a start index for searching within strings, and modify the existing `wrenStringFind` function to accept and use a start index parameter. The existing `indexOf(_)` and `contains(_)` methods now pass 0 as the start index to maintain backward compatibility. The Boyer-Moore-Horspool search algorithm is updated to offset comparisons by the start index and return the absolute position in the original string. New test cases verify correct behavior with various start index values including edge cases where the start index exceeds string length.
2016-08-04 04:51:46 +00:00
Bob Nystrom
0e4503726e fix: correct bytecode offset calculation in debug dump macro
The `DEBUG_TRACE` macro was using `fn->bytecode` instead of `fn->code.data` to compute the instruction offset for `wrenDumpInstruction`. This caused incorrect offset values when dumping bytecode during interpreter tracing, as the bytecode pointer is stored in the `code.data` field of the function object.
2016-08-04 04:45:09 +00:00
Bob Nystrom
5f8794fdc2 refactor: rename list C API functions and remove Slot suffix for consistency
- Rename wrenGetSlotListSize to wrenGetListCount and wrenGetSlotListValue to wrenGetListElement
- Change wrenGetListElement to move element directly to another slot instead of returning WrenValue
- Update all test bindings and calls to match new API signatures
2016-07-28 15:06:36 +00:00
Bob Nystrom
21a0eef834 feat: add wrenGetSlotListSize and wrenGetSlotListValue API functions for list introspection
Add two new C API functions to the Wren VM that allow foreign methods to query the size of a list stored in a slot and retrieve individual values from it by index. The implementation validates the slot holds a list, extracts the internal ValueBuffer, and returns the count or a captured WrenValue respectively. Corresponding test bindings (getListSize, getListValue) and Wren test cases are included to verify the new functionality.
2016-07-28 14:53:19 +00:00
root
02c2981d36 feat: rename List.new(_,_) to List.filled(_,_) for clarity
The two-argument constructor `List.new(size, element)` was renamed to
`List.filled(size, element)` to better convey its purpose of creating a
list filled with a default value. The underlying primitive
`list_newWithSizeDefault` remains unchanged. The test file
`test/core/list/new_extra_args.wren` was updated to use the new name.
2016-07-17 02:24:19 +00:00
root
89037e397a feat: add list constructors with size and default value arguments
Implement two new List constructors: `List.new(size)` creates a list of given size initialized to null, and `List.new(size, default)` creates a list with all elements set to the provided default value. Add corresponding C primitives `list_newWithSize` and `list_newWithSizeDefault` in wren_core.c, register them in the core initialization, and include test coverage for both constructors. Also add Max Ferguson to AUTHORS.
2016-07-17 02:01:50 +00:00
underscorediscovery
0b1a3cc3e5 feat: add string indexOf with startIndex parameter and update wrenStringFind signature
Add a new primitive `string_indexOf_with_startIndex` that accepts a second integer argument to specify the starting position for the search. Modify the existing `wrenStringFind` function to accept a `startIndex` parameter, updating its Boyer-Moore-Horspool algorithm to begin scanning from the given offset. Update the `string_contains` primitive to pass `0` as the start index. Register the new overloaded method as `indexOf(_,_)` on the string class and add test cases covering boundary conditions and out-of-range start indices.
2016-07-14 03:53:01 +00:00
minirop
c563d7d8ee fix: update bytecode offset calculation to use code.data field
The debug dump macro in runInterpreter was computing instruction offsets
by subtracting fn->bytecode from ip, but the bytecode field was renamed
to code.data during a prior refactoring. This caused incorrect offset
values in debug output when Wren_DEBUG_DUMP_OBJECTS is enabled.
2016-07-12 20:59:02 +00:00
Johann Muszynski
38b7ad62ad feat: add highest, lowest, and epsilon static properties to Num class using DBL_MAX and DBL_EPSILON
Add three new static primitives to the Num class: `highest` returning `DBL_MAX`, `lowest` returning `-DBL_MAX`, and `epsilon` returning `DBL_EPSILON`. Include `<float.h>` header for the floating-point limit constants. Register the new primitives in `wrenInitializeCore` alongside the existing `pi` static property.
2016-07-06 17:08:00 +00:00
Bob Nystrom
4d1215697e feat: add MapEntry class and make Map a Sequence for direct iteration
Add MapEntry class to expose key-value pairs during map iteration, and make Map extend Sequence so maps can be directly iterated with `for` loops. Rename the internal `iterate_` primitive to `iterate` and update error messages for invalid map iterators.
2016-07-06 14:17:07 +00:00
Paul
c2da44aa62 fix: return false instead of NULL in findEntry for zero-capacity map lookup 2016-07-02 11:40:00 +00:00
Bob Nystrom
d955842cf9 perf: add hashBits mixing function to fix integer hash collisions in map
The raw XOR of double's 32-bit halves causes small integers to have zero low bits,
mapping all small integer keys to entry zero in the hash map. This introduces a
bit-mixing function inspired by Java's HashMap that sloshes high bits downward,
eliminating the pathological collision pattern. The map_numeric benchmark improves
by ~18%, and a contrived benchmark with keys up to 1000 becomes 52x faster.
2016-06-27 15:13:45 +00:00
Bob Nystrom
adad9f4b26 fix: prevent duplicate keys by reusing tombstones in map probe sequence
Previously, when inserting a key that already existed in the map but was
located after a tombstone in the probe sequence, the insertion would stop
at the first tombstone and add the key there, resulting in duplicate
entries for the same key. This fix introduces a `findEntry` function that
tracks the first encountered tombstone during probing and reuses it for
insertion only when the key is not found elsewhere in the sequence.
2016-06-27 14:14:52 +00:00
Bob Nystrom
a44b210191 fix: allow optional module loading when host omits loadModuleFn
Previously, wrenImportModule unconditionally called vm->config.loadModuleFn,
causing a crash when the host did not set that function pointer. Now the
call is guarded by a NULL check, so hosts without a module loader can still
load built-in optional modules like "random" or "meta".
2016-06-27 14:08:08 +00:00
Bob Nystrom
b7de67aa20 fix: move tty reset inside stdin stream guard to avoid resetting when stream not owned 2016-05-27 14:01:10 +00:00
Bob Nystrom
72a0d8cf51 fix: reset TTY mode before closing stdin stream in shutdownStdin
Move the uv_tty_reset_mode() call to execute before uv_close() on the stdinStream handle, ensuring the terminal is restored to normal mode prior to stream closure rather than after.
2016-05-27 13:59:43 +00:00
Bob Nystrom
15eb651d1f refactor: extract character handling into separate method and add ANSI fallback support
Extract the inline character processing logic from the REPL's main loop into a dedicated `handleChar()` method that returns a boolean to indicate whether the loop should exit. Add `_allowAnsi` flag and corresponding getter/setters for cursor and line to support a simpler fallback REPL when ANSI escape sequences are unavailable.
2016-05-24 02:59:01 +00:00
Bob Nystrom
69498a4893 feat: add tab-completion in REPL and Meta.getModuleVariables API
Add tab-completion support to the interactive REPL by introducing a new `Meta.getModuleVariables` foreign method that returns all top-level variable names from a given module. The REPL's `run()` method now handles the tab key to append completions, and the `refreshLine` method accepts a boolean parameter to control whether completion hints are shown. Also fix the Ctrl-D exit logic (inverted condition) and remove the unused `EscapeBracket` class.
2016-05-22 22:32:17 +00:00
Bob Nystrom
38462ba4ed feat: add ctrl-b/f/k/l/u/n/p shortcuts to repl line editor
Implement cursor movement (ctrl-b left, ctrl-f right), line clearing (ctrl-k kill after cursor, ctrl-u clear entire line, ctrl-l clear screen), and history navigation (ctrl-n next, ctrl-p previous) in the repl module, along with updated TODO comments for future shortcuts.
2016-05-21 17:33:36 +00:00
Bob Nystrom
5207686395 feat: add command history with up/down arrow navigation to REPL
Implement a history buffer in the REPL class that stores previously entered commands and allows cycling through them using the up and down arrow keys. The `_history` list and `_historyIndex` track the current position, with `previousHistory()` and `nextHistory()` methods restoring lines from the buffer or clearing the input when reaching the end. The `executeInput()` method now appends the current line to history before resetting, and the Ctrl-D exit condition is fixed to check `_line.isEmpty` instead of `_line == ""`.
2016-05-21 17:05:28 +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
33c211f7c2 feat: implement interactive REPL with line editing and syntax highlighting in Wren
Replace the simple fgets-based REPL loop with a full-featured interactive Wren REPL module. The new implementation supports cursor movement via arrow keys, Ctrl-A/E for line start/end, Ctrl-C/D for exit/delete, character insertion/deletion, and syntax highlighting of the current input line. The C side now imports the "repl" Wren module and runs the libuv event loop instead of blocking on stdin reads.
2016-05-21 03:30:09 +00:00
Bob Nystrom
1de17224e8 feat: add wrenAbortFiber() API to abort current fiber with runtime error object
Add a new public API function `wrenAbortFiber()` that allows foreign methods to abort the currently executing fiber with a custom runtime error object. The function validates the API slot, then sets the fiber's error field to the value in the specified slot. The interpreter loop is updated to check for a non-null fiber error after calling a foreign method, triggering a runtime error if set. New test files (error.c, error.h, error.wren) demonstrate usage via a static Error.runtimeError foreign method, verifying that the error is propagated through Fiber.try() and that the fiber's isDone and error properties are correctly set. Xcode project updated to include the new error.c source file.
2016-06-10 02:14:21 +00:00
Bob Nystrom
7768d1c9cd feat: add Platform.isWindows static method to check for Windows OS
Add a new `isWindows` static method to the `Platform` class that returns `true` when the host operating system name equals "Windows". This provides a less stringly-typed API compared to checking `Platform.name` directly. The implementation is a simple delegation to the existing `name` foreign method, comparing it against the "Windows" string. Includes a test that verifies `Platform.isWindows` is equivalent to `Platform.name == "Windows"`.
2016-05-21 19:53:21 +00:00
Bob Nystrom
67bf74777c feat: add Stdin.isTerminal method to detect TTY connection
Add a new `isTerminal` static method to the Stdin class that returns `true` when
stdin is connected to a TTY (interactive terminal) and `false` when input comes
from a pipe. Implementation uses libuv's `uv_guess_handle` to check the stdin
descriptor. Includes documentation, foreign method declaration, module
registration, and a test expecting `false` since tests run non-interactively.
2016-05-21 19:51:11 +00:00
Bob Nystrom
95ef1a2814 feat: rename process module to os and add Platform class with name and isPosix methods
Rename the "process" module to "os" across all source files, documentation, tests, and build configuration. Add a new Platform class to the os module with static methods `name` (returns OS string like "Windows", "Linux", "OS X", "iOS", "Unix", "POSIX", or "Unknown") and `isPosix` (returns bool indicating POSIX compliance). Update all import paths from "process" to "os" in test files and module registrations. Move process.c/h to os.c/h, rename processSetArguments to osSetArguments, and regenerate the os.wren.inc bytecode source. Add documentation pages for the os module and Platform class.
2016-05-21 19:44:17 +00:00
Bob Nystrom
c5e1c2e57f feat: add versioning infrastructure and bump to 0.1.0
Define WREN_VERSION_MAJOR, WREN_VERSION_MINOR, WREN_VERSION_PATCH macros,
WREN_VERSION_STRING "0.1.0", and WREN_VERSION_NUMBER for monotonic checks.
Update REPL banner to use WREN_VERSION_STRING instead of hardcoded "v0.0.0".
Create CHANGELOG.md documenting the first declared version.
2016-05-21 17:53:05 +00:00
Bob Nystrom
caee692c32 docs: rename WrenValue to WrenHandle across embedding docs and C API
Rename the `WrenValue` type to `WrenHandle` in the public C header, update all
function signatures (`wrenMakeCallHandle`, `wrenCall`, `wrenReleaseHandle`),
and rename the documentation page from "Slots and Values" to "Slots and Handles"
with corresponding link updates throughout the embedding guide and module source
files.
2016-05-21 03:55:28 +00:00
Bob Nystrom
efa97cdccf feat: add Stdin.isRaw property to query and set terminal raw mode on stdin
Add foreign static getter `isRaw` and setter `isRaw=(value)` to the Stdin class, backed by a new `isStdinRaw` boolean flag and `uv_tty_set_mode` calls. The getter returns the current raw mode state, while the setter initializes the stdin stream if needed and applies raw or normal mode only when stdin is a TTY. Also includes a test file verifying default false, reading bytes in normal mode, enabling raw mode, and reading subsequent bytes.
2016-05-20 22:19:18 +00:00
Bob Nystrom
6394e1c486 feat: add Stdin.readByte() method for reading single byte from stdin
Implement a new `readByte()` static method on the `Stdin` class that reads one byte from standard input, blocking the current fiber until a byte is received. The method returns the byte value as a number or `null` if stdin is closed.

Refactor the internal buffering mechanism by introducing a shared `read_()` helper method that both `readByte()` and `readLine()` use, replacing the previous per-method buffering logic. The `readByte()` implementation peels off the first byte from the internal `__buffered` string using `bytes[0]` and slicing.

Add two test files: `read_byte.wren` verifying byte-by-byte reading of "first" and "second" input lines, and `read_byte_eof.wren` confirming that reading after stdin is closed returns the expected error message.
2016-05-20 18:50:14 +00:00
Damien Radtke
44be247762 feat: add wrenGetSlotListSize and wrenGetSlotListValue API for list element access
Implement two new C API functions to retrieve list metadata and values from Wren slots: wrenGetSlotListSize returns the element count of a list in a slot, and wrenGetSlotListValue returns a captured WrenValue pointer for a specific index. Add corresponding foreign method bindings in test/api/slots.c and test cases in test/api/slots.wren that verify size retrieval and indexed value access on a three-element list. Also add Damien Radtke to AUTHORS.
2016-05-19 18:26:01 +00:00
Bob Nystrom
d717f0f174 fix: count subscript parameters in wrenMakeCallHandle for bracket signatures
Add missing loop to count underscore parameters in subscript operator signatures
starting with '['. Previously only counted parameters in parenthesized signatures,
causing incorrect arity for methods like `[_,_]` and `[_,_]=(_)`. Also adds
validation assertions for null and empty signatures, and extends test coverage
with unary, binary, subscript, and subscript-set operator call handles.
2016-05-04 13:29:44 +00:00
Chris Sawczuk
9413fd0167 fix: correct typo "collecto" to "collect" and reword gc heapGrowthPercentage doc
- Fix typo in finalizer callback comment: "collecto" -> "collect"
- Reword heap growth explanation: replace "grow (and shrink)" with "resize"
- Clarify example sentence structure in heapGrowthPercentage docs
2016-05-03 17:48:08 +00:00
Andrew Murray
3f701512e6 fix: correct spelling of "executable" in src/README.md documentation
Fix the typo "exectuable" to "executable" in the description of the cli directory within the Wren source code organization documentation.
2016-05-03 14:16:02 +00:00
Bob Nystrom
07613f4eb0 style: align pointer asterisk to type name in MapEntry declarations across wren_value.c 2016-05-02 23:23:52 +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
82103a64f9 refactor: replace eager optional module loading with lazy source and foreign method hooks 2016-03-17 14:49:43 +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