2005年12月18日星期日

插件式编程

最近下载了一个软件,Babylon,很著名的翻译软件。

以前一直用金山词霸的。最近因为需要德语的翻译,金山词霸就做不到了,又懒得每次去找代理上线上翻译网站,所以找到了这款软件。这款软件好就好在,他的词库是按照插件的方式和主程序整合到一起,所以只要添加了词库,就等于多了一门语言。而如果想要改进软件本身的功能(如支持通配符,列出所有可查词汇,这在用户记不清词的准确拼写时很有用),只需要修改主程序即可。这样降低了程序模块之间的耦合度,也就增加了程序的灵活性。而且,Babylon 提供词库制作工具,使得用户们能够创造自己的词库,大大增加了软件的生命力。这也是拜开放的架构所赐。

写到这里,我想到了 Eclipse,同样也是一个插件式的 IDE。我本人不使用 Java,所以对 Eclipse 也不是很了解,不过从《程序员》我还是能看出,Eclipse 很成功,原因也是在于它先进的理念和开放的架构。似乎在这个时代,软件只有开放了才会有生命力。

我在想,其实一个计算机系统本身就是一个插件系统,操作系统就是主程序,而用户程序就是符合操作系统提供的接口的子程序。Windows 和 Linux 的不同在于,Windows 的主程序是封闭的,由 Microsoft 来负责维护,而 Linux 就连它的内核都是开放的。程度上的不同决定了软件本身的性质。

但是,正如我在第二段里面所说,“如果想要改进软件本身的功能,只需要修改主程序即可”。问题是,由谁来修改主程序呢?Babylon 可以由 Babylon Ltd. 来改进它,Linux 由谁来改进?Linus?Ecplise 呢?IBM?开源软件最大的特点在于它不是属于某一个人或某一个组织,它属于任何对它感兴趣的人们。那么,如果 10 个人对它感兴趣,那么软件前进的道路就有 10 条,从这点看,原本开源希望的将众人的力量合起来开发软件,反而分散了软件的开发者们,因为大家都没有一个领头羊。我在想,如果 Linux 从一开始就没有什么 Rad Hat,没有 Fedora,而是把这些公司里的人才们合到一块儿去开发 Linux,那么 Linux 还会是现在的样子吗?

我不反对开源的理念,但我觉得,群龙无首是不行的。

2005年12月11日星期日

人与人是不同的

越来越深切地发现,人与人之间的差异是那么的大。从小没有父亲的我,总是很自卑,总认为自己做事的形式和方法比别人的欠缺,没有别人的好。这是潜意识里面的一种感觉,虽然外表随着年龄增大和知识增多,越来越显得自信和骄傲,但心底深处仍然觉得我不如别人,那个虚构的、抽象意义上的人。我总是觉得,随大流,干大多数人干的事情,虽然自己不愿意,但至少会有安全感,至少不会被别人认为是另类。我害怕那种异样的眼光。

不太清楚具体从什么时候开始,我开始感觉到,很多大多数人的所作所为其实根本不适合我,而我就算按照自己的方式做事也不会受到伤害。我逐渐意识到,我长大了,我已经有了保留自己个性的权力了。人与人之间的不同是如此之大,似乎每个人都应该想想自己做每件事是否是出于自愿的。往往,我会羡慕某人是如此的善于交际,现在转念一想,他就是他,这是他的生活方式,不是我的。我,在很长时间里,是一个程序员,一个爱乐人,一个思考者,一个独一无二的组合。

我觉得,现在的我,就像是摆脱了缰绳的马,终于又打开了被父亲的死加上的另一把锁。

2005年12月7日星期三

最近的两点感想

1. 为什么人们总是喜欢家?为什么家总是有着那么一种特殊的吸引力?抛开其他的原因,我想,最重要的是,家常常代表着亲人,友人,熟悉的环境,熟悉的生活。同时,如果家没有了亲人,没有了朋友,那么,家也就失去了大多原来的意义。我想这也可以解释为什么莫扎特对曼海姆的喜爱甚于萨尔茨堡,因为曼海姆人喜欢他,喜欢他的音乐(当然还有韦伯一家),而萨尔茨堡,只有大主教。

