The Machines · Runtime stack

lineshaft

Control Flow and Execution Failure — machines/lineshaft.shoddy

the lineshaft machine's icon

Summary

lineshaft is where the language's own execution primitives are written down: Call and Ifte, which route execution, and Error and Assert, which end it. This machine declares no words of its own. All four are builtins: the engine dispatches them, so they are callable from any program with no Include at all, and including this file gives you nothing you did not already have. The page exists because these four are used almost everywhere in the tree and documented almost nowhere. A builtin used in ninety files is still a builtin a reader cannot find.

A Brief History of the Line Shaft

In a West Riding mill there was one source of power and hundreds of machines. The thing that connected them was the line shaft: a steel shaft running the length of every floor, turned by the engine, with a leather belt dropping from it to each loom and each carding engine. No machine had power of its own. Each one borrowed the shaft's motion through its belt, and when the engine stopped, the whole mill stopped at once. Electrification killed the arrangement in the early twentieth century by giving every machine its own motor. But the shape survives in software exactly: a program has one thread of execution, and every word borrows it for a while through a call. The four builtins documented here are the mill's transmission. Call and Ifte are the belts that route the turning to one machine or another. Error and Assert are the stop-rope that halts the shaft for the whole floor. That is why a page about control flow is named for a piece of Victorian millwork.

Why It's Useful

Call is the word every higher-order thing in Shoddy is built on — higher-order meaning a word that takes a function as an argument. Map, Filter and Fold reach their function through it. So do seq's Any and All, eng's numeric derivatives and integrators, and alg's compiled expressions. It is also the one builtin in the language whose stack effect is not fixed, which is a fact worth knowing before the stack checker tells you about it.

Error and Assert are how a Shoddy program stops. Shoddy has no exceptions and nothing to catch. A word that cannot honour its arguments does not raise something a caller might handle; it ends the run, naming the reason and the line. That is a real design decision with real consequences for how you write library code. It deserves somewhere to be explained, rather than being a one-line entry under "Errors" in the flat reference.

This is not a testing machine. Assert is here because it is a way for a program to stop, next to Error — not because this is a quality or test-tooling domain. There is no assertion-helper library in the tree to build one around. Both words are used across about two thirds of the machines as ordinary internal validation rather than as test apparatus. Words like AssertEqual or AssertClose would be a feature addition, and would not change where these two live.

User's Guide

You need no Include for any of this. The words below are already in scope in every Shoddy program.

Def Twice(f As [ Number -- Number ], x As Number) As Number
    Call(f, Call(f, x))          ' route execution out to the quotation

Def Half(x As Number) As Number
    If x < 0 Then
        Error("HALF: NEGATIVE")  ' ends the run, naming the line
    Else
        x / 2

Def Mean(total As Number, n As Number) As Number
    Assert(n > 0, "MEAN: NO VALUES")
    total / n

A few things worth remembering:

Builtins

The four execution words the runtime dispatches

None of these is a Def. The engine dispatches them, and a Def whose name is a builtin is refused. The same four are documented word for word in machines/lineshaft.shoddy's own header block. Stack effects are the ones the compiler's Effects.cs table declares.

Routing execution

WordDescription
Call(f, args…)Apply a function value to its arguments; the arity is the quotation's. The one genuinely dynamic builtin — its net stack effect is the quotation's, which is why Effects.cs lists it under Dynamic rather than as a fixed pair, and why the stack checker treats any Def reaching it as unknown. Every higher-order word in the library goes through it.
Ifte(cond, then, else)Call's fixed three-argument shell, and the expression form of If/Then/Else. Both arms are evaluated before the choice is made, since it is an ordinary word — so it is for choosing between two values already in hand.

Ending it

WordDescription
Error(why)End the run, reporting why and the line it happened on. Shoddy has no catchable errors, so this is final. It is the ordinary way a library word refuses an argument it cannot honour — str's Split on an empty separator, matrix on a dimension mismatch.
Assert(cond, why)Error unless cond is True; nothing at all when it is. The same finality, written as a precondition.

Who Uses It

Nothing includes it, and nothing needs to. This machine declares no words, so there is nothing to import. The four builtins it documents are in scope everywhere already, and are in fact among the most used words in the tree: Call and Ifte appear across the great majority of .shoddy files, and Error or Assert in about two thirds of the machines.

The Machines It Uses

None, and it could not use one — a file that declares nothing has nothing to build. It includes no machine and no machine includes it.