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.