BASIC without line numbers?

millenniumtree

New Member
Oct 2, 2019
24
16
3
Because I haven't written BASIC since the 90s, and primarily work with modern languages for work, line numbers and GOTOs kinda make my brain hurt.

So I wrote a small bash script (attached) to take a BASIC script with no line numbers, and auto-generate them!
The script uses bash, awk, sed, and egrep - tools that should be on every linux machine.
It also uses labels to simplify your GOSUBs, and eats extra whitespace so you can break up your code visually.

If you wrote a hello world like this:

PRINT "HELLO"
GOSUB WORLD
END

WORLD@
PRINT "WORLD!"
RETURN


It outputs this:

10 PRINT "HELLO"
20 GOSUB40
30 END
40 REM WORLD
50 PRINT "WORLD!"
60 RETURN


Make it executable, run it with:
./autonum.sh hello.bas

Then copy the output it gives you and paste it into the emulator, or just let it start the emu for you.

If this can already be done a different way, let me know, but I had fun writing it. Now I'm going to write some silly BASIC programs without line-number-induced eye-bleed!
 

Attachments

Last edited:
  • Like
Reactions: mobluse

x7c

New Member
Sep 15, 2019
5
5
3
I did a ton of Visual BASIC early on but never did any original BASIC beyond small tutorials. I always assumed the line number thing was just an easy way to introduce the language. There seriously isn't any Function, Sub or, at the very least, labels?
 
May 22, 2019
409
211
43
Here's something I've been working on for a while; it does the same thing, but in c#. It also emits different flavors of BASIC code, including Commodore BASIC 2.


I'm actually re-writing some of the logic and building a new tool specifically for the CX16, but it's not quite safe for public consumption yet. I'm hoping to get it ready in the next few days. It will create tokenized files and support auto numbering in real time.

The one thing I will mention is the BASIC labels usually end with the colon, rather than beginning with it. ie:
HELLO:
GOTO HELLO

However, when the time comes for the editor, I'm hoping to convince Lorin to adopt the @ symbol. Being distinct from any other BASIC operator, the @ symbol would be easily recognizable as the parser as a label, rather than an attempt to use a variable.
 
  • Like
Reactions: PowerfulBadBoy

millenniumtree

New Member
Oct 2, 2019
24
16
3
HELLO:
GOTO HELLO

However, when the time comes for the editor, I'm hoping to convince Lorin to adopt the @ symbol. Being distinct from any other BASIC operator, the @ symbol would be easily recognizable as the parser as a label, rather than an attempt to use a variable.
So like this?
@HELLO
GOTO HELLO

I updated the script to do both LABEL: and @LABEL
And also replace GOTOs and THENs using labels
And also launch the emulator.
And also remove spaces from the beginning of the lines, so you can indent your for loops like a hipster.
And also removes single-line comments beginning with a single quote or semicolon.

I replaced the script attached to the first post, and added an example program and the scripts numbered output.
 
Last edited:

millenniumtree

New Member
Oct 2, 2019
24
16
3
I did a ton of Visual BASIC early on but never did any original BASIC beyond small tutorials. I always assumed the line number thing was just an easy way to introduce the language. There seriously isn't any Function, Sub or, at the very least, labels?
I used to use QBasic back in high school, and you're right, no required line numbers there.
I never used BASIC on a C64 either, but I do remember playing some games on them in grade school.
I did my very first programming on the TI99/4A, which also requires line numbers.

I'm just learning all over what this language can do. It does have some function definitions available, and of course GOSUB, which is a lot like a function, but evidently no labels in this version of BASIC, and requires line numbers.
 
May 22, 2019
409
211
43
so you can indent your for loops like a hipster.
HA! So great!


