<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Compiler on icebear&#39;s blog</title>
    <link>https://sfclub.cc/~icybear/tags/compiler/</link>
    <description>Recent content in Compiler on icebear&#39;s blog</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 06 Jul 2022 19:25:58 +0000</lastBuildDate>
    <atom:link href="https://sfclub.cc/~icybear/tags/compiler/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>「9&#43;」 Java 编译器插件教程 101</title>
      <link>https://sfclub.cc/~icybear/posts/extending-java-compiler/</link>
      <pubDate>Wed, 06 Jul 2022 19:25:58 +0000</pubDate>
      <guid>https://sfclub.cc/~icybear/posts/extending-java-compiler/</guid>
      <description>&lt;p&gt;写了上万行 Java 代码，相比你已经对 Java &amp;ldquo;木纳呆板&amp;quot;的语法恨之入骨了。&lt;/p&gt;
&lt;p&gt;那么，有没有一种可能，我是说可能，我们可以给 Java 编译器写插件？&lt;/p&gt;
&lt;p&gt;如果你要在面包店里买面包，你最好跟店员说你要买哪块面包。本文所指的 &lt;code&gt;Java 编译器&lt;/code&gt; 均为 OpenJDK 自带的那个 &lt;code&gt;javac&lt;/code&gt;，而不是其他的前端编译器实现。&lt;/p&gt;
&lt;h1 id=&#34;前言&#34;&gt;前言&lt;/h1&gt;
&lt;p&gt;自从 Java 8 起，Oracle 就将&lt;a href=&#34;https://docs.oracle.com/javase/8/docs/jdk/api/javac/tree/com/sun/source/util/Plugin.html&#34;&gt;插件&lt;/a&gt;系统引入了 &lt;code&gt;javac&lt;/code&gt; 中，因此是可以写 Javac 插件的。&lt;/p&gt;
&lt;p&gt;虽然写一个 Javac 插件并且修改代码是可能的，但是这方面的资料很少（国内就更少了），并且大多内容重复（教你写个 HelloWorld 然后就结束），其次 javac 的东西也不是很好摸，毕竟不是公开 API（ JDK 9+ 开始已经不暴露在外了）。&lt;/p&gt;
&lt;p&gt;恰逢今年还没写技术类的博客，就拿来磨磨刀吧。&lt;/p&gt;
&lt;h1 id=&#34;先从插件说起&#34;&gt;先从插件说起&lt;/h1&gt;
&lt;p&gt;上文刚刚提到了一个词，&lt;code&gt;插件&lt;/code&gt;。它其实正是 &lt;a href=&#34;https://docs.oracle.com/javase/8/docs/jdk/api/javac/tree/com/sun/source/util/Plugin.html&#34;&gt;com.sun.source.util.Plugin&lt;/a&gt;。通过这个类，我们可以让 Javac 在编译时加载我们的代码。&lt;/p&gt;
&lt;p&gt;加载了代码，那么做什么呢？所以我们立一个目标：&lt;em&gt;给所有 &lt;code&gt;@Jsonized&lt;/code&gt; 标注过的类都生成一个可以输出 json 的 &lt;code&gt;toString()&lt;/code&gt; 方法。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;什么意思呢？就比如说这样一个类：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c678dd&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#c678dd&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#e5c07b&#34;&gt;MyResponse&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c678dd&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#c678dd&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;message&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c678dd&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#c678dd&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#e5c07b&#34;&gt;boolean&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;success&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c678dd&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#61afef;font-weight:bold&#34;&gt;MyResponse&lt;/span&gt;(&lt;span style=&#34;color:#e06c75&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;message&lt;/span&gt;, &lt;span style=&#34;color:#e5c07b&#34;&gt;boolean&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;success&lt;/span&gt;){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c678dd&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#e06c75&#34;&gt;message&lt;/span&gt; &lt;span style=&#34;color:#56b6c2&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;message&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#c678dd&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#e06c75&#34;&gt;success&lt;/span&gt; &lt;span style=&#34;color:#56b6c2&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;success&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后你想把它序列化成 Json。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c678dd&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;response&lt;/span&gt; &lt;span style=&#34;color:#56b6c2&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c678dd&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;MyResponse&lt;/span&gt;(&lt;span style=&#34;color:#98c379&#34;&gt;&amp;#34;\&amp;#34;Success!\&amp;#34; Took me 114514 yr 1919810 m&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e5c07b&#34;&gt;false&lt;/span&gt;).&lt;span style=&#34;color:#e06c75&#34;&gt;toString&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e06c75&#34;&gt;response&lt;/span&gt;.&lt;span style=&#34;color:#e06c75&#34;&gt;equals&lt;/span&gt;(&lt;span style=&#34;color:#98c379&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#98c379&#34;&gt;    {&amp;#34;message&amp;#34;: &amp;#34;\&amp;#34;Success!\&amp;#34; Took me 114514 yr 1919810 m&amp;#34;, &amp;#34;success&amp;#34;: false}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#98c379&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;又快又便捷，还不需要第三方类库，这就是我们的目标。&lt;/p&gt;</description>
    </item>
    <item>
      <title>从零开始的编译器生涯</title>
      <link>https://sfclub.cc/~icybear/posts/writting-a-compiler-1/</link>
      <pubDate>Fri, 01 Oct 2021 22:12:37 +0000</pubDate>
      <guid>https://sfclub.cc/~icybear/posts/writting-a-compiler-1/</guid>
      <description>&lt;p&gt;近日一屑高二学生无聊动手写起了编译器&amp;hellip;.这是他的珍贵作战记录&lt;/p&gt;
