Forth Fan Club

1 Name: Anonymous 2017-04-19 03:41
just a general thread for everything forth.

This was posted back on the previous progrider and it's a fantastic read.

Three Forths Make a Hole

There are many theories about the best way to program a computer – the ACE project showed just what can be done with Forth, especially in a situation which was constantly changing.
2 Name: Anonymous 2017-04-19 03:46

This has to be one of the most underrated points in Forth. Factoring words in Forth is natural and the lack of return addresses interspersed with the data allows this to be very efficient. In most languages you can't factor to the degree that you can in Forth without having severe run-time speed consequences. You can't keep passing data to lower and lower layers without building new stack frames, with the same data repeated in them, again and again.

$4000 constant +1. \ -- n
\ Integer +1 in 2.14 fractional arithmetic format.
: *. \ fr1 fr2 -- fr3
\ Fractional multiply.
+1. */ ;
: 1STEP+ \ sum -- sum'
\ Perform a multiply/accumulate step, incrementing both
\ pointers.
B@+ A@+ *. + ;
: 1STEP- \ sum -- sum'
\ Perform a multiply/accumulate step, incrementing the
\ coefficient pointer and decrementing the data pointer.
B@+ A@- *. + ;
: SHIFT2 \ fr --
\ The last step of the filter. The current data item
\ is shifted into the next data slot and replaced by fr.
A@ SWAP A!+ A!+ ;
: (BIQUAD) \ frx -- fry
\ The core of the biquad filter operation.
DUP >R B@+ *. \ initial sum = B0*input
: BIQUAD \ fx addr-filt addr-coef -- fry
\ A single order biquad filter.
: 2xBIQUAD \ fx addr-filt addr-coef -- fry
\ A second order biquad filter.
3 Name: Anonymous 2017-04-19 03:50
There is quite a fun comparison of the different sorts of threaded code that might occur in a forth system:

Of particular note is 'huffman' threading - you're literally executing compressed code.
4 Name: Anonymous 2017-04-19 03:52
>>2 page 2 of that talks about some wild stuff - Chucks massively multi core forth chip and how you use umbilical debugging chords. Why can't all programming be this fascinating?
6 Name: Anonymous 2017-04-19 21:26
thanks for your comment
7 Name: Anonymous 2017-04-21 01:25
8 Name: Anonymous 2017-05-02 21:53
9 Name: Anonymous 2017-05-02 22:02

Fixed Length Instruction Trade-offs

The advantages of fixed length instructions with a relatively uniform formatting is that fetching and parsing the instructions is substantially simpler.

For an implementation that fetches a single instruction per cycle, a single aligned memory (cache) access of the fixed size is guaranteed to provide one (and only one) instruction, so no buffering or shifting is required. There is also no concern about crossing a cache line or page boundary within a single instruction.

The instruction pointer is incremented by a fixed amount (except when executing control flow instructions--jumps and branches) independent of the instruction type, so the location of the next sequential instruction can be available early with minimal extra work (compared to having to at least partially decode the instruction). This also makes fetching and parsing more than one instruction per cycle relatively simple.

Having a uniform format for each instruction allows trivial parsing of the instruction into its components (immediate value, opcode, source register names, destination register name). Parsing out the source register names is the most timing critical; with these in fixed positions it is possible to begin reading the register values before the type of instruction has been determined. (This register reading is speculative since the operation might not actually use the values, but this speculation does not require any special recovery in the case of mistaken speculation but does take extra energy.) In the MIPS R2000's classic 5-stage pipeline, this allowed reading of the register values to be started immediately after instruction fetch providing half of a cycle to compare register values and resolve a branch's direction; with a (filled) branch delay slot this avoided stalls without branch prediction.

(Parsing out the opcode is generally a little less timing critical than source register names, but the sooner the opcode is extracted the sooner execution can begin. Simple parsing out of the destination register name makes detecting dependencies across instructions simpler; this is perhaps mainly helpful when attempting to execute more than one instruction per cycle.)

In addition to providing the parsing sooner, simpler encoding makes parsing less work (energy use and transistor logic).

A minor advantage of fixed length instructions compared to typical variable length encodings is that instruction addresses (and branch offsets) use fewer bits. This has been exploited in some ISAs to provide a small amount of extra storage for mode information. (Ironically, in cases like MIPS/MIPS16, to indicate a mode with smaller or variable length instructions.)

Fixed length instruction encoding and uniform formatting do have disadvantages. The most obvious disadvantage is relatively low code density. Instruction length cannot be set according to frequency of use or how much distinct information is required. Strict uniform formatting would also tend to exclude implicit operands (though even MIPS uses an implicit destination register name for the link register) and variable-sized operands (most RISC variable length encodings have short instructions that can only access a subset of the total number of registers).

(In a RISC-oriented ISA, this has the additional minor issue of not allowing more work to be bundled into an instruction to equalize the amount of information required by the instruction.)

Fixed length instructions also make using large immediates (constant operands included in the instruction) more difficult. Classic RISCs limited immediate lengths to 16-bits. If the constant is larger, it must either be loaded as data (which means an extra load instruction with its overhead of address calculation, register use, address translation, tag check, etc.) or a second instruction must provide the rest of the constant. (MIPS provides a load high immediate instruction, partially under the assumption that large constants are mainly used to load addresses which will later be used for accessing data in memory. PowerPC provides several operations using high immediates, allowing, e.g., the addition of a 32-bit immediate in two instructions.) Using two instructions is obviously more overhead than using a single instruction (though a clever implementation could fuse the two instructions in the front-end [What Intel calls macro-op fusion]).

Fixed length instructions also makes it more difficult to extend an instruction set while retaining binary compatibility (and not requiring addition modes of operation). Even strictly uniform formatting can hinder extension of an instruction set, particularly for increasing the number of registers available.

Fujitsu's SPARC64 VIIIfx is an interesting example. It uses a two-bit opcode (in its 32-bit instructions) to indicate a loading of a special register with two 15-bit instruction extensions for the next two instructions. These extensions provide extra register bits and indication of SIMD operation (i.e., extending the opcode space of the instruction to which the extension is applied). This means that the full register name of an instruction not only is not entirely in a fixed position, but not even in the same "instruction". (Similarities to x86's REX prefix--which provides bits to extend register names encoded in the main part of the instruction--might be noted.)

(One aspect of fixed length encodings is the tyranny of powers of two. Although it is possible to used non-power-of-two instruction lengths [Tensilica's XTensa now has fixed 24-bit instructions as its base ISA--with 16-bit short instruction support being an extension, previously they were part of the base ISA; IBM had an experimental ISA with 40-bit instructions.], such adds a little complexity. If one size, e.g., 32bits, is a little too short, the next available size, e.g., 64 bits, is likely to be too long, sacrificing too much code density.)

For implementations with deep pipelines the extra time required for parsing instructions is less significant. The extra dynamic work done by hardware and the extra design complexity are reduced in significance for high performance implementations which add sophisticated branch prediction, out-of-order execution, and other features.
Variable Length Instruction Trade-offs

For variable length instructions, the trade-offs are essentially reversed.

Greater code density is the most obvious advantage. Greater code density can improve static code size (the amount of storage needed for a given program). This is particularly important for some embedded systems, especially microcontrollers, since it can be a large fraction of the system cost and influence the system's physical size (which has impact on fitness for purpose and manufacturing cost).

Improving dynamic code size reduces the amount of bandwidth used to fetch instructions (both from memory and from cache). This can reduce cost and energy use and can improve performance. Smaller dynamic code size also reduces the size of caches needed for a given hit rate; smaller caches can use less energy and less chip area and can have lower access latency.

(In a non- or minimally pipelined implementation with a narrow memory interface, fetching only a portion of an instruction in a cycle in some cases does not hurt performance as much as it would in a more pipelined design less limited by fetch bandwidth.)

With variable length instructions, large constants can be used in instructions without requiring all instructions to be large. Using an immediate rather than loading a constant from data memory exploits spatial locality, provides the value earlier in the pipeline, avoids an extra instruction, and removed a data cache access. (A wider access is simpler than multiple accesses of the same total size.)

Extending the instruction set is also generally easier given support for variable length instructions. Addition information can be included by using extra long instructions. (In the case of some encoding techniques--particularly using prefixes--, it is also possible to add hint information to existing instructions allowing backward compatibility with additional new information. x86 has exploited this not only to provide branch hints [which are mostly unused] but also the Hardware Lock Elision extension. For a fixed length encoding, it would be difficult to choose in advance which operations should have additional opcodes reserved for possible future addition of hint information.)

Variable length encoding clearly makes finding the start of the next sequential instruction more difficult. This is somewhat less of a problem for implementations that only decode one instruction per cycle, but even in that case it adds extra work for the hardware (which can increase cycle time or pipeline length as well as use more energy). For wider decode several tricks are available to reduce the cost of parsing out individual instructions from a block of instruction memory.

One technique that has mainly been used microarchitecturally (i.e., not included in the interface exposed to software but only an implementation technique) is to use marker bits to indicate the start or end of an instruction. Such marker bits would be set for each parcel of instruction encoding and stored in the instruction cache. Such delays the availability of such information on a instruction cache miss, but this delay is typically small compared to the ordinary delay in filling a cache miss. The extra (pre)decoding work is only needed on a cache miss, so time and energy is saved in the common case of a cache hit (at the cost of some extra storage and bandwidth which has some energy cost).

(Several AMD x86 implementations have used marker bit techniques.)

Alternatively, marker bits could be included in the instruction encoding. This places some constrains on opcode assignment and placement since the marker bits effectively become part of the opcode.

Another technique, used by the IBM zSeries (S/360 and descendants), is to encode the instruction length in a simple way in the opcode in the first parcel. The zSeries uses two bits to encode three different instruction lengths (16, 32, and 48 bits) with two encodings used for 16 bit length. By placing this in a fixed position, it is relatively easy to quickly determine where the next sequential instruction begins.

(More aggressive predecoding is also possible. The Pentium 4 used a trace cache containing fixed-length micro-ops and recent Intel processors use a micro-op cache with [presumably] fixed-length micro-ops.)

Obviously, variable length encodings require addressing at the granularity of a parcel which is typically smaller than an instruction for a fixed-length ISA. This means that branch offsets either lose some range or must use more bits. This can be compensated by support for more different immediate sizes.

Likewise, fetching a single instruction can be more complex since the start of the instruction is likely to not be aligned to a larger power of two. Buffering instruction fetch reduces the impact of this, but adds (trivial) delay and complexity.

With variable length instructions it is also more difficult to have uniform encoding. This means that part of the opcode must often be decoded before the basic parsing of the instruction can be started. This tends to delay the availability of register names and other, less critical information. Significant uniformity can still be obtained, but it requires more careful design and weighing of trade-offs (which are likely to change over the lifetime of the ISA).

As noted earlier, with more complex implementations (deeper pipelines, out-of-order execution, etc.), the extra relative complexity of handling variable length instructions is reduced. After instruction decode, a sophisticated implementation of an ISA with variable length instructions tends to look very similar to one of an ISA with fixed length instructions.

It might also be noted that much of the design complexity for variable length instructions is a one-time cost; once an organization has learned techniques (including the development of validation software) to handle the quirks, the cost of this complexity is lower for later implementations.

Because of the code density concerns for many embedded systems, several RISC ISAs provide variable length encodings (e.g., microMIPS, Thumb2). These generally only have two instruction lengths, so the additional complexity is constrained.
Bundling as a Compromise Design

One (sort of intermediate) alternative chosen for some ISAs is to use a fixed length bundle of instructions with different length instructions. By containing instructions in a bundle, each bundle has the advantages of a fixed length instruction and the first instruction in each bundle has a fixed, aligned starting position. The CDC 6600 used 60-bit bundles with 15-bit and 30-bit operations. The M32R uses 32-bit bundles with 16-bit and 32-bit instructions.

(Itanium uses fixed length power-of-two bundles to support non-power of two [41-bit] instructions and has a few cases where two "instructions" are joined to allow 64-bit immediates. Heidi Pan's [academic] Heads and Tails encoding used fixed length bundles to encode fixed length base instruction parts from left to right and variable length chunks from right to left.)

Some VLIW instruction sets use a fixed size instruction word but individual operation slots within the word can be a different (but fixed for the particular slot) length. Because different operation types (corresponding to slots) have different information requirements, using different sizes for different slots is sensible. This provides the advantages of fixed size instructions with some code density benefit. (In addition, a slot might be allocated to optionally provide an immediate to one of the operations in the instruction word.)
10 Name: Anonymous 2017-07-02 02:06
11 Name: eforth 2017-07-02 02:20
TOKEN CHAR \ ( .( PARSE parse ? . U. U.R .R ."| $"| do$ CR TYPE SPACES
AND 0< SP! SP@ OVER SWAP DUP DROP >R R@ R> RP! RP@ C@ C! @ ! branch
?branch next EXIT doLIT EXECUTE TX! ?RX !IO doLIST CALL BYE ok
12 Name: Anonymous 2017-07-02 02:21
Moving Forth: a series on writing Forth kernels

Part 1: Design Decisions in the Forth Kernel (33K text, 21K images)
Part 2: Benchmarks and Case Studies of Forth Kernels (31K text)
Part 3: Demystifying DOES> (48K text, 45K images)
Part 4: Assemble or Metacompile? (8K text)
Part 5: The Z80 Primitives (9K text, 38K linked files)
Part 6: The Z80 High-level Kernel (20K text, 36K linked files)
Part 7: CamelForth for the 8051 (12K text, 5K images)
Part 8: CamelForth for the 6809 (10K text, 33K linked files)
13 Name: Anonymous 2017-07-02 02:26
Proof that forth is the best programming language:
14 Name: Anonymous 2017-07-02 02:33
In 1986, I bought an Atari ST. Compared to other home computers of that time, it was bleeding fast, and had a wonderful GUI. It had virtually no software, but this was supposed to change. The main reason I bought it was to become a [html]hacker (in the sense of ESR's [html]"New Hacker's Dictionary"), and the main excuse was to computerize a comic strip a friend and I had been drawing for three years.

this is a nice blog post about forth

Programming in Forth is generating higher levels of abstractions, until you have a language well fitted to solve your problem
15 Name: Anonymous 2017-07-02 02:34
There are also reasons not to use Forth. One of the most important reason is that Forth is said to be an amplifier. A good programmer programs better in Forth (and he learns to program better in other languages, too, when he masters Forth); a bad programmer programs worse in Forth, and he's spoiled when working with other programming languages, then. The sad fact is that too many programmers must be considered "bad".

this is true. lol
16 Name: Anonymous 2017-07-02 02:35
There have been successful attepts to learn Forth to childrens who have learning difficulties. These childs have shown that they can use Forth. They even use Forth in a professional manner, i.e. they write short words which do one thing right, and without any comments except stack effect and word name. It might take them longer than a Forth professional to find solutions, and they might not find as clever solutions, but they find solutions, and some are quite interesting

Forth is the plogramming language for slow-types!
17 Name: Anonymous 2017-07-03 22:43
Once, I tried to implement FORTH on the 6502, bootstrapping style. It surprised me greatly how elegant the word-to-word interface can be made when code is translated to literally a series of absolute JSR instructions. Never got far with it, but I got in deep enough to understand why FORTH environments for the C-64 were reputed for extreme speed among high-level programming languages.

I'd love to have a FORTH that applied static typechecking even today, despite the whole thing being mostly just the most practical of esoteric programming languages.
18 Name: Anonymous 2017-07-04 01:10
So has anyone heard from Mentifex lately?
19 Name: Anonymous 2017-07-04 02:13
he seriously needs to find this place already. we've have suigin, nikita, steve..
20 Name: Anonymous 2017-07-16 03:32
21 Name: Anonymous 2017-07-27 23:57
Ima bump this back to the front. There, bumped.
22 Name: Anonymous 2017-07-27 23:58
Wow thanks now i get to see all the posts ive already seen soth no new content
23 Name: Anonymous 2017-07-28 15:16
I just don't want the forth thread to die, so people have another chance at updating with new fresh content. Polite sage because I already bumped
24 Name: Anonymous 2017-07-28 23:51
You must be an imagebabby. What imageboard was goatfinger linked on?
25 Name: Anonymous 2017-07-29 04:30
>>23 snivel all you like, you're still a cunt.
26 Name: Anonymous 2017-07-29 09:44
I went to goatfingers forth thread a while ago; you know, that total board failure? Well anyways there was hardly any new posts there, and I couldn't understand any of it. Then, I looked at the forth thread, and it had "Ima bump this back to the front. There, bumped." written on it. Oh, the stupidity. Those idiots. You, don't come to a goatfinger thread just because it was bumped off, fool. theres' a fucking list of every thread every created, SEE ALL THREADS for crying out loud. There're even imagebabbys here. Summerfags, all out for some shitposting, huh? How fucking nice. "Alright, daddy's gonna bump his favorite threads, hoping for more posts to consume." God I can't bear to watch. You people, I'll give you a bump if you go back to dis.tinychan. Goatfinger should be a bloody place. That tense atmosphere, where two guys on opposite sides of the U-shaped table can start a fight at any time, the stab-or-be-stabbed mentality, that's what's great about this place. Women and children should screw off and stay home. Anyways, I was about to start /G/RO-posting, and then the bastard in this thread goes "snivel all you like, you're still a cunt." Who in the world replies to posts this way anymore, you moron? I want to ask him, "do you REALLY have nothing more to say?" I want to interrogate him. I want to interrogate him for roughly an hour. Are you sure you don't just want to try saying "cunt"? Coming from a goatfinger veteran such as myself, the latest trend among us vets is this, incoherent necrosaging. That's right, incoherent necrosaging. This is the vet's way of eating. Finding an ancient thread, writing some absolutely nonsense babble that nobody will ever see. This is the key. And then, it's delicious. This is unbeatable. However, if you do this then there is danger that you'll be marked by the software as a spammer; it's a double-edged sword. I can't recommend it to amateurs. What this all really means, though, is that you, >>23, should just stick with imageboards.
27 Name: Anonymous 2017-08-19 11:43


Let's Design the Simplest Possible Forth

1. Initialize the processor.
2. Initialize the serial port.
3. Repeat the following forever:
Get a byte from the serial port.
If byte = 01 [fetch]
A. Get address from the serial port.
B. Fetch the byte from that address.
C. Send the byte to the serial port.
Else If byte = 02 [store]
A. Get address from the serial port.
B. Get a byte from the serial port.
C. Store the byte at that address.
Else If byte = 03 [call]
A. Get address from the serial port.
B. Jump to the subroutine at that address.
End If.
28 Name: Anonymous 2017-08-23 04:16
Please do not bully the Forth lovers!
29 Name: Anonymous 2017-11-13 11:36

nice little forth and even has a lisp.fs interpreter
30 Name: Anonymous 2017-11-20 18:37
when is a forth a better unix than Unix?
posted by Andreas Bernhard Wagner on Jul 17, 2016

Is Forth a better unix than Unix?

If a unix is a bag of tools in which each tool does one thing, and does it well, then Forth is a better unix than Unix, especially if you don’t use conditionals. However, Forth philosophy is quite a bit more radical than the unix philosophy.

Rule of Modularity: Developers should build a program out of simple parts connected by well defined interfaces, so problems are local, and parts of the program can be replaced in future versions to support new features. This rule aims to save time on debugging code that is complex, long, and unreadable.

In Forth we avoid hooks for future functionality because they lead to stack juggling at the front of word. Instead of juggling arguments into position at the beginning of a word as if it were an interface, put them where they belong at edit-time, and then slice the code up into factors as needed. A word is a slice of functionality not a self contained bubble. Stack juggling is a symptom of code that is too general and doesn’t do one thing well.

Rule of Composition: Developers should write programs that can communicate easily with other programs. This rule aims to allow developers to break down projects into small, simple programs rather than overly complex monolithic programs.

Yes, but words are not functions and don’t encapsulate anything. They are documentation. Mnemonics for slices of functionality. Hooks for future functionality reduce future flexibility. Forth words shouldn’t talk to each other any more than they would without factoring.

Choose portability over efficiency.

In the same vein as the previous two points, portable software tries to fit every platform but works well on none of them.

Store data in flat text files.

Parse as early as possible, store data in data structures as soon as possible, or better yet use on-line algorithms. Multiple levels of parsing means you have unnecessary extra steps.

Use software leverage to your advantage.

A Forth program executes in four phases: the design time, the edit time, the compile time and the run time. The former phases should be enough unless there are externalities on the latter phases.

Make every program a filter.

Avoid the need to filter. Filtering is an extra step for all but the uncontrollable world beyond the sensors.
31 Name: Anonymous 2017-11-29 12:41
The first step in using the computer language Forth is using the compiler word : to create user defined words. The second step is often learning to define words that define words. The third step is often learning to write a new Forth in Forth.
32 Name: Anonymous 2017-11-30 11:14
Concatenative languages such as Forth force you to anally deform your brain into the shape of a stack. Besides that, they don't offer any advantages. Having formal parameters in functions is a big win, and concatenative languages lose because of that.
33 Name: Anonymous 2017-11-30 19:41
pride comes before a fall
34 Name: Anonymous 2017-11-30 20:32
fall comes before a winter
35 Name: Anonymous 2017-12-04 05:07
fail comes before win
36 Name: Anonymous 2018-09-12 00:50

"I have yet to see a decent piece of software written in Forth. Let's face it. Forth stinks." --- John Dvorak, provocateur and columnist, InfoWorld, October 29, 1984.
"Forth is the first language which has been honed against the rock of experience before being cast into bronze." --- Charles Moore, inventor of Forth.

"Only brain-damaged programmers use Forth." --- Alan Holub, ex-C columnist, Dr. Dobb's Journal.

"Forth is like the T'ao; it is a Way, and is realized when followed. Its fragility is its strength; its simplicity is its direction." --- Michael Ham, ex-Forth columnist, Dr. Dobb's Journal.
37 Name: Anonymous 2018-09-19 20:18
Concatenative languages can have formal parameters just as non-concatenative languages can not have them.

what are you talking about?
38 Name: Anonymous 2018-10-03 02:19
I've been playing around with Forth after seeing this thread. I'm still learning but so far I can't seem to figure out how to get Forth to print out how words are defined in its dictionary entry. Using a search engine yields too many irrelevant results.
39 Name: Anonymous 2018-10-09 01:49
I eventually encountered the relevant word, see, which does just that.

Leave this field blank: