The Broken BASIC Years
Posted by scruss@reddit | vintagecomputing | View on Reddit | 36 comments
You'd be surprised that this little program produces different results on different BASIC systems:
10 FOR X=3 TO 2 STEP 1
20 PRINT X
30 NEXT X
40 PRINT X
Up until 1975 or so, all BASIC systems produced the same result. But from about 1975–1981, many small systems produced a different result. Then, around 1981, Microsoft changed how FOR loops worked to comply with an ANSI standard. More used to setting de facto standards, Microsoft had a particularly good reason for meeting this de jure one …
I tested 39 different BASIC systems across 14 different processor types and wrote it all up here: The Broken BASIC Years.
BrobdingnagLilliput@reddit
I can't say I'm fond of your clickbait headline. "You've done a nifty job testing and cataloging this edge case on multiple implementations of BASIC, but"bBroken" implies an implementation that doesn't do what its documentation says it does. Without checking the docs for each implementation, there's no way to say that they're either correct or incorrect.
rlauzon@reddit
No. Not surprised at all. Early on, BASIC was primarily "roll your own". So there would be variations.
Microsoft pulled ahead on PCs and most of them used Microsoft's BASIC after a while. It may have been consistently wrong, but it was consistent.
ziplock9000@reddit
BBC B Basic was amazing in the 1980's. Could do in-line assembler.
lkesteloot@reddit
I'm confused about how the interpreter would even find the matching `NEXT` to jump to. Isn't that dynamically determined?
Future-Side4440@reddit
Back in the 8-bit days, no one really cared about interoperability. Systems were so wildly different that it didn’t matter. Only the most crudely written BASIC programs worked across systems.
The parts that actually mattered like graphics, sound, and disk operating systems were so completely different that the idea of interoperability was laughable.
canthearu_ack@reddit
This is the sort of broken code that programmers should avoid writing.
No surprise -> broken code -> broken interpreter -> random results!
Of course, I am not going to get on any sort of moral soapbox over this. Systems were extremely limited back in the day ... you did what you had to do, to get your code working in the highly constrained environments of these old PCs.
TheLowestFormOfHumor@reddit
Came here to say this... that code as written is illogical, so it's not surprising it gets interpreted in random ways. Relying on the quirks of a particular version / language is always going to catch you out eventually.
NetFu@reddit
This is interesting, because I know of one BASIC called Basis BBX Pro/5 that is still used today, which executes for loops at least once as you describe only old BASIC systems doing.
We still have one customer who runs their ERP system on this, I've been doing modifications on it for 36 years, even still today.
In fact, I tested it:
draculero@reddit
probably it needs `step -1` in the line 20, if not it will start with 3, print "3 to 2" and then next x increase the counter to +1 by default, it breaks the loop and finally prints 4.
So makes sense because the FOR loop is stupid and it doesn't know that if the initial value is > the final value the increment should be -1.
Olofahere@reddit
Do you want the FOR loop deciding that for you? Suppose your code is
FOR X=3 TO Y
and sometimes Y is 5 and sometimes Y is 1. Do you want it counting 3 4 5 or 3 2 1 depending?
bwyer@reddit
Agreed. The only function of the FOR statement is to assign an initial value to the variable and establish the rules. NEXT does the increment (or decrement) and evaluation.
BCProgramming@reddit
Hah, If only. BASIC systems literally produced different results as soon as there were two of them. The first non-Dartmouth implementation was HP's Time-Shared BASIC for their HP-2000 in 1968, and it wasn't fully source compatible with Dartmouth BASIC. Same applied to the third implementation by DEC in the VAX-11.
For example if you used the LEFT, MID, or RIGHT functions, that was only in DEC's BASIC; HP's version didn't have those, instead using string slicing. DartMouth BASIC didn't have string variables or functions.
"Street BASIC" was the term the BASIC Creators used to describe the limited versions of the language that were being used by most people at the time; things like only using two letters for a variable, type specifier characters, etc seemed to be the hallmark of a "Street" BASIC implementation.
bwyer@reddit
Ugh. AppleSoft BASIC only paid attention to the first two characters of a variable name, but would happily allow you to create as many iterations of that as you like.
daddyd@reddit
basic pretty much had the same issue as unix had, the name was the same, but each system had it's own implementation and differences. it did teach you a lot though, i did a lot of type-ins from magazines, ofcourse these were never for the computer i had, so you had to translate them to make them run properly.
stuffitystuff@reddit
Always worked for me when I'd type in programs from the back of 3-2-1 Contact magazine into my Apple ][ but f-ck if I can ever get the original teletype version of The Oregon Trail to run without pulling my hair out. Glad I got to BASIC when it was mature otherwise I might still be flippin' burgers.
Sgeo@reddit
Sgeo@reddit
This is the nitpick to rule all nitpicks, but I think FORTRAN 66 leaves the comparable behavior of DO loops undefined. IBM's FORTRAN IV compilers (which 66 was based on, to my understanding) specified that the loops ran at least once.
I was recently hitting my head on why a program was behaving differently when compiled for 66 vs 77 (using VS FORTRAN 2), and when I asked about behavior differences on IRC, the DO loop at least once vs zero times was the first thing brought up.
RenderedMeat@reddit
I think on most systems I ever used that would just print “3” twice unless I did “STEP -1”.
bwyer@reddit
Which would be the appropriate behavior, in my opinion.
RenderedMeat@reddit
Yes, it makes the most sense.
HomeComp1977@reddit
I had a quick look at the history of BASIC the other day. Pretty fascinating stuff. It’s starts with Dartmouth and then HP and as you say everything is pretty consistent. Then home micros come along and there’s essentially a two horse race on how to adapt BASIC to these low memory machines. The split is largely on Tiny vs Microsoft lines. For US machines Microsoft wins out, most micros use a MS variant. Then the British micros turn up and it’s like the Wild West. Everyone doing their own thing, not really based on what’s gone before.
2raysdiver@reddit
I used Basic on the BBC Micro. It was brilliant, efficient, and even allowed you to embed 6502 assembler instructions in the BASIC source. It was superior to anything MS had produced up to that point.
HomeComp1977@reddit
I’d say Beeb was the best BASIC of the era by a wide margin. Though I always had a biased personal preference towards Locomotive BASIC on the Anstrad CPC which was heavily influenced by BBC BASIC.
Guruchill@reddit
[ OPT 2
iykyk
Low-Charge-8554@reddit
I could not find the results for the 39 systems.
flatfinger@reddit
In many older versions of BASIC, both FOR and NEXT are imperative statements rather than structural elements. As such, there is no static relationship between a FOR statement and "its" corresponding NEXT statement. Consider the following program:
If S were greater than 5, where should execution proceed in order to skip the FOR I loop? Note that line 50 would sometimes jump back to the J loop and sometimes the I loop.
BCProgramming@reddit
BASICA is arguably a later one but it actually functions oddly with this.
entering a number smaller than 5 would iterate until it issued a "NEXT without FOR in 50". With a value larger than 5, it skips directly to line 60 and issues a similar error for that line.
since it skips to line 60 it must be scanning forward for NEXT statements to match up with when it hits the FOR to know where it will hop to. so arguably BASICA wants to treat FOR...NEXT as static blocks, not imperative statements. the colon seems to mess it up a bit though.
What is more interesting though is that if you save and reload the file, even using ASCII format, it will just issue a syntax error trying to run, which is pretty weird, since it works after entering it manually. Might have something to do with that internal tokenization it does?
Hjalfi@reddit
...and you couldn't jump out of a FOR loop --- without executing the NEXT you'd end up with an entry on the stack and all sorts of bad things would happen. This kind of idiom was popular:
Vinylmaster3000@reddit
I tried it on my 6502 SBC and it gives me 3 and 4, interestingly enough
Jorpho@reddit
There were so many books out there with BASIC program listings to type in, and they had to include so many variants for so many different kinds of BASIC – and so many of them preceded the widespread adoption of the PC and didn't have workarounds for GW-BASIC/BASICA.
anotherspaceguy100@reddit
"BBC Basic.. almost perfect" - nice one, scruss 😉
scruss@reddit (OP)
If they'd only fixed the FOR loop - it was in the spec! - it would have been truly great. Though its print formatting and file compatibility is exceptionally weak
Guruchill@reddit
[ OPT 2
IYKYK
mcsuper5@reddit
After reading the article, it sounds like the "for" is supposed to set up and test the value and the next is a simple increment and goto the test at the start of the loop?
Slightly simplified since you would need to alter the comparison on a negative step value.
flatfinger@reddit
Microsoft's BASIC implementations for the 6502, and likely 6800 and 8080 as well, use the CPU stack to keep track of FOR loops and GOSUBs. A FOR statement sets the control value's value and pushes an entry with the address of the control variable, the step and ending values, and a bookmark of the code address following the statement. NEXT looks to ensure that there is a FOR loop on top of the stack. If the name of the variable is specified, it will pop entries until it finds a FOR statement entry with the given name or the stack is exhausted. GOSUB pushes an entry with the code address following the statement along with its line number. RETURN will pop off any FOR loop entries until it finds a GOSUB entry and then set the program address and line number appropriately.
2raysdiver@reddit
Acording to an article I read in the mid 1980s (Byte?? Apple Incident? ?? I don't recall), Apple BASIC was particularly buggy early on, as written by Mr. Gates, himself. A high school student wrote them a letter about all the bugs he'd found, and using the BASIC and Applesoft source from the Apple II technical reference, pointed out some of the places in the code that needed to be fixed. Bill "hired" the kid as a summer intern and had the kid fix all his bugs. The kid received a new Apple II as payment.