Does anyone know of an 8-bit era system that did this?
No, at least not the way the question proposes, which is essentially turning 16 bit values into 17 bit. Something no (BASIC) system supports. The only ones that come close are BASICs offering long integer or arbitrary size BCD formats. To be used as 16 bit value, they (and the proposed 17 bit format as well) would need to be converted into 16 bit - while maybe faster, it does not have make any difference from using FP and converting as well.
Also it must be noted that many BASICs allowed to use either format for numbers, so using
CALL -151
or
CALL 65385
will both make the Apple II enter the Monitor. Still, the first not only saves a byte in the source text (yeah, I know, MS; *1), but also seems way better to remember.
Is there a performance issue this raises that I'm not immediately seeing?
No, there's a missing use case - well, that and the fact that BASIC is intended as a ... well ... basic programming language. So why add more variable types for such a nice issue?
In addition it might be useful to keep in mind that BASICs with compressed storage are never about preserving the source lines as entered, i.e literal, but only in spirit. Keywords get extended, blanks inserted or removed, parenthesis added, lower case becomes upper case and so on. Using compressed form with integers means that they will be output in the default form used by the system (like signed) (*2). Still, this may not stop someone writing a cruncher able to parse signed as well as unsigned (positive) integers when entered. Wouldn't it?
No, lets forget about all of that stupid sensibility and simply implement it:
Dropping the rather pointless idea of negative integers below -32768 opens a possible way to incooperate what I see as you core intention, the display of a 16 bit integer value (like $EA60) when listing, dependant on how it has been entered (like (+)60,000 or -5,536).
In the end it's simply a hint for the LIST command how to treat a constant. THe least intrusive way would be modifying the way Integer BASIC stores numeric constants, where the first byte of a constant is preserved to simplify the interpreter.
If we assume that the cruncher accepts numerical constant in the range 32,768..65,535 without throwing an error, it could set the first byte to a value outside that $B0..$B9 range, signalling that it is to be taken as unsigned (positive) integer and prepared as such. This may or may not work depending on the rest of the interpreters checks.
A less intrusive way would be 'hooking' one of the legal values for special treatment. The number zero might be a good candidate, as, by definition, negative zero does not exist. Also, it should not come as the first digit of a constant (*3). Do the cruncher will act as usual (with suppression of leading zeroes) but now don't issue an error when a number greater 32768 comes along, but goes ahead after turning the identifier into $B0. Whenever now the LIST routine encounters a constant with $B0 as identifier, it treats the following value as unsigned 16 bit for display.
This should result in the minimal possible intervention to the interpreter and no change for run time routines or decreased performance.
Of course, it'll still introduce the same number of problems as any alternation without adding areal 17 bit type would bring. For example an expression like
A = 40000 - 1000
is as well legal for the cruncher as for the interpreter. Still the result would not be 39,000 as most would expect, but
$9C40 - $03E8 = $9858 -> 26,526
So while it seams nice at first sight, it will introduce a lot of hard to find bugs that no part of BASIC can detect.
Long story short, to handle this integer arithmetic has to be turned to 17 bit (*4) or introduce severe inconsistency for users on places not expected. I wouldn't enjoy either.
*1 - In addition, and that's something MS can be proud of, their full BASIC allowed to write CALL &HFF69
as well. Not better in any way, still, the &H
could be turned into (yet another) token to be handled like an integer, but always listed again as hex.
*2 - In fact, output could be made on a case-by-case basis, not just using hex notation when added explicit (&H
), but whenever it seems appropriate as default - like CALLs ... all the way to make CALL even more luxurious by including any constant value right after the token without any number identifier ... did I hear anyone mention Pandora's Box?
*3 - If one constant is entered with leading zeroes, they get suppressed during crunching and not displayed when listing ... It's not a bug, it's a feature: This BASIC eliminated leading zeroes
*4 - Effectively just postponing the problem until bit 17 is hit.