Required a few changes to APIs, namely janet_root_fiber()
to get topmost fiber that is active in the current scheduler.
This is distinct from janet_current_fiber(), which gets the bottom
most fiber in the fiber stack - it might have a parent, and so cannot
be reliably resumed.
This is the kind of situation that makes symmetric coroutines more
attractive.
These functions interact with Janet's dynamically scoped
IO functions in a manner that is more useful the file/flush.
We can still redirect to a buffer without changing our code.
This way we can support fewer build configurations. Also, remove
all undefined behavior due to use of memcpy with NULL pointers. GCC
was exploiting this to remove NULL checks in some builds.
This means we can add new properties to abstract types without
breaking old code. We can also make simple abstract types without
needing to add many NULL fields to the type.
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.
In some cases, one might want to disable what is currently
SipHash for speed / better security mechansims. For example, using
red black trees for caches rather than hash tables.
The hash key still needs to randomly initialized
for the security advantage, but this patch is a
step closer to avoiding hash based DOS.
Further work may including exposing the raw hash
function for use by abstract types who also choose to
implement hash.
On very long binding names > 256 characters, a buffer overrun would be
trigger in janet_cfuns. Not a huge issue, since this is not really code
that would ever be user facing, but we can fix this.
While C functions are not re-entrant, signaling from a C function
can be used to implement async returns. When resuming a fiber that
signalled from within a C function, the fiber is started after the
instruction that emitted the signal. The resume argument is used
as the return result from the c function.
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 adds several common patterns, which are defined in
boot.janet. This essentially gives more primitive patterns
to work with out of the box.
Fix build when JANET_REDUCED_OS is defined.
(thread/send thread msg &opt timeout) can now timeout. Also
changed thread/self to thread/current for better consistency with
fibers, and all blocking operations will by default timeout after 1
second. I think its bad to make things block forerver by default.
Gives more control over unmarshalling
abstract types. This should also
make it possible/easy to write abstract types that cannot
cause unmarshal to segfault.
True top level unquote currently requires basically double compilation
as it currently stands. Also, implementing such double compilation
looses all source mapping information. This is a compromise
implementation that makes it clear that this works differently than
a true top-level unquote.
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.
Rather than messing with janet_core_dictionary, we
instead cache the core enevironment, and pull out the
needed tables from there. This is more flexible, more correct, and
also exposes janet_resolve_core, which can be easily used from the C
API.
The janet_get_permissive function implements the core semantics
of the 'get' function. The original janet_get implements the semantics of
the 'in' function and also the OP_GET opcode. This slight oddity is
to avoid a backwards incompatible change.
A finalizer can be attached to scratch allocations efficiently at any point in
it's lifecycle via janet_sfinalizer. Care was taken to keep allocations aligned
with platform alignment requirements.
A big drawbacks to this approach is the waste of up to 16 bytes per scratch
allocation in the case the scratch memory does not require a finalizer.
doc macro can take no arguments and print out
all bindings. Fix an issues with the vm skipping
over a breakpoint in some situations.
Add examples/debugger.janet for proof of concept
debugger.
When file was created with file/popen, the current optimization
of using fseek on windows fails due to windows not properly returning
and error code and just returning 0. Windows :(.
The new RNG wraps up state for random number generation, so
one can have many rngs and even marshal and unmarshal them.
Adds math/rng, math/rng-uniform, and math/rng-int.
Also introduce `in` and change semantics for
indexing out of range. This commit enforces stricter
invariants on keys when indexing via a function call
on the data structure, or the new `in` function.
The `get` function is now more lax about keys, and will
not throw an error when a bad key is used for a data structure, instead
returning the default value.
Flychecking will now work correctly with arity checking, and
will better handle imports. Well structured modules should interact
cleanly with the flychecker in a mostly safe manner, but maliciously
crafted modules can execute arbitrary code. As such, the flychecker is
not a good way to validate completely untrusted modules.
We also extend run-context with an :evaluator option to replace
:compile-only. This is more flexible and allows users to create their
own flychecker like functionality.
This allows some more optimizations when printing to
buffers or when output is disabled. It also makes printf
more consistent with print and prin (Same with eprintf).
The print family of functions now writes output
to an optional buffer instead of a file bound to :out.
This means output can be more easily captured an redirected.
This should help catch a number of errors, but it
is a very shallow implementation of type checking. It will
catch some common misuses of functions at compile time
rather than runtime.
This will prevent these functions from being run
with empty strings, which usually produces useless
output, as the internal string search algorithm will
never "find" empty strings. This is by design, as it is
not always obvious which empty strings should be found in
the search text.
This should be friendlier to most users. It does, however, mean
we lose range information. However, range information could be
recovered by re-parsing, as janet's grammar is simple enough to do this.
Also adds the janet_lengthv API call. This is
needed because janet_length returns a 32 bit integer, where
as lengthv lets us return larger values (useful for typed arrays).
janet_mcall is an api function that should make it easier to call
a janet method from C code. It shares a similar signature with
janet_call.
Remove the multiple caching tables we were using
and use the grammar table for caching. This works
well because we can use raw_get for checking the local cache, and normal
get fro checking the global cache.
A keyword reference only counts as visited if we have
it as cached in the memoized->table, and we know it was
originally referenced from the same grammar table. If these
two conditions are true, then compilation must work correctly.
Also add janet_table_get_ex.
(backmatch [tag?]) is similar to a back reference in regular expressions
(NOT to backwards capture in a peg). It only matches a pattern if
it exactly matches the text of the last capture. It does not consume
or push any captures to the capture stack.