I’ve mentioned the BASIC Utilities from Alex Evans quite a bit lately. These Python scripts can be run on any system that has Python. I have used them under Windows 11 and macOS. In addition to having scripts that will tokenize and de-tokenize BASIC programs, it has some other interesting capabilities. One is the ability to have a BASIC source file that is written in a more user-friendly way — using labels instead of line numbers, and then only having them where needed.
Consider this example of a “guess the number” game:
NUMBER = RND(100) PRINT "I AM THINKING OF A NUMBER FROM" PRINT "1 TO 100. CAN YOU GUESS IT?" LOOP: INPUT "WHAT IS YOUR GUESS";GUESS IF GUESS > NUMBER THEN PRINT "THAT IS TOO HIGH!" IF GUESS < NUMBER THEN PRINT "THAT IS TOO LOW!" IF GUESS = NUMBER THEN PRINT "YOU GOT IT!":END GOTO LOOP
This code can be processed through “coco_pack.py” and it will become a tokenized program (guess.bas.pack) that runs on a CoCo. The PACK routine will do things like rename longer variables (such as “GUESS”) to valid short ones, as well as change labels (LABEL:) in to line numbers. Obviously, it also adds line numbers to everything in between, giving the programmer one less thing to worry about.
I processed this file using “coco_pack.py -t guess.bas” to have it generate a text file (-t) rather than a tokenized file. It produced “guess.bas.pack” as a text file which looked like this:
0 A=RND(100):PRINT"I AM THINKING OF A NUMBER FROM":PRINT"1 TO 100. CAN YOU GUESS IT?" 1 INPUT"WHAT IS YOUR GUESS";B:IFB>A THENPRINT"THAT IS TOO HIGH!" 2 IFB<A THENPRINT"THAT IS TOO LOW!" 3 IFB=A THENPRINT"YOU GOT IT!":END 4 GOTO1
You can see how it combined as much as possible on each line, taking three separate lines (RND, and two PRINTs) in to one. The INPUT needed to be on its own line since it will be the target of a GOTO loop. The first comparison (is guess too high) could be moved to the end of that line, but the next ones needed to be separate lines.
The result is something that looks a bit more friendly being turned in to something much more compact. Using “coco_pack guess.bas” without “-t” would have produced a tokenized file ready to load on the CoCo.
A warning about variable and label names
In BASIC, there are certain things you cannot use for variable names. You cannot have a variable named “FOR” since that is a keyword, but you can use “FO“. (Besides, if you use a variable name longer than two characters, the rest get ignored. “FOR” should be honored as “FO” and be allowed, but the BASIC parser has already found “FOR” and turned it in to a token … I think.)
Some variables work fine on Color BASIC, but cannot be used on Extended BASIC. “FN” is allowed on Color BASIC, but you cannot use “FN” as a variable under Extended/Disk BASIC because FN is a token (see DEF FN). “AS” works fine as a variable for Color or Extended BASIC, but cannot be used under Disk BASIC because “AS” is now a keyword (see the “FIELD” command).
The Alex Evans tools need to follow similar tools, since they are parsing the line looking for BASIC keywords to tokenize. If you tried to make a label called “ASK:”, as I initially did, you will find that a “GOTO ASK” does not work — it turns in to “GOTO ASx” where X is a variable it made, since it treated “AS” as a token, and then K as a variable. This is something that Alex may be able to resolve in a future update, but for right now, keep labels and long variables to things that are not conflicting with BASIC keywords.
Here’s an example of bad stuff. Notice that you can use leading tabs/spaces to help “prettify” the code if you want, but since it is still BASIC lines, everything that needs to be on the same line in BASIC will have to be on the same line of this code:
FOR=1 GOTO: PRINT "GOTO" GOTO GOTO LOOP: PRINT "LOOP" GOTO LOOP
And here is what it tries to create:
0 FOR=1:PRINT"GOTO":GOTOGOTO 1 PRINT"LOOP":GOTO1
You can see it tried to make “FOR=1”, which will error out on the CoCo, and it did not treat “GOTO” as a label, since GOTO is a keyword.
Using LOOP: works just fine, since there is no LOOP keyword.
Just keep that in mind. This is a script that creates files, and not a full BASIC interpreter that can give you errors as you type things in. :)
A warning about line format
Since these are lines of BASIC, they have to be on the same line just as BASIC expects. You can NOT write something like:
REM * THIS WON'T WORK: IF G > N PRINT "THAT IS TOO HIGH!" ELSE IF G < N PRINT "THAT IS TOO LOW!"
…because that would be like doing this in BASIC:
10 REM * THIS WON'T WORK: 20 IF G > N 30 PRINT "THAT IS TOO HIGH" 40 ELSE IF G < N 50 PRINT "THAT IS TOO LOW!"
The PACK process would then combine lines and produce:
0 IFA>B 1 PRINT"THAT IS TOO HIGH!":ELSEIFA<B 2 PRINT"THAT IS TOO LOW!"
“It’s still BASIC, after all!”