diff --git a/1992/buzzard.2/README.md b/1992/buzzard.2/README.md index 35e19674f..eaa09cdb7 100644 --- a/1992/buzzard.2/README.md +++ b/1992/buzzard.2/README.md @@ -1,58 +1,73 @@ # Best Language Tool: - Sean Barrett - Software Construction Company - 430 Southwest Parkway, #1906 - College Station, TX 77840 - USA +Sean Barrett +Software Construction Company +430 Southwest Parkway, #1906 +College Station, TX 77840 +USA ## To build: - make all +```sh +make all +``` ## To run: First: - make first +```sh +make first +``` Second: - echo help | cat third help.th - | ./first - cat third demo5.th | ./first +```sh +echo help | cat third help.th - | ./first +cat third demo5.th | ./first +``` Third: - cat third help.th - | ./first +```sh +cat third help.th - | ./first +``` -NOTE: Wait until Ok is printed and the type: +NOTE: Wait until 'Ok' is printed and the type: - 2 3 + . cr - -Yes you should really type the 2 letters: cr. +``` +2 3 + . cr +``` + +Yes you should really type the 2 letters: `cr`. Fourth: - Sorry, this is third! +``` +Sorry, this is third! +``` ## Alternate code: -An alternate version of this entry, `buzzard.2.alt.c`, is provided. This alternate code -does not contain a fix that the author notes below. +An alternate version of this entry, [buzzard.2.alt.c](buzzard.2.alt.c), is +provided. This alternate code does not contain a fix that the author notes +below. To compile this alternate version: - make alt +```sh +make alt +``` Use `buzzard.2.alt` as you would `buzzard.2` above. -## Judges' comments +## Judges' comments: Have fun! -## Author's comments +## Author's comments: -What it does: +### What it does: `first` implements a relatively primitive stack machine. How primitive? It supplies 13 visible primitives: 3 arithmetic, @@ -88,152 +103,152 @@ included, but it only works on ASCII systems. Do not expect to be able to do anything interesting with first. To do something interesting, you need to feed first the file -third first. In unix, you can do +[third](third) first. In unix, you can do - % cat third help.th - | ./first +```sh +% cat third help.th - | ./first +``` -to do this. Hopefully most operating systems will provide a -way to do this. It may take some time for this to complete -(I seem to remember it taking several minutes on an 8086 PC); -THIRD will prompt you when it is finished. The file third has -not been obfuscated, due to sheer kindness on the author's part. +to do this. Hopefully most operating systems will provide a way to do this. It +may take some time for this to complete (I seem to remember it taking several +minutes on an 8086 PC); `THIRD` will prompt you when it is finished. The file +[third](third) has not been obfuscated, due to sheer kindness on the author's +part. -For more information on what you can do once you've piped -THIRD into first, type 'help' and consult FORTH manuals for -further reference. Six sample THIRD programs are included -in the files demo[1-6].th. buzzard.2.README has more -information. +For more information on what you can do once you've piped [third](third) into +first, type 'help' and consult FORTH manuals for further reference. Six sample +THIRD programs are included in the files demo[1-6].th. +[buzzard.2.README.md](buzzard.2.README.md) has more information. -Keep in mind that you are still running first, and -are for the most part limited by first's tokenizer -(notably, unknown words will attempt to be parsed as -integers.) It is possible to build a new parser that -parses by hand, reading a single character at a time; -however, such a parser cannot easily use the existing -dictionary, and so would have to implement its own, -thus requiring reimplementing all of first and third -a second time--I did not care to tackle this project. +Keep in mind that you are still running first, and are for the most part limited +by `first`'s tokenizer (notably, unknown words will attempt to be parsed as +integers.) It is possible to build a new parser that parses by hand, reading a +single character at a time; however, such a parser cannot easily use the +existing dictionary, and so would have to implement its own, thus requiring +reimplementing all of first and third a second time--I did not care to tackle +this project. ### Compiling: -`first` is reasonably portable. You may need to adjust the -size of the buffers on smaller machines; `m[]` needs to be -at least 2000 long, though. +`first` is reasonably portable. You may need to adjust the size of the buffers +on smaller machines; `m[]` needs to be at least 2000 long, though. -I say `first` is portable mainly because it uses native types. -Unlike FORTH, which traditionally allows byte and multi-byte -operations, all operations are performed on C `int`s. That -means first code is only as portable as the same code would -be in C. As in C, the result of dividing -1 by 2 is machine -(or rather compiler) dependent. +I say `first` is portable mainly because it uses native types. Unlike +[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language), which +traditionally allows byte and multi-byte operations, all operations are +performed on C `int`s. That means first code is only as portable as the same +code would be in C. As in C, the result of dividing -1 by 2 is machine (or +rather compiler) dependent. ### How is first obfuscated? -`first` is obfuscated in several ways. Some minor obfuscations -like `&w[&m[1]][s]` for `s+m[w+1]` were in the original source -but are no longer because, apparently, ANSI doesn't allow it -(gcc -ansi -pedantic doesn't mind it, though.) -Other related obfuscations are still present. The top of the -stack is cached in a variable, which increases performance -massively if the compiler can figure out to keep it in a register; -it also obfuscates the code. (Unfortunately, the top of stack -is a global variable and neither gcc nor most bundled compilers -seem to register allocate it.) +`first` is obfuscated in several ways. Some minor obfuscations like +`&w[&m[1]][s]` for `s+m[w+1]` were in the original source but are no longer +because, apparently, ANSI doesn't allow it (gcc -ansi -pedantic doesn't mind it, +though.) -More significant are the design obfuscations. `m[0]` is the -"dictionary pointer", used when compiling words, and `m[1]` is -the return stack index. Both are used as integer offsets into -m. Both are kept in m, instead of as separate pointers, -because they are then accessible to first programs, which is a -crucial property of first. Similarly the way words are stored -in the dictionary is not obvious, so it can be difficult to -follow exactly what the compiler words are doing. +Other related obfuscations are still present. The top of the stack is cached in +a variable, which increases performance massively if the compiler can figure out +to keep it in a register; it also obfuscates the code. (Unfortunately, the top +of stack is a global variable and neither gcc nor most bundled compilers seem to +register allocate it.) -Assuming you've waded through all that, you still have -to penetrate the most significant obfuscation. Traditionally, -the question is whether a reader can answer the question "what -will this do when I run it". A reader who has deciphered first -to this point may think they know the answer to this question, -but they may not know the answer to the more important question, -"what will this program do when given the right input?" FORTH -aficionados, and especially FORTH implementers, may recognize -the similarity of the internal compiler format to many FORTH -internal representations, and, being aware that FORTH interpreters -can often by self-compiling, may be suspicious that this program -can compile FORTH, or a significant subset of it, or at least be -capable of doing so if fed the right input. Of course, the name -"THIRD" should be a dead giveaway, if the name "first" wasn't. -(These numbers were largely chosen because they were five letters -long, like "FORTH", and would not require truncation to five -letters, which would be a dead giveaway. Besides, THIRD represents -a step backwards, in more ways than one.) +More significant are the design obfuscations. `m[0]` is the "dictionary +pointer", used when compiling words, and `m[1]` is the return stack index. Both +are used as integer offsets into `m`. Both are kept in `m`, instead of as +separate pointers, because they are then accessible to first programs, which is +a crucial property of first. Similarly the way words are stored in the +dictionary is not obvious, so it can be difficult to follow exactly what the +compiler words are doing. + +Assuming you've waded through all that, you still have to penetrate the most +significant obfuscation. Traditionally, the question is whether a reader can +answer the question "what will this do when I run it". A reader who has +deciphered first to this point may think they know the answer to this question, +but they may not know the answer to the more important question, "what will this +program do when given the right input?" FORTH aficionados, and especially FORTH +implementers, may recognize the similarity of the internal compiler format to +many FORTH internal representations, and, being aware that FORTH interpreters +can often be self-compiling, may be suspicious that this program can compile +FORTH, or a significant subset of it, or at least be capable of doing so if fed +the right input. Of course, the name "THIRD" should be a dead giveaway, if the +name "first" wasn't. (These numbers were largely chosen because they were five +letters long, like "FORTH", and would not require truncation to five letters, +which would be a dead giveaway. Besides, THIRD represents a step backwards, in +more ways than one.) ### What exactly is `first`, then? -`first` is a tiny interpreter which implements a sufficient -pseudo-subset of FORTH to allow it to bootstrap a relatively -complete version of FORTH (based loosely on forth79), which -I call THIRD. Complete relative to what, I'm not sure. +`first` is a tiny interpreter which implements a sufficient pseudo-subset of +FORTH to allow it to bootstrap a relatively complete version of FORTH (based +loosely on forth79), which I call THIRD. Complete relative to what, I'm not +sure. -I believe first is close to the smallest amount of code possible -to get this effect *using forth-style primitives*, and still have -some efficiency (it is possible to get by without multiplication -if you have addition, obviously). In the design file, design, -I give a justification for why each primitive in first was included. +I believe first is close to the smallest amount of code possible to get this +effect *using forth-style primitives*, and still have some efficiency (it is +possible to get by without multiplication if you have addition, obviously). In +the design file, design, I give a justification for why each primitive in first +was included. -THIRD is sorta slow, because first has so few primitives that -many things that are primitives in FORTH (like swap) take a -significant amount of time in THIRD. +THIRD is sorta slow, because first has so few primitives that many things that +are primitives in FORTH (like swap) take a significant amount of time in THIRD. -When you get the 'Ok.' message from third, try out some sample -FORTH code (first has no way of knowing if keyboard input is -waiting, so it can't actually prompt you in a normal way. It -only prints 'Ok.' after you define a word). +When you get the 'Ok.' message from third, try out some sample FORTH code (first +has no way of knowing if keyboard input is waiting, so it can't actually prompt +you in a normal way. It only prints 'Ok.' after you define a word). - 2 3 + . cr ( add 2 and 3, and print it and a newline.) +```sh +2 3 + . cr +``` -and THIRD responds +(which adds 2 and 3, and print the result and a newline.) - 5 +THIRD responds: + +``` +5 +``` Now try: - : test 11 1 do i . loop cr ; - test +``` +: test 11 1 do i . loop cr ; +test +``` and THIRD responds - 1 2 3 4 5 6 7 8 9 10 +``` +1 2 3 4 5 6 7 8 9 10 +``` -When in THIRD, you can see how much space you're currently -using by typing +When in `THIRD`, you can see how much space you're currently +using by typing: - here . +``` +here . +``` -The number THIRD replies is the number of machine words (ints) -that the dictionary (the first code) takes up, plus the -512 ints for the return stack. If you compile the basic -THIRD system without the help word (strings take up one -int per character in the string!), you should find that -you're using around 1000 ints (plus the return stack). +The number THIRD replies with is the number of machine words (ints) that the +dictionary (the first code) takes up, plus the 512 ints for the return stack. +If you compile the basic THIRD system without the help word (strings take up one +int per character in the string!), you should find that you're using around 1000 +ints (plus the return stack). -Thus THIRD gives you a relatively complete FORTH system in -less than 700 chars of C source + about 1000 ints of -memory--and it's portable too (you could copy over the -THIRD memory dump to another machine, in theory). If the -above numbers seem to you to be mixing apples and oranges -(C source and compiled THIRD code), note that you should -in theory be able to stick the compiled THIRD code into -the C source. +Thus THIRD gives you a relatively complete FORTH system in less than 700 chars +of C source + about 1000 ints of memory--and it's portable too (you could copy +over the THIRD memory dump to another machine, in theory). If the above numbers +seem to you to be mixing apples and oranges (C source and compiled THIRD code), +note that you should in theory be able to stick the compiled THIRD code into the +C source. -Software Construction Company gets credit for rekindling -my interest in FORTH and thus indirectly inspiring me -to write this program. +Software Construction Company gets credit for rekindling my interest in FORTH +and thus indirectly inspiring me to write this program. ## Copyright and CC BY-SA 4.0 License: diff --git a/1992/buzzard.2/buzzard.2.README b/1992/buzzard.2/buzzard.2.README.md similarity index 72% rename from 1992/buzzard.2/buzzard.2.README rename to 1992/buzzard.2/buzzard.2.README.md index ee59a3b2e..1df412e17 100644 --- a/1992/buzzard.2/buzzard.2.README +++ b/1992/buzzard.2/buzzard.2.README.md @@ -3,11 +3,16 @@ buzzard.2.design description of FIRST (design documentation of THIRD) third implementation of THIRD in FIRST help.th online listing of THIRD primitives - FIRST demos: use 'first < {demo}' + +# FIRST demos: + +Use `first < {demo}`. demo1.1st prints Hello World! assuming ASCII - THIRD demos: use 'cat third {demo} | first' +# THIRD demos: + +Use `cat third {demo} | first`. demo1.th prints Hello World! regardless of character set demo2.th demonstrates a simple loop @@ -16,7 +21,9 @@ demo4.th recursive factorial calculating on the way up demo5.th recursive factorial calculating on the way down demo6.th demonstrates switching from compiler to execution mode - Interactive THIRD: use 'cat third - | first'. +# Interactive THIRD: - To include the primitive on-line help, use - 'cat third help.th - | first'. +Use `cat third - | first`. + +To include the primitive on-line help, use +`cat third help.th - | first`.