Neolithic Tiny Basic

Programming the 6502 microprocessor and its relatives in assembly and other languages.
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

I've been thinking about READ, DATA, and USR (and incidentally, @(peek)).

As pointed out earlier, there is no function capability in NTB. The only case where this occurs is with @, and that's bolted on in a messy way to factor().

The difference between a statement and a function is that the first takes one or more parameters, executes, and returns the address of the next line to execute. That allows both linear execution and recursion, which is used when control statements are nested. A function takes one or more parameters and returns a value... it seems to me that that a function is only useful as part of an assignation statement:

Code: Select all

1000 a = usr 57554, 55
and that without the assignation, even if the function doesn't return a value (as USR might not) it would be a syntax error. By providing the address of the usr target, the user doesn't have to mess around with poking values into memory before the call. The single parameter would be provided in Y:A and because the user has full access to the core software further parameters can be accessed in any desired style by using the existing parsing mechanism.

DATA is easy; it's a statement that does the same as a comment: nothing.

READ with a line number should return the first data item from that line; without a line number it should return successive data items.

Proposed changes, then:
  • define the DATA statement
  • add a new 'is' function: is_a_function() which will return true if the character tested is a function token, or @ (which is a function, but saves memory by not needing a table/enum entry).
  • change assignment() to test for and expect a function return value which it can save before moving to the next line.
This rather means that you can't

Code: Select all

 100 print read 1000
but you would have to

Code: Select all

 100 a = read 1000
110 print a
but I don't see that as too much of a headache.

Neil
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

Something like this:

Code: Select all

  100 q = 0
  110 a = read 1000
  120 while q <= 10
  130   print a
  140   a = read
  150   q = q + 1
  160   wend
  170 print "ok"
  180 end
  1000 data 0,1,1,2,3,5,8,13,21,34
Neil
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Neolithic Tiny Basic

Post by BigEd »

It's all good, but note that READ isn't normally a function, it works like INPUT var. (Doesn't normally take a line number, in my experience)

Not sure about your parser or syntax, but a function could normally appear in an expression, which in turn could appear as an argument to PRINT.

PRINT 22000/7
PRINT USR(57554)

Does your machinery have the idea of an expression?

(Sorry, I know I really ought to reread the thread carefully and make higher quality comments!)
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Neolithic Tiny Basic

Post by BigDumbDinosaur »

Interesting thing about READ and DATA is most of the timesharing business BASIC interpreters do not implement those two keywords as a pair.  DATA doesn’t exist as a keyword, and READ is a verb used to get data from a file, e.g., READ (4,KEY="6502") A$,B,C$.  That would read a record from the file opened on channel 4, using the record key “6502”, and loading three fields into corresponding variables.

In the few BASIC programs I wrote for the Commodore eight-bit machines, I can only recall one instance of using READ - DATA.  If I were going to implement your NTB on one of my POC units, I doubt I would find a use for READ - DATA—I got mass storage for that sort of thing.  :D
x86?  We ain't got no x86.  We don't NEED no stinking x86!
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

I suspect I will leave USR as it currently is and ignore READ and DATA for now. I think I'm going to need that space for a file system.

On the whole, I think I have succeeded in my objectives; I have a structured tiny basic in the mould of the originals from the seventies, usable for non-trivial programs and possibly as a simple (seventies style) operating system - though it'll never be a game system.

My thanks to all for the previous helpful comments and encouragement. It's nice to know that I can still do it (my last major project was a hundred thousand lines of C for - of all things - an intelligent cat feeder. Go figure!).

Neil

(I reserve the right to change my mind later, of course!)
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

I thought I should try it on real silicon, as opposed to simulation:

Code: Select all

Start
,,,,,,......................'''''''''~~~~~:;*&XB*%::~~''''''...........,,,,
,,,,,,,.....................'''''''''~~~::;$&B  %%$:~~~~'''''.........,,,,,
,,,,,,,,................''''''''~~~'::::;;*       $;;:~~~~''.........,,,,,,
,,,,,,,,...........'....'''''''~~~:;;**;%%&       $%*;;::::''''......,,,,,,
,,,,,............''''''''~~~~~~~::;% OX$              %&%X;:~'..........,,,
,,,...........''''''''''~~~~~~:::**%                       ;~''''.........,
,,,,...........'''~~~:::::::::;;;O                       $*::~~'''.......,,
,,,,,......''''''~~:;#**;% *;;;*%$                        OO:~~'''.......,,
,,,,..''''''''~~~~:;*$  &B  @&%&$                          X:~~''........,,
......''''''~~~~~:;;%&#        @                            :~~'''.........
.....'''~~~~:::::%&$O                                      ;:~~''..........
....''~~::;;;;*;&O                                       B*:~~''''''.......
....'                                                   $%;::~~''''........
....''~~::;;;;*;&O                                       B*:~~''''''.......
.....'''~~~~:::::%&$O                                      ;:~~''..........
......''''''~~~~~:;;%&#        @                            :~~'''.........
,,,,..''''''''~~~~:;*$  &B  @&%&$                          X:~~''........,,
,,,,,......''''''~~:;#**;% *;;;*%$                        OO:~~'''.......,,
,,,,...........'''~~~:::::::::;;;O                       $*::~~'''.......,,
,,,...........''''''''''~~~~~~:::**%                       ;~''''.........,
,,,,,............''''''''~~~~~~~::;% OX$              %&%X;:~'..........,,,
,,,,,,,,...........'....'''''''~~~:;;**;%%&       $%*;;::::''''......,,,,,,
,,,,,,,,................''''''''~~~'::::;;*       $;;:~~~~''.........,,,,,,
,,,,,,,.....................'''''''''~~~::;$&B  %%$:~~~~'''''.........,,,,,
,,,,,,......................'''''''''~~~~~:;*&XB*%::~~''''''...........,,,,
Finished
>
About five and a quarter minutes on a 1.8MHz machine.

Neil
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Neolithic Tiny Basic

Post by BigEd »

Not sure how you might check, but that doesn’t look quite right to me. And if so, it might indicate a problem in arithmetic.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Neolithic Tiny Basic

Post by drogon »

barnacle wrote:
I thought I should try it on real silicon, as opposed to simulation:

About five and a quarter minutes on a 1.8MHz machine.

Neil
Not bad at all.

It's about 10.5 minutes in my GIBL on a 2Mhz system. GIBL does not tokenise the source text - it's string compares all the way...

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

Checking for a single byte token certainly speeds things up, _and_ saves me having to worry too much about having to make an efficient strncasecmp() equivalent :)

