For clarity, it is valuable for the results of comparisons to show as "true"
and "false" rather than "1" and "0". This change implements a BOOL type
to facilitate that. Since we want logical operators to short-circuit, this
change also obliges the introduction of macros, which are just like functions
except their arguments are not evaluated before control is passed to the
routine implementing the macro.
This change is the "easy" part of #64, but to reduce the amount of duplicated
code, this change also modifies the internals of implementing a function.
The function identifier is now passed to the implementation as well, allowing
many implementations of similar functions to be collapsed more easily.
Prior to this change, every evaluation re-parses the expression. The
intermediate form as a parse tree is never stored anywhere. This change
adds a new token type, FUNCALL, which acts as a node in a parse tree, and
adds an (untested) evaluation method which returns the unevaluated parse tree
as opposed to evaluating as it goes.
This is preparation for a following step in which rather than storing a token
sequence for each variety of content, teapot will store a single token
representing the parse tree, allowing for quicker evaluation when the time
comes; no actual parsing will have to occur on evaluation.
The new function is X(SRC,REF), which briefly for a cell in the neighborhood
of REF returns the corresponding cell in the neighborhood in SRC. For
further details, see the updated documention.
In developing and documenting this function, I refined some of the
existing error messages (e.g. showing the coordinates when there is an
attempt to obtain a cell with a negative coordinate) and improved the
error propagation to increase the chance that the innermost error will
percolate to the top level.