FIGgyBasic features

91 views
Skip to first unread message

Julian Skidmore

unread,
Dec 28, 2014, 10:59:48 AM12/28/14
to FIGnition
Hi folks,

I was thinking a little bit about whether it might be good to write a
BASIC to FIGnitionForth compiler that could be integrated with the
Tape loader. If this was the case, then one of the FIGgyBasic runtime
features would be read / data / restore.

It turns out that with a bit of thinking, read / data / restore would
be quite easy to support in FIGnition Forth.

First we'd define a read pointer:

0 var *data

It's quite easy to create constant data containing assorted fields in
FIGnition Forth. For example:

create crazyData

" Hello World!" 15 , 120 c, 1.23e10 d, " Done!"

create moreCrazyData

90 , 50d d, " Pointless String"

Restore is just a matter of assigning to *data, e.g.

crazyData *data !

The question is, how do we read items of data? My idea was to support
a number of words such as: cread read 2read and "read to read in data
according to the given type. You start with a generic word for reading
any amount of data:

: data> ( dst len )
swap >r
*data >r r @ ( src : *data len dst)
r> r swap +! ( src \len *data\ : len dst)
r> r> swap cmove
;

And then define all the others you need for specific types:

: cread ( dst ) 1 data> ;
: read ( dst ) 2 data> ;
: 2read (dst ) 4 data> ;
: "read ( dst ) *data @ "len data> ;

And you could use it as follows:

create msgBuffer 100 allot
0 var aWord
create aByte 1 allot
0d dvar aFloat
create msg2 50 allot

: exampleReadDataRestore
crazyData *data !
msgBuffer "read
aWord read aByte cread
aFloat dread
msg2 "read
;

You have to be careful to know what data you expect to be able to
read, but in the end, pretty easy to support!

-cheers from Julz

--

The DIY 8-bit computer from nichemachines™

Mark Wills

unread,
Dec 28, 2014, 11:48:24 AM12/28/14
to fign...@googlegroups.com

Slightly tangential to your post, but I thought I would share it nevertheless. My system has DATA[ and ]DATA

Both are immediate words. They work like this:
: someWord data[ 9 5 6 3 5 9 ]data ;

The data is compiled inline within the colon definition. Executing the word causes the address of the beginning of the data, and the number of data items to be pushed to the stack. Very forthy. No need for RESTORE - just execute the word again to get the address and count.

I've found it very handy indeed over the years. I use it to define graphics characters. It's much more convenient than "comma-ing" (with C,) data into memory.

Mark

--
You received this message because you are subscribed to the Google Groups "FIGnition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fignition+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Julian Skidmore

unread,
Dec 28, 2014, 1:00:43 PM12/28/14
to FIGnition

Hi Mark,

it's a nice idea, very forthy and would work on FIGnition too.

-cheers Julz

Julian Skidmore

unread,
Dec 29, 2014, 8:40:53 AM12/29/14
to FIGnition
Hi folks,

Another Basicism would be multidimensional arrays. In Basic we have the command:

DIM var(d1,d2,d3..dn)

How would I do this in FIGnitionForth? The key idea is to store the
number of dimensions along with the sizes of each dimension:

[n][dn]..[d3][d2][d1][data].

: dim ( d1 .. dn n ; name --)
builds>
dup c, 2 swap 0 do ( di sz)
over * swap ,
loop
allot
<does ( ix1 .. ixn pfa -- addr)
2 swap dup c@ swap 1+ swap 0 do ( di sz pfa)
>r over r @ * + r> 2+
loop
+
;

10 5 7 3 dim arr3D

4 2 1 arr3D @ ( arr3D[1,2,4] )
1357 1 2 6 arr3D ! ( arr3D[6,2,1]=1357)

Mark Wills

unread,
Dec 29, 2014, 9:02:12 AM12/29/14
to fign...@googlegroups.com

Nice. Have you seen the BASIC compiler Charles Moore wrote way back in (IIRC) 1981? It's written in FIG Forth in blocks. It allows BASIC code (with line numbers) to be written inside colon definitions. Infix notation with operator precedence is supported so one can write complex expressions with lots of parenthesis, as we're used to seeing in BASIC and other Infix languages!

A follow up article which includes the compiler is in one of the Forth Dimensions issues. I can dig it up if you're interested.

