This exposes the optimization level for a few reasons.
First, Local value numbering exposed some bad codegen. Playing with
optimiaztion level exposes this more easily.
When compiling dead code in a known unused scope, we
would generate code that tried to load invalid slots.
Make sure that unused code will still pass `janet_verify()` as
invalid code could trigger bad behavior in our optimizer or garbage
collector.
Since the code was proven dead, this would not trigger any runtime
behavior issues though.
Second, even trivial optimizations tend to break debug information. For
example, constant propogation will eliminated symbol mappings which can
be useful for debugging. By default, don't eliminate any symbol map
debug info.
on 32 bit systems in some cases.
Since most internal arrays in Janet have 32 bit limits, this is is not
hit in practice on 64 bit systems, except in cases of user input. Apply
a fix more generally to simply avoid the issue by coding "defensively".
Some applications are not strictly needed.
Upvalues are stored in the symbol slots structure as well, but
since they are always live, we repurpose the death_pc field to
refer to the environment index that we want to look at at runtime.
Also fix marshalling functions without full
sourcemapping information, as well as thread/receive
ignoring bad messages. Instead, thread/receive will error
on bad messages.
This changes the implementation of the `next` function which
is now used to implement each. This let's us iterate over
more types, not just tables and structs.
Also make integer to size_t casts explicit rather than relying on
int32_t * sizeof(x) = size_t. This is kind of a personal preference for
this problem.
Because we use an amalgated build, feature
test macros should be set in a single file that
is included before any other headers, and is placed
at the top of the amalgamated build.
This unifies equality and comparison checking. Before, we had
separate functions and vm opcodes for comparing general values vs.
for comparing numbers, where the numberic functions were polymorphic and
had special cases for handling NaNs. By unfiying them, abstract types
can now better integrate with other number types and behave as keys.
For now, the old functions are aliased but will eventually be removed.
This makes the names of the opcodes match their implied functionality.
We also rename the C functions to match the opcodes and source level
functionality.