Close

Operators and precedence

A project log for One kilobyte Tiny BASIC for the 8080 and Z80

BASIC for the 8080 and Z80, fits in 1K of memory, runs BASIC games on a 2K system. Features similar to Palo Alto Tiny BASIC.

willstevenswill.stevens 02/11/2024 at 07:330 Comments

A discussion about this project on a forum on 6502.org led me to rewrite the code for the comparison operators because they didn’t handle edge cases correctly. E.g. I had implemented a<b as a<=b-1. This doesn’t work if b=-32768 because -32768-1 wraps round to 32767.

I rewrote the code to handle this correctly. I also came across another more significant error where I had made incorrect assumptions about the behaviour of the carry flag. It took 6 bytes to fix both of these problems: now <= and >= test for equality first, then fall through to < and >. Comparison is now done using SUB and SBB instructions rather than RST_NegateDE and DAD.

The way that I have implemented operator precedence is a problem. In my implementation no two operators can have the same precedence, whereas in other BASICs operators can have equal precedence and are evaluated in left to right order. E.g. in some other BASICs + and - have the same precedence, and * and / have the same precedence. My operator precedence code is 5 bytes long. Changing it to allow some operators to have equal precedence would increase this. Because BASIC programmers don’t usually use more than one comparison operator in an expression, and because having - as higher precedence than + has not seemed problematic so far, I think it is only * and / that may cause problems when running existing BASIC programs (I discovered this when running Gordon Henderson’s Mandelbrot set program that runs in Tiny BASICs). E.g. 3*4/3 evaluates as 3*(4/3)=3 rather than (3*4)/3=4.

I notice that some BASICs don’t have equal precedence for * and /. ZX80 integer BASIC gives * higher precedence than /, whereas in ZX81 BASIC they are equal precedence. So I could do the same and make * higher precedence than / at no cost (just rearranging the code). Or I could try to be consistent with other Tiny BASICs. I think that this could be done at a cost of 2 bytes by applying a bit wise OR operation to the operator code before comparing it with the operator on the stack during evaluation, but exactly how this will work will depend on the operator function address. This is the kind of nasty dependency  that occurs if trying to squeeze as much functionality as possible into 1K. I will leave this issue until I have thoroughly tested all other behaviour of operators and expressions, so that I can be reasonably sure that address will remain fixed.

Discussions