6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 21, 2024 7:51 pm

All times are UTC




Post new topic Reply to topic  [ 30 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Wed Dec 23, 2020 10:30 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
I'm used to DOES> being for defining the child words' runtime behavior in Forth, and ;CODE being for defining their behavior in assembly language.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 23, 2020 10:36 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895

Exactly! That is why I was trying to figure out IamRob's logic.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 23, 2020 10:52 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
JimBoyd wrote:
GARTHWILSON wrote:

You'll always have a column of mnemonics
Really?
Code:
CODE BOUNDS  ( N1 N2 -- N1+N2 N1 )
   CLC,
   0 ,X LDA,  2 ,X ADC,  0 ,X STA,
   1 ,X LDA,  3 ,X ADC,  1 ,X STA,
   ' SWAP @ JMP,  END-CODE


When practical, I group associated instructions on the same line like that too, and it is practical when they're short like the 0 ,X above. The RPN thing becomes more of a problem when you have for example FOOBAR1 6 + @ E0 AND # LDA or even longer, pushing that LDA way out to the right. If you're trying to vertically align mnemonics for visual factoring, you have to push them all way out. If the section is already indented for a loop, or nested structures, it gets worse. So you have things like (where "MNE" stands for "mnemonic"):
Code:
CODE FOOBAR2   ( a b -- c )
   <operand> MNE
   <operand> MNE
   BEGIN
      <operand> MNE
      <long operand calculation messes stuff up> MNE
      MNE              \ (with no operand)
      Z_flag_set
      IF
         <do stuff>
      THEN
      CS
   UNTIL
   NEXT  JMP
   END-CODE

The line with a mnemonic (like TAY) could be pushed way out under the previous line's mnemonic, but then the left margin's indentation no longer shows the structures.

However, individuality and being free-thinkers is part of being a Forth enthusiast. We do things our own way. The fact that Forth allows it is one of its strengths. It's also one of the things that makes others turn their noses up at it, but we don't care, because another of Forth's strengths is that we can carry on without the support of an industry. :D

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Thu Dec 24, 2020 6:34 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
IamRob wrote:
I created a Forth word call BLOAD. Which can load a binary file to a buffer. All we have to do is designate where that buffer is.

Quote:
If TEST is the latest word in the CURRENT vocabulary when it is executed, it will change it's own code field so it is no longer a colon definition. it's code field will point to the code following (;CODE) ( or DOES ) in it's body.
I agree that [ and ] are handy, when defining a colon definition. When assembling a code word or the assembly part of a CREATE ;CODE word, the state is interpret so they aren't even needed.

Does ProForth's ;CODE work differently because there is no Forth assembler?

The Forth assembler is in a new vocabulary, correct? I have the ability to create new vocabularies, but I have not tested that yet. I am still working in the Forth Vocabulary.

As far as I can see, TEST is still a colon word. The CFA points to indirect address for DOCOLON and the indirect address for (;CODE) is in the PFA that ends the interpretation of indirect addresses and starts the execution of ML code, and as far as I can see, nothing points to the ML code that follows (;CODE).


Top
 Profile  
Reply with quote  
PostPosted: Thu Dec 24, 2020 10:24 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895
IamRob wrote:
The Forth assembler is in a new vocabulary, correct? I have the ability to create new vocabularies, but I have not tested that yet. I am still working in the Forth Vocabulary.


Yes, it can be but not necessarily. Fleet Forth's assembler, as well as that of 64Forth and Blazin' Forth, is in a vocabulary named, appropriately enough, ASSEMBLER . If memory serves, Garth's Forth assembler is not in it's own vocabulary. His instruction names avoid redefining other Forth words.
Quote:
As far as I can see, TEST is still a colon word. The CFA points to indirect address for DOCOLON and the indirect address for (;CODE) is in the PFA that ends the interpretation of indirect addresses and starts the execution of ML code, and as far as I can see, nothing points to the ML code that follows (;CODE).

TEST is a colon word. It stops execution at (;CODE) . (;CODE) pulls the address of the following location from the return stack and stores it in the code field of the latest word defined ( at least in Forth-83 but I believe FIG Forth is similar). When (;CODE) exits, it returns control to the word that called TEST .
When TEST is executed, it patches the code field of the latest word and exits. If TEST is the latest word, it patches it's own code field so the next time it is executed, it performs the assembly code after (;CODE) in the body of TEST .
I ran some tests with ;CODE on three systems: 64Forth, Fleet Forth, and Gforth. On all three systems, when ;CODE executes ( it is immediate) the state is changed to interpreting so the leading [ is not needed.
Like Garth, I too am used to DOES> being for defining the child words' runtime behavior in Forth, and ;CODE for defining it in assembly language.
From my Forth-83 system:
Code:
: DEFER  ( -- )
   CREATE ['] -SET ,
   ;CODE
   2 # LDY,
   W )Y LDA,  PHA,  INY,  W )Y LDA,
   0 # LDY,
   W 1+ STA,  PLA,  W STA,
   W 1- JMP,
END-CODE

The Forth assembler used for the assembly code between ;CODE and END-CODE does not have to be RPN. Fleet Forth's is, but that's my preference.
I have not seen any other topics specifically about ;CODE but there is information on CREATE DOES> here and here.


Top
 Profile  
Reply with quote  
PostPosted: Thu Dec 24, 2020 10:53 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895
GARTHWILSON wrote:

The RPN thing becomes more of a problem when you have for example FOOBAR1 6 + @ E0 AND # LDA or even longer, pushing that LDA way out to the right. If you're trying to vertically align mnemonics for visual factoring, you have to push them all way out. If the section is already indented for a loop, or nested structures, it gets worse. So you have things like (where "MNE" stands for "mnemonic"):
Code:
CODE FOOBAR2   ( a b -- c )
   <operand> MNE
   <operand> MNE
   BEGIN
      <operands MNE
      <long operand calculation messes stuff up> MNE
      MNE              \ (with no operand)
      Z_flag_set
      IF
         <do stuff>
      THEN
      CS
   UNTIL
   NEXT  JMP
   END-CODE

The line with a mnemonic (like TAY) could be pushed way out under the previous line's mnemonic, but then the left margin's indentation no longer shows the structures.



Like this code fragment?
Code:
      BEGIN,
         0 # LDY,
         N )Y LDA,  TAX,  INY,
         N )Y LDA,
      0= NOT WHILE,
         N 1+ STA,  N STX,  INY,
         N )Y LDA,
         SBIT 1F OR # AND,
         N 2+ )Y EOR,
      CS-DUP 0= UNTIL, // CONTINUE
         BEGIN,
            INY,
            N 2+ )Y LDA,
            N    )Y EOR,
         0= NOT UNTIL,
         7F # AND,
      0= UNTIL,

