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就是把数据和代码都简化 ...
随机推荐
- django报错问题解决
注意以下修改文件均是修改虚拟python环境中的文件 1.执行(venv) E:\myproj\autotest>python manage.py makemigrations报错: 解决办法: ...
- JavaWeb 如何防止表单重复提交 - 使用Token,令牌
JavaWeb 如何防止表单重复提交 - 使用Token,令牌 说到重复提交 ,应该想到两种场景:1. 在下单,或者支付 这种情况 那么不允许 刷新,不允许后退再点击提交(后退之后提交会失败,修改了 ...
- 基于SEER的区块链版赛亚麻将游戏Pre alpha版本内测啦!
游戏基于SEER测试网络文体平台模块(Culture and Sports Platform,CSP),正在进行数据调试等工作,大家可以尝鲜体验. 此游戏账户和资金等核心系统完全基于区块链,但目前运行 ...
- 使用IDEA开发Spark程序
一.分布式估算圆周率 1.计算原理 假设正方形的面积S等于x²,而正方形的内切圆的面积C等于Pi×(x/2)²,因此圆面积与正方形面积之比C/S就为Pi/4,于是就有Pi=4×C/S. 可以利用计算机 ...
- django-表单之模型表单渲染(六)
class StudentForms(forms.ModelForm): formats=[ '%Y-%m-%d', '%m/%d/%Y', ] birthday = forms.DateField( ...
- fenby C语言 P6
printf=格式输出函数; printf=("两个相加的数字是:%d,%d,他们的和是:%d\n",a,b,c); %d整数方式输出; \n=Enter; int a=1; fl ...
- Linux进程组和会话
Linux的进程相互之间有一定的关系.比如说,在Linux进程基础中,我们看到,每个进程都有父进程,而所有的进程以init进程为根,形成一个树状结构.我们在这里讲解进程组和会话,以便以更加丰富的方式了 ...
- Django实现WebSSH操作物理机或虚拟机
我想用它替换掉xshell.crt之类的工具 WebSSH操作物理机或虚拟机 Django实现WebSSH操作Kubernetes Pod文章发布后,有小伙伴说咖啡哥,我们现在还没有用上Kuberne ...
- Netty 入门,这一篇文章就够了
Netty是Java领域有名的开源网络库,特点是高性能和高扩展性,因此很多流行的框架都是基于它来构建的,比如我们熟知的Dubbo.Rocketmq.Hadoop等,针对高性能RPC,一般都是基于Net ...
- IDEA 使用lombok
一.配置maven <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback ...