* Apply didn't increment reference count when appending
a list to the end of the arguments list
* Added checks in release_cons and release_array,
to ensure that objects are not released more than once.
Wasn't pushing Env, so wasn't releasing correctly.
Resulted in errors when in nested expressions.
Catch was also not popping the exception handler,
so repeated exceptions would not be handled correctly.
Concatenating multiple empty lists resulted in a return
which should be empty but was not checked.
(concat (list) (list))
-> ()
Test added to step 7 to catch, since this appeared in
self-hosting step 8 in the -> macro expansion.
* (list) wasn't always incrementing reference counts when needed
* The value from eval of a file shouldn't be printed, so defined
a small routine read_eval which doesn't print the final value.
Self-hosting now runs to step8, where two tests of the -> macro fail.
* rest wasn't incrementing reference count of CAR pointer
since cl was overwritten by a write to RCX
* println wasn't putting a space separator between items
MAL self-hosting now runs to step 6. Fails since (time-ms) not
defined.
Native and user-defined functions now have metadata,
which can be set using with-data, and retrieved using meta.
The ^ reader converts "^ A B" into (with-meta B A)
Changes to how eval works mean the previous
approach no longer works. Now uses the same method as
apply and map functions, calling apply_fn for user-defined
functions.
The list was released too early, before the function body
had its reference count incremented. If the function was
a lambda function then this released the function, leading
to odd behaviour
e.g. ((fn* [x] (+ 1 x)) 2)
nil? true? false? number? test the contents type
symbol? string? fn? and macro? test object types, similar to the atom?
function
These two sets of functions are each implemented as one function with
different input parameters.
Symbols are read by the tokenizer into RSI, but RSI
was overwritten when a new string chunk was fetched.
If the reader happened to be reading a symbol as the
end of an Array chunk was reached, then the symbol
would be changed to part of the input string.
All step 8 tests now pass.
If given a vector, allocates a new Cons for the head
of the list, pointing to the rest of the elements.
This is still O(1), since only needs to copy one element.
* Added macroexpand functions and special symbol
* Some changes to how AST is freed by apply_fn,
to avoid having to shuffle the stack after a call.
7 failing tests. "rest" can return vector or list,
but should always return a list. Other errors in
-> and ->> macros seem more difficult to solve.
Quasiquote (and macroexpand) replace the AST in eval.
This makes releasing the memory harder, so could give
rise to both double-frees, and memory leaks.
Eval now releases both its environment (for tail calls)
and the AST.
nth returns an element at given index in a list.
rest returns a list or vector with the first element removed.
Currently this works by just returning a pointer to the second element.
* Better handling of the final element in quasiquote
* Cons now increments reference counts of objects pointed to
so they are not accidentally deleted
Now passes step7 tests again, including new test
concat sets the container type so that return is always a list.
NOTE: The container type of every Cons is not changed, so if the
list is sliced then the pieces may be vectors or lists.
Needed to call quasiquote with first AST element,
which then wrapped symbol in (quote )
Two tests still failing. One for cons with empty list,
and another due to concat returning a vector
Quoting not yet working properly, so symbols in the input
AST are evaluated when they should not be.
Example failing test:
(quasiquote (1 a 3))
The quasiquote function turns this into
(cons 1 (cons a (quote (3))))
rather than
(cons 1 (cons (quote a) (quote (3))))
* Helper function cons_seq_copy, which copies a list or vector
This is used in concat to copy prepended lists (final list not
copied).
* Bug fix in printer, which would segfault if the container
of a Cons did not match that of the first Cons e.g. a vector in a
list.
* Seems to be a bug in print, which now segfaults on printing *env*
Can now run a script passed as first argument,
and puts any remaining arguments into a list *ARGV*.
All step 6 tests now pass
Some missing/buggy things:
* The error handler should be different to the REPL one,
or go into the REPL correctly on error
* Strange errors occur if the file is too long. Suspect string
problems
Added a core function swap! It works, but has some warts:
* No error message is thrown on error yet, needs adding
* To run the function, swap! calls into the middle of eval.
This probably indicates that eval needs to be split up.
* str was not copying the first argument, which was then being appended to.
If the str call was inside a function, then a string literal in the function
body would be modified with every call, leading to strange behaviour.
* eval was crashing on a value input like (eval nil) because
the return was not put into rax as it should.
Added string_copy, used in str function to copy the first input
so that it can then be modified.
Most step 6 tests now pass. 10 failing due to missing *ARGV* and swap!