Or this one without control flow structures?
Code:
HSUBR WARM
   FF # LDX,  TXS,
   'THERE USER.DATA - 1- # LDY,
   (WARM) JSR,
   >FORTH
   FORTH DEFINITIONS
   ." WARM START"
   ABORT ; -2 ALLOT

Even though the mnemonics don't line up and there is that transition to high level, I don't have a problem with it. I suppose that could be because I had very little assembly language experience before finding out about Forth. The first few Forths I've used had RPN assemblers and that is what I am comfortable with. Win32Forth's assembler could be set for either RPN or non RPN mode, if memory serves. It's been a while since I've done anything on Windows.

Quote:

However, individuality and being free-thinkers is part of being a Forth enthusiast. We do things our own way. The fact that Forth allows it is one of its strengths. It's also one of the things that makes others turn their noses up at it, but we don't care, because another of Forth's strengths is that we can carry on without the support of an industry. :D



I couldn't have said it better. :D


Top
 Profile  
Reply with quote  
PostPosted: Fri Dec 25, 2020 7:22 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
JimBoyd wrote:
TEST is a colon word. It stops execution at (;CODE) . (;CODE) pulls the address of the following location from the return stack and stores it in the code field of the latest word defined ( at least in Forth-83 but I believe FIG Forth is similar). When (;CODE) exits, it returns control to the word that called TEST .
When TEST is executed, it patches the code field of the latest word and exits. If TEST is the latest word, it patches it's own code field so the next time it is executed, it performs the assembly code after (;CODE) in the body of TEST .

