Red/System编译器实现分析(1)
来源:互联网 发布:手机如何修改mac地址 编辑:程序博客网 时间:2024/05/06 21:23
距离上一篇文章有一段时间了,之所以迟迟没有动笔,不是因为我太忙,而是我太懒了!嗯,要改,一定要改!
这一篇开始就要对Red编译器实现进行分析了,首先分析的是Red/System编译器的实现,之所以先讲 Red/System,是因为Red的运行时(Runtime)部分会使用Red/System编写,Red编译器生成的中间代码也是Red/System代码,熟悉了Red/System对后面理解Red编译器的实现有很大的好处。
计划以最快的速度完成下面三个主题:1.递归下降语法分析;2.代码生成(x86 code);3.Exe镜像文件的生成(以PE Format为例)。把整个流程打通后,逐步往里面添加内容就比较容易了,类似习武之人打通了任督二脉后的效果。;-) 下图是来自Red官方blog [Red/System compiler overview]。
因为目前Red正处于bootstrap阶段,所以大部分代码是使用Rebol来写的。一旦Red可用,将使用Red来重新实现Red。现阶段Red/System是由Rebol写成的。不熟悉Rebol的同学可移步[Rebol guide],这里就不再赘述。好了,准备好环境,我们就开始吧。
$ git clone https://github.com/red/red.git$ cd red$ git checkout v0.1.0我们使用v0.1.0版本。从简单的开始,弄懂了这个版本之后,以此为基础,通过查看commit来学习,不但容易入门,还有助于理解一些特性的缘由。
这个版本已经是一个可用的编译器了,虽然功能还不完善。查看red目录中的“README”,强烈建议参照里面的步骤,编译一下“hello.reds”。生成的hello.exe只有2.5KB,是不是很小,就算直接用汇编来写,也相差不大吧。
整个项目文件数目很少,每个文件的主要职责如下:
-- compiler.r ; 前端部分,如词法分析,语法分析-- emitter.r ; 代码生成,根据命令行参数,会调用targets目录下相应的代码-- linker.r ; 程序文件的组装,根据命令行参数,会调用formats目录下相应的代码-- rsc.r ; 命令行解析-- formats -- PE.r ; PE 文件格式定义-- targets -- IA32.r ; x86 目标代码生成假设我们要编译的程序如下:
Red/System []a: 1够简单吧,简直可以说是简单到毫无用处。; -) 不过对于我们学习编译器实现来说,是再好不过了。回忆一下,我们的学习都是从最简单的开始的。从1 + 1 = 2到微积分,从一个个汉字到长篇巨著,从单调的音符到绚丽的篇章,无不是由易到难,由简到繁。试了就知道,慢慢来真的会比较快。好了,不扯了,进入正题。
首先词法分析。使用Rebol有一个好处,那就是我们可以不用自己编写词法分析器,Rebol已经为我们做了这部分工作。
>> src: load "Red/System [] a: 1"== [Red/System [] a: 1] ; 已经变成一个个token了>> print src/3== a>> type? src/3== set-word!
实际上compiler.r中在load前还会有一个preprocess的过程,那是因为Red/System中像C一样允许宏定义,而load函数并不支持这个功能。我们的程序很简单,不需要预处理,所以先忽略掉它。token拆分好,该语法分析了,接下来就是有意思的部分了。
因为接下来代码比较多,所以许多分析直接注释在代码中。
compiler/run src; run函数如下run: func [src [block!]][ pc: src ; pc是一个全局变量,指向当前正在分析的token comp-header ; 检查文件头,也就是Red/System [] comp-dialect ; 这个函数是接下来的重点,负责编译我们写的程序 comp-natives ; 编译程序中定义的函数,暂时不讨论,以后回讲。]在进入comp-dialect函数后,
[Red/System [] a: 1] ; 此时pc变量指向的token ↑ pc;-- 再看comp-dialect函数comp-dialect: does [ while [not tail? pc][ case [ issue? pc/1 [comp-directive] find [ set-word! ; pc/1 指向的是 a: word! path! set-path! ] type?/word pc/1 [ fetch-expression/final ; 接下来运行这个函数,注意参数 'final' ] 'else [throw-error 'syntax] ] ]]跟进fetch-expression:
;-- 函数做了简化,去掉暂时不用的代码fetch-expression: func [/final /local expr][ ; ... expr: switch/default type?/word pc/1 [ set-word! [comp-set-word] ; pc/1 指向的是 a: , 类型是set-word! ; 接下来跟进这个函数了 word! [comp-word] integer! [also pc/1 pc: next pc] ; 如果类型是integer!, 直接返回 pc/1 , ; 并且向前移动pc ; ... ][;...] if final [ case [ block? expr [ order-args expr comp-expression expr ] ; ... ] ] expr]comp-set-word: has [name value][ name: pc/1 pc: next pc ; 注意这里向前移动了pc,现在pc指向 1 switch/default pc/1 [ ; 忽略大段代码 ;-) ][ value: fetch-expression ; 又是这个函数,但没有refinement: 'final' ; 同学们自己跟一下,就不细说了。此时 value: 1 new-line/all reduce [name value] no ; 最后返回 [a: 1] ]]
分析到这里,整个函数调用链如下:
当函数 ‘comp-set-word’ 运行结束,返回到函数 ‘fetch-expression’ 时,由于设置了Refinement ‘final’,所以函数 ‘fetch-expression’ 中会运行下面的代码:; 只涉及到三个函数comp-dialect --> fetch-expression/final --> comp-set-word --> fetch-expression
fetch-expression: func [/final /local expr][ ; ... expr: switch/default type?/word pc/1 [ set-word! [comp-set-word] ; comp-set-word 返回 word! [comp-word] integer! [also pc/1 pc: next pc] ; ... ][;...] ; 此时 expr: [a: 1] if final [ ; final 为 true case [ block? expr [ ; ... comp-expression expr ; 整个表达式搜集完成,开始编译! ] ; ... ] ] expr]从函数名字就可以看出,fetch-expression负责获取表达式,搜集相关的信息。comp-expression负责根据这些信息将表达式编译成机器码。至于怎么编译成机器码,请看下回分解。
- Red/System编译器实现分析(1)
- Red/System编译器实现分析(2)
- Red/System编译器实现分析(3)
- Red编译器阅读笔记(1)
- Red编译器阅读笔记(2)
- 大二的时候的一个小项目---实现四则运算的逻辑分析实现(小型编译器)
- LCC编译器的源程序分析(1)C编译器的目标
- LCC编译器的源程序分析(1)C编译器的目标
- JAVA实现一个简单的代数运算语言编译器(二)--词法分析准备
- JAVA实现一个简单的代数运算语言编译器(三)--词法分析
- Red语言入门(1)—— 为什么是Red?
- 编译器的设计与实现(1)-编译器的组成
- 手工打造编译器之词法分析1
- 手工打造编译器之语义分析1
- hive源码结构分析(编译器)
- hive源码结构分析(编译器)
- 编译器-语法分析(预测分析表法)
- ARMCC编译器优化分析(一)
- PHP的WebServices实现
- 简单的Linux脚本程序
- springmvc
- 查找文件中包含某个字符串的行并将所有满足条件行输出到新文件使用命令
- 几个网址
- Red/System编译器实现分析(1)
- [读PAPER]Online Unsupervised Feature Learning for Visual Tracking
- PHP 设置 Session Cookie 过期
- Linux rpm 命令参数使用详解[介绍和应用]【转载】
- linux下的shell 快捷键
- 关于SIO_RCVALL
- 产品收费、产品流程图
- oracle出异常:Io 异常: The Network Adapter could not establish the connection 解决办法
- PhoneGap 3.0 新建项目