广告
广告
CHAPTER 4. A GUIDED TOUR 47
Now we know we have to move our cursor two positions and enter a space. Entering text at the cursor position is done by the ”c” command, which stands for ”COPY”. Note that you have to add a space after each command, so adding a space at the cursor position is done by entering a ”c” with two spaces:
2 m c
."^Hello world!" cr
." ^Hello world!" cr
0 OK
0 OK
Now we can exit the editor again and rerun our program. Yes, 4tH will know you’ve changed the text and recompile your program automatically: wq
(S)creen file: new.scr
(O)bject file: out
(E)dit (C)ompile (R)un (A)rguments
(Q)uit (G)enerate (B)uild (D)ecompile
>r
Hello world!
That’s it! You’ve just successfully entered, compiled and ran your very first 4tH program!
4.6
A more complex program
Note that this is not a tutorial on Forth. If you do not know the language you’ll probably won’t understand the statements we’re going to enter. You don’t have to, but if you need to please refer to our highly acclaimed 4tH primer.
Okay, let’s presume you’re looking at your 4tH prompt. We want to write a program which converts Unix ASCII files to DOS ASCII files. Unix ASCII files use a single linefeed to signify the end of a line while DOS ASCII files use an carriage return/linefeed pair for that purpose.
First, we need to name our program, so we press ”s” to enter the name of the screen file.
We’ll call it ”convert.scr”. Then we enter the editor by pressing ”e” and are greeted by the
”OK” prompt. First we’ll define a word (that’s what a subroutine is called in Forth) that converts a file:
0 clear
0 p : ProcessFile
1 p
2 p
3 p
4 p
5 p
6 p
7 p ; begin refill while
0 parse-word type 13 emit 10 emit repeat
Note that 4tH confirms you after each line that everything is ”OK”, but we left those messages out. When we list our program it looks like this:
CHAPTER 4. A GUIDED TOUR 48 l
8
9
10
11
12
13
14
15
Scr # 0
0 : ProcessFile
1
2 begin refill
3
4
5
6
7 ; while
0 parse-word type 13 emit 10 emit repeat
^: ProcessFile 0 OK
It is a good custom to start each screen with a comment line, so others will know what we’ve been doing. However, line 0 is already taken. To insert a blank line we use the ”s” command, which stands for ”SPREAD”. All lines following it will move down. If you happen to use line 15 you’re in trouble since that one will be lost:
0 s 0 s l
Scr # 0
0
1
2 : ProcessFile
3 begin
4
5
6 refill while
0 parse-word
7
8
9 ;
10
11 type 13 emit 10 emit repeat
12
13
14
15
^ 0 OK
Yes, as long as you’re not entering a command with a trailing text parameter, you can enter multiple commands on a single line. So this one tells the editor ”spread at line 0, spread at line 0, list”. Now we’re going to enter our comment line:
0 p ( Conversion from UNIX ASCII files to DOS ASCII files - I)
OK l
Scr # 0
0 ( Conversion from UNIX ASCII files to DOS ASCII files - I)
1
2 : ProcessFile
3 begin
4
5 refill while
CHAPTER 4. A GUIDED TOUR 49
12
13
14
15
6
7
8
9 ;
10
11
0 parse-word type 13 emit 10 emit repeat
^( Conversion from UNIX ASCII files to DOS ASCII files - I) 0 OK
That will do nicely. Although this word will do the job, we still have to open the input- and the output file. Since we want to test our program quickly we make a quick and dirty word that will do the job:
11 p : test s" code.txt" inpud open s" out.txt" outpud open
12 p error? rot error? rot or abort" Error!" use use;
13 p ttest ProcessFile wq
When we try to compile this program by entering ”c”, it doesn’t work:
Compiling; Word 17: Undefined name
Oops, we’ve obviously made an error, but where? Word 17? Where is word 17? We can find that out by decompiling the program and see where it went wrong. Just press ”d”:
Object size: 17 words
String size: 9 chars
Variables : 0 cells
Strings
Reliable
: 0 chars
: No
[
[
8] type
9] literal
[ 10] emit
[ 11] literal
[ 12] emit
[ 13] branch
[ 14] exit
[ 15] branch
[ 16] s"
(0)
(13)
(0)
(10)
(0)
(0)
(0)
(0)
(0) code.txt
The last thing it compiled was the start of the ’TEST’ definition. It must have gone wrong right after that one. So we go back to the editor and find out. Sure, ”inpud” must be ”input”.
We can even find out it we made more errors like this: f pud n
: test s" code.txt" inpud^ open s" out.txt" outpud open n
: test s" code.txt" inpud open s" out.txt" outpud^ open
Not found OK
11 OK
11 OK
And yes, we did. On lines eleven and twelve to be exact. With the ”f” command (which stand for ”FIND”) we can find a string. By entering ”n” (which stands for ”NEXT”) we can find the same text again. Now we have to correct it. We’ll get back to the top of the screen and find the offending word:
CHAPTER 4. A GUIDED TOUR 50 top f pud
: test s" code.txt" inpud^ open s" out.txt" outpud open 11 OK
Note that the cursor is positioned at the end of ”input”. We only have to wipe one character and insert the correct one:
1 w c t
: test s" code.txt" inpu^ open s" out.txt" outpud open
: test s" code.txt" input^ open s" out.txt" outpud open
11
11 OK
With the command ”1 w” we destructively backup the cursor by one position. Then we enter the ’t’ at the cursor position by using the ”c” command. However, there is a quicker way to do this: x pud
: test s" code.txt" input open s" out.txt" out^ open c put
: test s" code.txt" input open s" out.txt" output^ open
11 OK
11 OK
The ”x” command works very much like ”f”, but it does not only find the string, it also deletes it. Still, there are other errors left in the source: f test b ttest^ ProcessFile t^test ProcessFile
1 w
13 OK
13 OK
Yes, ”test” has an extra ”t”. So we find the next occurrance of ”test”. Note that a search is always performed from the cursor position, so the definition of ”test” is not found. The ”b” command will move the cursor backwards up to the point where ”test” begins and we can delete the superfluous ”t” with the command ”1 w”. The final typo we have to correct is a lacking space between ”then” and the semicolon. That can be fixed pretty quickly: top f use n error? rot error? rot or abort" Error!" use^ use; error? rot error? rot or abort" Error!" use use^; till ; error? rot error? rot or abort" Error!" use use^ c ; error? rot error? rot or abort" Error!" use use ;^
12 OK
12 OK
12 OK
12 OK
Now the cursor is positioned right after then. The ”till” command deletes everything from the current cursor position (indicated by the caret, remember?) to the end of the following string. In this case the semicolon but you can use any string. Finally, we copy the correct string into the text, which is a space followed by a semicolon. Four errors corrected. Let’s write the screen back to RAM disk and see what we have got:
广告