随笔-341  评论-2670  文章-0  trackbacks-0
脚本技术
描述跟脚本相关的各种技术
手把手教你写脚本引擎(五)——简单的高级语言(3,符号表)      摘要: 符号表的结构的复杂度跟语言的语义规则的复杂度有关。对于C#来说,每一个符号都附带了一大堆信息,譬如位置啦,所在的namespace啦,类型啦什么的。对于JavaScript来说,符号表几乎是不需要的,因为东西都动态了,编译时几乎不检查内容。语义分析的输出是符号表,代码生成的输入是符号表和语法树。因此语法树除了放语法相关的内容,语义相关的内容最好放到符号表里面(譬如说表达式的类型啦,语句的scope结果啦)。  阅读全文
posted @ 2009-05-10 18:48 陈梓瀚(vczh) 阅读(7218) | 评论 (1)  编辑
手把手教你写脚本引擎 PPT与Demo(一)      摘要:
华南理工大学微软俱乐部程序设计语言特别兴趣小组——手把手教你写脚本引擎系列(一)
陈梓瀚

PPT内容:
1、简单指令集的设计方法(支持分支、循环、函数、递归)。
2、编译控制流程(分支和循环)的一般模式。
3、函数调用的详细过程。
4、5个示例程序。

Demo内容:
PPT中5个示例程序的运行过程(动画),左边是单步,右边是堆栈内容。

含下载,内详。  阅读全文
posted @ 2009-03-28 01:43 陈梓瀚(vczh) 阅读(10595) | 评论 (11)  编辑
Kernel FP的图形Demo实现!      摘要: 其实有了一整套的Kernel FP API之后,只需要插入几个外部函数就可以让Kernel FP绘图了。现在我们看一看这个Demo的样子。
  阅读全文
posted @ 2008-12-29 10:41 陈梓瀚(vczh) 阅读(2709) | 评论 (0)  编辑
Kernel FP编译器工具实现      摘要: 这次终于实现了两个exe,一个是编译器,一个是提供控制台API的虚拟机。等提供GUI的虚拟机出来之后就开放出来(内有图和代码)。  阅读全文
posted @ 2008-12-26 08:07 陈梓瀚(vczh) 阅读(2041) | 评论 (5)  编辑
Kernel FP 编译器MakeFile开发完成      摘要: Kernel FP的MakeFile可以指定输出文件、报告文件以及代码文件,并且可以继承其他的MakeFile。MakeFile的格式和分析器代码如下:  阅读全文
posted @ 2008-12-24 05:20 陈梓瀚(vczh) 阅读(1784) | 评论 (1)  编辑
Kernep FP实现虚拟机的序列化与反序列化      摘要: 由于Kernel FP的编译结果是独立的,执行的时候不需要源代码的符号的参与,因此可以将编译结果进行序列化与反序列化。  阅读全文
posted @ 2008-12-23 00:50 陈梓瀚(vczh) 阅读(1561) | 评论 (0)  编辑
Kernel FP添加反射API      摘要: 为了让宿主程序可以更加清楚一份Kernel FP代码的内容,我今天为Kernel FP添加了反射的API。  阅读全文
posted @ 2008-12-20 06:10 陈梓瀚(vczh) 阅读(1410) | 评论 (0)  编辑
使用Kernel FP的do-end语法糖添加自己的异常处理系统      摘要: 有的时候,IO的异常处理由于需要一个IOEnv类型的参数而显得非常麻烦。这个时候我们可以定制自己的一套异常处理系统,从而让程序变得清晰起来。自己的异常处理系统不同于IO,是没有副作用的函数集合。下面让我们看一看如何使用自定义的异常处理系统来分析一个四则运算表达式。  阅读全文
posted @ 2008-12-18 21:23 陈梓瀚(vczh) 阅读(1442) | 评论 (0)  编辑
使用Kernel FP API实现一个运行Kernel FP代码的控制台程序      摘要: 说到底Kernel FP是一个脚本引擎,所以是需要API的。接下来的代码用来加载一些Kernel FP代码文件,并执行main函数。  阅读全文
posted @ 2008-12-17 19:15 陈梓瀚(vczh) 阅读(1627) | 评论 (1)  编辑
在纯函数式语言内实现有关IO的循环      摘要: 我们知道,循环本身是没有返回值的。所以在纯函数式语言下,跟IO有关的循环才有足够的副作用来产生价值。于是利用IO Monad,我们就可以实现循环了。循环是一个函数:  阅读全文
posted @ 2008-12-15 07:56 陈梓瀚(vczh) 阅读(2141) | 评论 (2)  编辑
Kernel FP的do-end IO语法糖实现!      摘要: 前面说过,需要一个语法糖来组织IO,并且在其中的一步产生错误的时候立刻返回错误。现在我们看一段代码:  阅读全文
posted @ 2008-12-15 06:22 陈梓瀚(vczh) 阅读(1469) | 评论 (0)  编辑
Kernel FP的IO实验
posted @ 2008-12-14 22:44 陈梓瀚(vczh) 阅读(1761) | 评论 (0)  编辑
Kernel FP支持更精细的重载
posted @ 2008-12-14 19:42 陈梓瀚(vczh) 阅读(1460) | 评论 (0)  编辑
Kernel FP 的四则运算式子分析程序      摘要: 为了测试Kernel FP的健壮性以及进行一些bug的排除,一个四则运算式子的分析程序理所当然地就被实现了。代码如下:  阅读全文
posted @ 2008-12-13 07:13 陈梓瀚(vczh) 阅读(3341) | 评论 (2)  编辑
Kernel FP成功运行一部分列表处理程序      摘要: 经过1个小时的奋斗,修了3个bug,终于使得Kernel FP能运行的代码渐渐多了起来。现在可以看看纯函数式语言简洁的代码及运行结果啦!