2. 女性更大程度上还是一种感性的,如一个朋友说的,男人总是试图从他们自己的角度去理解女性,但结果常常是错误的,而且是不幸的,因为他们没有意识到,他们的理性思考在女性上常常是行不通的。一个女人爱一个男人,可能根本不会去思考这个男人会带给她多少好处,仅仅因为对他有好感,仅仅因为一种冲动。而男人一般首先是想这件事对自己有没有用。当然,不否认也有些女人是很理性的,但是我不会太喜欢这种类型,可能感性本事,不同于男人,才是女人可爱的本质吧。

2005年11月22日星期二

难得的闲暇

今天中午去修自行车。在那里等师傅修的时候,一个人坐在那里,看着那个湖面,那些小草,那个碧蓝的天空,吹着小风,突然想到,现在这样什么都不用去思考、什么都不用去顾虑、完全无所事事的闲暇已经那么得少了。

修车师傅的小孩在那里玩着轮胎,看着他,我想到自己小的时候也是那样,做着现在觉得幼稚无比的事,却能从中找到无比的乐趣,相比起来,现在的我活得真的太累了。再想想以后大学毕业了,需要整天为生活而奔波的日子,似乎小时候的那种闲暇可能只能等到老来才有可能重拾了。说实话,现在的我,确实无法控制自己在有空的时候不去思考计算机的问题,思考生活的问题,我也早已有些厌烦了。

现在,对老人们可能又有了一些新的认识吧,他们走过了几十年的人生道路,经历了各种各样的是非,在老了有机会的时候,选择了自己认为最适合、最喜欢的生活方式,消磨人生的最后时光。好吗?令人羡慕吗?不好吗?不令人羡慕吗?

托福也考完了,虽然感觉作文考砸了,但心底深处还是隐隐约约有一点成就感的,毕竟,自己的英语水平也由此提高了一些。

2005年11月17日星期四

最近的情况

总的来说,虽然没有什么大的变化,但我觉得现在的我总是在逃避,总是告诉自己不喜欢就不要去做,以至于现在的生活变得非常单调和形式化。我不知道这是不是大三学生应该有的特点,至少,我不喜欢这样。

似乎越来越受到广东这个大环境里面的一些思想的影响,虽然这些思想我认为无可厚非,但我个人不喜欢它们。现在,思考自己的时间越来越少了,更多的实在考虑更实际、更世俗的东西。上个星期花了两天去买了一辆破自行车,这周又努力复习托福,可能下周又是泡在宿舍里搞 Linux。这一切我为的是什么?为的就是尽量少去想那些不愿触动的东西,就好像刚失恋或者刚死了亲人的人总是拼命地工作一样。我从来没想过我会变成这样,我也不希望自己变成这样,但看来,人还是很容易受影响的。

现在听音乐更加专注于那几首曲子,巴赫的 BWV 1057(第六钢协?),布鲁克纳第七交响,还有拉赫玛尼诺夫第三钢协。管很久没练过了,给自己找的理由是等托福考完再说。现在想起来,大一那时虽然是最傻的,但也是这么几年里活的最轻松最快乐的,不是学习任务或者其他的什么少,而是心理的压力最少,幻想破灭地最少,也最像高中时那个纯洁的自己。

可能人确实不得不随着年龄增大而改变。但愿这是“不得不”的吧。

2005年11月4日星期五

上帝的惩罚?

看来星期二的疯狂工作导致了到今天还在持续的头昏脑涨,脑部缺血。一整天人昏昏沉沉没精神,偏偏又没有任何其他的症状。今天从医院回来的路上,突然想到,这可能是上帝的惩罚。

对于每个人来说,时间都是相同多的,但每个人完成的事却不一样多。努力的人,聪明的人,在相同的时间能就能做很多事。然而,上帝是公平的。你不能超越别人太多,他不能容许这种极端的不公平出现。天才很少会遗传,天才也很少会长寿,否则,大多数的人就没有什么存在的价值了。上帝是公平的。

