clean up internals of lispm.c
it's Sunday cleanup time!
git: commit
I moved all the bits hackery to internal-obj.h, and optimized the code
size such that it fits back into 4K limit, taking 4082 bytes according
to make stat
with my GCC version. This time I left more extended
explanation in the branch commits.
verbose branch logs
-
[6061537b] avoid unnecessary round trip through quote
Previously I turned the parsed empty list and numeric value into an instruction to quote them. The
eval()
would then reduce the(CONS QUOTE val)
to(CONS () val)
, and then returnval
. Notably, this extra step of reducingQUOTE
is not needed, and we can generate the(CONS () val)
instruction at the semantic analysis phase. -
[a679f6d2] introduce internal-obj.h
I extract all the bit-tagging hackery from lispm.c to a separate internal header file. I also noted a typo in internal-macros.h filename.
Another significant change is the rework of free/bound distinction. I rephrase it in terms of integer comparisons:
- forall p q. BOUND_REC(p) > BOUND(q) && BOUND_REC(p) > FREE(q)
- forall p. BOUND_REC(p+1) > BOUND_REC(p) && BOUND(p+1) > BOUND(p) && FREE(p+1) > FREE(p)
- forall p. BOUND_REC(p) > BOUND(p) > FREE(p)
Then lex_frame_use overwrites the current association only if it is larger than the previous association.
Frame depth handling got trickier. I want to avoid the
lispm_shortnum_val()
calls inevframe_set()
. This means that I need to store a shortnum inM.frame_depth
during evaluation. For this reason I always keep a shortnum in this field, however:eval()
treats this depth as a shortnum; whereassema()
treats this depth as a regular unsigned value. That is because I expecteval()
can causesema()
through a recursivelispm_eval0()
call caused by an extension, but I don’t expect any semantic analysis function to calleval()
. I also addedframe_depth_guard()
to verify in assertions mode that bothsema()
andeval()
restore the frame_depth upon exit.
A minor change is that I got rid of
lispm_is_valid_result()
check. I let the user decide which results they consider valid. -
[20761412] make lispm_init() non-throwing
Since this function is not expected to be guarded by
lispm_rt_try()
, it should not throw. This means thathtable_ensure()
must return an error status.I took this opportunity also to simplify the interaction between lexer and
htable_ensure()
. Now lexer always puts the currently read literal atM.tp
position and makes it NUL-terminated, whereashtable_hash
andhtable_ensure
rely on this convention.