<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>逸瑄</title>
    <link>https://www.wangyuhang.net/</link>
    <description>逸瑄的个人技术博客：记录学习路上的踩坑复盘和原理思考，写能照着做出来的教程，也留一些生活里的随笔。</description>
    <language>zh-CN</language>
    <lastBuildDate>Thu, 01 Oct 2026 03:01:29 GMT</lastBuildDate>
    <pubDate>Wed, 30 Sep 2026 00:00:00 GMT</pubDate>
    <generator>Astro</generator>
    <docs>https://www.rssboard.org/rss-specification</docs>
    <ttl>60</ttl>
    <atom:link href="https://www.wangyuhang.net/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>自己造一门语言：一个学习项目的开篇</title>
      <link>https://www.wangyuhang.net/posts/language-project/</link>
      <guid isPermaLink="true">https://www.wangyuhang.net/posts/language-project/</guid>
      <pubDate>Wed, 30 Sep 2026 00:00:00 GMT</pubDate>
      <description>用“自己造一门语言”当载体，重学编译原理和 Rust。</description>
      <content:encoded>&lt;h2 id=&quot;0x01-一个一直没解决的问题&quot;&gt;0x01 一个一直没解决的问题&lt;/h2&gt;
&lt;p&gt;我写过不少代码。每次敲下 &lt;code&gt;if&lt;/code&gt;，我大概知道它会编译成一条比较指令和一次跳转。但若有人问它是如何变成这两条指令的，我答不上来。&lt;/p&gt;
&lt;p&gt;这个空白我填过很多次：看视频、读《编译原理》、翻 LLVM 的文档。每次都看懂了，不到半年却忘干净。&lt;/p&gt;
&lt;p&gt;后来我找到了原因：我一直在读别人的做法，从未自己动手做过一次。&lt;/p&gt;
&lt;p&gt;看懂和做出来是两回事。看书、看视频，是别人把理解讲给你听；自己动手，才是把理解拿去给现实检验。检验一定会失败，而失败的地方，恰恰是真正学到东西的地方。&lt;/p&gt;
&lt;p&gt;所以这次我换了条路：不学编译原理，而是造一门语言。&lt;/p&gt;
&lt;p&gt;这个系列写完时，它能跑成这样：&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes material-theme-lighter material-theme-darker&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#212121;color:#90A4AE;--shiki-dark:#EEFFFF; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#39ADB5;--shiki-dark:#89DDFF&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#90A4AE;--shiki-dark:#EEFFFF&quot;&gt; varde run hello.vd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#90A4AE;--shiki-dark:#EEFFFF&quot;&gt;hello, varde&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#39ADB5;--shiki-dark:#89DDFF&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#90A4AE;--shiki-dark:#EEFFFF&quot;&gt; varde build hello.vd &lt;/span&gt;&lt;span style=&quot;color:#39ADB5;--shiki-dark:#89DDFF&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E2931D;--shiki-dark:#FFCB6B&quot;&gt; ls&lt;/span&gt;&lt;span style=&quot;color:#91B859;--shiki-dark:#C3E88D&quot;&gt; -lh&lt;/span&gt;&lt;span style=&quot;color:#91B859;--shiki-dark:#C3E88D&quot;&gt; hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#90A4AE;--shiki-dark:#EEFFFF&quot;&gt;-rwxrwxrwx 1 root root 16K Sep 30 10:34 hello&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;0x02-为什么选造语言作为学习载体&quot;&gt;0x02 为什么选“造语言”作为学习载体&lt;/h2&gt;
&lt;p&gt;学习编译原理大致有三条路：看书、看视频、读别人的编译器源码。它们都有用，却共享同一个缺口：没有必须做决定的时刻。&lt;/p&gt;
&lt;p&gt;而造一门语言，会在每个环节逼你做决定。举三个例子。&lt;/p&gt;
&lt;h3 id=&quot;例-1--词法分析&quot;&gt;例 1 · 词法分析&lt;/h3&gt;
&lt;p&gt;书上的“正规式 → NFA → DFA”是一套算法，三页纸讲完。轮到动手写，你要回答：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;gt;&lt;/code&gt; 和 &lt;code&gt;&amp;gt;=&lt;/code&gt; 怎么区分？（最长匹配）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;//&lt;/code&gt; 是注释，&lt;code&gt;/&lt;/code&gt; 是除号，扫描器怎么知道该看第二个字符？&lt;/li&gt;
&lt;li&gt;源码里有中文时，报错该报第几列？字节偏移与字符列号是两回事。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/* /* */ */&lt;/code&gt; 这种嵌套注释要不要支持？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些问题书上都不讲，因为它们不是算法问题，是工程问题。工程问题只能自己撞一次才会记住。&lt;/p&gt;
&lt;h3 id=&quot;例-2--类型系统&quot;&gt;例 2 · 类型系统&lt;/h3&gt;
&lt;p&gt;类型系统的教材定义只有一句：“静态类型 = 编译期检查类型”。真到自己写，问题就来了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;let j: i64 = i;&lt;/code&gt;（&lt;code&gt;i&lt;/code&gt; 是 &lt;code&gt;i32&lt;/code&gt;）该不该放过？&lt;code&gt;let f: f64 = i;&lt;/code&gt; 呢？&lt;/li&gt;
&lt;li&gt;函数体里的类型标注能省吗？函数签名上的呢？&lt;/li&gt;
&lt;li&gt;泛型要单态化，还是用虚表动态派发？&lt;/li&gt;
&lt;li&gt;若子类型只有“具体类型 → &lt;code&gt;dyn Trait&lt;/code&gt;”这一来源，那 &lt;code&gt;Vec&amp;lt;Dog&amp;gt;&lt;/code&gt; 能不能赋给 &lt;code&gt;Vec&amp;lt;Animal&amp;gt;&lt;/code&gt;？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;每一个问题都没有标准答案，只有取舍。做过取舍的人，才看得懂别人的取舍。&lt;/p&gt;
&lt;h3 id=&quot;例-3--内存管理&quot;&gt;例 3 · 内存管理&lt;/h3&gt;
&lt;p&gt;“引用计数”在书里是一个概念，配一张计数增减的示意图。把它真正实现出来时，你躲不开这些问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;赋值要不要拷贝对象？传参呢？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;let b = a;&lt;/code&gt; 之后改 &lt;code&gt;a&lt;/code&gt;，&lt;code&gt;b&lt;/code&gt; 该不该跟着变？&lt;/li&gt;
&lt;li&gt;两个对象互相引用，计数永远不归零，怎么办？&lt;/li&gt;
&lt;li&gt;析构函数在什么时刻执行？抛异常时还执行吗？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你必须把答案写进代码，然后承担它的全部后果。&lt;/p&gt;
&lt;p&gt;看书是输入，动手是输出。只有真正输出一次，你才知道自己懂没懂。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;0x03-为什么是自己造而不是跟着抄&quot;&gt;0x03 为什么是“自己造”，而不是“跟着抄”&lt;/h2&gt;
&lt;p&gt;跟着《Crafting Interpreters》抄一个 Lox，不失为一种有效的入门方式。很多人就是这么入门的，我自己也读过。&lt;/p&gt;
&lt;p&gt;但抄有一个代价：你没有决策时刻。&lt;/p&gt;
&lt;p&gt;抄的过程中，所有“为什么这样设计”的问题，答案都是“书里就这么写的”。抄完，你获得的是流程知识，不是判断力。换一个需求，你仍然不知道从何下手。&lt;/p&gt;
&lt;p&gt;自己造，差别就在这里：每一个设计决策都要自己拍板，而决策过程本身就是内容。&lt;/p&gt;
&lt;p&gt;设计语言时，每个决定都要回答：为什么这么选、放弃了什么、什么时候会咬人。这些“为什么”在任何教程里都找不到答案，因为那是你自己的取舍。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;0x04-这个项目是什么&quot;&gt;0x04 这个项目是什么&lt;/h2&gt;
&lt;p&gt;一个教学用的玩具语言 &lt;code&gt;varde&lt;/code&gt;。它存在的唯一目的，就是让我（和跟着做的你）把编译原理和 Rust 两件事真正学透。&lt;/p&gt;
&lt;p&gt;项目用 Rust 编写，代码总量不到 1 万行，编译后是单个可执行文件。&lt;/p&gt;
&lt;p&gt;还有一句话提前说：这门语言不会有用户。它的用户只有我和你。&lt;/p&gt;
&lt;h2 id=&quot;0x05-你跟着学完会得到什么&quot;&gt;0x05 你跟着学完会得到什么&lt;/h2&gt;
&lt;p&gt;你能得到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;从字符流到可执行文件的完整能力，不是片段知识&lt;/li&gt;
&lt;li&gt;一个真实项目的全部决策过程和踩坑记录&lt;/li&gt;
&lt;li&gt;Rust 与编译原理的贯通&lt;/li&gt;
&lt;li&gt;一套可迁移的方法论：怎么用“造东西”来学习任何系统性知识&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你得不到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一门生产可用的语言（varde 只是个玩具）&lt;/li&gt;
&lt;li&gt;速成。这是个以年计的项目&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你看到这里，还愿意跟下去，那这个系列就是为你写的。&lt;/p&gt;
&lt;h2 id=&quot;0x06-出发&quot;&gt;0x06 出发&lt;/h2&gt;
&lt;p&gt;回到开头那个问题：&lt;code&gt;if&lt;/code&gt; 是怎么被执行的？&lt;/p&gt;
&lt;p&gt;现在你大概知道了这条路要走哪些站——从字符流开始，切词、建树、查类型、降成中间表示、生成代码，最后落到机器上。中间每一站都有具体要做的决定，我会一站一站写下去。&lt;/p&gt;
&lt;p&gt;设计和实现都从零开始，正好从头记起。&lt;/p&gt;
&lt;p&gt;学一门语言最好的方式，是用它造一个东西；而造一个东西最好的方式，是造一门语言。这句话听着绕，但这个系列就是来把它跑通的。&lt;/p&gt;
</content:encoded>
      <category>语言设计</category>
      <category>编译原理</category>
      <category>Rust</category>
      <category>教程</category>
    </item>
    <item>
      <title>开站啦：这个博客终于上线了</title>
      <link>https://www.wangyuhang.net/posts/hello-blog/</link>
      <guid isPermaLink="true">https://www.wangyuhang.net/posts/hello-blog/</guid>
      <pubDate>Sat, 26 Sep 2026 00:00:00 GMT</pubDate>
      <description>经过开发、部署之后，这个基于 Astro 的博客终于跑起来了。写篇开站文，记录一下此刻的心情。</description>
      <content:encoded>&lt;p&gt;经过一番辗转打磨，这座小小的站点终于和大家见面了。🎉&lt;/p&gt;