下面是很多用于测试的main函数:  阅读全文
posted @ 2008-12-12 10:03 陈梓瀚(vczh) 阅读(1442) | 评论 (1)  编辑
Kernel FP成功运行小程序      摘要: Kernel FP已经可以运行小程序了。现在还处于测试阶段,过于复杂的程序估计是跑不过的。先简单介绍一下如何在C++调用Kernel FP的代码。  阅读全文
posted @ 2008-12-10 23:03 陈梓瀚(vczh) 阅读(1709) | 评论 (2)  编辑
Kernel FP:Expected语法完全支持!      摘要: 新加入的Expected语法已经完全支持了。使用了Expected的符号会因为调用者的不同而使用不同的scope内的函数。代码如下:  阅读全文
posted @ 2008-11-03 05:41 陈梓瀚(vczh) 阅读(1666) | 评论 (0)  编辑
Kernel FP的Expected语法实验      摘要: 有了Expected语法之后总是要实验一下的。现在给出一个非完整函数eq的声明,并用一个列表查找函数使用eq。已知代码如下:  阅读全文
posted @ 2008-11-02 07:36 陈梓瀚(vczh) 阅读(1513) | 评论 (0)  编辑
决定为Kernel FP加入一个跟模板函有关数的语法      摘要: Kernel FP的模板函数比较严格。对于任意的模板函数的类型参数,这个参数必须能够接受所有类型。当然,类型推导会通过阅读代码来精确化程序员设定的类型。譬如说一个函数F的类型是T->T,但是经过阅读代码发现,参数只能是某种类型的列表,那么类型推导就会将这个函数的类型修改为list T->list T。

但是这样会有一个问题。类型推导只能够推导已知的函数。如果一个模板函数里面用了操作符,而这个操作符暂时只为几个类型定义的话,那么由于不是所有的类型都能够接受该操作符,所以这个操作符就没办法给未知确切类型的参数使用。下面就有一个例子:  阅读全文
posted @ 2008-11-02 06:52 陈梓瀚(vczh) 阅读(1323) | 评论 (0)  编辑
Kernel FP 模板函数实例化      摘要: 今天写了Kernel FP模板函数实例化的代码。虽然还有一点小bug,不过还是说一下。  阅读全文
posted @ 2008-11-01 07:05 陈梓瀚(vczh) 阅读(1387) | 评论 (0)  编辑
改进Kernel FP编译器,生成类型推导的调试信息      摘要: 类型推导过于复杂,已经到了无法Step In/Over的地步了,于是只好靠输出大量调试信息来解决问题。这里给出了我为Kernel FP开发的一些简单的调试用宏。在不需要调试信息的时候,可以通过简单关闭调试而将产生调试信息的运行时负担完全去除。  阅读全文
posted @ 2008-10-29 10:04 陈梓瀚(vczh) 阅读(2244) | 评论 (3)  编辑
是时候重构了!      摘要: 实习的时候,自己的时间明显没有在学校的时候多啊。这次Kernel FP拖了很久,一个多月都还没写完。幸好语法分析器用了之前开发的Syngram,要不得多花一个月。Kernel FP的类型推导的代码实在是很难看,趁着又发现了一个Bug,重构一下。

