Author |
Topic: BB4W FORTH Thoughts... (Read 1216 times) |
|
afarlie
New Member
member is offline


Posts: 18
|
 |
BB4W FORTH Thoughts...
« Thread started on: Sep 5th, 2009, 10:23pm » |
|
i) Technical enquiry:
Jones Forth has no ROLL word.
I.E <n> ROLL would take the n'th item below the current top of stack and move it to the top of the stack.
I was looking into how to do some graphics commands, and found that to do one of the VDU commands related to setting up BBC style viewports, I wanted to be able to find an item more than 3 down on the FORTH stack.
IIRC some FORTH's Implemented ROLL and PICK words for dealing with 'arbitarily' deep stack items.
I'll have another read of what some of the basic FORTH words are supposed to do, to see if this is possible.
ii) Forth source code for some basic graphics operations follow on which comments are welcomed..
/ I am doing <x> <y> <word> because it makes for code that maybe easier to understand :)
/ The ultimate goal might be to implement some kind of /display list building capability, although I'm not entirly /sure how that might be done...
:ORIGIN / call as <x> <y> ORIGIN 29 EMIT SWAP DUP 256 MOD EMIT 256 \ EMIT DUP 256 MOD EMIT 256 \ EMIT
:PLOT / call as <x> <y> PLOT 25 EMIT 69 EMIT SWAP DUP 256 MOD EMIT 256 \ EMIT DUP 256 MOD EMIT 256 \ EMIT ;
:DRAW / call as <x><y> DRAW 25 EMIT 5 EMIT SWAP DUP 256 MOD EMIT 256 \ EMIT DUP 256 MOD EMIT 256 \ EMIT ;
:MOVE / call as <X> <Y> MOVE 25 EMIT 4 EMIT SWAP DUP 256 MOD EMIT 256 \ EMIT DUP 256 MOD EMIT 256 \ EMIT ;
;FILL / (<x> <y> FILL) 25 EMIT 133 EMIT SWAP DUP 256 MOD EMIT 256 \ EMIT DUP 256 MOD EMIT 256 \ EMIT ;
;FILL_BY / (<x> <y> FILL_BY) 25 EMIT 129 EMIT SWAP DUP 256 MOD EMIT 256 \ EMIT DUP 256 MOD EMIT 256 \ EMIT ;
:GCOL <color> GCOL 18 EMIT 0 EMIT EMIT ;
iii) Internal sounds - There are almost certainly emulations of sound chips on the net. There is NOT yet as far as I know an emulation of the Hybrid 5000 though...
On a BBC Micro - I think setting up a sound was OSWORD 7? (which BB4W AFIAK doesn't directly expose to the user).
The other thing that would be needed for a 'music' FORTH is some kind of timer routine, for which I probably need to go and look at some of the existing BB4W examples such as TIMERLIB which would callback to a specfic word. Hmm...
iv) A SYS call... I'm not sure if an explicity SYS word is needed.
As surely you just put a function address on the FORTH stack and do something like EXECUTE (which will jump to the appropriate address?)
If so and it's 'stdcall' (most API calls are) the params would need to be on the FORTH stack below the relevant address to call, something that could be done easily in a FORTH system.
The problem of calling API functions then becomes a case of how to do "LoadLibrary" and "GetProcedureAddress" in a FORTH safe way...
My train of thought here is that you would get an address for a procedure and a 'compile' a word which puts an appropriate address on the Forth stacks and EXECUTES it.
I was thinking of something like the following...
"EXTERNAL.DLL" LOADLIB TO ExternalLib
which would create a WORD ExternalLib which would put an appropriate pointer on the stack.
ExternalLib "ApiFunc" EXTERNAL Api_Func
Which would create a word called Api_Func which called the function Api_Func in the external Library.
The word EXTERNAL could add any generic sanity checking needed.
v) 'Environment' Variables : Assuming it's possible to have EXTERNAL words.. Things like HWND and the device context could be obtained directly. That said, to me it makes far more sense to use the BB4W environment.
I assume that by knowing appropriate addresses the VDU variables could be accessed within the FORTH system.. (This would be useful so that current positions could be preserved inside a CIRCLE word for example.)
Thanks for reading this far, I hope I am asking the right questions as well...
|
« Last Edit: Sep 5th, 2009, 10:36pm by afarlie » |
Logged
|
|
|
|
John F
Guest
|
 |
