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