Commit Graph

160 Commits

Author SHA1 Message Date
Bob Nystrom
a794ce4ee1 refactor: move global variable storage from VM into Module struct
Functions now hold a reference to the module where they were defined and load module-level variables from there instead of from the VM's global table. This introduces a new Module struct with its own variable buffer and symbol table, replacing the VM-level globals and globalNames. The main module is stored directly in the VM as a temporary measure. Performance regresses slightly due to the indirection through the function's module pointer.
2015-01-26 15:45:21 +00:00
Bob Nystrom
55851d35ba feat: replace string-specific eqeq/bangeq with generic wrenValuesEqual for range equality support
Remove the dedicated string equality operators (string_eqeq, string_bangeq) and their NATIVE registrations, switching object_eqeq and object_bangeq to use the generic wrenValuesEqual instead of wrenValuesSame. Also fix wrenValuesEqual to use memcmp instead of strncmp for string comparison. Add a new test file test/range/equality.wren verifying inclusive and exclusive range equality and inequality.
2015-01-26 15:01:15 +00:00
Gavin Schulz
4042cd6500 refactor: remove redundant string and range equality natives, delegate to wrenValuesEqual 2015-01-26 07:26:59 +00:00
Bob Nystrom
bee26d2ab2 refactor: remove dedicated CODE_LIST bytecode in favor of new List instantiation with .add() calls
Eliminate the LIST opcode and its interpreter case, debug printing, and enum entry. Instead compile list literals by loading the List class, calling its constructor, then emitting DUP, element expression, CALL_1 for add(), and POP for each element. This removes interpreter loop code and lifts the previous 255-element limit on list literals.
2015-01-26 06:49:30 +00:00
Gavin Schulz
b0b3256335 feat: add == and != operators to Range class with equality tests
Implement equality comparison for Range objects by defining `range_eqeq` and `range_bangeq` native methods that delegate to `wrenValuesEqual`. Register both operators on the Range class in `wrenInitializeCore` and add a comprehensive test suite in `test/range/equality.wren` covering inclusive/exclusive ranges and cross-type inequality checks.
2015-01-26 03:50:54 +00:00
Bob Nystrom
f647680184 feat: add remove() method to Map class with native implementation and tests 2015-01-26 01:42:36 +00:00
Bob Nystrom
a83205ef89 feat: add containsKey method to Map and validate key types in subscript operations
Implement `containsKey()` native method on Map that returns a boolean indicating whether the given key exists in the map. Add `validateKey()` helper to reject non-value-type keys (objects, lists, fibers, etc.) with a clear runtime error. Refactor `wrenMapGet()` signature to return success/failure via bool and output the value through an out-parameter, enabling both `containsKey()` and the existing subscript operator to share the same key validation and lookup logic. Update `map_subscript` to return `null` instead of crashing when a key is not found. Add test cases for `containsKey` success/failure, and runtime error tests for invalid key types in subscript getter, setter, and containsKey.
2015-01-25 20:39:19 +00:00
Bob Nystrom
f093d0a42a feat: implement Map.keys, Map.values iterators and proper toString with key-value formatting
Add MapKeySequence and MapValueSequence classes in core.wren to expose iterable key and value views on Map instances. Implement native iterate_, keyIteratorValue_, and valueIteratorValue_ primitives in wren_core.c to support these sequences. Replace the stub Map.toString with a full implementation that iterates keys and formats each entry as "key: value", handling empty maps and nested maps correctly. Include comprehensive test suites for key iteration, value iteration, iterator type validation, and toString output across multiple orderings.
2015-01-25 18:27:38 +00:00
Bob Nystrom
56123c71e3 feat: implement map clear method to remove all entries
Add DEF_NATIVE(map_clear) that frees the underlying entries array and resets
capacity and count to zero, returning null. Register the "clear" method on
the Map class in wrenInitializeCore and include a test verifying the map is
emptied and the return value is null.
2015-01-25 16:39:44 +00:00
Bob Nystrom
5c33ecc04f feat: add initial Map class with hash table, subscript, and count support
Implement the core Map data structure in Wren, including the ObjMap type with
hash table storage, native methods for instantiation, subscript get/set, and
count. Add Map class declaration to core.wren with a basic toString stub.
Introduce MapEntry struct and hash table growth logic with configurable load
factor. Add test files for map creation, count tracking, key type support
(including null, bool, num, string, range, and class keys), and growth
behavior. Refactor list capacity constants into shared MIN_CAPACITY and
GROW_FACTOR macros. Change object equality operators to use wrenValuesSame
instead of wrenValuesEqual.
2015-01-25 06:27:35 +00:00
Bob Nystrom
239c65201b feat: add join method to Sequence and refactor List toString to use it 2015-01-24 22:39:45 +00:00
Gavin Schulz
9e20b3935a feat: abstract List's toString into generic join method on Sequence
Add `join` and `join(sep)` methods to the `Sequence` class, allowing any sequence to produce a concatenated string of its elements with an optional separator. Refactor `List.toString` to delegate to `join(", ")` with bracket wrapping, removing the manual iteration logic from List. Include new test files for List, Range, and String join behavior, plus runtime error tests for non-string separators.
2015-01-24 04:45:23 +00:00
Bob Nystrom
368d9a3052 feat: add arity getter to Fn class and rename numParams to arity
Add a public `arity` getter to the Fn class that returns the number of required arguments for a function. Internally rename the `numParams` field to `arity` across the codebase for consistency, update the C API parameter name from `numParams` to `arity` in `wrenDefineMethod` and `wrenDefineStaticMethod`, and adjust the error message in `callFunction` to use the new field name. Also update documentation to clarify that extra arguments are ignored rather than causing an error, and add a new test file `test/function/arity.wren` verifying arity values from 0 to 4.
2015-01-24 04:33:05 +00:00
Bob Nystrom
488fb27b91 feat: make String iterable over code points with iterate/iteratorValue primitives
Add String as a subclass of Sequence in core.wren and implement the iterator protocol for strings in wren_core.c. The string_iterate native advances through UTF-8 code point boundaries, while string_iteratorValue extracts the full code point at a given byte index. Includes comprehensive test coverage for iteration, edge cases (empty strings, mid-sequence positions), and error handling for invalid iterator types and out-of-bounds indices. Also updates documentation for String, List, and Sequence classes with iterator protocol details and usage examples.
2015-01-23 04:58:22 +00:00
Bob Nystrom
7e52e36a1c docs: clarify UTF-8 byte indexing in string subscript and add wrenStringCodePointAt helper 2015-01-23 00:38:03 +00:00
Bob Nystrom
6223bb2342 fix: replace broken WREN_PIN macro with proper wrenPushRoot/wrenPopRoot GC root stack 2015-01-21 15:56:06 +00:00
Bob Nystrom
f0f03ec763 refactor: replace CalculatedRange struct with output parameters in calculateRange
The CalculatedRange struct is removed from the header and calculateRange now returns the start index directly while using pointer parameters for length and step, simplifying the API and reducing struct overhead.
2015-01-20 23:33:21 +00:00
Gavin Schulz
2799fa6b58 feat: add range subscripting support for strings with CalculatedRange helper
Extract range validation logic from list_subscript into a reusable calculateRange function that handles inclusive/exclusive bounds, negative indices, and direction stepping. Add CalculatedRange struct to wren_core.h and implement string subscripting via the new helper, including comprehensive test coverage for forward, backward, negative, and half-negative ranges with proper error messages for out-of-bounds and non-integer values.
2015-01-17 07:20:56 +00:00
Luchs
fb14301967 feat: implement single-argument reduce with manual iteration and empty-sequence abort
Replace the previous slice-based single-argument reduce implementation with an explicit iterator loop that seeds from the first element. This avoids the out-of-bounds range error on single-element lists and adds a Fiber.abort for empty sequences. Update the test to verify correct behavior for single-element and empty sequences.
2015-01-16 08:24:18 +00:00
Luchs
afa0a0a8e9 feat: add reduce method to Sequence with two overloads and tests
Implement `reduce` on the `Sequence` class in core.wren with two overloads: one taking an initial accumulator and a function, and another using the first element as the initial accumulator. Add three test files covering normal reduction, single-element edge case, and wrong arity error.
2015-01-15 15:29:49 +00:00
Bob Nystrom
d3ea153a31 feat: implement ! operator for all core types with proper truthiness semantics
Add native `!` methods to Null, Object, Num, String, and List classes so that `!` works reliably on any value. Null returns `true`, all other types return `false` since they are considered truthy. Update documentation to describe the operator as returning the logical complement and add comprehensive tests for each type. Also fix the `all` method test to use a truthy string instead of expecting a runtime error.
2015-01-16 05:50:01 +00:00
Bob Nystrom
4acdc503e4 feat: add Sequence.all method and forall documentation with tests
Implement `all(f)` method on Sequence class that returns true if all elements pass the predicate function. Add corresponding documentation entry for `forall(predicate)` in core-library.markdown. Include three test files covering basic functionality, non-boolean return handling, and non-function argument error cases.
2015-01-15 14:52:43 +00:00
Gavin Schulz
adee8ac482 refactor: rename Sequence method forall to all across core lib, C source, and test files 2015-01-15 07:19:31 +00:00
Gavin Schulz
cb1703409c test: add forall test for empty list and non-bool/non-function args
Add test case verifying that `forall` returns true for an empty list regardless of predicate, and add two new test files covering runtime errors when `forall` receives a non-boolean-returning function or a non-function argument. Also refactor the `forall` implementation to use logical negation (`!`) instead of explicit `!= true` comparison.
2015-01-15 06:42:15 +00:00
Gavin Schulz
580ca8cf27 feat: add forall method to Sequence class for testing all elements pass predicate
Implement a `forall` method on the Sequence class that takes a predicate function and returns true only if every element in the sequence satisfies the predicate. The method iterates through all elements, returning false immediately upon encountering any element where the predicate does not return exactly true. Includes core library documentation and a test file verifying behavior with numeric comparisons and non-boolean predicate returns.
2015-01-14 07:47:01 +00:00
Bob Nystrom
d6b70a0af3 feat: add type validation for IO.read prompt and stdin support in test runner
Add string type check for IO.read() prompt argument with Fiber.abort on non-string input. Implement stdin piping in test runner via // stdin: comments, allowing tests to provide input lines. Update stack trace filtering to omit built-in library frames with empty source paths. Add io/read.wren and io/read_arg_not_string.wren test cases.
2015-01-12 05:47:29 +00:00
Bob Nystrom
887afc03be feat: add Set class example and List.contains method to core library
Add a complete Set class implementation in example/set.wren with union, intersection, and set minus operations. Implement List.contains method in builtin/core.wren and its C source to support element existence checks via iteration.
2015-01-12 03:50:07 +00:00
Bob Nystrom
6928ba9935 chore: rename test files to snake_case and update string class docs
Rename indexOf.wren and startsWith.wren test files to index_of.wren and
starts_with.wren respectively, fix missing trailing newlines, update
string class documentation to clarify UTF-8 storage and move the
note about incorrect UTF-8 handling in the index operator, and
remove unnecessary parentheses in string_indexOf native return.
2015-01-12 03:13:15 +00:00
Gavin Schulz
de5e69aab0 docs: document String class methods and add startsWith, endsWith, indexOf natives 2015-01-10 22:45:14 +00:00
Kyle Marek-Spartz
b949886707 feat: add contains method to List and update Set example to new operator syntax
Add a `contains(element)` method to the `List` class in the core library,
enabling linear search for an element across all list items. Update the
`example/set.wren` file to use the new Wren operator syntax for `|`, `+`,
`&`, and `-` methods, replacing old function-style parameter definitions
with block-style closures. Also fix trailing whitespace throughout the
Set example and embed the new `contains` method into the C source string
in `src/wren_core.c` for the built-in List class.
2015-01-09 22:02:40 +00:00
Bob Nystrom
f010c8d79f fix: correct buffer size in string subscript operator to prevent off-by-one allocation
The `string_subscript` native was allocating a 2-byte buffer for single-character
results, causing a one-byte over-allocation. Changed to allocate exactly 1 byte
for the character plus the null terminator handled by `wrenNewUninitializedString`.

