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.
- Rename "Expressions" -> "Method Calls".
- Organize "Types" and "Language" into a single linear narrative.
- Mobile-specific navigation to handle the longer guide.
- Rename "Fibers" -> "Concurrency".
- Get rid of duplicate stuff about signatures in "Classes".
- Add next/prev links to each page in the guide.
- Move "Contributing" and "Community" up to the top level.
- Move the precendence table to a separate "Grammar" page.
- Lots of other little stuff.
- 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.