Commit graph

15 commits

Author SHA1 Message Date
8233e94ab3 gc: Speed up new_object by adding new blocks to the front of the list
This way we don't have to traverse the whole list to the very end every
time we want a new object.
2023-03-21 20:54:09 +01:00
55c95f99ad Rename format => io_writer
To make it clearer that this can be used for writing binary data too.
2023-02-10 21:48:31 +01:00
607da73c62 Add functions for reading/writing files and introduce native objects 2023-01-29 16:46:00 +01:00
20c2880f4c Implement assigning into dictionaries
It's now possible to assign to a key of a dictionary and even to a nested
key path.

This patch changes the way matchers work a bit:
First, a function call stack frame now has a stack of matchers that are
manipulateable instead of a single matcher.
Second, the matcher is now in charge of setting the matched values to the
variables (previously the caller of the matcher needed to extract the
matched values and assign them itself). This change simplifies code
generation, especially for chained assignments and dictionary key paths.

This removes the last usage of APFL_ERR_NOT_IMPLEMENTED :)
2022-11-19 23:26:52 +01:00
f0811ba8fe Implement global "gc" function
To dump the current GC state and do a manual collection
2022-11-19 22:21:32 +01:00
0474a85c6f gc: New debug flag to log oject creation/destruction 2022-08-12 14:50:28 +02:00
1630314dc7 Implement matching assignments
This allows the destructuring of lists into individual values.
We can have arbitrarily nested lists, can check for constant values and can
have up to one '~'-prefixed variable per list, that will capture the
remaining elements of the list.

It is implemented as a second set of bytecode instructions, which define a
matcher. These matchers should also enable us to implement the same pattern
matching capabiities for function parameters.

Not all matching features are implemented yet, predicate matching and
matching into a dictionary key is not implemented yet.
2022-07-28 20:46:32 +02:00
55fb3c6345 gc: Add some optional debugging features 2022-07-15 21:56:30 +02:00
7e592cdb96 gc: Prevent recursive garbage collection 2022-07-14 22:08:50 +02:00
a4f7f0f2ff Implement functions and function calls
We can now define and call functions. Lexical closure scopes are also
working :).

It's limited to simple functions or complex functions with a single
argument list of only variable names for now.
2022-07-11 21:41:05 +02:00
eb7cb0baf7 gc+context: Make stack no longer a gc object
The new roots callback mechanism makes it possible to traverse the gc
objects on the stack without needing the stack to be an gc object.

This also uncovered a nasty bug in apfl_stack_pop where we passed in a
wrong mem pointer into apfl_resizable_splice. We should probably find a way
to make the apfl_resizable_* functions a bit safer, the need for casting
stuff to void** easily hides errors.
2022-07-01 22:40:43 +02:00
c974b675e1 gc: Use a callback to get the (non-tmp) roots
This let's us get rid of that awkward hashmap in the GC that was used as a
set, makes determining the roots more flexible and now gc_init can't even
fail any more, as there are no allocations happening here any more :)
2022-07-01 22:00:58 +02:00
b3322c93e9 Move scope functions/structs out of context.[ch] 2022-04-15 14:41:22 +02:00
6add5e47b9 hashmap: Improve cursor / peek API
- peek functions will now return pointers directly
- cursor access methods can now return an error, if the cursor is already
  at the end

Also rewrote some cursor loops to use the HASHMAP_EACH macro.
2022-04-11 23:31:20 +02:00
90a80152e1 Implement mark&sweep garbage collection and bytecode compilation
Instead of the previous refcount base garbage collection, we're now using
a basic tri-color mark&sweep collector. This is done to support cyclical
value relationships in the future (functions can form cycles, all values
implemented up to this point can not).

The collector maintains a set of roots and a set of objects (grouped into
blocks). The GC enabled objects are no longer allocated manually, but will
be allocated by the GC. The GC also wraps an allocator, this way the GC
knows, if we ran out of memory and will try to get out of this situation by
performing a full collection cycle.

The tri-color abstraction was chosen for two reasons:

- We don't have to maintain a list of objects that need to be marked, we
  can simply grab the next grey one.
- It should allow us to later implement incremental collection (right now
  we only do a stop-the-world collection).

This also switches to a bytecode based evaluation of the code: We no longer
directly evaluate the AST, but first compile it into a series of
instructions, that are evaluated in a separate step. This was done in
preparation for inplementing functions: We only need to turn a function
body into instructions instead of evaluating the node again with each call
of the function. Also, since an instruction list is implemented as a GC
object, this then removes manual memory management of the function body and
it's child nodes. Since the GC and the bytecode go hand in hand, this was
done in one (giant) commit.

As a downside, we've now lost the ability do do list matching on
assignments. I've already started to work on implementing this in the new
architecture, but left it out of this commit, as it's already quite a large
commit :)
2022-04-11 22:24:22 +02:00