Preface
Preface
Einlang began from a small irritation: tensor programs often depend on facts that are not written in the program.
A line of PyTorch or NumPy can reshape, transpose, broadcast, reduce, and feed an automatic differentiation engine. The program runs. The shapes line up. But the source often leaves the central intention implicit. Which dimension is the batch? Which one was split? Which one is being silently repeated? Which dependency is a time step rather than a storage update?
The compiler sees extents. The reader remembers roles. A surprising number of bugs live between those two kinds of knowledge.
This book works in that gap. It does not try to present Einlang as a universal programming language, a full deep learning framework, a hardware scheduler, or a theorem prover. The scope is smaller:
Make tensor dimensions visible.
The seven sections are not lessons in a complete syntax. They are a sequence of design decisions. Each section takes a familiar tensor habit and asks what the program has left implicit:
- reshape chains hide semantic roles;
- broadcasting hides missing coordinates;
- loops hide time-step dependencies;
- informal shape prose hides compile-time contracts;
- automatic differentiation hides the structure of sensitivities;
- whole frameworks hide the cost of relying on convention;
- final notation decides which source-level facts remain available.
Einlang’s role in these pages is to provide a small, inspectable language. Its
minimal core is enough: let, indices, sum, derivative requests, and
recurrence. With those pieces, we can ask what changes when formulas are
written as coordinate relationships instead of shape manipulations.
The implementation keeps the book honest. Einlang’s compiler parses source, resolves names, lowers AST to IR, groups Einstein declarations, infers ranges, checks shapes, infers types, rewrites autodiff requests, lowers Einstein notation, orders recurrences, records lowered execution facts, and then validates the result. The book follows that spine conceptually, even when a chapter uses a small mathematical spelling to keep the coordinate idea in view.
This also fixes one important vocabulary boundary. Axis names are semantic
roles, not scalar types. The real type syntax is i32, f32, [f32; 3, 4],
[f32; ?, ?], and [f32; *]. An index binder is written as a name or as a
range such as i in 0..n; it is not written as i: batch. When the book says
that an axis behaves like a contract, it means the compiler uses the name,
range, and rectangular type information together. It does not invent a second
type syntax for dimensions.
The chapters do not simply announce the resulting design. They follow the pressure that leads to it. Position-only axes are fine until two roles share a shape. Implicit broadcasting is convenient until the missing coordinate is the mistake. Runtime tapes are useful until the derivative shape could have been read from the source. Ordinary loops are natural until time becomes a dependency axis that analysis needs to inspect.
The examples should be read as ramps, not as demonstrations of the obvious. A chapter may begin with one cell or one row because that is often the fastest way to see the rule. It should not stay there. The useful examples are the ones where the first reading leads into a harder question: what if two roles have the same extent, what if a shared parameter should or should not accumulate, what if a recurrence can be stored with a rolling window until an observation changes the contract, what if an optimized lowering erases the surface structure unless the IR has already captured it?
The design law is simple:
Do not hide a fact that later reasoning must recover.
The rest of the book applies that law to tensor programs.
The answer will not be that every program should be written this way. A good host language still matters. Existing tensor libraries still matter. The practical answer is this: when dimensions have names, the program can say more of what it meant. The code no longer merely performs a shape operation. It states a relationship among coordinates.
That is the standard this book uses to read tensor code.