Don't know what's wrong with the picture, Ed, perhaps the perspective is squished horizontally? It surprised me that it's symmetrical north and south; I'd have expected it to be slightly different for positive and negative multiplication / division. Oh, wait: I do signed mul/div by inverting, doing the operation, and inverting when required. That would move rounding results to zero in both positive and negative cases; that could be a difference?

Neil
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Neolithic Tiny Basic

Post by drogon »

barnacle wrote:
Checking for a single byte token certainly speeds things up, _and_ saves me having to worry too much about having to make an efficient strncasecmp() equivalent :)
GIBL is upper case only. That does help.

And it's using a highly specific string compare - e.g. the last character of the string has the top-bit set rather than being a C style zero terminated - this was more to save code space than anything else though.

However it is the crux of GIBL (and other "IL" TinyBasics). I did try to arrange keywords in order of most to least used as it's a linear search for the most part. There is also a single character compare which is further optimised. Even so - it's a lot of overhead )-:
Quote:
Don't know what's wrong with the picture, Ed, perhaps the perspective is squished horizontally? It surprised me that it's symmetrical north and south; I'd have expected it to be slightly different for positive and negative multiplication / division. Oh, wait: I do signed mul/div by inverting, doing the operation, and inverting when required. That would move rounding results to zero in both positive and negative cases; that could be a difference?

Neil
It is expected to be symmetrical north/south. Or should be.

FWIW: I generated mine again:

Code: Select all

