在编译原理中,最难的步骤应该是代码的优化。只有通过不停的优化代码才能得到更好的性能,而性能又是商业编译器的重要指标。这一切就注定了码优化是一个没有止境的过程。但是对于不争早夕的初级语言来说,这一步骤就显得可有可无,因为有足够的时间让我去等待一个结果的出现。就像我花了很长很长的时间去等待斐波那契第30个结果的出现,而一个经过优化的编译器能在很短的时间内完成计算。
    除了代码的优化,中间语言的生成好像也是一根难啃的骨头。Snail Language的最终目标是成为一款.NET语言,所以将自己编译成CIL的过程也在所难免。在我实现编译器之前,我对中间语言生成的步骤一直处于雾里看花终隔一层。但随着实践的深入,有一朝我突然顿悟:将snail language翻译成CIL,其实就是用CIL实现当前的语义;和将snail language翻译成java、C的过程是一致的;翻译的过程不存在一个标准的教程,好坏都凭作者对语言的理解能力和写代码的功力。于是乎,我开始了自己的试验。

我的目标是翻译Snail Language的一小段特定的代码到CIL。(目前的release版本只支持下面片段)

Snail Language:

if(1 < 2)
{print(100)
}

我们用TR()函数对表达式进行翻译,TR函数有两个重载TR(node)和TR("string"),一个对节点进行递归操作,如果当前node是一个终结符,就调用字符串求值。

分析过程如下:

  1. 如果是 if 表达,肯定有一个跳转语句,语句有两部分组成ifnode和跳转标签IFLabel:TR(ifnode) + TR("IFEnd");
  2. ifnode由两部分组成,括号表达式和块表达式:TR(parent_expr) + TR(Block_expr);
  3. parent_expr:TR(Number1) + TR(Opt) + TR(Number2)。由于在汇编中两个操作符必须先压栈,然后调用操作符。所有表达式的过程如下:
  4. parent_expr:TR(Number1) + TR(Number2) + TR(Opt)。现在例子中的数据为TR(1) + TR(2) + TR("<")。
  5. 1和2是操作数需要压栈:TR("ldc.i4 1") + TR("ldc.i4 2") + TR("bgt IFLabel")。这一步表示对两个操作数压栈,然后进行比较:如果number1 > number2,则不执行Block_expr,直接跳转到ifnode的结尾,也就是IFLabel。
  6. 对print表达式,也要做节点求值顺序的变换:TR(number) + TR(printnode)。我们知道print的操作数为int,所以就用call void[mscorlib]System.Console::WriteLine(int32)替换print语句。

得到的CIL结果:

ldc.i4 1
ldc.i4 2
bgt IFEnd
ldc.i4 100
call void [mscorlib]System.Console::WriteLine(int32)
IFEnd:

验证结果:

将上面的CIL片段,放入CIL文件中。

.assembly extern mscorlib {}
.assembly Test{.ver 1:0:1:0}
.module test.exe.method static void main() cil managed
{.maxstack 3.entrypointldc.i4 1ldc.i4 2bgt IFEndldc.i4 100call void [mscorlib]System.Console::WriteLine(int32)
IFEnd:Exit:ret
}

执行CIL:

我们用ilasm.exe编译Snail Language生成的CIL。ilasm是一个MS提供的可执行文件,用于将CIL文件编译成exe文件。实验结果和我们预期的一致。

  • > ilasm test.il
  • > test.exe
  • ==> 100

两种实现方案:

将Snail Language编译成CIL,有两种可选的方案。第一:将Snail用上述的方式打包成exe文件。第二,对于生成的CIL文件,我们不直接打包成exe,而是用snail从新解析执行CIL,得到运行结果。第一种方案完全依赖于.NET runtime,而不需要自己去解析代码的逻辑。第二种方案比较灵活,以后可以进一步脱离.NET,实现自己的虚拟机。

软件下载:

http://download.csdn.net/detail/u012813593/6844057

选择生成中间语言:菜单 -> 编译 -> 中间语言(打勾)

测试代码:

if(1 < 2)
{print(1)
}
else if (2 < 3)
{print(3)
}
else
{print(4)
}

结果:

ldc.i4 1
ldc.i4 2
bgt IfEnd1
ldc.i4 1
call void [mscorlib]System.Console::WriteLine(int32)
br ElseEnd1
IfEnd1:
ldc.i4 2
ldc.i4 3
bgt IfEnd2
ldc.i4 3
call void [mscorlib]System.Console::WriteLine(int32)
br ElseEnd2
IfEnd2:
ldc.i4 4
call void [mscorlib]System.Console::WriteLine(int32)
ElseEnd2:
ElseEnd1:

目前还只有实现上述简单的代码,如果其他代码有bug,请关注后期修改。

