6 ms·
Hmmm, should't it be something like FORTH KNOW HONK FORTH LEARN IFELSE
by enriquto 5y ago
Hmmm, should't it be something like
FORTH KNOW
HONK
FORTH LEARN
IFELSE
- jacquesm 5y agoArguing with the Don? It was nice knowing you...
- enriquto 5y agoI don't know forth but it seemed more natural that way (as in postscript).
- DonHopkins 5y agoIn PostScript that would be: /PostScript Know? { Honk! } { /PostScript Learn! } ifelse FORTH doesn't have an IFELSE unless you define it yourself of course, but it would have no way of telling which part of your code was the conditional, part to do if true, or part to do if false, since white space and line breaks have no meaning to it, except for a few cases like \ comments. The IF comes between the conditional and the part to do if true, the ELSE comes between the part to do if true and the part to do if false, and the THEN comes at the end. The structure of PostScript code, conditionals, and flow control is homoiconic, made of nested arrays, like polymorphic JSON arrays, where FORTH code is flat untyped arrays of threaded pointers with relative branching. Forth has an "inner interpreter" called NEXT that threads from one pointer to the next (sometimes implemented as one machine language instruction, or just a few), and also an "outer interpreter" or compiler that translates text into threaded code for the inner interpreter. https://en.wikipedia.org/wiki/Polymorphism_(computer_science) https://en.wikipedia.org/wiki/Polymorphism_(computer_science... https://en.wikipedia.org/wiki/Homoiconicity https://en.wikipedia.org/wiki/Homoiconicity https://en.wikipedia.org/wiki/Threaded_code https://en.wikipedia.org/wiki/Threaded_code Here's Mitch Bradley's implementation of interactive control structures (IF, ELSE, THEN, BEGIN, UNTIL, AGAIN, REPEAT, WHILE, DO, LOOP, etc) in the outer interpreter of his FORTH system, which actually allows you to use conditionals and loops at the interactive top level of the interpreter, not just in compiled words (which solves a traditional and frustrating limitation of classic FORTH). https://github.com/MitchBradley/openfirmware/blob/master/forth/kernel/kernel.fth#L771 https://github.com/MitchBradley/openfirmware/blob/master/for... Here is an alternative but equivalent implementation of interactive Forth control structures in his CForth (Forth implemented in C, of course): https://github.com/MitchBradley/cforth/blob/master/src/cforth/forth.c#L652 https://github.com/MitchBradley/cforth/blob/master/src/cfort... Here's some more of Mitch's beautiful code from OpenFirmware, his Forth kernel meta-compiler written in Forth, which supports 8, 16, 32, an 64 bit, big-endian and little-endian architectures, as well as direct, indirect, and token threaded code: https://github.com/MitchBradley/openfirmware/blob/master/forth/kernel/kernel.fth https://github.com/MitchBradley/openfirmware/blob/master/for... https://en.wikipedia.org/wiki/Threaded_code#Direct_threading https://en.wikipedia.org/wiki/Threaded_code#Direct_threading https://en.wikipedia.org/wiki/Threaded_code#Indirect_threading https://en.wikipedia.org/wiki/Threaded_code#Indirect_threadi... https://en.wikipedia.org/wiki/Threaded_code#Token_threading https://en.wikipedia.org/wiki/Threaded_code#Token_threading
- DonHopkins 5y agohttps://news.ycombinator.com/item?id=26913281 https://news.ycombinator.com/item?id=26913281 (edited and expanded) DonHopkins 6 months ago | parent | context | favorite | on: Moving Forth (1993) >Some FORTH systems even have a "metacompiler" that lets one FORTH system compile another FORTH system for the same or different CPU, word size, byte order, threading technique, with or without a built-in compiler, etc, from the same source code! >OpenFirmware (the FORTH burnt into boot roms of SPARC, PowerPC, OLPC, and other systems) is a great highly refined example that supports many different architectures: >openfirmware/forth/kernel/metacompile.fth https://github.com/openbios/openfirmware/blob/master/forth/kernel/metacompile.fth https://github.com/openbios/openfirmware/blob/master/forth/k... >openfirmware/forth/kernel/meta1.fth https://github.com/openbios/openfirmware/blob/master/forth/kernel/meta1.fth https://github.com/openbios/openfirmware/blob/master/forth/k... The OpenFirmware kernel is a Forth meta-compiler, which can compile itself on any architecture, and also cross-compile for different target architectures. It has cross-architecture extensions to FORTH (like \16 \32 comments and /n /n* generically typed words) that make it possible to write platform, word size, byte order, and threading independent code, and compile images (stripped or with headers) for embedded systems (like the OLPC boot ROMs) and new CPU architectures (like Sun's transition from 68K to SPARC), and share code with a more powerful development environments. https://en.wikipedia.org/wiki/Compiler-compiler#Forth_metacompiler https://en.wikipedia.org/wiki/Compiler-compiler#Forth_metaco... >Many advocates of the language Forth call the process of creating a new implementation of Forth a meta-compilation and that it constitutes a metacompiler. The Forth definition of metacompiler is: >"A metacompiler is a compiler which processes its own source code, resulting in an executable version of itself." >This Forth use of the term metacompiler is disputed in mainstream computer science. See Forth (programming language) and History of compiler construction. The actual Forth process of compiling itself is a combination of a Forth being a self-hosting extensible programming language and sometimes cross compilation, long established terminology in computer science. Metacompilers are a general compiler writing system. Besides the Forth metacompiler concept being indistinguishable from self-hosting and extensible language. The actual process acts at a lower level defining a minimum subset of forth words, that can be used to define additional forth words, A full Forth implementation can then be defined from the base set. This sounds like a bootstrap process. The problem is that almost every general purpose language compiler also fits the Forth metacompiler description. >When (self-hosting compiler) X processes its own source code, resulting in an executable version of itself, X is a metacompiler. >Just replace X with any common language, C, C++, Pascal, COBOL, Fortran, Ada, Modula-2, etc. And X would be a metacompiler according to the Forth usage of metacompiler. A metacompiler operates at an abstraction level above the compiler it compiles. It only operates at the same (self-hosting compiler) level when compiling itself. One has to see the problem with this definition of metacompiler. It can be applied to most any language. >However, on examining the concept of programming in Forth, adding new words to the dictionary, extending the language in this way is metaprogramming. It is this metaprogramming in Forth that makes it a metacompiler. >Programming in Forth is adding new words to the language. Changing the language in this way is metaprogramming. Forth is a metacompiler because Forth is a language specifically designed for metaprogramming. Programming in Forth is extending Forth adding words to the Forth vocabulary creates a new Forth dialect. Forth is a specialized metacompiler for Forth language dialects. Mitch's OpenFirmware code is one end of the readability spectrum. But for shock value, here are some beautiful but inscrutable FORTH code excerpts that define cellular automata rules with lots of deeply nested conditionals around mysterious but exquisitely indented BEEPS and BOOPS and line noise that makes Perl look clean and elegant. ;) https://donhopkins.com/home/code/tomt-users-forth-scr.txt https://donhopkins.com/home/code/tomt-users-forth-scr.txt ( A-BOMB) 24 LOAD : KN C0 X0 Y0 Z0 + + + C1 X1 Y1 Z1 + + + * 0> ; : KC C0 C1 * X0 X1 * Y0 Y1 * Z0 Z1 * + + + 0> ; : EXPL X1 Y1 + X1 Y1 * - ; : RULE0 C0 KN IF DROP 0 THEN KC IF DROP 0 THEN C0 C1 * 1 = IF DROP 1 THEN ; : RULE1 Z1 KN IF DROP EXPL THEN KC IF DROP 0 THEN C0 C1 * 1 = IF DROP 1 THEN ; ( CASEN ) FORGET TASK : TASK ; : NSUM NORTH SOUTH EAST WEST N.WEST N.EAST S.WEST S.EAST CENTER + + + + + + + + ; : CASEN NSUM 0 = IF 0 ELSE NSUM 1 = IF 0 ELSE NSUM 2 = IF 1 ELSE NSUM 3 = IF 0 ELSE NSUM 4 = IF 0 ELSE NSUM 5 = IF 0 ELSE NSUM 6 = IF 0 ELSE NSUM 7 = IF 0 ELSE NSUM 8 = IF 0 ELSE NSUM 9 = IF 0 ELSE THEN THEN THEN THEN THEN THEN THEN THEN THEN THEN ; <T> ( BRAIN ) 36 LOAD : CENTERS CENTER1 2 * CENTER + ; : FEEP CENTERS 0 = IF 1 ELSE CENTERS 1 = IF 0 ELSE CENTERS 2 = IF 0 ELSE CENTERS 3 = IF 0 ELSE THEN THEN THEN THEN ; : RULE CASEN FEEP AND ; <T> f1 BBM01 ( READY ) FORGET TASK : TASK ; : CENTERS CENTER1 2 * CENTER + ; : READY CENTERS 0 = IF 1 ELSE CENTERS 1 = IF 0 ELSE CENTERS 2 = IF 0 ELSE CENTERS 3 = IF 0 ELSE THEN THEN THEN THEN ; <T> ( PUCCIO1) 24 LOAD : K7 C0 C1 * X0 X1 * Y0 Y1 * Z0 Z1 * + + + 0<> ; : K71 C0 C1 X0 1 X1 Y0 Y1 Z0 Z1 + + + + + * * * 1 = ; : K72 X0 X1 Z0 1 C0 C1 Y0 Y1 Z1 + + + + + * * * 1 = ; : K73 Z0 Z1 Y0 1 Y1 C0 C1 X0 X1 + + + + + * * * 1 = ; : K74 Y0 Y1 C0 1 C1 X0 X1 Z0 Z1 + + + + + * * * 1 = ; : K81 X0 X1 Y0 1 C0 C1 Z0 Z1 Y1 + + + + + * * * 1 = ; : K82 Z0 Z1 C0 1 X0 X1 Y0 Y1 C1 + + + + + * * * 1 = ; : K83 Y0 Y1 X0 1 Z0 Z1 C0 C1 X1 + + + + + * * * 1 = ; : K84 C0 C1 Z0 1 Y0 Y1 X0 X1 Z1 + + + + + * * * 1 = ; --> : RULE0 Y1 ( X1 Z1 + Z1 Y1 + Y1 C1 + * * 1 = IF DROP C1 THEN ) K7 IF DROP Z0 THEN K71 IF DROP 0 THEN K72 IF DROP 1 THEN K73 IF DROP 0 THEN K74 IF DROP 1 THEN K81 IF DROP 0 THEN K82 IF DROP 1 THEN K83 IF DROP 1 THEN K84 IF DROP 0 THEN ; ( DOUBLE GAS etoile on P0 and P1) 24 LOAD : KK C0 X0 Y0 Z0 + + + 1+ C1 X1 Y1 Z1 + + + 1+ * 5 = ; ( rotate right/left w/collisions ) : RULE0 KC0 IF C0 ELSE T0 0= IF Y0 ELSE X0 THEN THEN KK IF DROP C1 THEN ; ( diagonal gas, w/collisions) : RULE1 KC1 IF X1 ELSE Z1 THEN KK IF DROP C0 THEN ; BBM01 https://donhopkins.com/home/code/tomt-cam-forth-scr.txt https://donhopkins.com/home/code/tomt-cam-forth-scr.txt ( MENU of keys ) VARIABLE UNFLG : ?UNDEF UNFLG @ IF OUT @ SWAP $. OUT @ - 6 + SPACES ." is undefined" ELSE DROP THEN ; : K. ( string.addr --) FIND IF OUT @ OVER >NAME .NAME OUT @ - 6 + SPACES >BODY BEGIN DUP @ ['] ;S <> WHILE DUP @ >NAME .NAME 2+ REPEAT DROP ELSE ?UNDEF THEN ; ( == creates fast code words for picking out bits of variable X) VARIABLE X CODE X! AX POP X , AX MOV NEXT, END-CODE CODE X@ AX, X MOV AX PUSH NEXT, END-CODE CREATE ZPUSH ASSEMBLER 1$ JNZ AX, # 0 MOV AX PUSH NEXT, 1$: AX, # 1 MOV AX PUSH NEXT, : X? ( mask byt#-) ASSEMBLER AL, X + MOV AL, # TEST ZPUSH JMP ; 0 CARRAY 2^N 1 C, 2 C, 4 C, 8 C, 10 C, 20 C, 40 C, 80 C, : == ( bit# --) ( ---- name ) >R [COMPILE] CODE R> 8 /MOD SWAP 2^N C@ SWAP X? ASSEMBLER [COMPILE] END-CODE ; 1 == NORTH 3 == WEST 5 == N.WEST 7 == S.WEST 9 == CENTER1 2 == SOUTH 4 == EAST 6 == N.EAST 8 == S.EAST 0 == CENTER ( eg. NORTH will return bit #1 of X when executed ) --> : #DX! ASSEMBLER DX, # MOV ; : #AL! ASSEMBLER AL, # MOV ; : AL.IN ASSEMBLER AL, DX IN ; : AL.OUT ASSEMBLER DX, AL OUT ; : SRCE BEGIN ?STEPPING @ (?TERMINAL) NOT AND WHILE STEPPING REPEAT (?TERMINAL) DLAST @ AND DNUM @ 0= OR SRCE.SEG SPOINT @ @L 0= OR IF SAVE.INPUT KSAV ELSE SRCE.SEG SPOINT GET DUP KPUT DUP DLAST C! THEN ;