&lt;h1 id=&#34;0x01-理论基础&#34;&gt;0x01 理论基础&lt;/h1&gt;
&lt;p&gt;我摊牌，我没有看任何编译原理相关的书籍，因此这篇文章并不能作为严格的参考资料，甚至很多地方可能是错误的。&lt;/p&gt;
&lt;p&gt;编译器，编译器，就是把高级语言的代码编译成另一种形式（class，asm，二进制，IR），而他在编译成另一种形式之前大概需要过这么个流程:&lt;/p&gt;
&lt;p&gt;Lex -&amp;gt; Parse -&amp;gt; Compile&lt;/p&gt;
&lt;p&gt;接下来逐步讲解这个过程。&lt;/p&gt;
&lt;h2 id=&#34;lexer&#34;&gt;Lexer&lt;/h2&gt;
&lt;p&gt;就是分词器，输入用户提供的代码接着把他分成 &lt;code&gt;tokens&lt;/code&gt;，也就是 &lt;code&gt;tokenstream&lt;/code&gt;。&lt;br&gt;
你肯定看不懂上面那句话的意思，让我们来点实例：&lt;br&gt;
&lt;img alt=&#34;image&#34; loading=&#34;lazy&#34; src=&#34;https://i.ibb.co/7rHNypx/image.png&#34;&gt;&lt;br&gt;
&lt;code&gt;a.value&lt;/code&gt; 里的那个 &lt;code&gt;ArrayList&lt;/code&gt; 就是一个 &lt;code&gt;token stream&lt;/code&gt;，&lt;code&gt;str&lt;/code&gt; 是被解析的代码。不难发现，语句被 Lexer 按顺序进行了分类以及数据的分割，如 &lt;code&gt;a&lt;/code&gt; 被识别为了一个 &lt;code&gt;Identify&lt;/code&gt; (标记)。&lt;/p&gt;
&lt;p&gt;因此也可以归纳出来 &lt;code&gt;Token&lt;/code&gt; 大致的代码长啥样：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#61afef&#34;&gt;@AllArgsConstructor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#61afef&#34;&gt;@Getter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c678dd&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#c678dd&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#e5c07b&#34;&gt;Token&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c678dd&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#e5c07b&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;line&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c678dd&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;Type&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;type&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#c678dd&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;String&lt;/span&gt; &lt;span style=&#34;color:#e06c75&#34;&gt;content&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;parser&#34;&gt;Parser&lt;/h2&gt;
&lt;p&gt;Lexer 从源码中提取出 &lt;code&gt;token stream&lt;/code&gt; 后将会交给 &lt;code&gt;Parser&lt;/code&gt; 处理，它负责对 &lt;code&gt;token stream&lt;/code&gt; 进行解析，生成一个 &lt;code&gt;AST (Abstract Syntax Tree)&lt;/code&gt;，也就是 &lt;code&gt;抽象语法树&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://i.ibb.co/7rHNypx/image.png&#34;&gt;&lt;br&gt;
这张图直观的描述了这一过程，你可以看到它以树状的形式表现编程语言的语法结构，树上的每个节点都表示源代码中的一种结构。之所以说语法是“抽象”的，是因为这里的语法并不会表示出真实语法中出现的每个细节。&lt;/p&gt;
&lt;p&gt;接着，AST 将会丢给代码生成器用于生成代码，但是一般会先对 AST 进行优化，例如 &lt;code&gt;常量折叠&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;static-analyzing&#34;&gt;Static Analyzing&lt;/h2&gt;
&lt;p&gt;但在这之前，我们还有一些问题要解决。&lt;br&gt;
&lt;del&gt;其实这玩意我是和 Parser 写一块的&lt;/del&gt;&lt;br&gt;
试想一下，如果有这样一行代码：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
