Closures (and garbage collection for environments, which is required by closures) (#1)
* Add proper reference counting to environments
* It has become clear we need a garbage collector for environments before we can implement closures
* Allow line comments starting with #
* Allocate Environments from a garbage-collected EnvironmentPool
* Wrap closure functions in a struct in preparation for storing the defining environment with them
* Move the instantiation of closures into where they are created
* Fixed a bug in the mark/sweep algorithm:
* It would infinitely recurse in the case of cycles, because nothing was
checking that Environments had already been marked.
* Simply exiting on self->mark == mark would fix this, but introduce a
separate, worse bug where recursion wouldn't reach some live objects,
since some objects might already be marked with the current mark due
to previous cycles.
* To fix, I introduced a pass over the pool that marks everything false
so we can reliably assume that self->mark == true means that the
environment has been marked in the current GC round. It's slower than
I wanted, but it's better to do the correct thing slowly than the
wrong thing quickly.
* Store the defining environment on closures and GC it appropriately
* Test a simple case of closures and fix the discovered errors
* Add a test that explicitly demonstrates freeing a cycle
* Allow user-defined functions to take arguments
* Another closure example
16 files changed: