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 »

Rats... I came up with a mechanism to include if/else/endif rather than just if/endif, which worked nicely... until I realised that if there were no 'else' clause, it had to scan the whole of the basic program text before it didn't find it (if you see what I mean).

A rethink is required, methinks!

Neil
User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: Neolithic Tiny Basic

Post by Dr Jefyll »

if/else/endif does sound worthwhile!
Quote:
it had to scan the whole of the basic program text before it didn't find it
I'm still on my first cup of coffee, but couldn't it start by scanning 'til it finds the endif? Then do a second scan looking for the else... but give up when you reach the endif's location; don't scan the whole of the basic program text.

Alternatively, do a scan that simultaneously searches for else and for endif. But that could get gnarly in a hurry... :|

Waddaya think of my re-think? (In regard to the second part, I think my re-think stinks!) :-)

-- Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Neolithic Tiny Basic

Post by barrym95838 »

TRS-80 Level II BASIC had ELSE but no ENDIF, so you had to keep everything in one numbered line. My 7th grade friend Joe Bridgewater was fond of coming up with complex and confusing nested IF/THEN/ELSEs in a single line, but he always got them to work somehow.
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
User avatar
BigDumbDinosaur
Posts: 9426
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Neolithic Tiny Basic

Post by BigDumbDinosaur »

Dr Jefyll wrote:
I'm still on my first cup of coffee...

That’s no excuse!  :D

Quote:
...but couldn't it start by scanning 'til it finds the endif? Then do a second scan looking for the else... but give up when you reach the endif's location; don't scan the whole of the basic program text.

That, to me, sounds like the logical way to handle it.  Write the interpreter to require that ELSE has to be bounded by an IF/ENDIF pair.  That being the case, if an ELSE is *not* encountered in a statement between IF and ENDIF, it syntactically doesn’t exist in the code block—no need to look ahead on the off-chance there’s an ELSE somewhere.  If an ELSE is later encountered after an ENDIF but before another IF, it’s a syntax error.

Quote:
Alternatively, do a scan that simultaneously searches for else and for endif. But that could get gnarly in a hurry... :|

Yes it could...I suspect a not-insignificant performance penalty would result.  Realistically, that sort of scan needs to occur when the program is written and saved...the save process could do a syntax check.  Obviously, saving the program would take a little longer, but runtime performance wouldn’t be affected.

Quote:
Waddaya think of my re-think? (In regard to the second part, I think my re-think stinks!) :-)

Well, as you said, you’re still slurping your first coffee...  :D

BTW, Jeff, what’s your preferred brand of coffee?
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 »

Yeah, my first thought was

Code: Select all

	char * tmp;

	where -= 4;				// back to the start of the line
	where = find_next_line(where);
	if (!compare())
	{
		tmp = find_pair(where, IF, ELSE);
		if (NULL == tmp)
		{
			where = find_pair(where, IF, ENDIF);
		}
		else
		{
			//printf ("next line is: %d\n", get_line(tmp));
			where = find_next_line(tmp);
		}
	}
	return where;
}
which works, but because it's trying to find a matching else (i.e. on the same level as the if), if there isn't one, it scans the whole of the text before it gives up and starts looking for endif. Find_pair() matches only one match against one pair; it can't handle two without getting - as you say - really gnarly because it also has to handle while/endwhile and for/next.

So the next plan is to incorporate the pair finding into if(); it will look for either of an else or an endif - at the right level - and continue executing thereafter, which should be correct in either case. This is only for the non-true case; when true it just executes the next line until it meets endif (which just continues) or else (which looks for the matching endif and goes there).

Neil
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Neolithic Tiny Basic

Post by barrym95838 »

BigDumbDinosaur wrote:
That being the case, if an ELSE is *not* encountered in a statement between IF and ENDIF, it syntactically doesn’t exist in the code block—no need to look ahead on the off-chance there’s an ELSE somewhere.  If an ELSE is later encountered after an ENDIF but before another IF, it’s a syntax error.
Yeah, BASIC allows structured coding techniques but *doesn't require* them, so forcing a block paradigm on the language is likely a recipe for frustration, both for the implementer and the user.
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Neolithic Tiny Basic

Post by BigEd »