开发自己的编程语言(五)—— CIL中间代码的生成相关推荐

  1. iOS 11开发教程(十五)iOS11应用视图的位置和大小

    iOS 11开发教程(十五)iOS11应用视图的位置和大小 当一个视图使用拖动的方式添加到主视图后,它的位置和大小可以使用拖动的方式进行设置,也可以使用尺寸检查器面板中的内容进行设置,如图1.52所示 ...

  2. python开发移动应用_什么是移动应用开发的最佳编程语言?(一)Python?c++?

    什么是移动应用开发的最佳编程语言? 移动应用程序的三种类型: •本机应用程序:这是设备操作系统本机支持的一种编码类型. •混合应用程序:应用程序以一种特定的语言编码,可以轻松地在多个平台上运行. •渐 ...

  3. Windows驱动开发学习笔记(五)—— SSDT HOOK

    Windows驱动开发学习笔记(五)-- SSDT HOOK 系统服务表 系统服务描述符表 实验一:通过代码获取SSDT表地址 通过页表基址修改页属性 方法1:修改页属性 方法2:修改CR0寄存器 实 ...

  4. SAP UI5 应用开发教程之五十五 - 如何将本地 SAP UI5 应用通过 Node.js Express 部署到公网上试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  5. SAP UI5 应用开发教程之五十五 - 如何将本地 SAP UI5 应用通过 Node.js Express 部署到公网上

    本教程迄今为止的前 54 个步骤,开发出来的 SAP UI5 应用都只能在本地通过 localhost 访问,除非将其部署到 ABAP 服务器上. SAP UI5 应用开发教程之三十五 - 如何把本地 ...

  6. SAP UI5 应用开发教程之四十五 - 如何在 SAP UI5 应用里使用 jQuery 和原生的 DOM API

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  7. SAP UI5 应用开发教程之三十五 - 如何把本地开发的 SAP UI5 应用部署到 ABAP 服务器上试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  8. 使用IntelliJ IDEA开发SpringMVC网站(五)博客文章管理

    原文:使用IntelliJ IDEA开发SpringMVC网站(五)博客文章管理 摘要 通过对博客文章的管理,实现外键操作. 目录[-] 八.博客文章管理 1.查看文章 2.添加博客        3 ...

  9. Android开发笔记(九十五)自定义Drawable

    Drawable Bitmap是Android对图像的定义描述,而Drawable则是对图像的展现描述,在View视图中显示图像都是通过Drawable来实现的.其中有关Bitmap的介绍参见< ...

最新文章

  1. F5 BIG-IP 远程代码执行漏洞 CVE-2021-22986 虚拟机上复现
  2. php图形界面框架,python GUI 图形化界面框架的选择
  3. Spring4中的@Value的使用(学习笔记)
  4. IntelliJ idea 中使用Git
  5. 每日一笑 | 程序员千万不能轻易去网吧!
  6. 谷歌浏览器怎么设置字体 chrome默认字体设置方法
  7. 韩媒体:900万人个人信息被非法泄露到中国
  8. 【报告分享】2020年重点行业薪酬趋势指南.pdf(附下载链接)
  9. 苹果Mac移动复制文件效率工具:Yoink
  10. 梦幻手游网页版校验服务器失败,梦幻神域手游服务器验证失败进不去解决办法...
  11. ISSN码和ISBN码的区别
  12. (论文加源码)基于自动编码器和LSTM的脑电情感识别(数据集为DEAP)提取了功率谱密度,并进行了无编码和SVM的对比实验。
  13. 看我们无处安放的青春
  14. EasyExcel学习笔记
  15. k8s技术预研8--深入掌握Kubernetes Service
  16. 2023超好用的Mac清理优化工具CleanMyMacX
  17. mysql reorg_生产数据库性能优化之reorg和表重建
  18. 斗圣传说找不到服务器,斗圣传说三界幻境攻略_斗圣传说三界幻境怎么玩_游戏堡...
  19. matlab读取igs文件,Matlab 等間隔讀取IGS對流層天頂延遲(ZPD)文件
  20. 商城分销商子等级设置介绍

热门文章

  1. table中 点击某一行变色
  2. HTTP中get和post方法的区别
  3. python 打印机控制_python调用打印机
  4. mysql excel 同步数据_mysql导入excel数据
  5. 华为摄像机搜索软件_构建AI新生态,“软件定义”摄像机打造机器智能新捷径...
  6. 《C Prime Plus》(第六版) 第03章 编程练习 7 英寸转换成厘米
  7. 【翻译】开发者体验门户 后台 如何解决Spotify的复杂性问题
  8. 以计算机写一篇作文500字,描写计算机的作文
  9. java实现字符串中的中文繁简转换
  10. 前端基础 CSS 第十一章 使用CSS样式表 特效属性部分 ----暑假学习第九天