Start
......,,,,,,,,,,,,,,,,,,,,,,'''''''''~~~~~=+:*$O:;==~~'''''',,,,,,,,,,,........
.......,,,,,,,,,,,,,,,,,,,,,'''''''''~~~==+%*O  ;;%=~~~~''''',,,,,,,,,.........
........,,,,,,,,,,,,,,,,''''''''~~~'====++:       %++=~~~~'',,,,,,,,,..........
........,,,,,,,,,,,',,,,'''''''~~~=++::+;;*       %;:++===='''',,,,,,..........
.....,,,,,,,,,,,,''''''''~~~~~~~==+; &$%              ;*;$+=~',,,,,,,,,,.......
...,,,,,,,,,,,''''''''''~~~~~~===::;                       +~'''',,,,,,,,,.....
....,,,,,,,,,,,'''~~~=========+++&                       %:==~~''',,,,,,,......
.....,,,,,,''''''~~=+X::+; :+++:;%                        &&=~~''',,,,,,,......
....,,''''''''~~~~=+:%  *O  B*;*%                          $=~~'',,,,,,,,......
,,,,,,''''''~~~~~=++;*X        B                            =~~''',,,,,,,,,,,,.
,,,,,'''~~~~=====;*%&                                      +=~~'',,,,,,,,,,,,,.
,,,,''~~==++++:+*&                                       O:=~~'''''',,,,,,,,,,.
,,,,'                                                   %;+==~~'''',,,,,,,,,,,.
,,,,''~~==++++:+*&                                       O:=~~'''''',,,,,,,,,,.
,,,,,'''~~~~=====;*%&                                      +=~~'',,,,,,,,,,,,,.
,,,,,,''''''~~~~~=++;*X        B                            =~~''',,,,,,,,,,,,.
....,,''''''''~~~~=+:%  *O  B*;*%                          $=~~'',,,,,,,,......
.....,,,,,,''''''~~=+X::+; :+++:;%                        &&=~~''',,,,,,,......
....,,,,,,,,,,,'''~~~=========+++&                       %:==~~''',,,,,,,......
...,,,,,,,,,,,''''''''''~~~~~~===::;                       +~'''',,,,,,,,,.....
.....,,,,,,,,,,,,''''''''~~~~~~~==+; &$%              ;*;$+=~',,,,,,,,,,.......
........,,,,,,,,,,,',,,,'''''''~~~=++::+;;*       %;:++===='''',,,,,,..........
........,,,,,,,,,,,,,,,,''''''''~~~'====++:       %++=~~~~'',,,,,,,,,..........
.......,,,,,,,,,,,,,,,,,,,,,'''''''''~~~==+%*O  ;;%=~~~~''''',,,,,,,,,.........
......,,,,,,,,,,,,,,,,,,,,,,'''''''''~~~~~=+:*$O:;==~~'''''',,,,,,,,,,,........
Finished
If I compare them then what I see is that the number of lines are correct but the line length in NTB is shorter by 4 characters. Possibly that would affect the outcome?

The shape does appear correct though.

My code:

Code: Select all

    0 REM Mandelbrot
  100 VDU12:PRINT "Mandelbrot - Gordons TinyBasic - Integers"
  110 PRINT "Start" : VDU 7
  120 REM !160=0:REM Initialise TIME in Ruby board
  130 Z=TOP:$Z=".,'~=+:;*%&$OXB#@ "
  140 F=50
  150 FOR Y = -12 TO 12
  160 FOR X = -49 TO 29
  170 C=X*229/100
  180 D=Y*416/100
  190 A=C:B=D:I=0
  200 Q=B/F:S=B-(Q*F)
  210 T=((A*A)-(B*B))/F+C
  220 B=2*((A*Q)+(A*S/F))+D
  230 A=T: P=A/F:Q=B/F
  240 IF ((P*P)+(Q*Q))>=5 GOTO 280
  250 I=I+1:IF I<16 GOTO 200
  260 PRINT" ";
  270 GOTO 290
  280 VDU ?(Z+I)
  290 NEXT X
  300 PRINT ""
  310 NEXT Y
  320 Q=!160
  330 PRINT"Finished" : VDU 7
  340 REM PRINT"Time: ", Q/100, " secs."
-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

Heh.

Code: Select all

  160   for x = -49 to 25
Plus the comma and full stop were swapped.
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Neolithic Tiny Basic

Post by BigDumbDinosaur »

barnacle wrote:
I suspect I will leave USR as it currently is and ignore READ and DATA for now. I think I'm going to need that space for a file system.

USR is another one I didn’t use.  At least on the C-64 and C-128, I gravitated to using built-in BASIC interpreter functions to parse variables attached to a SYS call.  I could pass as many variables as I wanted and modify any or all of them for the return.  USR just seemed too constrained.

Quote:
...my last major project was a hundred thousand lines of C for - of all things - an intelligent cat feeder...

I’m confused.  Was it the cat who was intelligent or the feeder?  :D  What really has me puzzled is how it took 100K code lines to dispense some Meow-Mix and water to a likely-ungrateful feline.  :? :?: :shock:
x86?  We ain't got no x86.  We don't NEED no stinking x86!
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

Aha, and other swapped characters in the string. With those corrected, my output is character identical with yours, Gordon.

Code: Select all

......,,,,,,,,,,,,,,,,,,,,,,'''''''''~~~~~=+:*$O:;==~~'''''',,,,,,,,,,,........
.......,,,,,,,,,,,,,,,,,,,,,'''''''''~~~==+%*O  ;;%=~~~~''''',,,,,,,,,.........
........,,,,,,,,,,,,,,,,''''''''~~~'====++:       %++=~~~~'',,,,,,,,,..........
........,,,,,,,,,,,',,,,'''''''~~~=++::+;;*       %;:++===='''',,,,,,..........
.....,,,,,,,,,,,,''''''''~~~~~~~==+; &$%              ;*;$+=~',,,,,,,,,,.......
...,,,,,,,,,,,''''''''''~~~~~~===::;                       +~'''',,,,,,,,,.....
....,,,,,,,,,,,'''~~~=========+++&                       %:==~~''',,,,,,,......
.....,,,,,,''''''~~=+X::+; :+++:;%                        &&=~~''',,,,,,,......
....,,''''''''~~~~=+:%  *O  B*;*%                          $=~~'',,,,,,,,......
,,,,,,''''''~~~~~=++;*X        B                            =~~''',,,,,,,,,,,,.
,,,,,'''~~~~=====;*%&                                      +=~~'',,,,,,,,,,,,,.
,,,,''~~==++++:+*&                                       O:=~~'''''',,,,,,,,,,.
,,,,'                                                   %;+==~~'''',,,,,,,,,,,.
,,,,''~~==++++:+*&                                       O:=~~'''''',,,,,,,,,,.
,,,,,'''~~~~=====;*%&                                      +=~~'',,,,,,,,,,,,,.
,,,,,,''''''~~~~~=++;*X        B                            =~~''',,,,,,,,,,,,.
....,,''''''''~~~~=+:%  *O  B*;*%                          $=~~'',,,,,,,,......
.....,,,,,,''''''~~=+X::+; :+++:;%                        &&=~~''',,,,,,,......
....,,,,,,,,,,,'''~~~=========+++&                       %:==~~''',,,,,,,......
...,,,,,,,,,,,''''''''''~~~~~~===::;                       +~'''',,,,,,,,,.....
.....,,,,,,,,,,,,''''''''~~~~~~~==+; &$%              ;*;$+=~',,,,,,,,,,.......
........,,,,,,,,,,,',,,,'''''''~~~=++::+;;*       %;:++===='''',,,,,,..........
........,,,,,,,,,,,,,,,,''''''''~~~'====++:       %++=~~~~'',,,,,,,,,..........
.......,,,,,,,,,,,,,,,,,,,,,'''''''''~~~==+%*O  ;;%=~~~~''''',,,,,,,,,.........
......,,,,,,,,,,,,,,,,,,,,,,'''''''''~~~~~=+:*$O:;==~~'''''',,,,,,,,,,,........
Finished