内含代码  阅读全文
posted @ 2008-10-27 05:23 陈梓瀚(vczh) 阅读(1981) | 评论 (6)  编辑
Kernel FP 虚拟机结构      摘要: Kernel FP的虚拟机设计起来比较别扭,主要还是因为laziness的问题。不过现在已经有了一个能用的想法了。  阅读全文
posted @ 2008-10-18 23:29 陈梓瀚(vczh) 阅读(1528) | 评论 (1)  编辑
Kernel FP 指令集      摘要: 类型推导到这里也就结束了。虽然可能有点小bug,不过这个以后遇到再处理了。接下来的一个模块是跟类型推导没有耦合的新模块,两边可以平行处理。

Kernel FP的指令集不同于以往的指令集。因为作为一门纯函数式语言,就必须要有laziness。这就是说,凡是可以不运行的代码都一定不运行,凡是可以晚一点执行的代码一律等到需要的时候再执行。也就是说,参数传进函数的时候,传的是代码而不是值。因此指令集只能用来表达代码的逻辑结构。
  阅读全文
posted @ 2008-10-11 02:10 陈梓瀚(vczh) 阅读(1428) | 评论 (1)  编辑
Kernel FP let-in表达式子函数包含父函数对象的类型推导      摘要: 有一些主函数的某些参数只在let-in表达式所定义的子函数使用,然后被主函数间接使用。今天修了一个bug支持了这种函数的类型推导。例子如下:  阅读全文
posted @ 2008-10-08 08:19 陈梓瀚(vczh) 阅读(1351) | 评论 (0)  编辑
Kernel FP 更多的类型推导      摘要: 今天将Haskell的一部分列表处理函数抄进了Kernel FP里,坚持所有函数(模板函数)不写类型,而让编译器进行类型推导:  阅读全文
posted @ 2008-10-07 08:10 陈梓瀚(vczh) 阅读(1273) | 评论 (0)  编辑
Kernal FP所有表达式种类实现类型推导!      摘要: 经过上一次的成功试验,这次终于完成了剩余的表达式类型的类型推导。过程及结果如下:  阅读全文
posted @ 2008-10-06 06:47 陈梓瀚(vczh) 阅读(1492) | 评论 (1)  编辑
Kernel FP 类型推导(Type Inference)实验成功!      摘要: 我终于在实验阶段解决了这个困扰了我5个月(虽然实际上我花了3个星期)的问题。目标是这样的:你写程序,可以尽可能的不写一些类型信息,譬如函数参数和返回值的类型信息等。我的编译器帮你把它的类型算出来。

内详,有例子、方法和模型。  阅读全文
posted @ 2008-10-04 07:19 陈梓瀚(vczh) 阅读(1825) | 评论 (3)  编辑
Kernel FP符号表完成      摘要: 经过了5个小时的艰苦奋斗,符号表终于计算出来了,而且也做了一部分语法分析。接下来的工作是类型推导。今天的结果如下。  阅读全文
posted @ 2008-10-02 07:46 陈梓瀚(vczh) 阅读(1680) | 评论 (1)  编辑
KernelFP 写的一个用通配符匹配字符串的程序      摘要: 输入:
pattern : 含有通配符*与?的字符串
string : 被匹配的字符串
输出:true与false代表匹配成功与失败

仅19行  阅读全文
posted @ 2008-10-01 09:41 陈梓瀚(vczh) 阅读(1469) | 评论 (0)  编辑
Kernel FP 语法分析完成      摘要: 语法分析器终于完成了,总共花了7个小时的时间。其中遇到了一些小问题,譬如lambda expression的\param->expression和let-in expression的let declaration-list in expression里面的expression需要尽可能长的解决办法。因为用了Syngram,所以不得不调整出符合需求的文法。

为了大概看一看文法有没有写对,我写了一个程序,读入KernelFP语言写的一份代码,将其格式化并输出。  阅读全文
posted @ 2008-10-01 01:31 陈梓瀚(vczh) 阅读(1562) | 评论 (0)  编辑
最小内核语言      摘要: 国庆7天容易无聊,于是我打算实现一下以前失败过的一种语言的特性:类型推导。于是顺便做一做惰性计算吧。于是我尝试设计了一门特性尽可能少的语言,并且强制让一个函数的返回值仅跟输入的参数有关。虽然这个特性不适合用来做IO,但是是有办法解决的,而且不需要修改语言就可以直接支持。