Also fixed `wrenNewUninitializedString` to properly cast the `length` parameter
to `int` when assigning to `ObjString->length`, resolving a potential
truncation warning on 64-bit systems.

Added a test case to verify that subscript access returns a properly formed
string that compares equal to the expected character.
2015-01-09 15:12:25 +00:00
Bob Nystrom
56355baf42 refactor: use sprintf return value to avoid redundant strlen calls in num_toString and range_toString
Replace strlen(buffer) calls with the length returned directly by sprintf in the
num_toString and range_toString native functions, eliminating unnecessary string
length calculations after formatting.
2015-01-08 15:01:21 +00:00
Evan Shaw
38d93e9850 style: align continuation indentation and rephrase comment in ObjString length field 2015-01-08 06:34:58 +00:00
Evan Shaw
1293a64451 refactor: use sprintf return value to eliminate redundant strlen calls in num_toString and range_toString
Replace separate strlen(buffer) calls with the length returned directly by sprintf in both
num_toString and range_toString native functions. This avoids an unnecessary pass over the
formatted string buffer, improving performance for these hot-path number and range conversions.
2015-01-08 00:41:22 +00:00
Evan Shaw
7a80f801a8 feat: replace strlen calls with stored ObjString length for string operations
Refactor string_contains, string_count, string_eqeq, string_bangeq, and string_subscript to use the precomputed ObjString->length field instead of calling strlen() on the C string. This avoids O(n) length calculations on every string comparison and count operation.

