- Use variables A1, A2, B2 for Z%(A+1), Z%(A+2), Z%(B+2) respectively.
- Replace Z%(R)=Z%(R)+32 with GOSUB INC_REF_R
- Add functions TYPE_A and TYPE_F for (Z%(A)AND 31) and (Z%(F)AND 31)
respectively.
- Inline NATIVE_FUNCTION and MAL_FUNCTION.
All together saves over 500 bytes so increase Z% value memory by 250
entries.
Use a one dimensional array for the Z% value array. This enables
lists, vectors, environments and metadata pointers to all save off
1 word (2 bytes) of space.
Split the memory init and functions into mem.in.bas.
In addition, change type 14 to be metdata rather than any type 16-31.
This change saves about 560 bytes (no second array dimension
subscripts) and reduces Z% value usage by 10%-15%.
Bump the number of Z% words by 200 (to 8591). This enables
self-hosting up to step7 (without step8-stepA functions in core.mal).
- Alternate memory layout of hash-maps:
Instead of hash-maps being an alternating sequence of keys and values,
combine the key/values into a single entry. In other words, switch
from this:
8 -> next Z% index (0 for last)
14 key/value (alternating)
To this:
8 -> next Z% index (0 for last)
key value
This requires refactoring of the sequence reader, EVAL_AST and
especially DO_HASHMAP and DO_KEY_VALS. So that leads to the next big
refactoring:
- Change mapping/lapping constructs to share code:
Several pieces of mapping/looping code have a common structure, so
this moves that common structure to types.in.bas: MAP_LOOP_START,
MAP_LOOP_UPDATE, MAP_LOOP_DONE. Then use this code in:
- EVAL_AST
- READ_SEQ_*
- DO_MAP
- DO_HASH_MAP
- DO_KEYS_VALS
This also fixes the issue that several of these looping constructs
were creating new empty sequence entries instead of using the common
ones at the beginning of memory.
- Remove the use of DEREF_*.
This isn't actually needed because we no longer create structure that
refer to multiple levels of type 14 references. Replace DEREF_* with
VAL_* which gets the value of a particular sequence element i.e.
Z%(A+1,1).
All together, the above changes save over 300 bytes.
Also:
- Fix empty nil/false/true entries so they
are treated the same as other types of data with regards to
reference counting and ALLOC/RELEASE.
- Add a new memory summary function in debug.in.bas that just prints
out free, value count, and references for the early scalar and empty
list elements. Comment out the larger one. This saves about 90
bytes.
Save about 400 bytes.
Increase value Z% array by 100 to 4195.
Reduce string array by 1 (to 199) since in BASIC the value is the last
index not the size.
In core move incrementing of function index into
INIT_CORE_SET_FUNCTION. Switch 3 IF GOTO to ON GOTO. Reuse some
temporary variables.
Saves about 480 bytes.
Bump value array from 3950 to 4096. This allows step4 (sumdown 2) to
pass. Previously only (sumdown 1) passed.
- Save over 450 bytes. Bump up Z values by 128.
- Fix function printing when function is embedded in something else by
using strings storage as a stack while printing rather than using
RR$
- Simplify some error messages and sanity checks in RELEASE.
- Metadata support required expanding the type size (to 5 bits). This
also implies that ref cnt now only has 11 bits (2048).
- Added ^ reader macro (with-meta) which required some refactoring of
READ_MACRO to share code.
- Rename some more variables:
ZJ -> S
S% -> X%
ZR% -> Y%
ZM% -> Y
RE% -> D
This removes remaining % variables apart from the pre-allocated
arrays Z%, S% and X%.
- Modify ALLOC to take a type (rather than size) and take default
values to set for the 1-3 values/pointers. Let alloc do the
ownership taking of the referred values when appropriate.
- Add FORCE_SEQ_TYPE function to coerce sequence to given type. Fixes
apply and rest on vector. Simplifies concat.
- Use a double ON GOTO structure for calling the native functions in
DO_FUNCTION.
- Add some stub core functions.
- Move CHECK_FREE_LIST to debug.in.bas
- All changes together save over 1K
- Move apply logic in swap! to APPLY function in types and use that
for macroexpand
- Abort def! if error before updating the environment
- let* wasn't properly saving A2% for the final eval. Also, the
environment release check should be against the top-level EVAL env,
not the root repl env.
- (concat (list) ...) was broken so fix it to ignore empty lists that
aren't in the trailing position.
- nil, false and true in the reader were always being returned as
references (with an ref cnt) but we have the assumption that
references (14) are not ref cnt'd and are always part of a compound
type so fix the reader to just return the interned addresses.
- combine some lines
- remove some unnecessary spaces and parens
- add string allocations to single routine in types
Also:
- remove blank lines in qb2cbm.sh output (does not save memory)
- Add TCO recur to let*
- Release of all memory from recursive function and let* calls.
- Fix a number of cases of trying to release already freed memory.
- Print function in memory as 2 byte unit rather than two separate
memory locations.
Also:
- More/better detail in PR_MEMORY/PR_MEMORY_SUMMARY
- Fix *.prg image build (for running under Vice). Have to lower-case
everything since what C64/Vice shows as capitals are actually
lowercase.
Also:
- qb2cbm.sh: Add KEEP_REM level variable to tweak which REM/comments
are emitted/skipped.
- fix printer issue with recursive sequences after evaluation (with
refeerences in them)
- add stats target