Re: BB4W FORTH Thoughts...
« Reply #1 on: Sep 6th, 2009, 07:52am » |
|
-PICK exists in JonesForth. eg try '1 2 3 4 5 6 7 4 PICK .' and it does what you describe the missing 'ROLL' word doing.
I was fazed by missing the 'DO ... LOOP' structure and don't even know how I'd open a view port!!
You are clearly getting stuck well in here & I'll follow with interest. I have the old Acornsoft Forth (Grandis-Harrison) manual from 1983- I may scan the 'Graphics' chapter if you or Richard are interested in what it implemented. It sounds as if you are already beyond this....
|
|
Logged
|
|
|
|
John F
Guest
|
 |
Re: BB4W FORTH Thoughts...
« Reply #2 on: Sep 6th, 2009, 07:59am » |
|
Sorry. Just realised it copies rather than moves. Ooops!!
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: BB4W FORTH Thoughts...
« Reply #3 on: Sep 6th, 2009, 09:35am » |
|
Quote:Jones Forth has no ROLL word |
|
Can this be implemented in Forth? If so you obviously have your solution, but if not it will require an assembler primitive to be added. I would be happy to do that.
The next version I release will have the necessary primitive for DOES> to be implemented.
Quote:Forth source code for some basic graphics operations follow on which comments are welcomed.. |
|
They're very much the kind of thing I had in mind, although the repeated use of DUP 256 MOD EMIT 256 / EMIT doesn't seem very 'Forth-like' to me: wouldn't it be better to define a word (e.g. EMIT16) to do it (and indeed another word to output two 16-bit values)?
Quote:A SYS call... I'm not sure if an explicity SYS word is needed. |
|
It may be that you don't need a specific SYS word, but I'm not sure how you'd get the 'return value' from an API function onto the stack without one.
My thinking about API access was similar to yours, but I'd envisaged just a single word, e.g. SYSADDR, which would be used as follows:
Code:S" GetTickCount" S" kernel32" SYSADDR
In practical terms you'd put the address in a 'constant':
Code:S" GetTickCount" S" kernel32" SYSADDR CONSTANT GetTickCount
Richard.
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: BB4W FORTH Thoughts...
« Reply #4 on: Sep 6th, 2009, 10:13am » |
|
Quote:I was fazed by missing the 'DO ... LOOP' structure |
|
Again, the obvious question is "can this be implemented in Forth"? AIUI JonesForth actually implements rather more words as assembler primitives than some other Forths (probably done for speed).
If DO ... LOOP cannot be implemented in Forth then I'd ideally like to see another assembler implementation; I'm not sure that my primitive knowledge of Forth is good enough to write the code from scratch.
Richard.
|
|
Logged
|
|
|
|
Malcolm
Guest
|
 |
Re: BB4W FORTH Thoughts...
« Reply #5 on: Sep 6th, 2009, 5:31pm » |
|
Be aware of this from a Forth blog:
Quote:ROT reversed?
Am I crazy, or is ROT/-ROT swapped compared to the standard (as in Starting Forth)? By kotlinski at Thu, 2009-01-15 10:38 | login or register to post comments No
No you're not crazy. I did get them backwards. By Richard W.M. Jones at Fri, 2009-08-14 15:02 |
|
regards, Malcolm.
|
|
Logged
|
|
|
|
afarlie
New Member
member is offline


Posts: 18
|
 |
Re: BB4W FORTH Thoughts...
« Reply #6 on: Sep 6th, 2009, 5:44pm » |
|
on Sep 6th, 2009, 09:35am, Richard Russell wrote:Can this be implemented in Forth? If so you obviously have your solution, but if not it will require an assembler primitive to be added. I would be happy to do that. |
|
ROLL does the following IIRC... -
7 6 5 4 3 2 1 6 ROLL
Would leave the stack as : 6 5 4 3 2 1 7
I'm not sure how to do this in pure FORTH.
Quote:The next version I release will have the necessary primitive for DOES> to be implemented. |
|
And BUILDS?
Quote:They're very much the kind of thing I had in mind, although the repeated use of DUP 256 MOD EMIT 256 / EMIT doesn't seem very 'Forth-like' to me: wouldn't it be better to define a word (e.g. EMIT16) to do it (and indeed another word to output two 16-bit values)? |
|
I will post the revised version later...
Quote:It may be that you don't need a specific SYS word, but I'm not sure how you'd get the 'return value' from an API function onto the stack without one.
My thinking about API access was similar to yours, but I'd envisaged just a single word, e.g. SYSADDR, which would be used as follows:
Code:S" GetTickCount" S" kernel32" SYSADDR
In practical terms you'd put the address in a 'constant':
Code:S" GetTickCount" S" kernel32" SYSADDR CONSTANT GetTickCount
|
|
So typing GetTickCount would execute the relevant item putting the returns on the FORTH stack ? Hmm :)
|
« Last Edit: Sep 6th, 2009, 5:45pm by afarlie » |
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: BB4W FORTH Thoughts...
« Reply #7 on: Sep 6th, 2009, 8:29pm » |
|
Quote:Be aware of this from a Forth blog: |
|
I was already aware of that (and the compatibility problems with HERE, ALLOT, CREATE). Unfortunately ROT and -ROT can't straightforwardly be corrected, because they're used extensively in jonesforth.f.
In principle it would be possible to change the primitives, and then edit every occurrence in jonesforth.f, but then it would be incompatible with every other implementation of JonesForth. This would cause problems updating to a later version, if one was ever released by Richard Jones.
Not being a Forth enthusiast, I don't really understand why the mistakes went uncorrected up to version 45, and still haven't been. I can only assume that the language isn't as standardised as some, and that users cope with this kind of thing.
It would appear that JonesForth was written by somebody who knew (at the start) virtually nothing about Forth. As a result the implementation is faulty in several respects, and wastefully inefficient in others. Unfortunately it's the only 'free' IA-32 implementation of Forth that I know of.
Richard.
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: BB4W FORTH Thoughts...
« Reply #8 on: Sep 6th, 2009, 8:31pm » |
|
Quote:So typing GetTickCount would execute the relevant item putting the returns on the FORTH stack ? |
|
No, you'd have to do:
Code: (with my proposal of adding SYSADDR and SYSCALL words).
Richard.
|
|
Logged
|
|
|
|
afarlie
New Member
member is offline


