Scene 1 The pot at the end of the path
LineySo who made the tool that checked me?
SeedlingPeople did.The compiler that checked you is a program someone wrote, Liney.Want to see which language they used?
The Life of Code 06
Is a compiler a program someone wrote, too?
Liney has met every friend on the first lap, and one question is left.
This time we look at the tool that checked Liney.
The answer is on the back of the map.
Let's turn it over with Seedling.
LineySo who made the tool that checked me?
SeedlingPeople did.The compiler that checked you is a program someone wrote, Liney.Want to see which language they used?
LineyWhoa, the back is full of writing!
SeedlingIt's the source of the compiler that checked you.Today we've copied out its first ten lines.
Lineysrc/main.tpz? It ends just like my file name!
SeedlingThe compiler's settings file names this file as its starting place.Like you, this file is written in Topaz.
TwigHang on, haven't I seen this word before?
SeedlingYou don't live in here, of course.But the jobs we explored on the first lap are written here by name.Want to find them?
TinkerWhat's that 5.21.1 in the corner?
SeedlingIt's the version of Topaz we opened.That number tells us which release this source came from.
Now it's your turn to read the back of the map.
Experiment
Liney's file is called main.tpz.
The compiler's settings point to a file called src/main.tpz as its starting place.
Both names end in main.tpz.
Let's open the compiler's file and read its first ten lines.
Nothing runs on this page. The text on the back is copied exactly from the source Topaz published.
main.tpz
1 + 26 bytes · 1 line · The file we've followed since Episode 1
src/main.tpz
16,891 bytes · The first 10 of 560 lines · Topaz 5.21.1 public source
Topaz 5.21.1 public source
What's on the other side of the map?
import std.json as jsonBoundaryimport checker { check }import emitter { emitRust, emitStep }import layout { normalize }import lowering { lowerStep, lowerValue }import parser { parse }import profile { checkProfile }import raw { lex }import resolver { resolvePreview, resolveWithFacts }Think back to the job you explored with this friend on the first lap. Which line brings in a name for that job?
Try each of the four friends' pins once and the discovery card opens.
The import lines show where this file gets its names.
Farther down, you can see one of them at work in lex(request.source).
The four friends' lines
Snip Line 9 import raw { lex }
lex is the name. It matches the first three letters of lexical. Line 261 of the full file passes the source in with lex(request.source), and the very next line takes out raw.tokens.
Twig Line 7 import parser { parse }
parse is the name. It connects to the parsing in Episode 2, where we grouped the pieces into a tree.
Tami Line 3 import checker { check }
check is the name. The first comment in checker.tpz says this module does type checking.
Momo Line 6 import lowering { lowerStep, lowerValue }
lowerStep and lowerValue are the names. Both connect to the lowering in Episode 4, where we copied the tree onto cards.
std.json module of the standard library under the name jsonBoundary.emitter. The compiler calls emitRust to generate Rust code. Which line names the lowering we saw in Episode 4?normalize from layout. Line 262 uses it on raw.tokens. See how normalize handles line breaks in Episode 7checkProfile from profile. Which line imports from checker, the module for the type check we saw in Episode 3?resolvePreview and resolveWithFacts from resolver. To resolve a name is to find what it points to.Your computer runs the installed topaz file. The text we're reading comes from the source Topaz published.
The settings file topaz.toml says entry = "src/main.tpz".
Only the first 10 of 560 lines are copied here. The whole file is in the official source archive.
topaz-source-snapshot-v5.21.1.tar.gzd3a0e5365b8a39605f095a7c07b43556848a95042e7efd346ab84c95e583cf3dcompiler/crates/topaz_self_frontend/topaz/src/main.tpzef16cb39e9956e7e3aaed8023f9a45388c49a17bd9336a6e6f29dfa5aeb63bd3The copied source comes under the license and notice of the same release. Read LICENSE, opens in a new tab Read NOTICE, opens in a new tab
The map and the pins are part of the story. The text and numbers on the back come from the published originals.
The real story
The writing on the back of the map is the compiler's source code. Like Liney, it's a program someone wrote out in text.
The Topaz documentation says The default compiler is written in Topaz. Toolchain Status, opens in a new tab
A self-hosting compiler is written in the language it compiles and can compile its own source.
The compiler's folder holds 50 .tpz files. Its entry file, main.tpz, is 560 lines long. Liney's main.tpz is one line.
Inside the compiler, let gives a value a name too. Line 261 has let raw = lex(request.source), and the very next line takes out that raw.tokens.
We used the default compiler in Topaz 5.21.1 for the token, tree, type and operation records in Episodes 1 to 4. Today we opened that compiler's published source.
The copied source comes under the license and notice of the same release. Read LICENSE, opens in a new tab Read NOTICE, opens in a new tab
No. The friends are how the story pictures things. The compiler splits its work across files and names, and some of those names look like the jobs we explored on the first lap.
The import lines from line 3 to line 10 are in alphabetical order of their module names, not the order the work happens in. How the work is split, and in what order, can differ from compiler to compiler.
No. Some compilers are written in the language they compile, and some are written in another language.
Topaz 5.21.1 records and public source
Look closer
Written in the record Ask Topaz 5.21.1 for its status and it names a default compiler and a reference compiler.
Default compiler: self
Reference compiler: rustWritten in the record It lists self as the default compiler and rust as the reference compiler.
Written in the record We checked 1 + 2 three times. The note tray names the compiler selected each time.
Commandtopaz check -v main.tpz
Note traytopaz: compiler selection: self (current-default)
main.tpz: types-ok (1 module)
main.tpz: resolve-ok (1 module)Original files main.tpzcheck.cmdcheck.stdoutcheck.stderrcheck.exit
Commandtopaz check -v --compiler self main.tpz
Note traytopaz: compiler selection: self (explicit)
main.tpz: types-ok (1 module)
main.tpz: resolve-ok (1 module)Original files main.tpzcheck.cmdcheck.stdoutcheck.stderrcheck.exit
Commandtopaz check -v --compiler rust main.tpz
Note traytopaz: compiler selection: rust (explicit)
main.tpz: types-ok (1 module)
main.tpz: resolve-ok (1 module)Original files main.tpzcheck.cmdcheck.stdoutcheck.stderrcheck.exit
Written in the record A check that chose nothing says current-default, and a check that named a compiler says explicit.
Compared by this site The two lines in the screen window matched byte for byte across all three checks.
Setting the two compilers side by side to see whether they do the same work is for a later lap.
Original files topaz compiler statustopaz compiler status --json
The 1 + 2 observation behind Momo's cards in Episode 4 also has a provenance file, provenance.json.
Written in the record The Episode 4 record says two successive stages produced identical Rust bytes.
Written in the record It lists the fixed point for the intermediate records as not-established.
Written in the record For the executable-byte comparison, it says not-run.
Written in the record The record lists rustc 1.96.0 under the tools used to link this compiler.
Compared by this site The nine fields we compared had the same values in 5.21.0 and 5.21.1. The two provenance files differed at the byte level.
Topaz 5.21.1's compiler seed is published as one compressed bundle and a list of what's in it.
Compared by this site The seed contains the compiler source written in Topaz, the Rust generated from it, runtime code and build scripts.
Compared by this site Three identifiers in the seed list match the installed compiler's provenance record.
Compared by this site We also took the Rust file out of the bundle and found that its hash matched the one listed.
topaz-bootstrap-seed-v5.21.1.tar.gzcf6a09b66fa5197472808fc01388e799b394686fb705b8e977cc39962583e974The three identifiers we matched
compiler.sourceSetIdsha256:17d598ebcb0dea65195aba8c0b3ab20f94003a7f343714f7b1df25d790cdacd5sourceReuse.compilerSourceSetIdsha256:17d598ebcb0dea65195aba8c0b3ab20f94003a7f343714f7b1df25d790cdacd5compiler.runtimeSourceSetIdsha256:85ed8d3b0571c34bc40c3ffd1be8bcda2a539d6c82c92b417c834507200d9c60sourceReuse.runtimeSourceSetIdsha256:85ed8d3b0571c34bc40c3ffd1be8bcda2a539d6c82c92b417c834507200d9c60compiler.generatedRustSha256sha256:5f32cee07a1adea1c67ba8ac8fbd4f3ee4051f019a7856fcdb228740a1d4b8b1sourceReuse.generatedRustSha256sha256:5f32cee07a1adea1c67ba8ac8fbd4f3ee4051f019a7856fcdb228740a1d4b8b1Hash we took again from the file in the bundle generated/compiler.rs 5f32cee07a1adea1c67ba8ac8fbd4f3ee4051f019a7856fcdb228740a1d4b8b1
That's as far as this site went.
Compared by this site We matched the compiler's 50 .tpz files by path across the seed lists for 5.21.0 and 5.21.1. Nine files had different hashes. The entry file we opened had the same hash in both.
Files with different hashes
checker/call_complete.tpzchecker/call_facts.tpzchecker/expression_control.tpzchecker/expression_core.tpzchecker/members_capabilities.tpzchecker/statements.tpzchecker/type_algebra.tpzemitter/emit.tpzresolver/scopes_walk.tpzWritten in the record The publisher records whether it built the seed bundle in built and whether it regenerated the Rust in regenerated.
builttrueregeneratedtrueWritten in the record The seed's guide says The compiler written in Topaz performs parsing, checking, lowering and Rust generation.
A question for the next lap
Will the regenerated Rust match the Rust in the bundle byte for byte?
The copied source comes under the license and notice of the same release. Read LICENSE, opens in a new tab Read NOTICE, opens in a new tab
In one line
A compiler is a program someone wrote in some language, too.
The default Topaz compiler that checked Liney is written in Topaz.
How did Seedling know to open src/main.tpz first?
The settings file, topaz.toml, names src/main.tpz as the entry file.
We followed it and found compiler code written in Topaz.
Next time you meet a compiler, you might picture the source on its back.
Field GuideRevisit these wordsCompilerSelf-Hosting Compiler
Looking back
With Snip, we split 1 + 2 into tokens.
With Twig, we found where the two numbers fit in the addition tree.
Read Episode 2 againWith Tami, we read why the type check stopped at 1 + "apple".
On Momo's cards, we found the two numbers in 1 + 2 again.
With Tinker, we read the run record for a program with lines that print. The screen window showed start, then 3.
With Seedling, we turned the map over and opened the source of the compiler that checked our code.
On this lap we explored 1 + 2 and a few other examples in Topaz 5.21.1.
The next lap starts at Snip's stop with a new question.
Next story
SnipI'm not done yet. Let's talk about spaces.
Back at the first stop on the path, Snip picks up the scissors again.
When do spaces and line breaks mean something?
Next time, let's head back to the first stop.