It's the perfect illustration of the power of the Forth language; that a BASIC compiler can be implemented in Forth, allowing Forth code and BASIC code to be freely mixed within an application.

Mark

Julian Skidmore

unread,
Dec 29, 2014, 5:10:25 PM12/29/14
to FIGnition

Hi Mark,

Yes I think I have seen it in a scan of forth dimensions online.

Did his version still require separators between BASIC tokens (keywords/variables/separators)?

In my concept of figgybasic, there would be no line numbers & consequently no goto nor gosub. Instead it'd be a sort of BBC / ZX basic hybrid with defproc .. Endproc + deffn .. Endfn support, along with structured control flow and the main program at the end.

At the moment I'd probably implement it in (shock-horror) java so that I can integrate it with figgytape and also support syntax checking.

The output would be FIGnition forth as text.

I would need to deal with differences between BASIC semantics & forth (e.g. for .. Next with variable names vs do .. Loop with implicit loop variable names).

I think it's good to be able to switch to forth though:

BBC style *forth and *BASIC commands I think :-)

Cheers Julz

David Buckley

unread,
Dec 29, 2014, 6:28:37 PM12/29/14
to fign...@googlegroups.com
Not having GOTO means you end up with crippleware where other than very simplistic/educational state machines are next to impossible to implement.

Mark Wills

unread,
Dec 29, 2014, 7:56:27 PM12/29/14
to fign...@googlegroups.com

No GOTO required to implement state machines in my experience. Can you elaborate?

Mark

Mark Wills

unread,
Dec 29, 2014, 8:02:47 PM12/29/14
to fign...@googlegroups.com

Hi Julian

AFAIR separators are still required, yes, because words such as LET (to assign something to a variable) are just immediate words in the dictionary that compile their own code when encountered in the colon definition. Consequently you can't say LET AREA=WIDTH*HEIGHT - you have to say LET AREA = WIDTH * HEIGHT

One benefit is that you can literally mix forth and basic side-by-side, as both pass through the inner interpreter.  No need to explicitly switch from one mode to another. It's all forth, even the basic code ;-)

Gotta love Forth!

Mark

David Buckley

unread,
Dec 29, 2014, 8:33:17 PM12/29/14
to fign...@googlegroups.com
Unless there is a supervisor level to implement state jumps then at each state transition the code for the old state must necessarily abort in favour of the code for the new state. New states can not be called by the previous state otherwise the return stacks would overflow.

Julian Skidmore

unread,
Dec 30, 2014, 3:44:29 AM12/30/14
to FIGnition

Hi David,

FIGnition forth suffers from a similar problem, since (branch) / (branch0) only have 8-bit displacements and you can't assign to IP because that won't affect the address counter & FIGnition would still end up executing the following token.

In FIGnition forth I can think of two ways to execute a jump. Firstly, by assigning to IP and then doing (branch) 0, causing a jump to IP .

Secondly, definitions that start:

: myExampleState0 r> drop ..... ;

Can be used to implement states. How would we do this in figgybasic? The answer is that Figgybasic will support vectored execution. It will be possible to have code like:

Deffn myExampleState()
*forth
r> drop
*basic
...
Return 1
EndFn

Rem initialize states
Dim gStates(5)
gState(0)=myExampleState

Rem Execute state
LET state=gState(state)()

Not quite as fast as in forth of course!

Cheers Julz

Julian Skidmore

unread,
Dec 30, 2014, 1:00:26 PM12/30/14
to FIGnition

One clarification: figgybasic would adopt traditional BASIC notation for simple variable types: append % for 16-bit integers, %% for 32-bit integers; $ for string variables and nothing for floats.

It will be possible to take the address of a simple variable by preceding it with '@' (the result is a16-bit value). Constants can be preceded by '&' to denote hexadecimal.

The pervious example code could transform into:

: myExampleState r> drop 1 ;

5 arr gStates
0 var state

: run
myExampleState 0 gStates !
state @ gStates @ exec state !
;

There are some ambiguities i need to sort out in my figgybasic model particularly in differentiating between declarations and execution. E.g. BASIC can allocate runtime arrays, but that's not possible with the above model. One solution is to differentiate between compile-time and run time variables.

Cheers Julz

Reply all
Reply to author
Forward
0 new messages