PL真有意思(一):引言
前言
断断续续学编译原理到之前发过写一个编译器和正则表达式引擎系列文章也有一段时间了,然后最近看完PLP这本书,这本书应该算是入门书,但是对我这种半吊子收获很大。所以为了弥补最近学操作系统和接外包摸的鱼,就想写写看完这本书的收获。(为拙劣的标题道歉
程序设计语言的谱系
现在的新语言都是一撮一撮的出来,但是基本都可以用他们的计算模型来分成两类,一类是更关心计算机做什么的说明式,一类是更关心计算机怎么做的命令式
一般认为像函数式逻辑式语言都算是说明式,而冯诺依曼式和面向对象的都被认为是命令式
函数式
函数式是基于函数的递归定义的计算模型,一般从本质上来看,函数式把程序认为是一种从输入到输出的函数,使用更简单的函数通过逐步细化的过程来定义
逻辑式
逻辑式里经典的应该就是Prolog了,逻辑式一般将计算看作是一种找出满足某些特定关系的值的尝试过程
冯诺依曼式
冯诺依曼式最重要的就是通过副作用也就是修改寄存器里的值来对后续计算产生影响,像C和Fortran都属于冯诺依曼式
几个例子
如果C语言来实现求最大公约数,可以发现C语言偏向通过迭代和反复修改变量的值来实现
int gcd(int a, intb) {
while (a != b) {
if (a > b) {
a = a - b;
} else {
b = b - a;
}
}
}
从lisp来看,则更加关注输入和输出的数学关系,要算出最大公约数,需要对函数的不断的扩充和精简
(define gcd
(lambda (a b)
(cond ((= a b) a)
((> a b) (gcd (- a b) b))
(else (gcd (- b a) a)))))
对于像C或者Java入门的人,看到Prolog可能头都大了,因为Prolog和命令式的思考逻辑完全不同,逻辑式更倾向给出一组公理和检测规则,期望系统能给出相应合理的值,我也仅限于能看懂这些小程序
gcd(A,B,G) :- A = B, G = A.
gcd(A,B,G) :- A > B, C is A - B, gcd(C,B,G)
gcd(A,B,G) :- B > A, C is B-A
gcd(C,A,G)
编译和解释
下面再看两个概念,编译和解释。
编译一般是指从一个语言到另一个语言的翻译,无论是高级语言到汇编还是高级语言到高级语言都算是编译。而解释就是直接执行代码,但是现代的解释器,一般还有虚拟机一层,即翻译到虚拟机指令再由虚拟机进行执行
自举
很多语言的编译器都是由自己编译而成的,所以问题就是,最开始的编译器是怎么编译的?
假设现在要为Java编写一个编译器,我们可以先用C语言编写一个Java小子集的编译器,然后再手动将C语言翻译到这个Java子集,就可以由这个子集编译运行自己,然后就可以不断扩充这个编译器
编译概览
其实这个在之前那个写编译器的系列是说得最详细的,这个系列是想要写写笔记对实践和语言设计结合的说。
词法分析
有关词法分析其实就是将字符流化成单词流,记录每个单词的信息,然后通常还会有其它更多的信息让编译器更好的生成错误信息
语法分析
语法分析通常会用到一个概念:上下文无关文法,就是用来定义语法形式的,比如while语句就可以这样表示
while-statment := WHILE ( expr ) statment
一般语法分析过程最后的输出都是树状结构
语义分析和中间代码生成
语法分析只保证源代码语法格式的正确,但是却不能保证其它的正确性,比如对于静态类型的语言,可能就会在编译时直接检测出类型错误
而在语义分析过程一般还需要借助一个叫做符号表的数据结构,这个符号表将每个标识符都映射到关于它的已知信息
中间代码的生成通常是会将树形结构翻译成更接近汇编的中间线性格式,但是中间格式不是必须的,比如之前那个系列里还写了C的解释器,虽然很残缺,它是没有中间代码的,连虚拟机都没有,是直接进行遍历语法树进行执行解释的
代码优化
有些代码改进是机器无关的,即可以在中间格式上就进行优化,但是有的代码优化是平台相关的,所以就需要在最后对目标语言优化
目标代码生成
代码生成阶段就是根据之前生成的线性结构和符号表信息对目标代码的生成
小结
这一篇主要说了几个范式的语言和编译过程的概括,对摸鱼进行忏悔
PL真有意思(一):引言的更多相关文章
- PL真有意思(四):控制流
前言 对大多数计算模型而言,顺序都是基本的东西,它确定了为完成所期望的某种工作,什么事情应该最先做,什么事应该随后做,我们可以将语言规定顺序的机制分为几个类别: 顺序执行 选择 迭代 过程抽象 递归 ...
- PL真有意思(二):程序设计语言语法
前言 虽然标题是程序语言的语法,但是讲的是对词法和语法的解析,其实关于这个前面那个写编译器系列的描述会更清楚,有关语言语法的部分应该是穿插在整个设计当中的,也看语言设计者的心情了 和英语汉语这些自然语 ...
- PL真有意思(三):名字、作用域和约束
前言 这两篇写了词法分析和语法分析,比较偏向实践.这一篇来看一下语言设计里一个比较重要的部分:名字.在大部分语言里,名字就是标识符,如果从抽象层面来看名字就是对更低一级的内存之类的概念的一层抽象.但是 ...
- PL真有意思(五):数据类型
前言 现在大多数程序设计语言中都有表达式和/或对象的类型概念.类型起着两种主要作用: 为许多操作提供了隐含的上下文信息,使程序员可以在许多情况下不必显示的描述这种上下文.比如int类型的两个对象相加就 ...
- PL真有意思(六):子程序和控制抽象
前言 在之前我们把抽象定义为一种过程,程序员可以通过它将一个名字与一段可能很复杂的程序片段关联起来.抽象最大的意义就在于,我们可以从功能和用途的角度来考虑它,而不是实现. 在大多数程序设计语言中,子程 ...
- PL真有意思(七):数据抽象和面向对象
前言 在之前的名字.作用域那篇提到模块类型,它使程序员可以从一个给定抽象出发,通过实例化产生多个实例:再后面是类,它使程序员可以定义一族相关的抽象. 在这一篇里,我们会来看一下面向对象程序设计及其三个 ...
- PL真有意思(八):其它程序设计模型
前言 在之前几篇我们讨论的语法.语义.命名.类型和抽象适用于所有语言.然而我们的注意力都主要集中在命令式语言上,现在这篇来看看其它范式的语言.函数式和逻辑式语言是最主要的非命令式语言. 函数式语言 命 ...
- R统计软件真有意思哈,以后我怕要用得着,先自学
呵呵,作数据分析是数据监控后的动作. 思路是用监控系统产生数据, 如果监控本身提供统计最好,如果不提供,则可以用R来作分析统计和预测. 如果数据不符合规范,则用PYTHON进行处理转换. ~~~~~~ ...
- 悟透JavaScript
要理解JavaScript,你得首先放下对象和类的概念,回到数据和代码的本原.前面说过,编程世界只有数据和代码两种基本元素,而这两种元素又有着纠缠不清的关系.JavaScript就是把数据和代码都简化 ...
随机推荐
- libevent环境搭建
环境 VS2017.ubuntu16.04 官网网址:http://www.linuxfromscratch.org/blfs/view/svn/basicnet/libevent.html 下载 ...
- C#刷遍Leetcode面试题系列连载(5):No.593 - 有效的正方形
上一篇 LeetCode 面试题中,我们分析了一道难度为 Easy 的数学题 - 自除数,提供了两种方法.今天我们来分析一道难度为 Medium 的面试题. 今天要给大家分析的面试题是 LeetCod ...
- 基于SkyWalking的分布式跟踪系统 - 环境搭建
前面的几篇文章我们聊了基于Metrics的监控Prometheus,利用Prometheus和Grafana可以全方位监控你的服务器及应用的性能指标,在出现异常时利用Alertmanager告警及时通 ...
- Centos中查找文件、目录、内容
1.查找文件 find / -name 'filename' 2.查找文件夹(目录) find / -name 'path' -type d 3.查找内容 find . | xargs grep -r ...
- codeforce - 13A A.Numbers
A. Numbers time limit per test 1 second memory limit per test 64 megabytes input standard input outp ...
- 5.分析snkrs的Android的DeviceID生产规则
分析Android的DeviceID生产 前面已经把web端的分析了一些,要想实现其实容易也难,容易是规则很容易,难是时间生成控制很难,我之前大概花了一周时间分析和梳理,然后行为测试,之前我已经讲过c ...
- Veins(车载通信仿真框架)入门教程(三)——多跳路由实现指导
Veins(车载通信仿真框架)入门教程(三)——多跳路由实现指导 Veins(车载通信仿真框架)入门教程(三)——多跳路由实现指导 必要的message类实现 从下面开始是在veins/src/vei ...
- iOS Undefined ..Arm64问题解决
Undefined symbols for architecture arm64 此问题由一下集中解决办法: 1)如果是引用第三方库导致则把第三方库删除重新添加一下,若果不行在添加如下几个依赖库 如 ...
- hystrix原理
一.hystrix 产生背景 微服务是解决复杂服务的一个方案,在功能不变的情况下,对一个复杂的单体服务分解为多个可管理的分支.每个服务作为轻量的子服务,通过RPC实现服务间的关联,将服务简单化.每个服 ...
- SpringCloud之Feign负载均衡(四)
整合Feign pom.xml <dependency> <groupId>org.springframework.cloud</groupId> <arti ...