BBC Basic in later iterations (after 6502) did allow for block-structured IF-THEN-ELSE-ENDIF as well as the single-line IF-THEN-ELSE, but I don't know exactly how it did it. Example from the manual:
Each IF statement can only have one corresponding ENDIF and, optionally, one ELSE. It is possible to nest statements:

Code: Select all

IF S>1000000 THEN
  Y=1
  IF R=1 THEN
    V=1
    H=1
  ENDIF
ELSE
  PRINT "not enough"
ENDIF
Worth noting that 8-bit BBC Basic was 16k bytes, and the later ones with the more complex grammar were even larger.
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

That's exactly the approach I'm using. Each if _must_ have an endif, and _may_ have an else. The endif and else must be at the same nesting depth; jumping out between the if and endif will almost certainly break things.

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

Re: Neolithic Tiny Basic

Post by barnacle »

I think I have an approach that works, which handles nested if/else/endif and with the else optional. But I haven't translated it to assembly yet; this is from my C master:

Code: Select all

> list
   10 for q = 1 to 10
   20   print q;
   30   if q <= 5
   40     print "small"
   50     else
   60     if q < 8
   70       print "largeish"
   80       else
   90       print "large"
  100       endif
  110     endif
  120   next
  130 print "done"
> run
1 small
2 small
3 small
4 small
5 small
6 largeish
7 largeish
8 large
9 large
10 large
done
> 
But there is still testing to do; if/else/endif allows for more scope for confusion.

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

Re: Neolithic Tiny Basic

Post by barnacle »

Yup, it works in assembly too (first time, though it could use some optimisation).
Screenshot from 2025-03-25 07-30-19.png
and after running
Screenshot from 2025-03-25 07-30-53.png
demonstrating nesting within if/endif and within for/next, and also showing both with and without the optional else.

The bad news is

Code: Select all

f007 :                  main_99:
f007 : 4c00ef           	jmp main_1
when I'd like it to finish _before_ $efff, but BB8 has been amusing himself with some optimisations and has many savings I have still to test.

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

Re: Neolithic Tiny Basic

Post by BigEd »

Do you still support the single line version without the endif?
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

No, it's always had separate lines for
  • if [condition]
  • things to do if the condition is true
  • (optional) else
  • (optional) things to do if condition is false
  • endif
The first round of changes resulted in

Code: Select all

effd :                  main_99:
effd : 4cf6ee           	jmp main_1
:mrgreen:

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

Re: Neolithic Tiny Basic

Post by barnacle »

The latest and greatest, courtesy of some excellent smallifying by BB8 - build size is now only 3,797 bytes. In particular, storeline has been completely rewritten by BB8 to make it half its previous size, and I've chopped a lot out of execute, factoring out a repeated load at four bytes per chop (for a total of 36 bytes) and incidentally made use of the REPTOS macro to save some text space - it generates the same code as it's replacing.

At this point, it's probably worth drawing a line under (except for bugs) and saving the space for a mechanism to save and load a program using a DOS that doesn't yet exist... though I am still contemplating a RND function; low priority because it would just be a 'multiply by a prime number and add another prime' type of thing, easy to do as a gosub anyway. Perhaps more interesting would be a USR function which would call a binary blob...

I haven't made explicit reference, but a program line can be stored even if it makes no program sense. Any text stored within quotes will be stored without compression, so one might use a string (or strings) composed of ascii hex data to store a program before converting it to binary code. You'd have to do some juggling to find the line(s) containing the data, but I think it's doable as things stand.

But I digress... here's the code:
tiny.asm
(76.05 KiB) Downloaded 162 times
Neil

Edit: I've updated the Rough Guide on page 10
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Neolithic Tiny Basic

Post by BigEd »

Excellent! For me, USR is more useful than RND, because a USR routine could offer a RND if so desired.
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Neolithic Tiny Basic

Post by barnacle »

Usr, Ed? What? You mean like this?
Screenshot from 2025-03-26 22-26-25.png
That was easier than I though it might be, though it does require building a jsr and ret in the maths variables (hmm, have I missed a jsr (abs)?) but the target address can be any valid expression. I've called an internal routine here; building some code could be, um, interesting... (I mean, of course, is left as an exercise for the student!) though I suppose a routine to return the address of a given line could be helpful.

At the moment there are still around 250 bytes left...

Neil
Post Reply