- Allow this for both argument lists and block arguments.
- Tweak precedence to make "." higher than infix "{}" to avoid a
class body being parsed as the superclass clause's block argument.
- Convert all uses of ".call" to use this. (There was not a single
case in the repo that ran into the getter ambiguity.)
This fixes the nasty case where "foo(bar)" is context-sensitive, and
generally simplifies the compiler a lot since there is a clear
distinction between lexical and dynamic scope.
Also:
- Remove the special handling of capitalized names since all names are
lexical now.
- Allow methods to close over local variables in enclosing functions.
- Allow implicit definition of all lexical names.
If we ever support custom string templates, we'll need to go back to
compiling them to functions. But, for now, they can be evaluated
eagerly, leading to simpler code.
This allows "%(...)" inside a string literal to interpolate the
stringified result of an expression.
It doesn't support custom interpolators or format strings, but we can
consider extending that later.
- Make sure it handles an empty gray set.
- Make sure growing the gray stack doesn't itself trigger a GC.
- Make sure it works when stress testing is enabled.
- Ensure the tests kick off a GC.
The previous GC implementation used a recursive mark method. This can
result in stack overflows when attempting to mark deeply nested objects.
This commit replaces the recursive approach with an iteritive one,
moving the state stack from the C call stack to the `WrenVM` structure.
As objects are 'grayed' they are pushed onto the VM's gray stack. When
we have grayed all of the root objects we iterate until the stack is
empty graying any obejcts which haven't been marked as dark before. At
the end of the process we clean up all unmarked objects as before.
This commit also adds a few new tests which check garbage collection by
allocating some new deeply nested objects and triggering the GC a few
times in the process.
Wren now has three classes of modules:
- The one magic "core" module that's built in and always needed.
- Auxiliary libraries like "meta" and "random". These do not have any
dependencies, so can be used even when you embed Wren inside an
application. But they're also optional and can be disabled if you
don't need them.
- CLI modules. These ones need libuv and are tied to the CLI wrapper
around the VM.
Primitives still have a return value to indicate normal value returning
versus runtime errors or fiber switching since it minimizes branches
in the common case of a normal value result.
Instead, Fn.call(...) is a special *method* type that has the same
special sauce. The goal is eventually to get rid of the primitive
result type entirely.
- Add Fiber.transferError(_).
- Primitives place runtime errors directly in the fiber instead of on
the stack.
- Primitives that change fibers set it directly in the VM.
- Allow a fiber's error to be any object (except null).
- Add an explicit va_list version. That lets variadic functions
forward to it.
- Fix a GC bug in wrenCall() with return values.
- Make the call API test not re-enter the VM.
- Test that a foreign method can return strings.
- Test that a foreign method can return a string with null bytes.
- Test wrenCall().
- Allow passing NULL for "v" to wrenCall().
- Allow "a" for passing an explicit length byte array to wrenCall().
Get rid of the separate opt-in IO class and replace it with a core
System class.
- Remove wren_io.c, wren_io.h, and io.wren.
- Remove the flags that disable it.
- Remove the overloads for print() with different arity. (It was an
experiment, but I don't think it's that useful.)
- Remove IO.read(). That will reappear using libuv in the CLI at some
point.
- Remove IO.time. Doesn't seem to have been used.
- Update all of the tests, docs, etc.
I'm sorry for all the breakage this causes, but I think "System" is a
better name for this class (it makes it natural to add things like
"System.gc()") and frees up "IO" for referring to the CLI's IO module.