[讨论] 《自制编程语言》集中讨论帖

RednaxelaFX 2013-12-16
最近,由前橋和弥编写的『プログラミング言語を作る』中文版《自制编程语言》已经上市,相信已经有不少同好拿到手了。


(图片源自图灵社区

HLLVM群组这边也欢迎讨论此书。集中在这帖讨论吧~
@faicm开了个非官方QQ讨论群讨论本书:126629972
<- 不过我与原作者一样更推荐大家在公开论坛里讨论,互相帮助共同进步。
前橋和弥 写道
お願い:
この文書にウソ、間違い、誤解を招く表現などを見つけられた方は、 ぜひ掲示板の方にご連絡願います。 「確かにそれでもできるけど、その実装はアホだろ」というご指摘も歓迎いたします。
私は言語処理系が専門というわけではないので、 結構変なことをやってる可能性もあります…
また、このページに関していただいたご意見・ご質問・ご感想等は、 公開することがありますのであらかじめご承知おきください。
反論があるようでしたら、オープンな場で議論すべきだと思いますし、 同じ疑問を持っている人が他にもいるかもしれないからです。


中文版的翻译在首次印刷版中有些不足之处, 目前出版社与译者已经在跟进,应该能在后面重印的时候修正过来。已经购买首次印刷版的同学也不用担心,会有对应的勘误表的。有消息我也会在这帖更新。

==================================

本楼目录

1楼:我的简要书评
2楼:关于配套代码的构建
3楼:备用楼

==================================

相关链接

本书官方网站:http://kmaebashi.com/programmer/devlang/book/index.html 配套源码可在此下载
(中文版:http://avnpc.com/pages/devlang 配套源码的部分中文翻译版可在此下载。有介绍配套代码在Windows上的构建方法)
原Web连载:http://kmaebashi.com/programmer/devlang/
图灵社区:http://www.ituring.com.cn/book/1159

我以前推荐过本书的帖:[真相帖] 书堆-20100327
引用
Crowbar,动态类型、支持嵌套函数/匿名函数/闭包的语言,有标记-清除式的GC,后期加入正则表达式支持,类似JavaScript。解释器是树遍历式的。
Diksam,静态类型的面向对象语言,与Java/C#类似。同样有标记-清除式GC。解释器是字节码解释器,字节码指令集很大程度上参考了JVM的。

我以前玩crowbar的帖:编译crowbar 0.4.02 (在Windows上构建2008年时的crowbar⋯)
我的吐槽帖:http://kmaebashi.com/bbs/thread.php?boardid=kmaebashibbs&from=1878&range=1
豆列:高级语言解释器相关的入门级读物 http://book.douban.com/doulist/2529382/
豆列:从表到里学习JVM实现 http://book.douban.com/doulist/2545443/
RednaxelaFX 2013-12-19
我的简要书评

一点历史

几年前日本流行过一段时间「俺言語」「オレオレ言語」「OreScript」(自制语言)潮。Ruby作为编程语言的成功普及对这个潮流有很大推动作用。本书便是在此背景下诞生的。

作者之前就对C、Java等语言挺熟悉的,写过几本书,也一直有意愿写本实现编程语言的书。后来看到这本之后大概更加觉得应该自己出马了吧

虽然这本书不是我写的,也不是我翻译的,但我对它还是颇有感情。某种意义上说,我对引进这本书也有一点责任感。大概是2007年底或者2008年初,我应该是在看Lightweight Language Spirit 2007的资料时留意到原本作者还在自己的主页Hatena上Web连载自制编程语言系列的文章。当时我就有跟着读,觉得作者能一步步把语言功能都实现出来挺好的。

光读文章不动手练练也没用,所以我也有把这系列配套的代码编译出来把玩。当然,这系列两种语言的实现都只是入门级,边把玩边能找出很多可以改进的地方,可以在上面做各种实验做优化或添加功能,也挺好玩的。

后来作者把整个系列整理成书,我也就赶紧买了一本以表支持。

然后断断续续有试着把这本书推荐给国内的出版社看看有没有机会引进,终于图灵接了下来,我也觉得挺欣慰的。虽然最终结果上来说我会期待能翻译得更好一些⋯呃呵呵。

本书定位

本书明确定位为一本入门书,面向的读者群是没有实现过编程语言、对编译原理不熟悉,但又对此感兴趣、想学习这方面知识的人。
在此定位之上,我相当推荐本书作为入门的第一本书,学习实现编程语言相关的基本知识点。同时自己动手使用配套代码做实验,观察和感受实际程序的运行,并尝试自己动手修改和增强其实现代码。

光读这本书还只是挠了挠痒痒,读了觉得还没吃饱那就对了,上道了
后续还想进一步学习的话,可以再读些经典书籍,例如:在编译原理方面可以读虎书龙书;特定于语法分析方面可以读Parsing Techniques;在GC方面可以读GC手册,等等。

既然已有那么多经典书,为什么我还要推荐从这本开始,而不是直接去读那些经典书呢?
我一直觉得在入门阶段能够有实际可运行的、小规模简单的实现作为参考,对学习有很大帮助。本书正好提供了充分的范例代码来让读者把玩。

相比之下,
* 虎书还好,言简意赅但一路有范例代码,但它的C版代码写得像Java一样、Java版代码写得像C一样,ML版虽然很赞又可能有很多人看不懂⋯
* 龙书只有第二章对应有编译器前段的范例代码,后面大部分内容都比较抽象,用这本书来入门恐怕会觉得像撞墙一样;
* GC手册直接啥范例代码都没有,只有理论⋯

而从知识面来看,本书也比较出色。本书循序渐进、由浅到深地讲解了丰富的基础知识,不但覆盖了常见的编译原理入门,更难能可贵的覆盖了许多运行时支持系统(runtime system)的知识,特别是对象、虚方法分派、闭包、异常、GC等。对这些知识点好奇的读者至少能通过本书了解到相应的基础概念以及入门级实现是怎样的。
与此相比,其它一些同类入门书通常只覆盖到编译原理入门,外加只支持数字、字符串等原始类型的解释器,而没有覆盖前面提到的运行时支持系统的知识点。

从语言设计看,本书的两个范例语言,crowbar可以看作是简化的JavaScript(没有实现原型继承), 而Diksam可以看作是基本版的Java,在入门范例语言中已经算不那么玩具的了。两者都与热门语言沾边,正好迎合了一些同学想窥探热门语言的实现、但苦于没有足够知识基础的学习需求。

从实际实现看,crowbar与Diksam都确实相当的入门级:结构简单,功能基本正确(配套代码有少量问题),性能嘛⋯就呵呵了。
但还别说,现实中许多大名鼎鼎的编程语言的实现也没好到哪儿去。早期JavaScript引擎中,像JavaScriptCore的早期版及其前身的KJS都使用树遍历解释器,跟crowbar的相似。这些引擎中使用最弱的形态的discriminated union来实现值表现形式(value representation)也跟crowbar的做法相似。而某些早期JVM的内部实现也跟Diksam的许多部分颇为相似。有了本书的基础,再去了解实际生活中可以见到的基于解释器的编程语言实现就会轻松许多。

稍有基础的读者读了可能会觉得不过瘾,因为想进阶阅读的知识在这本书里很难找到:更完善的语法分析器、高性能的解释器、高性能的对象系统和GC、JIT编译器等等,所以可能会对本书有所不满。但这本书本来就不是进阶读物而是入门读物,如果有同学仔细阅读完还觉得不过瘾的话,那您的水平应该已经超过这本书的目标读者群,该去读点重量级一点的书了。

P.S. 作为JVM从业者,我也不隐瞒我推荐这本书有私心:有这么一本书介绍了各种知识点的基本概念和简易实现,我就不用总是费那么多事去讲解;而没比较就没有进步,知道简易实现是怎样的之后会更有动力追求高效的实现,这样我就可以有更多同行了

P.S.S. 这本书的配套代码实现有些微妙的bug,如果读完整本书都没觉得有bug的话你可能就中招了⋯欢迎找茬~
RednaxelaFX 2013-12-19
关于配套代码的构建

我在Mac OS X上build过crowbar_book_0_4,用的是原版的UTF-8编码的版本。需要做下述修改才可以构建。构建时直接执行make就好了。
我在Mac上用MacPorts来装各种库和工具,鬼车也是用port装的。这些东西安装后都在/opt/local/下,所以需要相应在INCLUDES和LIBS里添加路径才编译得了。

diff --git a/Makefile b/Makefile
index afcfc3a..e9a59c3 100644
--- a/Makefile
+++ b/Makefile
@@ -27,15 +27,18 @@ BUILTINS = \
 CFLAGS = -c -g -Wall -Wswitch-enum -ansi -pedantic -DDEBUG -DUTF_8_SOURCE
 
 INCLUDES = \
-  -I/usr/local/include
+  -I/usr/local/include -I/opt/local/include
+
+LIBS = \
+  -L/opt/local/lib
 
 $(TARGET):$(MINICROWBAR) $(FINALOBJS)
 	cd ./memory; $(MAKE);
 	cd ./debug; $(MAKE);
-	$(CC) $(FINALOBJS) -o $@ -lm -lonig
+	$(CC) $(LIBS) $(FINALOBJS) -o $@ -lm -lonig
 
 $(MINICROWBAR):$(MINIOBJS)
-	$(CC) $(MINIOBJS) -o $@ -lm -lonig
+	$(CC) $(LIBS) $(MINIOBJS) -o $@ -lm -lonig
 
 clean:
 	rm -f *.o lex.yy.c y.tab.c y.tab.h *~
@@ -46,15 +49,15 @@ y.tab.c : crowbar.y
 lex.yy.c : crowbar.l crowbar.y y.tab.h
 	lex crowbar.l
 y.tab.o: y.tab.c crowbar.h MEM.h
-	$(CC) -c -g $*.c $(INCLUDES)
+	$(CC) -c -g $*.c $(INCLUDES) $(LIBS)
 lex.yy.o: lex.yy.c crowbar.h MEM.h
-	$(CC) -c -g $*.c $(INCLUDES)
+	$(CC) -c -g $*.c $(INCLUDES) $(LIBS)
 .c.o:
-	$(CC) $(CFLAGS) $*.c $(INCLUDES)
+	$(CC) $(CFLAGS) $*.c $(INCLUDES) $(LIBS)
 miniinterface.o: interface.c
-	$(CC) $(CFLAGS) -DMINICROWBAR -o $@ interface.c $(INCLUDES)
+	$(CC) $(CFLAGS) -DMINICROWBAR -o $@ interface.c $(INCLUDES) $(LIBS)
 interface.o:
-	$(CC) $(CFLAGS) -o $@ interface.c $(INCLUDES)
+	$(CC) $(CFLAGS) -o $@ interface.c $(INCLUDES) $(LIBS)
 builtin.c: ./builtin/builtin.crb
 	cd ./builtin; ../$(MINICROWBAR) conv.crb $(BUILTINS)
 


==================================

至于在Windows上的构建,请参考本书的中文版支持页面:http://avnpc.com/pages/devlang

其实crowbar和Diksam的代码本身并没特别用到只能用GCC才可以编译的功能,在Windows上本来可以直接用Visual C++来编译的。flexbison也不需要MinGW就可以用。鬼车也可以用VC++来编译。只是作者比较懒,没写Visual Studio的project和solution file而已。谁有Windows和VS的话来写个就好了,用Windows的读者就不用折腾半天装各种东西⋯MinGW和Cygwin都要装的话实在麻烦。
RednaxelaFX 2013-12-19
先在多占一楼备用。欢迎大家在回帖讨论书中问题
Willam2004 2013-12-19
有时间一定要看看。
vavi 2013-12-19
多谢R大推荐这本书,我也买了本,目前看到了3.3个章节。说下我现在的感觉。

前面的计算器例子都反复debug了好几遍,基本能够理解。

但是在3.3章节时,大量代码涌入,感觉有点消化不了。

请问是不是C基础太弱了?

PS1:为了看这本书,目前又把K&R,C for Java Programmer 和征服C指针(暂时没看完)看了下,等后续有空再继续看 自制编程语言。

PS2:当时看那个计算器例子了,感觉写得很好;然后去查阅了龙书,也基本看懂了例子背后的理论。但是看到NFA,子集构造算法时,又卡壳了。请问怎么破。。。

PS3: crowbar的词法和语法分析器如果都是作者手写的话,那该多好啊,这样便于循序渐进学习。
庄表伟 2013-12-19
引用
其实crowbar和Diksam的代码本身并没特别用到只能用GCC才可以编译的功能,在Windows上本来可以直接用Visual C++来编译的。


早点看到你这个帖子就好了,我在 Windows 下面弄 MinGW+MSYS,弄到欲生欲死...总算是搞出来了。
RednaxelaFX 2013-12-19
庄表伟 写道
引用
其实crowbar和Diksam的代码本身并没特别用到只能用GCC才可以编译的功能,在Windows上本来可以直接用Visual C++来编译的。

早点看到你这个帖子就好了,我在 Windows 下面弄 MinGW+MSYS,弄到欲生欲死...总算是搞出来了。

噗,你的痛苦我完全理解

我现在很少用Windows机器了而且没装VS,谁有装的话要是能做个VS的project/solution file出来大家就都可以少点麻烦了。这玩儿用免费的Visual Studio Express应该足矣。
RednaxelaFX 2013-12-19
vavi 写道
但是在3.3章节时,大量代码涌入,感觉有点消化不了。

请问是不是C基础太弱了?

我倒是读到3.3开始看到实际的核心数据结构的定义时有安心感⋯
如果以前对Java更了解的话把那些struct声明看作Java类的实例变量就好了呗?应该不算难懂?
可能作者大量使用了discriminated union让你不习惯了。

vavi 写道
PS2:当时看那个计算器例子了,感觉写得很好;然后去查阅了龙书,也基本看懂了例子背后的理论。但是看到NFA,子集构造算法时,又卡壳了。请问怎么破。。。

呵呵呵⋯这个只能慢慢来。多练习练习,画画过程图啥的。

vavi 写道
PS3: crowbar的词法和语法分析器如果都是作者手写的话,那该多好啊,这样便于循序渐进学习。

我的感觉是:如果让我来实现的话我可能也会手写,但作为一本入门书它本来就不希望太深入到编译原理中,用生成器正合适。作者都说了
写道
また、ソースから解析木を作るプログラムのことを「パーサ」 と呼びますが、 CやJavaでは、パーサをある程度自動生成してくれるプログラムが存在します。 有名なのは、Cではyacc, JavaではJavaCCです。 これらを使わずパーサを手書きするのは、勉強にはなるのかもしれませんが、 正直、私はやる気になれません ※2。

※2再帰下降パーサでよければ割と簡単に書けますが、 文法の可読性が低くなりますし、修正も大変ですので。

作者说虽然手写parser或许更有利于学习,但他觉得手写递归下降式parser不利于语法的可读性,而且要改语法的时候也比较麻烦,所以懒得手写。
budao 2014-01-16
在第二章讲到用yacc工具来实现计算器的语法分析器时,作者试图画图来讲解yacc的规约和移进操作,但就我本人而言,作者的讲解极其地苍白无力,我反复看了几遍,也未能看出作者表述的逻辑在哪里,而《Language Implementation Patterns》讲解地显然好得多。
Global site tag (gtag.js) - Google Analytics