Also update markString memory accounting to use the stored length plus null terminator instead of recalculating with strlen().
2015-01-07 21:05:33 +00:00
Bob Nystrom
44d667665b fix: handle NaN formatting in num_toString to ensure consistent output
The previous implementation relied on sprintf's "%.14g" format for NaN values,
which produces platform-dependent results (some libc versions add a sign prefix).
This change adds an explicit NaN check using the self-comparison idiom (value != value)
and returns a lowercase "nan" string directly, ensuring consistent behavior across
all platforms. The buffer size comment is also updated to remove the now-inaccurate
reference to NaN handling.
2015-01-06 15:09:45 +00:00
Bob Nystrom
1663d4d95c fix: name anonymous union in Method struct to comply with strict C99
The anonymous union inside the Method struct was previously unnamed, which is not allowed in strict C99 mode. This change names the union `fn` and updates all references to its members (`.primitive`, `.foreign`, `.obj`) to use the qualified syntax (`.fn.primitive`, `.fn.foreign`, `.fn.obj`). The NATIVE macro parameter was also renamed from `fn` to `function` to avoid shadowing the new union field name.
2015-01-03 04:17:10 +00:00
Bob Nystrom
0868cf1d8c chore: add TODO comment for arity getter in wren_core.c
- Inserted a TODO comment before the toString native binding in the
  function class initialization to remind about implementing an arity
  getter for Wren functions.
2015-01-02 02:49:10 +00:00
Bob Nystrom
0f5eb1885e feat: add Fiber.abort() method to abort fiber with error message
Implements a new `Fiber.abort()` static method that allows a fiber to terminate with a custom error message string. The method validates that the argument is a string, then returns a PRIM_ERROR to abort the current fiber. Includes three test cases: basic abort with error message retrieval via `fiber.try`, aborting the main fiber with a runtime error, and type checking that non-string arguments produce an appropriate error message.
2015-01-01 18:40:14 +00:00
Bob Nystrom
d287d084ed refactor: simplify empty list range check in list_subscript native
Consolidate the two separate conditional branches for empty range on zero-length list into a single expression using ternary on range->isInclusive, removing the TODO comment and reducing code duplication.
2014-12-31 18:34:44 +00:00
Bob Nystrom
0fafa4bd07 refactor: replace integer stack index with pointer for stack top in fiber
Migrate fiber stack management from an integer `stackSize` counter to a direct `Value* stackTop` pointer, eliminating repeated `stack[stackSize - 1]` calculations. Update all stack slot accesses, iteration loops, and the `CallFrame::stackStart` field to use pointer arithmetic, simplifying the code and reducing index arithmetic overhead.
2014-12-31 18:34:27 +00:00
Bob Nystrom
d224721f79 feat: store class reference directly in Obj struct and inline class lookup for method dispatch
Move the class pointer from ObjInstance into the base Obj struct and remove the separate metaclass field from ObjClass, allowing all heap objects to directly reference their class. Add an inlined wrenGetClassInline function in the header to eliminate function call overhead during method dispatch, yielding 10-43% performance gains across benchmarks.
2014-12-07 22:29:50 +00:00
Bob Nystrom
77bddf8f0a refactor: extract wrenNewUninitializedString to avoid passing NULL to wrenNewString for empty buffers 2014-12-06 18:04:46 +00:00
Bob Nystrom
306c33f01c fix: wrap ASSERT in do-while and add UNREACHABLE macro for GCC compatibility 2014-11-28 19:21:01 +00:00
Bob Nystrom
d60068db56 feat: add Fiber.try() method for catching errors across fiber boundaries
Implement a new `Fiber.try()` method that allows a calling fiber to catch runtime errors from a called fiber. When a fiber is invoked with `try()` instead of `call()`, any runtime error that occurs in the called fiber is returned as a string to the caller rather than terminating the program with a stack trace. The `callerIsTrying` flag on `ObjFiber` tracks this state, and the `runtimeError` function now checks this flag to redirect the error to the caller's stack. Also adds `Fiber.error` getter to retrieve the error string from a failed fiber, changes `Fiber.isDone` to return `true` for errored fibers, and migrates the fiber error field from a raw `char*` to an `ObjString*` for proper memory management. Includes comprehensive test cases for try behavior, re-entry prevention, and error state queries.
2014-10-15 13:36:42 +00:00
Bob Nystrom
10b19d969b feat: implement symmetric coroutines with fiber.call and fiber.run distinction
Add new `fiber.call` method that remembers the calling fiber for symmetric transfer, while `fiber.run` now performs tail-call style switching without preserving the caller. Introduce re-entrancy guards preventing a fiber from being called multiple times, update all test fixtures to use the new API, and add comprehensive test coverage for call semantics including direct/indirect re-entrancy, value passing, and finished fiber errors.
2014-04-14 14:23:05 +00:00
Bob Nystrom
0d74b128a5 fix: enforce string type validation in string_plus and remove coercion TODO
- Replace silent null return with explicit string type check in string_plus native
- Remove outdated TODO comments about string coercion from both num_plus and string_plus
- Add test for basic string concatenation ("a" + "b")
- Add test verifying runtime error when concatenating string with non-string ("a" + 123)
2014-04-09 04:17:49 +00:00
Bob Nystrom
fca506fdf1 feat: require parentheses around operator and setter method parameters in Wren
Enforce syntactic requirement for parentheses in operator method signatures (e.g., `+(other)` instead of `+ other`) and setter definitions (e.g., `bar=(value)` instead of `bar = value`). Update the compiler's `infixSignature`, `mixedSignature`, and `namedSignature` functions to consume explicit `(` and `)` tokens around parameter names. Migrate all built-in core library operator definitions and test fixtures to the new parenthesized syntax.
2014-04-09 00:54:37 +00:00
Bob Nystrom
8d1e9750b8 feat: implement List instantiation via "new" and fix inline functions to static
Add `list_instantiate` native to create empty lists, bind it to List's metaclass for `new` support, and remove the related TODO. Also change three `inline` functions in `wren_value.h` to `static inline` to prevent linker errors. Include a new test `test/list/new.wren` verifying `new List` yields an empty list that supports `add`.
2014-04-08 14:31:23 +00:00
Bob Nystrom
e1cd942656 refactor: rename SymbolTable fields and flatten struct to StringBuffer alias
Replace the nested `SymbolTable` struct (containing a `StringBuffer names` field) with a direct `typedef StringBuffer SymbolTable`, updating all internal accesses from `symbols->names.data` to `symbols->data` and `symbols->names.count` to `symbols->count`. Rename `vm->methods` to `vm->methodNames` and `vm->globalSymbols` to `vm->globalNames` across the codebase, including debug printing, compiler symbol resolution, core initialization, and VM interpreter error messages. Remove the stale TODO comment about error codes in `wren.h` and adjust the `instantiate` method name to include a leading space to prevent direct user invocation.
2014-04-07 01:59:53 +00:00
Bob Nystrom
e7d2684d30 feat: replace fixed-size global array with growable ValueBuffer to support more than 256 globals
Replace the static `Value globals[MAX_GLOBALS]` array in WrenVM with a dynamic `ValueBuffer` that grows on demand, removing the 256-global limit. Introduce `wrenDefineGlobal()` helper that adds a named global to the symbol table and stores its value in the buffer, returning -2 when the 65536 limit is reached. Update all global access sites (compiler emit, runtime interpreter, GC marking, debug disassembly, core class definition) to use the buffer's data pointer and short (16-bit) opcode arguments instead of byte-sized ones. Add a regression test `many_globals.wren` that defines 8200 globals to verify the new capacity.
2014-04-06 23:16:15 +00:00
Bob Nystrom
be8c586d4b feat: implement List.addAll() method to append elements from iterable
Add `addAll(other)` method to the List class in both the Wren core library source and its embedded C string representation. The method iterates over the given `other` sequence, appends each element to the list using the existing `add()` method, and returns the original `other` argument to match the documented return behavior. Include a new test file `test/list/add_all.wren` covering basic appending, empty iterable, range input, and return value verification.
2014-04-06 15:37:37 +00:00
Bob Nystrom
059d3e4fe6 feat: replace Fiber.create constructor with new Fiber instantiation pattern
Refactor fiber creation from a static `Fiber.create` method to a constructor-based `new Fiber` pattern. This introduces a `fiber_instantiate` native that returns the Fiber class itself, allowing `new Fiber` to invoke `fiber_new` for validation and creation. A shared `validateFn` helper is added to centralize function argument checking, replacing inline validation in both `fiber_new` and `fn_new`. All test files are updated to use the new syntax, and the old `create_wrong_arg_type` test is replaced with `new_wrong_arg_type`.
2014-04-05 01:24:55 +00:00
Bob Nystrom
4c4f32b5b2 feat: validate argument type in Fn.new and add runtime error test
Add type checking to the `fn_new` native function to ensure the argument
passed to `Fn.new` is either a function or closure. Previously, passing
an invalid type like an integer would silently succeed. Now it returns
a clear runtime error message: "Argument must be a function."

Also remove two stale TODO comments about newline handling in the
compiler that were no longer relevant to current parsing logic.
2014-04-05 01:13:13 +00:00
Bob Nystrom
81f20caf33 feat: replace CODE_NEW instruction with instantiate method call for class and Fn
Refactor the 'new' operator compilation to emit a method call to 'instantiate' on the class instead of using a dedicated bytecode instruction. This allows built-in types like Fn to override instantiation behavior, enabling `new Fn { ... }` to return the block argument directly. Remove the CODE_NEW opcode from the VM, compiler, and debug printer, and add native methods `class_instantiate`, `fn_instantiate`, `fn_new`, and `object_instantiate` to handle the new dispatch. Update test files to reflect the renamed `Function` class to `Fn`.
2014-04-03 00:42:30 +00:00
Bob Nystrom
b36705d3f3 feat: add bitwise AND and OR operators for numbers with 32-bit unsigned semantics
Implement num_bitwiseAnd and num_bitwiseOr native methods that cast operands to uint32_t before applying bitwise operations, matching the existing bitwiseNot pattern. Register both operators on the number class and add test files covering basic cases, max u32 boundary, overflow behavior, and non-numeric operand error handling.
2014-02-24 15:27:43 +00:00
Kyle Marek-Spartz
e9391313b7 style: remove space before parentheses in map and where method definitions in core.wren and generated wren_core.c 2014-02-18 17:54:55 +00:00
Bob Nystrom
31ee167168 feat: extract map and where into Sequence base class for List and Range
Extract the common `map` and `where` methods from `List` into a new `Sequence` base class, making `List is Sequence` and `Range is Sequence`. Remove duplicate native method registrations for Range in wren_core.c and add new test files for Range map/where operations.
2014-02-16 17:20:31 +00:00
Bob Nystrom
73b92ca7f3 feat: add conditional operator and fn toString to wren compiler and core
Add TOKEN_QUESTION token type and implement conditional() parsing function in wren_compiler.c to support the ternary conditional operator (condition ? then : else). Register fn_toString native in wren_core.c to return "<fn>" string for function objects. Include comprehensive test suite covering precedence, short-circuit evaluation, and error cases for missing tokens.
2014-02-15 19:36:01 +00:00
Bob Nystrom
d335116799 feat: add List.where method for filtering elements with a predicate function
Implement a `where` method on the List class that takes a function `f` and returns a new list containing only elements for which `f.call(element)` returns true. The implementation is added both in the builtin core.wren source and embedded in the C library source string in wren_core.c. Also includes a new test file `test/list/where.wren` verifying filtering with matching and non-matching predicates.
2014-02-15 19:21:24 +00:00
Kyle Marek-Spartz
35fbcc5b49 feat: add List.where method for filtering elements with predicate function
Implement a `where` method on the List class that takes a predicate function and returns a new list containing only elements for which the predicate returns true. The implementation iterates over the list, calls the predicate on each element, and collects matching elements into a new list. Includes test cases verifying filtering with both matching and non-matching predicates.
2014-02-15 06:42:14 +00:00
Kyle Marek-Spartz
48ef257973 feat: add List.map method with test for element transformation
Implement a `map` method on the List class that applies a given function `f` to each element, returning a new list with the transformed values. Includes a test case verifying incrementing each element by 1.
2014-02-15 05:06:29 +00:00
Bob Nystrom
08618abc5d fix: allow empty range subscripts [0..-1] and [0...0] on empty lists
Add special case in list_subscript native to return a new empty list when
the source list is empty and the requested range is [0..-1] (inclusive) or
[0...0] (exclusive). This enables using list[0..-1] as a universal copy
idiom that works even for empty lists. Update the List.+ operator to use
this idiom instead of manual iteration. Add test cases for both range
forms on empty lists.
2014-02-15 04:10:41 +00:00
Bob Nystrom
5f16a3a1cc fix: remove conditional guards in List.+ and handle empty list iteration in iterate native
The previous implementation of List.+ used conditional checks (`this.count > 0`, `that.count > 0`) before iterating, which caused the loop body to be skipped entirely for empty lists. This commit removes those guards, allowing the for-in loops to run unconditionally — the Wren VM's iterate/iterateValue protocol already handles the empty case correctly at the native level. Additionally, the `list_iterate` native in `wren_core.c` now returns `false` immediately when the list count is zero and the iterator argument is null, preventing an out-of-bounds index of 0 from being returned for empty lists. The test file `test/list/concat.wren` is renamed to `test/list/plus.wren` and extended with a check that the original list `a` remains unmodified after concatenation. A new test in `test/list/iterate.wren` verifies that iterating over an empty list returns `false`.
2014-02-15 01:24:06 +00:00
Kyle Marek-Spartz
e690a48e45 feat: implement List concat operator + supporting Range and empty lists
Add `+` method to List class in core.wren that creates a new list by concatenating elements from both operands. Supports concatenation with Range objects and handles empty lists on either side. Includes comprehensive test cases in test/list/concat.wren covering list-list, list-range, and empty list combinations.
2014-02-14 17:09:02 +00:00
Bob Nystrom
e3b3fef0fb feat: make this the implicit receiver for method calls inside class bodies
In the compiler, when a bare name is encountered inside a class definition and it does not resolve to a local variable or global, emit an implicit `this.` load before the call, enabling getter, setter, and method calls without explicit receiver. Update all benchmark, builtin, and test files to remove redundant `this.` qualifiers, and add comprehensive test suites for implicit receiver behavior across instance, inherited, static, nested, and shadowing scenarios.
2014-02-13 01:33:35 +00:00
Bob Nystrom
f3d287d430 fix: handle parameter list checking for closures in callFunction 2014-02-10 15:53:09 +00:00
Bob Nystrom
86015f4e48 feat: add numParams tracking and arity-checked fn.call variants for extra/missing args
Add `numParams` field to `ObjFn` and `Compiler` structs to track expected parameter count. Refactor `parameterList` to return count and store it in compiler. Modify `endCompiler` to pass `numParams` to `wrenNewFunction`. Replace single `fn_call` native with 17 arity-specific `fn_call0` through `fn_call16` natives that validate argument count against `fn->numParams` via `callFunction` helper, returning error on missing args. Remove stale TODO comment in VM interpreter. Add test files `call_extra_arguments.wren` and `call_missing_arguments.wren`.
2014-02-04 17:34:05 +00:00
Bob Nystrom
dbf0131776 feat: move OS.clock to IO.clock and remove deprecated os_clock native
Migrate the clock timing functionality from the OS class to the IO class across all benchmark scripts and the core library. Remove the os_clock native function and its associated OS class definition from wren_core.c, while adding a new ioClock native in wren_io.c that uses the same clock()/CLOCKS_PER_SEC logic. Update all benchmark files (binary_trees, fib, for, method_call) to reference IO.clock instead of OS.clock for both start time and elapsed time calculations.
2014-02-04 16:49:16 +00:00
Bob Nystrom
99eac12fd3 refactor: extract IO class into separate module with wrenLoadIOLibrary and wren_io.c
Replace monolithic corelib.wren with per-class builtin/*.wren files and generate_builtins.py script. Move IO class definition and its native writeString_ method from wren_core.c to new wren_io.c, adding wrenGetArgumentString and wrenDefineStaticMethod to the public API. Update Makefile target from corelib to builtin and remove generate_corelib.py.
2014-02-04 16:44:59 +00:00
Bob Nystrom
1607b6d2dd feat: allow Range objects as list subscript operator arguments
Extend the list subscript operator to accept Range arguments in addition to plain numbers. When a Range is provided, the operator returns a new list containing the elements within that range, supporting inclusive (..) and exclusive (...) bounds, negative indices that count from the end, and automatic reversal for backwards ranges. Added validation functions for integer values and range bounds, with dedicated error messages for non-integer range endpoints and out-of-bounds conditions. Updated the test suite with comprehensive range subscript tests and removed the old test that only checked for non-numeric subscripts.
2014-01-30 17:12:44 +00:00
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
7a2fad17ed fix: remove redundant manual increment of loop variable in List.toString
The for-in loop in Wren already increments the loop variable automatically, so the explicit `i = i + 1` inside the loop body was causing every other element to be skipped when building the string representation of a List. This fix removes the unnecessary increment from both the corelib.wren source and the embedded string in wren_core.c.
2014-01-21 16:23:30 +00:00
Bob Nystrom
7e3b9a6bcb fix: validate number comparison operand types in num_lt, num_gt, num_lte, num_gte
Replace silent RETURN_NULL for non-numeric right operands with explicit runtime error via validateNum in four comparison primitives (num_lt, num_gt, num_lte, num_gte). Also remove redundant IS_NUM check in num_mod. Add four new test files verifying runtime error messages for each comparison operator when given a boolean operand.
2014-01-21 15:44:11 +00:00
Bob Nystrom
00008eae9a refactor: replace while loop with for-in range in List.toString method 2014-01-20 21:43:22 +00:00
Bob Nystrom
cf5a34025b feat: add isInclusive field to ObjRange and implement proper exclusive range iteration
Add isInclusive boolean to ObjRange struct to distinguish between inclusive (..) and exclusive (...) ranges. Update wrenNewRange signature to accept isInclusive parameter. Implement correct iteration logic for both ascending and descending ranges, handling empty exclusive ranges and floating-point iteration. Add type validation for range RHS operands. Update min/max/to properties to return raw endpoint values instead of adjusted ones. Add comprehensive test coverage for inclusive/exclusive ranges, negative ranges, empty ranges, floating-point iteration, isInclusive property, toString, and type error cases.
2014-01-20 21:20:22 +00:00
Bob Nystrom
ebb47d30e6 feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 16:45:15 +00:00
Bob Nystrom
8abfb4ec7d feat: add fiber.isDone property and runtime error checks for finished fiber operations
Add a new `isDone` native method to the Fiber class that returns true when the fiber has no remaining frames. Replace TODO comments with proper runtime error handling in `fiber_run`, `fiber_run1`, `fiber_yield`, and `fiber_yield1` to prevent running finished fibers or yielding from the main fiber. Include test cases verifying the new property and error conditions.
2014-01-13 14:58:27 +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
fc4880774e feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 19:02:07 +00:00
Bob Nystrom
193e4e30ab feat: add ceil, cos, sin, sqrt, isNan native methods and division-by-zero tests
Implement five new Num methods (ceil, cos, sin, sqrt, isNan) in wren_core.c and register them on the Num class. Add corresponding test files for ceil, floor, is_nan, and sqrt. Extend divide.wren with division-by-zero edge cases (inf, -inf, nan). Remove stale TODO comments from minus, multiply, and plus tests.
2014-01-08 15:47:14 +00:00
Bob Nystrom
ce2e227683 feat: add floor method to Num class for rounding down to nearest integer
Implement the `floor` native method on the `Num` class in `wren_core.c`, which delegates to C's `floor()` function to round a number down to the nearest integer value. Register the new method in `wrenInitializeCore` alongside the existing `abs` method.
2014-01-08 07:03:25 +00:00
Bob Nystrom
01cc6538ef fix: increase number-to-string buffer size from 21 to 24 for double precision
The previous buffer size of 21 bytes was insufficient to hold the longest possible
double representation formatted with "%.14g", which can reach 24 bytes including
the null terminator. Updated the buffer to 24 bytes and extracted the numeric
value into a local variable for clarity.
2014-01-06 15:53:41 +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
53884b1332 feat: replace validateIndexOld with validateIndex and add validateString for core methods
Remove the deprecated validateIndexOld function and migrate all callers to the new validateIndex that reports runtime errors. Add validateString helper for string argument checking. Introduce comprehensive runtime error tests for list and string subscript operations, removeAt, and contains methods, replacing old silent null returns with proper error halting.
2014-01-03 18:47:26 +00:00
Bob Nystrom
6fb8804c9e feat: add validateNum/validateInt helpers and runtime type checks for list methods
Replace the old validateIndex function with validateNum and validateInt helpers that produce descriptive runtime error messages. Add new test files covering invalid index types, out-of-bounds indices, and iterator validation for list insert, iterate, and iteratorValue methods. Rename existing number operator error tests to use consistent "must be a number" phrasing.
2014-01-02 15:32:00 +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
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
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
d6e4d6bcf7 refactor: change CallFrame and Method fn fields from Value to Obj*
Replace the `fn` field in `CallFrame` and `Method` structs from `Value` to `Obj*`, since it always holds an ObjFn or ObjClosure. Update all callers to use `AS_OBJ` and `markObj` instead of `markValue`. Fix a bug in `freeObj` where `OBJ_CLOSURE` case incorrectly freed the upvalues flexible array instead of falling through to the no-op case.
2013-12-26 00:12:07 +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
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
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
8c13258ef6 feat: promote Fiber from raw struct to heap-allocated ObjFiber with GC support
Refactor the VM's fiber representation from a stack-allocated `Fiber` struct embedded in `WrenVM` to a full `ObjFiber` object managed by the garbage collector. This includes adding the `OBJ_FIBER` object type enum, a `wrenNewFiber` allocation function, a `markFiber` traversal routine for GC marking, and updating all internal APIs (`DEF_FIBER_NATIVE`, `wrenDebugDumpStack`) to use `ObjFiber*` instead of `Fiber*`. The `Fiber` struct definition and its associated `CallFrame` type are moved from `wren_vm.h` into `wren_value.h`, and the `STACK_SIZE`/`MAX_CALL_FRAMES` constants are relocated accordingly. Additionally, the `vm->fiber` singleton pointer is removed, the `vm->unsupported` sentinel value is eliminated (replaced by returning `NULL_VAL` for invalid numeric operands), and the `wrenInterpret` function is temporarily removed. The `wrenNewClass` function's metaclass pinning order is also corrected to prevent premature GC collection.
2013-12-22 22:31:33 +00:00
Bob Nystrom
7e8edd68ea feat: make IO.write call toString on argument and add corelib with List.toString 2013-12-22 19:50:00 +00:00
Bob Nystrom
91873b3a90 refactor: split class creation into raw single-class and superclass binding phases
The bootstrapping of Object and Class now uses a two-phase approach: first creating a raw class with no metaclass or superclass via wrenNewSingleClass, then explicitly wiring superclass relationships with wrenBindSuperclass. This eliminates the need for special-case handling of null superclasses in the old newClass function and makes the metaclass chain setup explicit in wrenInitializeCore.
2013-12-22 04:44:37 +00:00
Bob Nystrom
8bb1a94a25 refactor: convert IO from singleton instance to static class with metaclass native methods
Replace the global `io` singleton object with a static `IO` class, moving the `write` native from the instance to the metaclass. Update all benchmark, example, and test files to use `IO.write()` instead of `io.write()`.
2013-12-22 03:25:09 +00:00