In ProForth, there is no patching when using ;CODE. Are you confusing it with DOES>?
When TEST is compiled using ;CODE, the CFA holds the address to start indirect interpretation. The PFA is an indirect address that calls a routine that basically does a JSR to the code that follows the PFA, then upon return of executing the ML code, control is returned to the routine at the PFA address. Which in turn pops the TEST address off the stack and continues on with the next word that follows [b[]TEST[/b]. Or one could say, control returns to the word that called [b[]TEST[/b]. But nothing gets patched that I can see.


Top
 Profile  
Reply with quote  
PostPosted: Fri Dec 25, 2020 7:46 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
JimBoyd wrote:

Exactly! That is why I was trying to figure out IamRob's logic.

It is not so much my logic as it is a preference for me at this stage.

If I am not mistaken, only the Forth vocabulary can be saved as part of the Forth system. and the Assembler and Editor have to be re-compiled every time Forth is started for them to be in their own Vocabularies.

But if my logic is correct in what I believe can be done, then one can load the entire Assembler or Editor into their own vocabularies without having to compile them. Not only would this be a time saver, but also a space saver as the binary of the compiled vocabularies will be much smaller than the text one typed in to create the Assembler or Editor.

And looking down the road, when applications or games are created, the Forth system is always part of every program. This takes up a lot of extra space having duplicate Forth systems. But what if one only wants one Forth system on their hard drive, but has the ability to load utilities like the Assembler and Editor, games, applications, ...etc from just that one Forth system?


Top
 Profile  
Reply with quote  
PostPosted: Fri Dec 25, 2020 7:53 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
GARTHWILSON wrote:
I'm used to DOES> being for defining the child words' runtime behavior in Forth, and ;CODE being for defining their behavior in assembly language.

I agree with this behavior as well and for the most part have adopted it. But I am sure I would get all giddy if I found a use for ;CODE if it followed DOES>.

The diversity of Forth seems to be endless.


Top
 Profile  
Reply with quote  
PostPosted: Sat Dec 26, 2020 4:00 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
SamCoVT wrote:
IamRob wrote:
Currently I am writing some ProDOS commands for ProForth on the Apple II.
Is there a place I can follow your progress? I'm currently looking into adding file support into Tali2. I don't have an OS to help get info from disk, so I've written a very basic FAT32 implementation to access the files. I have support for using a file as a block device (reading and writing data, but I don't have support for writing to the FAT so it can't be resized), but I'd prefer to be able to do something like:
Code:
S" AFILE.FS" INCLUDED
or ANS2012 Forth's File-Access extension word INCLUDE
Code:
INCLUDE AFILE.FS

On Facebooks Programming Language 21st Century someone posted this link for accessing FAT16 files in Forth.

https://github.com/aik/SLOF/blob/master ... jhBLqZ8Yzs


Top
 Profile  
Reply with quote  
PostPosted: Sun Dec 27, 2020 9:21 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 255
IamRob wrote:
On Facebooks Programming Language 21st Century someone posted this link for accessing FAT16 files in Forth.
I do wish I had gone with FAT16 instead of FAT32. Juggling the 32-bit values around on a 16-bit Forth is a big hassle, and my Linux PC is just as happy to use a FAT16 file system on a compact flash card.

Back to your original topic (what?? that never happens....), I use [ and ] to compute things while compiling (as mentioned already by Garth). I do cycle testing on words as part of TaliForth2's test suite and use the following code. This test code predates Tali2 having an assembler, so you also get to see the pretendo-assembler using C, (note that Tali is an STC Forth, so all words are essentially CODE words and nothing special needs to be done to switch between assembly and regular Forth code):

Code:
hex

\ The location of the result
F008 constant cycles

\ direct byte compiled
\  lda $f006
\  lda $f007
: cycles_overhead [ AD c, 06 c, F0 c, AD c, 07 c, F0 c, ] cycles 2@ ;

\ direct byte compiled
\  lda $F006
\  jsr (xt on stack goes here)
\  lda $f007
\ then forth code to fetch and print results.
: cycle_test_runtime
    [ AD c, 06 c, F0 c,    \ lda $F006
      20 c,  0000 ,        \ jsr (address to be filled in)
      AD c, 07 c, F0 c, ]  \ lda $F007
    cycles 2@              \ fetch result
    cycles_overhead d-     \ subtract overhead
    ." CYCLES: " 6 ud.r    \ print results
;

\ cycle_test updates the address of the given xt in cycle_test_runtime
\ then it runs the test.

\ To test a word, put any arguments it needs on the stack, use tick
\ (') on the word to get it's execution token (xt) and then put
\ cycle_test, then any stack cleanup.
\ eg. 5 ' dup cycle_test 2drop
: cycle_test ( xt -- )
    [ ' cycle_test_runtime 4 + ] literal ! cycle_test_runtime ;
Here you can see that cycle_test calculates the correct location to stuff the XT into the assembly so it becomes part of the JSR there. The code accesses one address ($F006) to start a (simulated in py65mon) cycle counter, another address ($F007) to stop the counter, and a third address ($F008) to get the result as a 32-bit number.


Top
 Profile  
Reply with quote  
PostPosted: Mon Dec 28, 2020 9:28 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895
IamRob wrote:
In ProForth, there is no patching when using ;CODE. Are you confusing it with DOES>?


I haven't confused anything.

You said the original ProForth followed the fig Forth standard. Here is the definition of ;CODE from 64Forth, a superset of fig Forth
Code:
: ;CODE
   ?CSP COMPILE (;CODE)
   [COMPILE] [ SMUDGE ; IMMEDIATE

Here is the definition of (;CODE)
Code:
: (;CODE)
   R> LATEST PFA CFA ! ;

These definitions are also in agreement with the information in the publication "fig-FORTH 6502 ASSEMBLY SOURCE LISTING" Release 1.1 .
As you can see, ;CODE is immediate and compiles (;CODE) into the definition of the word being compiled. When this word is later executed, an address is removed from the return stack by R> and stored in the code field of the latest word by
Code:
LATEST PFA CFA !

Perhaps it is ProForth that is different.

Forth-79 and Forth-83 are similar. DOES> works differently than in fig-Forth. This excerpt is from the book "All About Forth" :
Quote:
Comment: This implementation uses the Forth-79 CREATE ...
DOES> technique which differs internally from fig-forth's
now obsolete <BUILDS ... DOES> . DOES> is immediate. it
compiles <;CODE> and a machine language call to the low level
routine labeled "DODOES". By embedding that one machine
instruction in the body of the defining word, two bytes are saved
from every one of its generated offspring.

MVP-FORTH uses < and > instead of parenthesis in names to avoid problems with comments.

Here are two excerpts from the Forth-79 Standard. The first is from the assembler word set.
Quote:
;CODE C,I,206

Used in the form:

: <name> . . . ;code

Stop compilation and terminate a defining word <name>. ASSEMBLER becomes
the CONTEXT vocabulary. When <name> is executed in the form:

<name> <namex>

to define the new <namex>, the execution address of <namex> will contain
the address of the code sequence following the ;CODE in <name>. Execution
of any <namex> will cause this machine code sequence to be executed.
"semi-colon-code"

and this is from the required word set.
Quote:
DOES> I,C,168

Define the run-time action of a word created by a high-level defining
word. Used in the form:

: <name> . . . CREATE . . . DOES> . . . ;

and then <name> <namex>

Marks the termination of the defining part of the defining word <name> and
begins the definition of the run time action for words that will later be
defined by <name>. On execution of <namex> the sequence of words between
DOES> and ; will be executed, with the address of <namex>'s parameter
field on the stack. "does"

The following excerpts are from the Forth-83 standard, the one my own Fleet Forth follows. From the assembler extension word set.
Quote:
;CODE -- C,I,79 "semi-colon-
sys1 -- sys2 (compiling) code"
Used in the form:
: <namex> ... <create> ... ;CODE ... END-CODE
_____ ______
Stops compilation, terminates the defining word <namex> and
_____
executes ASSEMBLER. When <namex> is executed in the form:
_____
<namex> <name>
_____ ____
to define the new <name>, the execution address of <name>
____ ____
will contain the address of the code sequence following the
;CODE in <namex>. Execution of any <name> will cause this
_____ ____
machine code sequence to be executed. sys1 is balanced with
its corresponding : . sys2 is balanced with its
corresponding END-CODE . See: CODE DOES>

and the required wordset.
Quote:
DOES> -- addr C,I,83 "does"
-- (compiling)
Defines the execution-time action of a word created by a
high-level defining word. Used in the form:
: <namex> ... <create> ... DOES> ... ;
and then
<namex> <name>
____
where <create> is CREATE or any user defined word which
executes CREATE .

Marks the termination of the defining part of the defining
word <namex> and then begins the definition of the
execution-time action for words that will later be defined
by <namex>. When <name> is later executed, the address of
____
<name>'s parameter field is placed on the stack and then the
____
sequence of words between DOES> and ; are executed.



Top
 Profile  
Reply with quote  
PostPosted: Mon Dec 28, 2020 9:31 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895
IamRob wrote:
If I am not mistaken, only the Forth vocabulary can be saved as part of the Forth system. and the Assembler and Editor have to be re-compiled every time Forth is started for them to be in their own Vocabularies.


You are mistaken.
Even with 64Forth for the C64, a system on a cartridge, there is a word to save the user's dictionary and a word to load a user's dictionary. I can testify from personal experience that all vocabularies and their definitions that are added to the system are saved.
My own Fleet Forth has the command FSAVE to save the Forth system. All vocabularies and their words are saved.
The Forth word FSAVE does not read a name from the text stream. It prompts for a name and reads it in with EXPECT . Here is a session log of saving Forth.
Code:
 OK
FSAVE
FILENAME? HMS HEXAPUMA  OK

and checking the directory.
Code:
DIR
0 "VICE            " 01 2A
81   "HMS HEXAPUMA"     PRG   
583 BLOCKS FREE.              OK
CONSOLE

I intentionally did not call this new system 'FORTH' to show that any filename can be used.
When I built my metacompiler I saved it as a separate Forth system. My metacompiler has seven vocabularies and I'm glad everything in the dictionary gets saved. When I power up the C64, or the VICE simulation of the C64, if I want to build a new Forth system, I insert the disk with the metacompiler and load it like so:
Code:
LOAD"METACOMPILER",8,1

And the entire metacompiler with all seven vocabularies, is loaded into memory.


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 29, 2020 3:53 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
JimBoyd wrote:
IamRob wrote:
I created a Forth word call BLOAD. Which can load a binary file to a buffer. All we have to do is designate where that buffer is.

In ProForth one creates a code word like this:

: TEST ;CODE [ HEX 20 C, FC58 , A0 , ... etc ] ;

As you can see, it takes a bit of typing to type in the code by hand. Then it finally dawned on me that since all code between [ and ] are immediately executed I should also be able to use disk commands.

The final result is:

: TEST ;CODE [ HERE BLOAD BINARY.PRGRM ] ;

HERE designates the address after the word TEST and the binary program is loaded right there.


Remember that all words between the brackets are executed immediately (just as if typing at the OK prompt) and does not get compiled into the word definition.


I have looked at ;CODE on three Forth implementations. 64Forth is a superset of FIG Forth for the C64. My Fleet Forth is a Forth-83 Forth for the C64. Gforth is an Ansi Standard Forth. In all three ;CODE compiles a word named (;CODE) on some systems, and DOES on others, and changes state to interpret. When executed, TEST will change the code field of the latest word in the CURRENT vocabulary to point to the code that follows ;CODE. If TEST is the latest word in the CURRENT vocabulary when it is executed, it will change it's own code field so it is no longer a colon definition. it's code field will point to the code following (;CODE) ( or DOES ) in it's body.
I agree that [ and ] are handy, when defining a colon definition. When assembling a code word or the assembly part of a CREATE ;CODE word, the state is interpret so they aren't even needed.

Does ProForth's ;CODE work differently because there is no Forth assembler?

No it works the same. I was misunderstanding the use-case of (;CODE), but after finally finding an example, I am starting to see how it is supposed to be used.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jul 23, 2022 2:36 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895

I realize this thread is a little old.
Getting back to IamRob's original topic, the real power of [ and ] is that you can do just about anything after [ .
Here is an example from my redefinition of Fleet Forth's LOAD .
Note that BRANCH is NOT immediate. It is normally compiled by immediate words such as AHEAD , ELSE , AGAIN , and REPEAT .
Code:
: LINELOAD  ( LINE# BLK# -- )
   DUP 0=
   ABORT" CAN'T LOAD 0"
   RB DECIMAL
   BLK 2@ 2>R
   BLK !  C/L * >IN !
   INTERPRET  2R>
   BRANCH [ BLK.2! , ] ; -2 ALLOT
: LOAD  ( U -- )
   0 SWAP BRANCH
   [ ' LINELOAD >BODY , ] ; -2 ALLOT

But that's not all. As long as you don't disturb the definition in progress by altering the contents of the data stack (compiler security) or adding to the dictionary (unless what is added is meant to be part of the definition in progress) you can play with the Forth system after [ . Examine the source of words, list words in a vocabulary, crunch some numbers. As long as any compiler security data is as it was and the dictionary is as you intend it for the definition in progress, you can resume where you left off after ] .


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 30 posts ]  Go to page Previous  1, 2

All times are UTC


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: