After two years, I have released yet another new version of WimBasic, in which more improvements have been implemented.
The most noticeable improvements are around the PRINT USING statement.
In previous versions:
1) a formatting string containing double quotes would be misinterpreted
2) the syntaxis for printing to a file (PRINT USING#1, "<format>") was incorrect
3) the tape-buffer was used for temporary storage of the output string (limiting the output to 192 characters and interfering with tape I/O)
4) the implementation of rounding decimals was dodgy
5) the format string could possibly be hit by a garbage collection and lead to strange results
This is now fixed:
1) the format string may now hold double quotes and yield correct results
2) the syntaxis is now PRINT#1,USING "<format>", this also works with the CMD statement
3) regular stringbuffer storage is now used for the output string
4) the dodgy code is removed, so now it truncates (use ROUND() to obtain rounded values)
5) both the formatstring and the resultstring are now protected from garbage collections
This improvement taught me a lot about how strings are handled in the interpreter, and how the improvement should be realised so that it works transparently across garbage collections.
A garbage collection (GC) occurs during FRE(0), and also when top of arrays hits bottom of strings. That is, during creation of any variable or array, or during creation and manipulation of strings (INPUT/READ/GET, concatenation, CHR$, STR$, LEFT$/MID$/RIGHT$). In that sense, a call to $CD9E (formula evaluation) may trigger a GC.
A GC reorganizes all of string space by checking all stringdescriptors that are known through stringvariables (simple or array) or through the descriptorstack (used for temporary strings: a call to $D4CA puts it there, a call to $D6AA removes the top one). The descriptors are updated in the process of a GC.
So, when during processing of stringcontents a call to $CD9E is done (like it is in PRINT USING), relocation of the string that is being processed may happen. And thus lead to corruption. To resolve this, after returning from $CD9E, the address of the strings' contents needs to be re-established by following the descriptor (the descriptor itself is not moved: it is on the descriptor stack or in the stringvariable).
Pseudocode as follows:
Code: Select all
evaluate formatstring
save descriptor on stack when it is a temporary value
save address of descriptor
allocate buffer for resultstring
save descriptor on stack
save address of descriptor
establish adresses of the format and resultstrings from the descriptors
process formatstring
copy literal characters from formatstring to resultstring
process control characters in formatstring
evaluate next numeric expression (*)
perform STR$() of the result while fixing up numbers between -0.001 and 0.001
(STR$ puts them in exponential notation, this leads to overflow notation)
re-establish the addresses of the format- and resultstrings from the descriptors
fill value following the group of format control characters into the resultstring
get descriptor for resultstring from stack and unpack it
print the resultstring
discard possible descriptor for formatstring from stack
print cr/lf when end-of-command, no cr/lf when semi-colon
otherwise signal format error
(*) may lead to garbage collection that relocates the buffers
Regards,
Wim.