ワンクリックで
yuyan-bootstrap
How to bootstrap the Yuyan self-hosting compiler — 5-stage chain, common pitfalls, build commands, and pipeline architecture
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
How to bootstrap the Yuyan self-hosting compiler — 5-stage chain, common pitfalls, build commands, and pipeline architecture
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
豫言源码引号标识符迁移规则。用于编辑 .豫/.yuyan 编译器或库代码,把所有普通名字写成「」形式,同时保持语法关键字、列表括号、占位符、字符串字面量、注释和操作符声明结构正确。
Project-specific Yuyan migration rules for replacing local structure blocks such as `虑(...)` / structure-recursive declarations with expression-level `递归虑...其...者...而...` and `虑...者...而...`. Use when editing yylib or compiler `.豫`/`.yuyan` code to exercise the structure recursion operator / reclet syntax, especially when converting old structure declarations, local recursive helper functions, or direct expressions separated by `。`.
Manually remove yylib custom operator declarations and their supporting definitions from the Yuyan codebase, without Python or automated rewrites.
Migration from component-based operators to fixity-based operators in the Yuyan self-hosting compiler
| name | yuyan-bootstrap |
| description | How to bootstrap the Yuyan self-hosting compiler — 5-stage chain, common pitfalls, build commands, and pipeline architecture |
The Yuyan self-hosting compiler is built through a 5-stage bootstrap chain:
yy (SML, MLton) → yy_bs → yy_bs_bs → yy_bs_bs_bs → yy_bs_bs_bs_bs → yy_bs_bs_bs_bs_bs
| Stage | Built by | Speed | Notes |
|---|---|---|---|
yy | MLton (src/) | fast | SML bootstrap compiler. One-time build from src/development.mlb. |
yy_bs | yy | ~400s | First Yuyan-compiled compiler. Uses SML codegen (i64, monolithic .ll). |
yy_bs_bs | yy_bs | ~slow | Self-hosting codegen (i128 tagged, modular .o files). First stage with full optimization pipeline. |
yy_bs_bs_bs | yy_bs_bs | faster | Optimization passes compound. --parallel works here. |
yy_bs_bs_bs_bs | yy_bs_bs_bs | ~35s | Fast enough for development. Use --parallel --static-linking. |
Bootstrap principle: each stage compiles the same source (豫言编译器/入口。豫) to produce the next stage. Stages 3+ should produce identical binaries (verified by hash).
# macOS (Apple Silicon)
brew install mlton bdw-gc libuv llvm
# Ensure llvm-as is in PATH
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
yy (SML bootstrap compiler)cd /Users/zc/repos/yuyan
make yy
Common issues:
JSONUtil.FieldNotFound API mismatch → fix: change FieldNotFound (jv, s) to FieldNotFound s in src/lsp/language-server-mode.sml$(SML_LIB) pathTwo runtime directories exist:
runtime/ — used by SML yy (old entry point, -D OLD_ENTRY)运行时支持库/ — used by self-hosting stages# Build both
make -C runtime/ debug_old
make -C ./运行时支持库 all VERSION=v0.1.0rc2+0019
Common issues:
gc.h not found → the Makefiles use -I /usr/local/include. On Apple Silicon, add -I /opt/homebrew/include. Both Makefiles should already be patched.-Werror failures on newer clang → change to -Wno-error. Both Makefiles should already be patched.yy_bs (first self-hosting stage)./yy -c --use-local-lib 豫言编译器/入口。豫 -o yy_bs
This generates a ~286MB monolithic .ll file in .yybuild.nosync/, then invokes clang.
Common issues:
musttail call failures on newer clang (83K errors) → the SML codegen emits musttail calls that don't satisfy LLVM's strict matching requirements. Fix:
sed -i '' 's/musttail call/tail call/g' .yybuild.nosync/yy*.ll
Then run clang manually:
clang .yybuild.nosync/yy*.ll runtime/libyyrtdebug_old.a -g -o yy_bs \
-L /opt/homebrew/lib -l gc -l uv -Wno-override-module
-L /opt/homebrew/lib for Apple Siliconyy_bs_bs (second stage, uses self-hosting codegen)# Fix rpath on yy_bs first
install_name_tool -change libyyrtoptv0.1.0rc2+0019.dylib \
@loader_path/运行时支持库/libyyrtoptv0.1.0rc2+0019.dylib yy_bs
# Build. Add --do-not-optimize to skip LLVM optimization passes for faster build
./yy_bs 豫言编译器/入口。豫 -o yy_bs_bs -c --do-not-optimize
Common issues:
libyyrtopt...dylib not found at runtime → yy_bs was linked with -Wl,-rpath,./运行时支持库 which macOS dyld doesn't resolve. Use install_name_tool above. The fix is in 主程序生成。豫 source (absolute rpath), but that requires recompiling yy_bs from scratch.llvm-as: no such file or directory → ensure llvm from homebrew is in PATH# yy_bs_bs_bs — ~35s with parallel + static linking
./yy_bs_bs 豫言编译器/入口。豫 -o yy_bs_bs_bs -c --parallel --static-linking
# yy_bs_bs_bs_bs — even faster
./yy_bs_bs_bs 豫言编译器/入口。豫 -o yy_bs_bs_bs_bs -c --parallel --static-linking
# yy_bs_bs_bs_bs_bs
./yy_bs_bs_bs_bs 豫言编译器/入口。豫 -o yy_bs_bs_bs_bs_bs -c --parallel --static-linking --optimize
Key flags:
-c — compile only, don't run--parallel — invoke parallel_compile.py for multi-file parallel compilation--static-linking — link .a file instead of .dylib (avoids rpath issues)--do-not-optimize — skip LLVM opt passes (faster build, slower binary)--optimize — enable opt -O3 and LTO (slower build, faster binary)--debug — generate debug infoThe self-hosting compiler (yy_bs and beyond) uses this pipeline per file:
Parse → TypeCheck → TypeErase → ANF(无类型正则变换) → CPS(续延传递变换)
→ ClosureConvert(前闭包转换) → FunctionHoist(函数提升)
→ CrossModuleOpt(跨文件优化: 去柯里化, 常量内联, 函数参数优化)
→ LocalOpt(本地优化: 栈分配, 尾调用, 树组优化)
→ CodegenPrep(代码生成准备: 栈帧布局, GC检查注入)
→ LLVM Codegen(emit i128-tagged LLVM IR)
→ llvm-as → opt → llc → clang .o → link
Optimization passes compound across stages: each stage's compiler has all previous optimizations baked in, so yy_bs_bs_bs compiles faster than yy_bs_bs.
parallel_compile.py breaks compilation into stages:
dependency-analysis — resolve importsparse — lex + parse each filetype-check-and-erase — bidirectional type check + erase typescross-module-optimize — uncurrying, constant inliningpre-closure-convert — closure conversion prepanf — A-Normal Form + CPS transformall-codegen — LLVM IR gen + llvm-as + llc → .oEach stage processes files in parallel using ProcessPoolExecutor. Stages are pipelined: a file can be in codegen while another is still parsing. Dependencies are tracked so a file waits for its imports to complete each stage before proceeding.
To debug parallel build issues, check:
yy_parallel_log.txt — detailed worker logsyy_parallel_deps.txt — dependency graph| File | Role |
|---|---|
豫言编译器/入口。豫 | Compiler entry point, CLI argument handling |
豫言编译器/编译步骤/类型检查/对象类型检查。豫 | Bidirectional type checker (55K, largest file) |
豫言编译器/编译步骤/语法分析/抽象语法分析。豫 | Mixfix parser |
豫言编译器/编译步骤/求值正则变换/无类型正则变换。豫 | ANF transform |
豫言编译器/编译步骤/闭包转换/正则前闭包转换。豫 | Closure conversion |
豫言编译器/编译步骤/代码生成准备变换/代码生成准备变换。豫 | Stack frame + GC injection |
豫言编译器/编译步骤/代码生成/低级虚拟机/直接代码生成。豫 | i128 LLVM IR emitter |
豫言编译器/编译步骤/代码生成/低级虚拟机/主程序生成。豫 | Link command generation, main entry |
豫言编译器/编译步骤/总体过程/编译过程。豫 | Pipeline orchestration |
parallel_compile.py | Parallel build orchestrator |
src/passes/codegen/llvm-codegen.sml | SML codegen (i64, only used by yy) |
src/passes/cps-transform/cps-pass.sml | SML CPS transform (only used by yy) |
make yy # Build SML bootstrap compiler
make yy_bs # Build first self-hosting stage
make yy_bs_bs # Build second stage (serial)
make yy_bs_bs_parallel # Build second stage (parallel)
make yy_bs_bs_bs # Build third stage
make yy_bs_bs_bs_bs # Build fourth stage
make yy_bs_bs_bs_bs_bs # Build fifth stage
make yyrt # Build old runtime library
make yy_runtime_lib # Build self-hosting runtime library
make test # Run tests
make clean # Remove yy
make cleanbs # Remove yy_bs
make superclean # Remove all build artifacts + caches
衔 vs 附: 衔 is list concatenation (from 多态列), 附 is string concatenation (from 字符串术). Using the wrong one causes type unification failures.-Wl,-rpath,./dir doesn't work with dyld. Use absolute paths or @loader_path.musttail call that fails verification on LLVM 16+. Fix: sed 's/musttail call/tail call/g' on the .ll file.i64, self-hosting codegen uses i128 (tagged union).--debug flag: Not recognized by SML yy, use --super-verbose for yy. For self-hosting stages, --debug works and -v/-vv/-vvv control verbosity.yy codegen produces a 286MB monolithic .ll file. clang compilation alone takes ~400s. Subsequent stages use modular .o files which link much faster.parallel_compile.py needs Python 3.12+ (uses new ProcessPoolExecutor features)..yybuild.v0.1.0rc2+0019.nosync/ — contains per-file .o, .ll, .bc files and JSON caches. Delete to force full rebuild.