Posts: 18
|
 |
Re: BB4W FORTH Thoughts...
« Reply #9 on: Sep 6th, 2009, 9:37pm » |
|
on Sep 6th, 2009, 8:29pm, Richard Russell wrote:I was already aware of that (and the compatibility problems with HERE, ALLOT, CREATE). Unfortunately ROT and -ROT can't straightforwardly be corrected, because they're used extensively in jonesforth.f.
....
It would appear that JonesForth was written by somebody who knew (at the start) virtually nothing about Forth. As a result the implementation is faulty in several respects, and wastefully inefficient in others. Unfortunately it's the only 'free' IA-32 implementation of Forth that I know of.
Richard. |
|
on Sep 6th, 2009, 8:29pm, Richard Russell wrote: Unfortunately it's the only 'free' IA-32 implementation of Forth that I know of. |
|
In terms of other 'free'-ish FORTH's around there are :
gForth http://www.jwdt.com/~paysan/gforth.html - GNU Forth implementation ( which being GNU is assumed to be GPL)
There is also Win32Forth (http://win32forth.sourceforge.net/) which also has a Yahoo group - here (http://tech.groups.yahoo.com/group/win32forth/)
It may be possible to patch Win32Forth to use oswrch or to use Win32Forth as reference for someone willing to fix JonesForth's shortcomings.
There are also seemingly a number of freeware and proprietary systems targeting both i386 and ARM (There are some fairly developed FORTH's for RISC OS if anyones interested.)
Obviously these may not implement their output via oswrch, or use the intended SYSADDR and SYSCALL words that were being considered for addition to the JonesForth port.
if anyone is still bothered at this point, the 'standard' for ANS FORTH appears to have been archived here... "http://www.taygeta.com/forth/dpans.htm".
|
« Last Edit: Sep 6th, 2009, 9:48pm by afarlie » |
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: BB4W FORTH Thoughts...
« Reply #10 on: Sep 6th, 2009, 10:01pm » |
|
Quote:gForth... There is also Win32Forth |
|
I'm pretty sure they're both written in C (or C++), so not really relevant to the current discussion.
Quote:There are also seemingly a number of freeware and proprietary systems targeting both i386 and ARM |
|
In the context of Forth, i386 may mean 16-bit (i.e. MS-DOS), so again not really relevant to BB4W; and of course ARM code is totally incompatible.
Let's not lose sight of the fact that we are here primarily discussing BBC BASIC, not Forth! This is not the place to talk about Forth in general, or other ways in which to get Forth working under Windows.
I still see some benefits of a BBC BASIC-hosted Forth, principally the VDU drivers which give easy access to a graphical output capability. At the moment that means JonesForth, for good or ill.
If the consensus of opinion is that the shortcomings of JonesForth make it unacceptable, I suggest we draw this to a close. Those interested more in Forth than in BBC BASIC are requested to take their discussions elsewhere.
Richard.
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: BB4W FORTH Thoughts...
« Reply #11 on: Sep 7th, 2009, 12:27pm » |
|
Rich Jones, the author of JonesForth, has contacted me to ask if he can link to the BBC BASIC version on his site! I've responded, for the moment, to the effect that it isn't appropriate to promote it until issues such as the ROT/-ROT reversal are addressed.
I've also asked questions on comp.lang.forth, where one correspondent has described JonesForth as "pretty hopeless".
So I still don't know what is the best course of action. It would seem a shame to abandon the considerable work I have done so far, but if JonesForth is incapable of becoming a 'useful' Forth implementation then I don't want to waste my time expending extra effort.
Richard.
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: BB4W FORTH Thoughts...
« Reply #12 on: Sep 8th, 2009, 3:51pm » |
|
Quote:My thinking about API access was similar to yours, but I'd envisaged just a single word, e.g. SYSADDR, which would be used as follows: S" GetTickCount" S" kernel32" SYSADDR |
|
That appears to be impossible (in Jonesforth at least) because there's only one buffer for strings, so "GetTickCount" immediately gets overwritten with "kernel32".
I can split the LoadLibrary and GetProcAddress into separate words, as somebody suggested, but I need a word for FreeLibrary as well:
Code:Z" kernel32.dll" LoadLibrary DUP
Z" GetTickCount" GetProcAddress
CONSTANT GetTickCount
GetTickCount SYSCALL .
6491875
GetTickCount SYSCALL .
6499843
FreeLibrary
It works, as you can see (this is a snapshot of the actual output), but it's messy. Can anybody think of a nicer way?
Richard.
|
« Last Edit: Sep 8th, 2009, 9:48pm by admin » |
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: BB4W FORTH Thoughts...
« Reply #14 on: Sep 14th, 2009, 2:15pm » |
|
I have uploaded the latest version (0.22) of BB4Wforth:
http://groups.yahoo.com/group/bb4w/files/Miscellaneous/forth.zip
Changes in this version include:
1. The following standard Forth words, which work incorrectly in Jonesforth (v45), have been corrected: ROT, -ROT, ALLOT, DEPTH, HERE, MOD, / and U. (etc.)
2. The following standard Forth words, which aren't present at all in Jonesforth (v45) have been added: ROLL, DO, ?DO, LOOP, +LOOP, I, J, LEAVE, UNLOOP, <BUILDS, DOES>
3. The following custom Forth words (specific to this version) have been added: ERR, OSCLI, SYSCALL, HWND, VERSION$, LoadLibrary, FreeLibrary, GetProcAddress, EMIT16, XY, MODE, CLS, CLG, COLOUR, GCOL, ORIGIN, PLOT, MOVE, DRAW, FILL, MOVEBY, DRAWBY, EXEC
4. Operation of the following Forth words has been slightly modified: DEPTH, .S
Also supplied is the program fern.f which is a Forth version of the FERN.BBC graphics demo supplied with BB4W (translating it into Forth with virtually zero knowledge of the language was interesting!):
Code:\ 'Fake' fractal fern
\ Original QBASIC program published in PC Magazine
\ BB4Wforth version by Richard Russell, 14-Sep-2009
VARIABLE RND
: RANDOM ( n -- u ) RND @ 134775813 * 1 + DUP RND ! SWAP U/MOD DROP 1 + ;
: FERN
8 MODE
2 0 GCOL
0 0 ( X Y )
80000 1 DO ( Loop 80000 times )
100 RANDOM
DUP 10 <= IF DROP
SWAP DROP 0 SWAP 16 * 100 /
ELSE
DUP 86 <= IF DROP
2DUP 2DUP ( X Y X Y X Y )
4 * 100 / SWAP 85 * 100 / + ( X Y X Y x )
-ROT ( X Y x X Y )
85 * 100 / SWAP 4 * 100 / - 160 + ( X Y x y )
2SWAP 2DROP
ELSE
DUP 93 <= IF DROP
2DUP 2DUP ( X Y X Y X Y )
-26 * 100 / SWAP 20 * 100 / + ( X Y X Y x )
-ROT ( X Y x X Y )
22 * 100 / SWAP 23 * 100 / + 160 + ( X Y x y )
2SWAP 2DROP
ELSE DROP
2DUP 2DUP ( X Y X Y X Y )
28 * 100 / SWAP 15 * 100 / - ( X Y X Y x )
-ROT ( X Y x X Y )
24 * 100 / SWAP 26 * 100 / + 44 + ( X Y x y )
2SWAP 2DROP
THEN
THEN
THEN
2DUP SWAP 600 + SWAP 2DUP MOVE DRAW
LOOP
2DROP
." OK"
;
FERN You can run the program from BB4Wforth using the command:
Code: As this thread has gone very quiet, I would value any feedback, bug reports etc. to indicate that somebody out there is appreciative of my efforts!
Richard.
|
|
Logged
|
|
|
|
|