1 # Snobol4th
2
3 A toy Forth written in Snobol4.
4
5 This Forth is implemented as a "pure" interpreter, which simply
6 means it has no compiling or translation step before immediately
7 executing the source code as string data. In other words, it
8 reads the program pretty much exactly like a human would.
9
10 Only enough of the Forth language was implemented to be able to
11 execute a "99 Bottles of Beer" lyric-printing program.
12
13 [I learned Snobol and then wrote a toy Forth](https://ratfactor.com/snobol/)
14
15 Snobol4 is an unusual language of contrasts. String
16 pattern-matching operations are first-class items in the language
17 and can be combined and composed into expressive string parsing
18 and tokenization. Yet general program control flow is essentially
19 a bunch of labeled GOTOs and branching is based on a hidden layer
20 of "success" and "fail" results of any operation.
21
22 [Ratfactor's Judgement of Snobol4](https://ratfactor.com/snobol/judgement)
23
24 I highly recommend having a small, specific goal when implementing
25 any project as open-ended as a programming language. A lot of my
26 real-world programming often comes down to relatively simple
27 string manipulation, so the 99 bottles program has long been a
28 favorite. It also exercises basic repetition and if/else logic.
29
30 [99-bottles-of-beer-.net](https://www.99-bottles-of-beer.net/)
31
32 [Have a target for your programming language](https://ratfactor.com/cards/toy-language-target)
33
34
35 ## The files
36
37 **forth.sno** - The actual program, a minimal Forth implemented
38 in Snobol4.
39
40 **99.forth** - A Forth entry for the 99 bottles...
41
42 **99output.txt** - Your very own souvenir copy of the successful run of 99.forth!
43
44 **test.forth** - The test Forth I _actually_ ran as I built up the word dictionary needed to execute 99.forth.
45
46 **README.md** - That's me!
47
48 **log.txt** - Abandoned dev log of dubious worth!
49
50 ## Running it
51
52 You can interact directly with the interpreter like so:
53
54 $ snobol forth.sno
55 ." Hello world!" CR
56 Hello world!
57 ^D
58
59 Run a Forth script by piping it to the interpreter:
60
61 $ snobol forth.sno < 99.forth
62 99 bottles of beer on the wall
63 99 bottles of beer
64 Take one down and pass it around.
65 98 bottles of beer on the wall
66 ...
67
68 ## A bit more about this implementation
69
70 I chose to play to Snobol's strengths by storing and executing
71 even "compiled" words in string form rather than machine code or
72 bytecode for a VM.
73
74 Because of the GOTO-like behavior of control flow, writing a Forth
75 in Snobol is both very different and very similar to writing one
76 in assembly language.
77
78 It feels like cheating and a bit un-Forthy, but while matching and
79 executing source code directly makes a lot of things easier (and
80 simpler!), it also means you're going well off the beaten path in
81 terms of how various words are implemented. Some words don't even
82 make much sense when you're not actually converting the source
83 into bytecode or working with raw memory.
84
85 However, jumping around in strings can actually be quite similar
86 to jumping around in binary code in memory. Again, it's very
87 similar to how you might "execute" the code yourself if you were
88 doing it on paper.