Commit Graph
507 Commits
Author SHA1 Message Date
Bob Nystrom 041e6213d5 refactor: change ObjString length field from size_t to int for consistency and reduced memory usage
The length field in ObjString struct now uses int instead of size_t, saving memory
and aligning with other string length storage conventions throughout the VM.
This eliminates signed/unsigned conversion warnings and matches the type used
elsewhere for string lengths.
2015-01-08 15:41:30 +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
Evan Shaw 34670fa586 feat: store explicit string length in ObjString struct for wren values
Add a `length` field to the `ObjString` struct in `wren_value.h` and initialize it in `wrenNewUninitializedString()` in `wren_value.c`. This stores the string's byte count excluding the null terminator, enabling O(1) length retrieval while preserving null-terminated C string compatibility.
2015-01-07 20:53:32 +00:00
Bob Nystrom c1980e4c58 refactor: embed string data as flexible array member in ObjString
Remove separate heap allocation for string text by converting ObjString.value from a char pointer to a C99 flexible array member. This eliminates the extra allocation in wrenNewUninitializedString and the corresponding free in wrenFreeObj, reducing memory fragmentation and pointer indirection for all string objects.
2015-01-07 15:20:12 +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
Yury Korchemkin c769f93833 fix: treat carriage return as whitespace instead of line token in lexer 2015-01-06 02:33:49 +00:00
Evan Shaw 0dcd7bbffc refactor: embed string data as flexible array member in ObjString struct
Remove separate heap allocation for string text by storing it directly in the ObjString struct using a C99 flexible array member. This eliminates the need for an extra pointer indirection and a separate memory allocation call in wrenNewUninitializedString, while also simplifying the cleanup logic in wrenFreeObj by removing the explicit deallocation of the string's value buffer.
2015-01-05 02:03:50 +00:00
Yury Korchemkin a137ea8ccd feat: add support for carriage return as line terminator in lexer
- Open source files in binary mode to prevent OS-level newline translation
- Treat '\r' character as equivalent to '\n' in the tokenizer
- Handle '\r' followed by '\n' as a single line break via twoCharToken
2015-01-04 22:25:17 +00:00
Bob Nystrom b61e55d4c9 fix: skip duplicate lexer error reporting in compiler error handler
The `error()` function in the compiler now returns early when the offending token
is of type `TOKEN_ERROR`, preventing the lexer's already-reported error from
being emitted a second time to stderr. This eliminates redundant error messages
for malformed tokens.
2015-01-04 21:10:46 +00:00
Bob Nystrom 96d893a637 feat: ignore shebang lines starting with #! on first line of source
Add special handling in the lexer's nextToken function to detect a '#' character followed by '!' on the first line (currentLine == 1) and skip the entire line as a comment. If the shebang appears on any other line, or if a '#' is not followed by '!', emit a lex error for invalid character. Include test cases for valid shebang execution, shebang at EOF, shebang on a non-first line (expected error), and an invalid shebang pattern (expected error).
2015-01-04 21:02:42 +00:00
Bob Nystrom ed31544ead fix: handle empty and comment-only files by removing early skip in repl and compiler
Remove the empty-line check in runRepl that skipped interpretation for blank input, and refactor the main compilation loop in wrenCompile to use a while loop with TOKEN_EOF matching instead of a for loop with redundant EOF break. This allows the compiler to process files containing only comments or whitespace without prematurely terminating, fixing issue #57. Add test fixtures for comment-only source files.
2015-01-04 21:00:53 +00:00
Gavin Schulz 9fe43fec45 feat: include method arity in missing method runtime error messages
Add helper functions `canonicalSymbol` and `methodArgumentsString` to extract and format the argument count from symbol names. Update the runtime error message in `runInterpreter` to append the arity (e.g., "with 0 arguments", "with 2 arguments", "with 1 argument") when a class does not implement a method. Add new test cases for missing methods with one, two, and eleven arguments, and update all existing test expectations to include the arity suffix.
2015-01-04 19:42:11 +00:00
mauvm 6a69382275 refactor: inline unmatchedChar logic into nextToken and add shebang error test 2015-01-04 18:56:16 +00:00
mauvm 685f791fb0 fix: remove duplicate comment in unmatchedChar function in wren_compiler.c 2015-01-04 07:52:40 +00:00
Bob Nystrom 0451059109 fix: skip wrenInterpret call when REPL input is empty newline 2015-01-04 07:40:20 +00:00
mauvm 9828fafee7 feat: ignore shebang lines starting with #! on first line in compiler lexer 2015-01-03 19:53:12 +00:00
Gavin Schulz 7048facaa4 fix: skip wrenInterpret call when REPL input is empty line
Add a strcmp check against "\n" before invoking wrenInterpret in the
runRepl function, preventing an unnecessary interpretation attempt and
potential error handling for blank user input.
2015-01-03 19:25:10 +00:00
Bob Nystrom 1951059c8f feat: remove semicolon token from lexer and treat it as invalid syntax
Remove the `;` case from the `nextToken` function in `wren_compiler.c` so that semicolons are no longer lexed as `TOKEN_LINE`. Update the documentation in `doc/site/syntax.markdown` to describe newlines as the sole statement separator, and adjust all test files (`test/limit/many_constants.wren`, `test/limit/many_globals.wren`, `test/limit/too_many_constants.wren`, `test/semicolon.wren`) to reflect that semicolons now produce an error instead of being treated as line breaks.
2015-01-03 18:02:45 +00:00
Aleksander d67036b95d fix: extend whitespace skipping in nextToken to handle tabs and add test coverage 2015-01-03 13:57:34 +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
Aleksander 4236d1e2de fix: treat tab character as valid whitespace in tokenizer
Add explicit case for '\t' alongside space character in the nextToken function's whitespace-skipping logic. Previously, only spaces were consumed during whitespace skipping, causing tab characters to be incorrectly treated as unexpected tokens. The fix ensures tabs are properly skipped by first matching the tab case and then falling through to the existing space-handling loop.
2015-01-02 22:22:09 +00:00
Paul Woolcock bdede9cd32 feat: implement IO.read method with stdin input buffer and prompt support
Add static `IO.read(prompt)` method to the IO class that writes the prompt to stdout
and reads a line from stdin into a 1024-byte buffer. The C implementation uses
`fgets` for input and returns the string via `wrenReturnString`. The Wren wrapper
calls `IO.write` for the prompt before delegating to the native `IO.read` method.
2015-01-02 16:07:43 +00:00
Bob Nystrom f069a38228 style: rename local variable num_read to numRead and reorder feof check in runRepl 2015-01-02 15:31:02 +00:00
Paul Woolcock 7c25b4e187 fix: check getline return value to suppress gcc warning and fix build failure
The getline function's return value was previously ignored, causing gcc to emit a
warning that was treated as an error during build. This commit captures the return
value in a ssize_t variable and adds a check for -1 (indicating read failure) to
the existing feof(stdin) condition, ensuring both EOF and error conditions are
properly handled.
2015-01-02 13:10:03 +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 d34cbd33ee perf: cache frame stack start pointer in local variable to reduce memory accesses
Store the start of the current frame's stack in a local `stackStart` variable
during LOAD_FRAME() macro execution, replacing repeated calculations of
`fiber->stack[frame->stackStart + offset]` with `stackStart[offset]` across
LOAD_LOCAL and LOAD_FIELD opcodes. Also remove unused `upvalues` register
variable and its assignments from closure handling paths.
2014-12-08 14:57:36 +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 520e841044 feat: add specialized LOAD_LOCAL_0..8 instructions to skip arg byte decode
Introduce nine new bytecode instructions (CODE_LOAD_LOCAL_0 through CODE_LOAD_LOCAL_8) that directly encode the local slot number in the opcode itself, eliminating the need to read and decode a separate argument byte for the most frequently accessed local variables. This optimization targets the hottest path in the interpreter, as LOAD_LOCAL is the most executed instruction across benchmarks (e.g., 3.75M times in delta_blue). The compiler's `loadLocal` helper emits the specialized opcode when the slot index is ≤8, falling back to the generic `CODE_LOAD_LOCAL` with an argument byte otherwise. The VM dispatch table and debug printer are updated accordingly. Benchmarks show consistent speedups: fib +7.3%, method_call +5.9%, binary_trees +1.9%, for +2.8%, delta_blue +1.0%.
2014-12-07 03:59:11 +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 9b498b4638 fix: ensure all switch and unreachable paths return a value in release builds
In `getNumArguments`, add a `return 0` after the `UNREACHABLE()` default case to prevent
undefined behavior when assertions are disabled. In `wrenGetClass`, reorder the
`UNREACHABLE()` macro before the `return NULL` so the unreachable annotation is
always emitted. In `runInterpreter`, replace the `ASSERT(0, ...)` with an explicit
`UNREACHABLE()` and `return false` to guarantee a return value on all control paths
when the interpreter exits unexpectedly.
2014-12-02 05:36:06 +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 3266491cf5 fix: correct break statement instruction size from 2 to 3 in endLoop to prevent code walker from misinterpreting arguments 2014-11-27 02:33:54 +00:00
Bob Nystrom d9a42f21ba fix: add missing -lm link flag and fix GCC warnings for getline and switch coverage
Add -lm flag to both debug and release linker commands in Makefile to resolve
undefined math library references. Define _GNU_SOURCE in main.c to make getline()
available under GCC. Add default cases to switch statements in runFile and
getNumArguments to suppress -Wswitch warnings. Fix u_int8_t to uint8_t type in
wrenNewFunction declaration and definition for POSIX compliance.
2014-11-26 22:03:05 +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 4d413f3473 fix: add null check when walking upvalue list in captureUpvalue
The crash occurred in captureUpvalue() when an upvalue for an earlier local
variable was captured after a later one. The function walked to the end of the
open upvalue list but then dereferenced a NULL pointer when comparing
upvalue->value against the target local slot.

Added a NULL guard before the equality check so that if no existing upvalue
is found, the function correctly proceeds to create a new one instead of
dereferencing a null pointer.

Also fixed a typo in the comment ("existsing" -> "existing").

Added regression test close_over_later_variable.wren that exercises the
scenario of capturing upvalues for locals in reverse declaration order.
2014-04-25 00:52:53 +00:00
Bob Nystrom 8abbc4197c feat: add MAX_VARIABLE_NAME limit and improve field overflow error message
Add a 64-character maximum identifier length with compile-time error reporting, and enhance the runtime field overflow error to include the class name and remove the TODO comment. Update test expectations for both limit scenarios.
2014-04-22 14:06:26 +00:00
Bob Nystrom e665d4a9d3 feat: add closure test for shadowing closed-over variable with local
Add a new test case `shadow_closure_with_local.wren` that verifies a closed-over
variable can be shadowed by a local variable in an inner scope within the same
closure. The test ensures that the outer closure variable retains its value
outside the inner scope after the shadowing local goes out of scope.

Also remove an incomplete TODO comment from `reuse_closure_slot.wren` and add
a detailed TODO comment in `wren_compiler.c` discussing the design trade-off
between treating capitalized names as globals versus implicit `this` calls
when walking the scope chain.
2014-04-20 00:48:06 +00:00
Bob Nystrom 29f4b8167c feat: add zero-arg IO.print overload and remove newline skipping in parameter parsing
Add a static `print` method with no arguments that writes only a newline, enabling blank-line output. Remove the `ignoreNewlines` calls before closing parentheses in parameter lists and method calls, tightening syntax rules. Add a `strlen` TODO comment in symbol table lookup for future optimization. Move the `Foo.toString` test from `test/io/write.wren` to `test/io/print.wren` and delete the old write test file.
2014-04-19 18:44:51 +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 3e5fdc2250 feat: add overloaded IO.print methods accepting 2-16 arguments and printList_ helper
Add 15 static overloads of IO.print in builtin/io.wren and src/wren_io.c, each delegating to a new private printList_ method that iterates over a list of objects. Update all benchmark and test files to use the new multi-argument syntax, removing explicit .toString calls and string concatenation. Add a comprehensive test/io/print.wren verifying single-argument return value, multi-argument null return, and concatenation of up to 16 arguments.
2014-04-09 14:48:35 +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 8113e0bfc0 perf: inline wrenIsBool and wrenIsObjType into header, remove from source
Move the wrenIsBool and wrenIsObjType function definitions from wren_value.c
into wren_value.h as inline functions, eliminating function call overhead.
Also relocate OBJ_VAL macro definition to appear before its first use in the
header and add inline for wrenObjectToValue. This yields 3-13% speedup across
benchmarks (binary_trees, delta_blue, fib, for, method_call).
2014-04-08 14:17:25 +00:00