And also removes single-line comments beginning with a single quote, semicolon, hash, or double-slash because why not?
Definitely the apostrophe (') (aka "single quote") and semicolon. Hash should be reserved for directives, like
#pack: remove all unnecessary spaces, compact code into one line when possible
#64 #X16 #VIC, etc: Only emit the following lines on that platform. End the block with #/xxx

Actually, you and I should get together and work out a common syntax for this. If we put together tools now, this will become the de facto standard when Lorin and team go to do the official editor on the CX16.
 

millenniumtree

New Member
Oct 2, 2019
24
16
3
Actually, you and I should get together and work out a common syntax for this. If we put together tools now, this will become the de facto standard when Lorin and team go to do the official editor on the CX16.
I don't know that anyone needs more than 1 comment character. I just threw them in there because I could, and I have literally no idea what people SHOULD use. I'm an absolutely bog standard beginner to the Commodore/Commander, have never written assembly, and the last time I used line numbers, I was in MIDDLE SCHOOL, creeping up on 30 years ago!

I suspect our fearless 8-Bit leader may not even want an alternate syntax for BASIC. :p But it makes things a little more fun for us that don't care to type integers at the beginning of every line. I don't know, what do you think?

I've spent the last hour optimizing that bouncing ball demo. It's way simpler and smaller now.
And that's all the BASIC experience I have in the last 3 decades. :D
 

millenniumtree

New Member
Oct 2, 2019
24
16
3
Just removed the hash and double-slash commenting from the script. Unnecessary.
I think the single quote is kind of a standard for more modern basic like VB, and semicolons are used in assembler??
 
May 22, 2019
409
211
43
Yes, assembler (especially 6502 assembler) uses ; as a comment character.

The // has become a standard on many modern languages. I don't know of any BASIC interpreters that use // as any specific syntax, so leaving it in probably can't hurt. However, with / being a BASIC token, it might be simpler to leave that out.

Single quote (') is definitely worth leaving in. My editor also uses that as a comment. What I think I want to do (if I haven't done it yet) is always strip ' comments from the output, while leaving REM in (except when packing the code or removing all comments with #comments 0)
 

Schlowski

Member
Sep 24, 2019
45
22
8
For windows users BasEdit.Net can work without line numbers, too.
Link to forum thread
Single quote (') is definitely worth leaving in. My editor also uses that as a comment. What I think I want to do (if I haven't done it yet) is always strip ' comments from the output, while leaving REM in (except when packing the code or removing all comments with #comments 0)
That's exactly what I have done in BasEdit :) I'm relatively sure I implemented WHILE...WEND and REPEAT...UNTIL as well as multiline IF's and ELSE in label mode too, but I can't find any info in my own documentation...
 
  • Like
Reactions: TomXP411
May 22, 2019
409
211
43
I suspect our fearless 8-Bit leader may not even want an alternate syntax for BASIC. :p But it makes things a little more fun for us that don't care to type integers at the beginning of every line. I don't know, what do you think?
Well, Lorin did specifically say that they were going to create a "non line numbered editor," and the way he described it to me was that the editor would tokenize BASIC code in much the same way the full screen BASIC does. It is also possible they may add structured code keywords, faking them in by emitting IF/THEN tokens.

So something like
WHILE DONE=FALSE
...
WEND

Would emit this in token code:
100 GOTO 120
110 do stuff
120 IF DONE=FALSE GOTO 100

And here's a DO WHILE
DO
...
WHILE DONE=FALSE

that becomes

100 do stuff
120 IF DONE=FALSE GOTO 100

As you can see, DO WHILE is a little less expensive than WHILE/WEND, but it also will always execute the loop at least once.

Subroutines are also easy, although passing parameters will require a user stack:

Code:
sub PrintHex(n)
  print h$(int(n/256) and 255); 
  print h$(n and 255);
end sub

PRINTHEX 23
This becomes something crazy like...
100 SP=SP+1:ST(SP)=23:GOSUB 1010

1000 REM PRINTHEX(N)
1010 PRINT H$(INT(ST(SP))/256) AND 255);
1020 PRINT H$(ST(SP) AND 255);
1030 SP=SP-1
1040 RETURN

In this example, we create a pseudo-stack using the ST array and SP as the stack pointer. If this had been a function that returned a value, the function would have pushed a value back on to the stack in the same manner we saw on 100.
 

millenniumtree

New Member
Oct 2, 2019
24
16
3
Well, I just tried to optimize the 40x30 black board draw for the bouncing balls demo program...
And it ended up just about the same speed.

I figured out how to do the increment on every POKE feature of the VERA chip, but since you have to poke twice to get a black-on-black character (not sure why this is), it ended up pretty much the same speed as the VPOKEs

Is the emulator slower than the real hardware will be? It seems to be pretty sluggish, even for BASIC.

BEFORE:
Code:
FOR Y=0 TO 29:FOR X=0 TO 39
  Q=Y*256+X*2
  VPOKE 0,Q,81:VPOKE 0,Q+1,0
NEXT X,Y
AFTER:
Code:
' Increment every poke to $9F23
POKE $9F22,16
FOR Y=0 TO 29
  ' Sets Y row and X to the beginning
  POKE $9F21,Y
  POKE $9F20,0
  ' This simple for loop actually writes a line of black out
  FOR X=0 TO 39
    ' Character 81
    POKE $9F23,81
    ' Black on black?
    POKE $9F23,0
  NEXT
NEXT
 

BruceMcF

Active Member
May 19, 2019
100
30
28
HA! So great!




Definitely the apostrophe (') (aka "single quote") and semicolon. Hash should be reserved for directives, like
#pack: remove all unnecessary spaces, compact code into one line when possible
#64 #X16 #VIC, etc: Only emit the following lines on that platform. End the block with #/xxx

Actually, you and I should get together and work out a common syntax for this. If we put together tools now, this will become the de facto standard when Lorin and team go to do the official editor on the CX16.
QBasic is basically the Big Brother to Microsoft's 6502 Basics, and uses the # as a auto-type prefix for 32bit bytes. And while 64bit floats are not really all that useful for game programming, 32bit integers really could be.

So I would really prefer if use of # is reserved for things that are compatible with using it as an postfix autotype character.
# as a comment character does not work for that.
# as an prefix for operatives talking to the "basic editor" program itself would not interfere with that.
 

BruceMcF

Active Member
May 19, 2019
100
30
28
I did a ton of Visual BASIC early on but never did any original BASIC beyond small tutorials. I always assumed the line number thing was just an easy way to introduce the language. There seriously isn't any Function, Sub or, at the very least, labels?
Microsoft's 6502 BASICs relied on a line editor, not a screen editor ... indeed, the vendor that bought the Basic added the I/O, so the Basic that Microsoft delivered had no idea how the screen that it was attached to even worked. So you want to include a line between the lines you had as 10 and 20, you called it 15. You want to add three, you might call them 12 15 and 17. You ran out of line numbers, you ran a renumber utility program to make them all go by 10's again and now you have more editing space.

Enter a Basic command without a line number, it is an immediate command, so that is how Basic worked as the command shell for the system.

The C64 could TAKE a Basic line from anywhere on the screen, so if you listed a set of lines and edited one on the screen, you could save the result by just hitting "return" in that line. But that was due to how the C64 KERNAL functions worked, that was nothing that Basic knew about. It just knew that you had entered a line that started with a number, so it added it to the program, replacing the previous line with that number if it existed.
 
May 22, 2019
409
211
43
I did a ton of Visual BASIC early on but never did any original BASIC beyond small tutorials. I always assumed the line number thing was just an easy way to introduce the language. There seriously isn't any Function, Sub or, at the very least, labels?
BASIC originated in 1959, when computers were still pretty primitive. Other languages of the time also used line numbers, because that was all that was really available on punch cards and teletype machines. (There were no CRT terminals at the time.)

The syntax was influenced by FORTRAN, which also used numbers for labeling lines.

Yes, labels and structured code blocks would be nice to have, but considering the interactive, real-time nature of the interpreter, I can see why they were left out.
 

Schlowski

Member
Sep 24, 2019
45
22
8
Yes, labels and structured code blocks would be nice to have, but considering the interactive, real-time nature of the interpreter, I can see why they were left out.
I think that has more to do with space constraints in ROM than anything else. Otherwise we would not have GOSUB which also could not be used in direct mode. (As in defining a sub routine in direct mode, not calling one)
 

BruceMcF

Active Member
May 19, 2019
100
30
28
I think that has more to do with space constraints in ROM than anything else. Otherwise we would not have GOSUB which also could not be used in direct mode. (As in defining a sub routine in direct mode, not calling one)
That GOSUB works by scanning through the program looking for the line number to jump to, saving the call location on a stack to be used by the return. Direct mode is recognized by not having a line number.

The direct mode = no line number, subroutine start = its line number syntax implies that subroutines cannot be defined in direct mode. The lack of demand for doing so is why extended Microsoft 6502 Basics did not add that ability.

The first Dartmouth BASICS were on timeshare systems that were accessed with a paper teletype terminal. Screen editing was not an option in that context ... there is no screen to edit.

And text file editing a paper teletype uses line numbers anyway (look up the command syntax for the original DOS EDLIN program) ... if no built-in line number is available, they are a linecount from the file, and keeping track of which line has which number is a headeache.

User specified line numbers were an upgrade in usability.

And this is not "ancient history" at the time of CBM V2 ... some of the systems that the original Microsoft 6502 Basic was connected to actually still would have had a paper teletype.
 

Schlowski

Member
Sep 24, 2019
45
22
8
That GOSUB works by scanning through the program looking for the line number to jump to, saving the call location on a stack to be used by the return. Direct mode is recognized by not having a line number.

The direct mode = no line number, subroutine start = its line number syntax implies that subroutines cannot be defined in direct mode. The lack of demand for doing so is why extended Microsoft 6502 Basics did not add that ability.
I know how that works, I just wanted to point out the other direction, there are some constructs which cannot be (fully) utilized in direct mode. WHILE...WEND on the other hand could be used in direct mode like a FOR...NEXT loop. So the argument of BASIC being interactive and therefore omitting some of the structured blocks don't fit.
The worst omission cause of space constraints is the lack of ELSE which leads to a lot of unnecessary complicated constructs with IF...THEN and GOTOS so simulate the ELSE case.
 
  • Like
Reactions: BruceMcF

BruceMcF

Active Member
May 19, 2019
100
30
28
I know how that works, I just wanted to point out the other direction, there are some constructs which cannot be (fully) utilized in direct mode. WHILE...WEND on the other hand could be used in direct mode like a FOR...NEXT loop. So the argument of BASIC being interactive and therefore omitting some of the structured blocks don't fit.
Sorry, I didn't realize the context was addressing a claim that no structured blocks is about being interactive.

That seems a bit dubious as a claim, to me, given the way that you can use nested {{}} blocks on the shell command line in AWK ... and given the fact that FOR/NEXT is itself a structured block.

No structured blocks was from the time that Basic was first designed in the early 1960's at Dartmouth, and the early Microsoft Basics were two steps removed from a late 60s Dartmouth Basic.

That was at the same time as structured programming advocacy was really getting going with Pascal, which was picked up in C in the early 70s. Structured programming words started getting added to Basic early on by different implementers ... which is where an incomplete syntax like While/Wend gets added to Basic fairly early on before getting superceded by more complete structures later.

When the 6th edition of Dartmouth Basic released in 1971 added a named subroutine, it didn't change the GOSUB {line_number} keyword, it added a CALL {functionname} keyword, with SUB...SUBEND defining the subroutines, and parameters able to be defined to be passed to the function.

But 6502 Basic was a port of 8080 Microsoft Basic which was based on HP Basic Plus which was based on the then-mature Dartmouth 5th edition Basic rather than the 6th edition then in beta, so named subroutines were not stripped out in the first Microsoft Basic ... they were missing from the reference implementation by a matter of months. Microsoft didn't pick that up until well after their early 6502 Basic, but it does show up in two versions (either returning or not returning a value) in QBasic.

The worst omission cause of space constraints is the lack of ELSE which leads to a lot of unnecessary complicated constructs with IF...THEN and GOTOS so simulate the ELSE case.
I guess the way you were intended to do "ELSE" in Dartmouth Basic was to do a second IF, "IF X>6 THEN ...", "IF X<7 THEN". I've done something like that sometime in AWK ... match a pattern, do this action, mismatch the same pattern, do that action ... but as a longtime Forth programmer I have been indoctrinated into preferring the structured programming with ELSE.