这门语言的定义及其简单,需要预先定义的部分也是很少的,于是我尝试实现了if、逻辑运算符以及itoa和atoi两个函数  阅读全文
posted @ 2008-09-28 07:14 陈梓瀚(vczh) 阅读(2140) | 评论 (4)  编辑
自定义数据结构的语法分析器成功!      摘要: 经过三个小时的努力,一个供调试用的模拟器终于做出来了。对于一份语法说明来讲,我们需要提供调试器,一直到调试完了才生成代码,这样比较容易找到问题。同时为了验证自己的那个设计,于是做了一个调试器出来。这个调试器使用了这篇文章里的数据结构文件以及文法文件,以及使用了这篇文章里开发的一个树到图的转换程序,成功得到结果!  阅读全文
posted @ 2008-09-14 07:22 陈梓瀚(vczh) 阅读(1830) | 评论 (1)  编辑
语法分析器定义接近完成!      摘要: 除了错误处理文件还没有定义好以外,现在语法定义跟语法树的数据结构定义以及分析器都完成了!有了这两个文件,我的工具就可以替你生成一个函数和一堆类,让你使用这个函数就可以将一份代码转换为一颗语法树啦。娃哈哈……

现在让我们来看一个例子  阅读全文
posted @ 2008-09-14 00:53 陈梓瀚(vczh) 阅读(1421) | 评论 (3)  编辑
数据结构定义 分析器完成
posted @ 2008-09-12 05:49 陈梓瀚(vczh) 阅读(1224) | 评论 (0)  编辑
项目实验2:动态生成编译器前端      摘要: 我们知道Yacc和Bison都是产生C++的代码作为编译器的前端的。但是有时候我们需要动态地产生一个编译器前端,极端一点讲,譬如“文法调试器”。调试器总不能动态生成.y文件,让yacc编译,让gcc再度编译,然后execute,最后将程序的输出结果读进来。这样就太麻烦了,于是我们需要重新写一个生成编译器前端的程序。  阅读全文
posted @ 2008-09-06 02:45 陈梓瀚(vczh) 阅读(2290) | 评论 (3)  编辑
项目实验1:将算法与数据结构分开      摘要: 现在的OOP都提倡将操作与数据结构结合在一起。为什么这里要提出将算法与数据结构分开呢?第一个原因是一个算法可能是用来处理一组数据结构的。第二个原因是算法并不属于操作。我们可以借鉴访问者模式来实现这个分离,但是这里有一个特别之处:我们要将访问者模式带给我们的那个接口实现得让我们用起来很漂亮。  阅读全文
posted @ 2008-09-02 04:43 陈梓瀚(vczh) 阅读(2600) | 评论 (10)  编辑
Syngram Helper开始设计:一个能用来写编译器的工具      摘要: 大概一年前曾经用C++开发了一个可以在C++中直接写上下文无关文法的上下文无关文法分析器。这玩意儿叫Syngram。Syngram曾经做了两次,第一次做成了用一个类去读文法文件,后来不爽就改成了直接在C++里面写的。我弄了一个叫Term的类,重载了一些操作符,于是你可以搞分支、可选、错误处理等复杂的文法推导式。现在打算做一个周边工具。  阅读全文
posted @ 2008-08-27 05:11 陈梓瀚(vczh) 阅读(1853) | 评论 (5)  编辑
手把手教你写脚本引擎(四)——简单的高级语言(2,处理语法)      摘要: 有了全盘的计划之后,我们必须先处理输入的脚本,才能够进行下一步的工作。字符串处理方面可以参照一下三篇文章:《构造可配置语法分析器》、《构造正则表达式引擎》以及《如何手写语法分析器》。作为补充,这里再说一说其他的办法。  阅读全文
posted @ 2008-08-01 23:19 陈梓瀚(vczh) 阅读(5153) | 评论 (4)  编辑
手把手教你写脚本引擎(三)——简单的高级语言(1,基本原理)      摘要: 这一篇文章开始讲述如何实现一个高级语言的脚本引擎了。由于工程量较为庞大,因此将分开几篇文章讲。学习做脚本还是要从简单的东西做起的。上一篇文章介绍的命令脚本为实现高级语言的原理做了铺垫。首先,高级语言和低级语言脚本的架构是一致的。其次,为了具有较大的优化的空间,我们将把高级语言转换成低级语言,并配合一个低级语言的脚本引擎来实现高级语言的脚本引擎。当然,习惯上,在这种情况下我们把低级语言叫『指令』。  阅读全文
posted @ 2008-07-18 20:31 陈梓瀚(vczh) 阅读(6595) | 评论 (8)  编辑
手把手教你写脚本引擎(二)——命令脚本      摘要: 这次要实现的是一个形式最简单的脚本。这种脚本仅有命令、标号及跳转构成,看起来就跟汇编一样,不过好是比较好读的。虽然这种脚本语言的语法非常简单,但是最基本的要素还是要有的。