我想起了父亲,也是年轻的时候很刻苦,很努力,做到了绝大多数人无法想象的事。正打算在 30 岁以后大干一场,成就一番事业,上帝却看不过了。他或许是太努力了,把他的天才使用得太过度了,上帝告诉他:“凭什么你要在这么短的时间里面完成那么多事?既然这样,我就得让你生病,让你不能再做出成绩,直到你赎清了你的债。”无奈,他是太刻苦、太天才了,直到死的那一天都还不完。

我得出的结论是,上帝可能不公平(否则,他干嘛又麻麻烦烦要造出那么多天才来?大家一个样不更好?),父亲可能的确是寿终正寝,但有两件事是要记住的:一、什么事都要慢慢来,切不可急躁;二、每操作计算机一个小时,就要起来活动一下,疏络经骨,否则搞计算机这一行,短命。

2005年11月1日星期二

完成中间代码生成

最晚突发灵感,一口气写代码生成写到凌晨 5 点。睡了一觉,逃了一天课,下午又接着写,终于完成了这个 "Simple Compiler"。说实话,写这个编译器花的时间最多的不在代码生成,但确实感到代码生成的技术含量是最高的,也难怪每一本讲编译的书在代码生成上的章节是最长的。想想 2 个月前的暑假时还认为写编译器是一项不可能在短时间完成的任务,而现在基本上对编译器的流程有了一个大致的了解和实践,真的还是应了那句老话:“没有什么是学不会的。”

这个编译器,词法分析方面主要参照了《编译原理与实践》(Compiler Construction Principles and Practice) 里的那个 TINY Compiler 处理方法和技巧,构造 DFA,分状态处理输入字符。语法分析就是纯正的 LL(1)。

语义分析和中间代码生成这个阶段就不像前两个阶段那样有一个公式可以套。可以说,每个语言都有不同的、属于自己的分析方法,所以这个部分我更多的参照了教科书里面的方法。虽然说先根据语法分析的结果生成语法树,再根据语法树生成代码会简单一些,但这样会增加代码,降低效率,而且在某些情况下不适用,同时因为我的语法分析是 LL(1),所以我还是选择在不改变语法的情况下直接在语法分析中间添加语义分析的代码。

具体技术上,主要是使用“回填”技术。为了解决如何延后修改已经生成的代码的问题,我设立了一个四元式的数组,把生成的中间代码写进去,在 backpatch 函数中修改相应四元式。在分析完了所有程序后,用 emit 函数将四元式输出到控制台上。

其实,虽然感觉在实际编写代码上的时间并不是很多,但平时一直都在看关于编译的书,也正是有这些积累,才能够有比较清晰的思路来完成它。还要感谢那些前辈们宝贵的智慧和经验,没有他们,编译还是 Mission Impossible。

《编译原理》,Compilers: Principles, Techniques, and Tools,龙书
《编译原理与实践》,Compiler Construction Principles and Practice
《可变目标C编译器——设计与实现》,A Retargetable C Compiler: Design and Implementation,lcc
《编译器构造:C语言描述》,Crafting a compiler with C

2005年10月19日星期三

Visual Studio 2005 试用

昨天从网上下载到了 Visual Studio 2005 Professional Edition 的 RTM 版,马上试着安装。遇到的第一个问题是,VS2005 需要 Windows XP SP2,我还是 SP1。在 Aaron Stebne 的 Blog 找到了没有 SP2 也能安装 VS2005 的方法。因为 setup.exe /NO_BSLN_CHECK 简单,也没仔细看就尝试。结果总是在安装 MSI 的时候出错。没办法,改了注册表重试,一切顺利。(根据 Aaron Stebne 的说法,VS2005 并没有使用 SP2 的特性,微软的这一限制只是为了推广 SP2,所以即使没 SP2 也不会对使用造成任何不同)

试用了一下,嗯,界面不错,但是和 2003 比起来,改变还是不大,主要是 Dock 上有点变化。2005 似乎很强调网络功能,从 Start Page 到 Search,都提供并推荐使用线上服务,而菜单中更是加入了 Community 选项,看来微软认为 2005 要把所有的程序员通过网络联系起来吧。

功能上,乍一看还真么什么新东西,只多了个 Call Browser 和 Code Definition Window。C++ 工程属性页加入了 Manifest Tool 和 XML Document Generator 两个,默认选项变了一些。现在,编译错误不再在 Task List 里面显示了,而是一个独立的 Error List,这样对经常使用 Task List 的人来说可能更方便一些了。其他的都大同小异。

说说问题。第一,设置、界面、习惯变了,虽然不大,但还是不爽。当然,这是可以预料的。第二,Visual Assist X 的 10.1.1301 版不能用在 2005 里面,10.1.1418 版又因为试用期已过,无法再用,所以现在写代码都有些没信心。第三,Start Page 里面的 Recent Projects 没用!我打开了无数次 Solution,但那里面永远都是空的。修改设置里面的值,可以看到空白变长变短。进到注册表里面,发现 ProjectMRUList 是空的。不知这个问题该怎么解决。第三,有很多功能在这个版本里面没有包含,如 Code Profiling 等,毕竟是 Professional 版。还是很期待 Team Suite 版,也不知什么时候才能得到。

另外,调试功能好像也有一点问题。经常下了断点,按下了 "Start Debugging" 按钮,也停在了断点处,居然 Debug 工具栏的所有按钮都是灰色的,但菜单里面的选项又可以用。而且,在这种情况下过不了多久就会弹出一个 "Stop Debugging" 窗口。停止重新运行后又恢复了正常。有些怀疑这个 RTM 版的真实身份。

总的来说,目前对 2005 没有失望,但也没什么值得兴奋的地方。

2005年9月25日星期日

Glenn Gould 诞辰 73 周年

总觉得把“诞辰”这个词用在古尔德身上不太合适(一般感觉都是那些优秀而先进的共产党员们才配得上这个伟大而光荣的词的),但这是事实:古尔德已逝。至今,古尔德仍然是我最习惯的诠释巴赫的音乐家。




2005年9月22日星期四

初识编译器设计

最近终于开始自己动手写编译器了。老师给了一个名为 SIMPLE 的语言,叫我们写一个词法分析和语法分析。我是用 C++ 写的,刚刚把语法分析做出来了,总的来说还是有点心得的。

词法方面更多的还是参照了《编译原理与实践 (Compiler Construction Principles and Practice, Kenneth C. Louden) 》的 TINY Compiler,原因主要还是因为对编译器不熟,现在有比较成熟的方法,先拿来再说。分析的方法还是先在纸上构造出相应的 DFA,然后用一个 switch 语句选择各种状态分别处理。实际编写的时候,还是发现了很多和 TINY 不同的地方,所以自己也在他的基础上进行了修改。

我们的 SIMPLE 语言比 TINY 要复杂很多(Simple > Tiny ?),所以语法分析方面,相应的函数也多了很多。语言是符合 LL(1) 文法的,所以用的还是递归下降分析法(后来发现,其实还是有一个表达式不符合 LL(1),不过找到了解决办法)。因为有一个非终结符的两个候选式的 First 集合有交集,所以一时想不到该怎么去选择候选式。后来发现,可以用以下办法解决这个问题:将两个候选式 First 集合的交集抽出来,如果一个候选式可以推出另一个候选式(前者比后者大),那么在遇到交集里的终结符时,选择大的候选式。其他的非交集部分则选择各自候选式。举个例子:

abc → id | | id relation id | arith_exp relation arith_exp

arith_exp 是算术表达式,可以是 id + id,也可以是 id,还可以是 id + num,等等。可以看出,由于 arith_exp 和 id 的 First 集合具有交集 id,如果当前符号是 id,则不知道应该选择哪一个候选式。因为 arith_exp 可以推出 id,所以我把上式改成了

abc → arith_exp [relation arith_exp]

因为如果满足了 id,则一定满足 arith_exp,反之如果满足 arith_exp,不一定满足 id。事实上,上面的例子只是一个简化了的表达式,实际中还要考虑一些其他因素,不过总的思路就是这样了。当然,最好的方法还是仔细的设计标准的 LL(1) 文法,这也算是一点教训吧。