This turns those functions into general-purpose functions for writing
raw C values into slots on the foreign call stack.
Writing a return just means writing a value to slot 0.
- wrenGetArgumentCount() -> wrenGetSlotCount()
- wrenGetArgument___() -> wrenGetSlot___()
Also, the get functions assert that the value is the right type instead
of checking at runtime. This puts the onus on the caller to be safe,
but maximizes performance.
I've got some ideas on how to tweak the embedding API, but I want to
see what performance impact they have first, so this adds a little
benchmark that just calls a foreign method a ton of times.
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.
- 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.
Most of the pieces are there:
- You can declare a foreign class.
- It will call your C function to provide an allocator function.
- Whenever a foreign object is created, it calls the allocator.
- Foreign methods can access the foreign bytes of an object.
- Most of the runtime checking is in place for things like subclassing
foreign classes.
There is still some loose ends to tie up:
- Finalizers are not called.
- Some of the error-handling could be better.
- The GC doesn't track how much memory a marked foreign object uses.