Code: Select all

".,'~=+:;*%&$OXB#@ " (yours)
",.'~:;*%&$OXB#@ "   (mine)
Looks like the equals and the plus fell out of mine.

The extra columns on the right hand edge make no significant difference to the execution time.

Neil
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

I never used USR either, as far as my fading recollection of fifty years ago works... I suspect it was invented by cats.

Who are far more intelligent than humans; witness that they not only parasitise upon us but, on the whole, humans seem to like them...

The feeder is pretty smart. I can't talk about the details for obvious reasons, but it identifies a cat (or group of cats), opening only to the correct animal and at the correct time; weighing the amount of food that the cat has eaten from both of two bowls, and logging that in real time. It weighs the food that the human slave puts in the bowl(s) in the first place. It allows software updates over the air without stopping operation. The back end sends updates and status to the human's mobile phone.

When we were originally planning all the interactions between the cat, the human, and the feeder, we filled three walls of whiteboards with flow diagrams; the final state machine has in excess of a thousand states and transistions (and I am very proud of the mechanism that translated an excel spreadsheet into C code to manage that).

In spite of which, we missed some notable cases: cats trying to break into feeders that wouldn't open for them by turning them upside down and hitting them; cats hiding favourite toys inside the food bowls so other cats in the household couldn't play with them, and in one case, a human who instead of pushing the 'open' button on the back of the feeder to, er, open it, picked up their kitten and waved it through the sensor...

Neil
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Neolithic Tiny Basic

Post by BigEd »

Glad the fractal matches now! I think I was mildly confused because Gordon exhibits both an integer and an FP fractal, and I shouldn't expect them to look exactly alike.
Post Reply