作为一个脚本引擎,为了可以在各种各样的合适的宿主程序中使用,脚本本身最好不要涉及到具体的领域。当然,如果这个脚本被创建的目的仅仅是为了某个领域的话,那就无所谓了。因此,一个脚本引擎需要一个检查和运行代码的机制、运行时环境的维护以及一个功能足够使用的插件系统。一个完整的脚本引擎至少需要如下部件:  阅读全文
posted @ 2008-07-09 21:43 陈梓瀚(vczh) 阅读(8849) | 评论 (10)  编辑
手把手教你写脚本引擎(一)——挑选语言的特性      摘要: 脚本引擎的作用在于增强程序的可配置性。从游戏到管理系统都需要脚本,甚至连工业级产品的Office、3DS Max以及AutoCAD等都添加了属于自己的脚本语言。DHTML的出现让我们可以在网页代码中嵌入脚本语言,PHP和ASP等技术的出现让我们可以将一个应用程序的界面换成网页,而逻辑使用脚本语言编写。现在脚本语言的种类繁多,Python的发展让BOOST库拥有了对Python的支持,Rails框架的出现壮大了Ruby的实力,LUA更是被大量应用在游戏开发中。Windows甚至提供了wscript以便让我们能够调用javascript和vbscript的代码。

既然有了这么多可供选择的脚本引擎,为什么我们仍然要开发自己的脚本引擎呢?  阅读全文
posted @ 2008-07-07 07:45 陈梓瀚(vczh) 阅读(21590) | 评论 (12)  编辑
关于脚本引擎
posted @ 2008-07-06 08:37 陈梓瀚(vczh) 阅读(2274) | 评论 (5)  编辑
使用高阶函数开发语法分析器      摘要: 这篇短文的Idea来源于一篇论文。这篇论文的题目是Higier-Order Functions for Parsing,Graham Hutton写的。论文中使用了一种叫Miranda的函数式语言来讲述如何使用高阶函数开发语法分析器。

高阶函数很多语言都支持,譬如JavaScript啊,C#的lambda expression啊,或者是我自己做的语言Vczh Free Script 2.0。不过Miranda是惰性计算的语言,我们常用的语言都不具有惰性计算的特性。因此我阅读了这篇文章之后,自己用Vczh Free Script 2.0写了一个等价的小规模的语法分析器。结构跟论文中所提到的那个有所区别,不过相同的经验可以直接应用在JavaScript里面或其它语言(例如Python等)的lambda expression里。C#我不知道行不行,没去考证。

这里首先要解决一个问题,就是如何引用没被定义的名字的问题。譬如如下文法:

Term= | "(" Exp ")"
Fa  阅读全文
posted @ 2008-05-21 00:57 陈梓瀚(vczh) 阅读(8141) | 评论 (5)  编辑
如何实现语言中的闭包(Closure)      摘要: 已经忘了是去年还是前年听到微软说要在C# 3.0里为C#添加lambda表达式,与此同时Java的团队也一直在说想为Java添加lambda表达式。到了今天,C#似乎已经把这个特性加进去了,Java还没有。Java说这个特性还在计划列表之中,不过暂时可以使用匿名类来代替。想必是因为在Java中表示函数指针的方法比较奇怪罢……

其实无论是lambda表达式(事实上应该叫匿名函数)或是匿名类,都能归属到一种叫闭包的东西上面。闭包原来是代数中的用语,只是那些研究理论的老大们觉得这玩意儿也能拉到“闭包”里面去,于是就叫闭包了。匿名函数原本是丘奇发明的一个lambda-calculus的其中一部分,后来计算机的老大们突然发现lambda-calculus非常适合用来充当程序设计语言的模型,于是就对它进行了非常多的扩充,还弄了个什么类型理论出来。好像扯远了。

想象一下如下使用闭包的代码:

MyClosure=func(Number1)
{
return func(Numbe  阅读全文
posted @ 2008-04-20 21:55 陈梓瀚(vczh) 阅读(7701) | 评论 (5)  编辑