&lt;h2 id=&quot;为什么搭建这个博客&quot;&gt;为什么搭建这个博客&lt;/h2&gt;
&lt;p&gt;这个想法早在一年前就埋下了种子。彼时临近毕业，琐事纷至沓来，搭建博客的计划只好暂时搁置。最早的版本基于 Vue
3，受限于当时的能力，代码写得并不理想。每发布一篇文章都要改动不少代码，写作体验十分繁琐，项目也就慢慢停了下来。&lt;/p&gt;
&lt;p&gt;今年九月中旬，偶然读到一篇使用 Astro 搭建静态博客的文章，沉睡许久的念头再次苏醒。干脆推倒旧代码，从头开始重构。一路赶工，终于在本月底完成上线。&lt;/p&gt;
&lt;p&gt;一直想拥有一处完全属于自己的角落：不必担忧平台关停，写下的每一段文字，都安稳存放于自己的代码仓库。这个博客便是这份心愿的落地。站点基于
Astro 7 构建，搭配 Tailwind CSS、Sass 与 TypeScript，托管在 Cloudflare Workers，源码托管于 GitHub，提交代码即可自动部署。&lt;/p&gt;
&lt;h2 id=&quot;我会写些什么&quot;&gt;我会写些什么&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;技术笔记&lt;/strong&gt;：读过的文档、踩过的坑、沉淀下来的解决方案&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;随笔感想&lt;/strong&gt;：未必实用，但皆是内心真实的文字&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;折腾记录&lt;/strong&gt;：工具调试、环境配置、提升效率的细碎探索&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;无法承诺稳定的更新频率，但每一篇文字，都会用心落笔。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;开篇就写到这里。愿日后回望，这里已攒下许多值得反复品读的篇章。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;开张快乐。🥂&lt;/strong&gt;&lt;/p&gt;
</content:encoded>
      <category>随笔</category>
    </item>
  </channel>
</rss>
