2007/6/4
脚本
本想在这里写一个感悟之类的东东,但最近理性思维转型到感性思维还没好,想写一些感性的文字,每每下笔,却不知从何说起。不如就随着心意写一些想些的东东吧。
最近在研究规则库的东东,发现为了让规则库脱离程序设计期,能够在运行期更好的合作,只有运用脚本。但目前主流的脚本机制跟业务逻辑无法挂钩,而且还跟win32系统紧密绑定,这是一个很要命的弱点,那些所谓的VBScripte,JS都是紧密的绑定在Application Script Host上。一直在寻找一种自然的、轻松的绑定机制,一直未果。
昨晚,在看fr源代码的时候,发现了Fast Script这个东东,其实fr公司为了让报表更强大,很久之前就使用了自定义脚本。那么fs内部究竟如何实现的呢?百闻不如一见,打开代码看看就知道了。以下是阅读笔记,发布出来跟大家共享。
单元功能简介:
fs7:包文件而已
fs_xml:定义了fr自己的xml解析器,包括读写机制在里面。其中特别要注意的是,他把xml的一些关键字给替换了。包含的类有TfsXMLDocument,TfsXMLItem,TfsXMLReader,TfsXMLWriter。
fs_tree:定义了一个fr风格的树。继承自一个Panle,但内部聚合了TTreeView、TfsScript和TfsXMLDocument,可以猜测其功能应该是从一个xml配置文件中加载并显示。
fs_synmemo:定义了类似Memo的东东,支持语法高亮。包含的类TfsSyntaxMemo = class(TCustomControl)//为了支持跨平台,TfsSynMemoSearch,THackScrollBar = class(TScrollBar)//直接继承;
fs_itools:属于公共函数单元了。里面包含了一些公用函数。详细如下
procedure fsRegisterLanguage(const Name, Grammar: String);//注册语言
function fsGetLanguage(const Name: String): String;//获取语言
procedure fsGetLanguageList(List: TStrings);//获取语言列表
procedure GenerateXMLContents(Prog: TfsScript; Item: TfsXMLItem;
FunctionsOnly: Boolean = False);
function StrToVarType(const TypeName: String; Script: TfsScript): TfsVarType;
function TypesCompatible(Typ1, Typ2: TfsTypeRec; Script: TfsScript): Boolean;
function AssignCompatible(Var1, Var2: TfsCustomVariable; Script: TfsScript): Boolean;
function VarRecToVariant(v: TVarRec): Variant;
procedure VariantToVarRec(v: Variant; var ar: TVarRecArray);
procedure ClearVarRec(var ar: TVarRecArray);
function ParserStringToVariant(s: String): Variant;
function ParseMethodSyntax(const Syntax: String; Script: TfsScript): TfsCustomVariable;
function fsPosToPoint(const ErrorPos: String): TPoint;
fs_ipascal:pascal语法描述,以xml的形式。在这里面为了兼容fr2也进行了一个转换。
fs_ijs:JS语法描述,同上。
fs_icpp:C++语法。同上
fs_ibasic:VB语法。同上。
fs_iparser:为了支持语法高亮而引入的一个单元,定义了TfsParser类,专门用来做这个事情。
fs_iilparser:这个一个语法分析的单元,支持以上所说的几种语法。TfsILParser专门用来进行语法分析并进行执行,但真正执行的地方在哪里呢?没有细细研读,但初步发现,变量的定义和函数的执行都在这个类中实现了。
fs_iconst:常量定义单元。
fs_isysrtti:TFunctions函数注册的一个类,通过定义了7种类型的方法,将一些常见的方法注册到系统中,内部其实就是将这些函数名词和函数参数保存在一个List中,在以后程序过程中进行遍历。里面用到了一个很重要的类fsGlobalUnit,这个东东是整个脚本能转起来的根本所在。待会细细讲述。
fs_igraphicsrtti:定义了有关图形的一些类和函数。通过注册机制,注册了一些几本的图形函数。TfsGraphicsRTTI,THackGraphic = class(TGraphic),TFunctions=函数注册过程。
fs_iformsrtti:定义并注册有关窗体的一些函数。TfsFormsRTTI,TFunctions=注册过程。依然跟fsGlobalUnit有关,再次体现了这个类的重要性。
fs_iextctrlsrtti:定义了一些常见控件的方法,TfsExtCtrlsRTTI,TFunctions=注册过程。
fs_idialogsrtti:定义了对话框的方法。TfsDialogsRTTI,THackDialog,TFunctions。
fs_iclassesrtti:定义了对象有关的方法。TfsClassesRTTI,TFunctions。
fs_ichartrtti:定义了图表有关的方法。TfsChartRTTI,TFunctions。
fs_idisp:一个无关紧要的单元,但这个单元将引出很重要的类TfsOLEHelper = class(TfsCustomHelper),名义上是支持OLE,实际上只是将IDispatch接口进行方法转发。
fs_ievents:定义了事件函数。TfsCanResizeEvent,TfsCloseEvent,TfsCloseQueryEvent,TfsKeyEvent,TfsKeyPressEvent,TfsMouseEvent,TfsMouseMoveEvent,TfsNotifyEvent。这些类都是继承自TfsCustomEvent。而且每个类都覆盖了function GetMethod: Pointer; override;可以推断这个方法是父类要调用的。
fs_iexpression:表达式。类太多就一一表示了,但有一个共同的特征,就是全部继承自TfsOperatorNode,可以推断出,每种类表达一个操作符,当然也就进行一种运算。
fs_iinterpreter:这是脚本的核心单元,连作者自己在注释中都写道"Main module ",呵呵。这个单元将近3k行,我们慢慢品位。
进入单元初始化部分
fsGlobalUnit;//创建传说中那个重要的类
fsEventList;//创建事件列表
FGlobalUnitDestroyed := False;//标记未释放
好了,先从简单的地方入手,事件列表吧。TfsEventList = class(TfsItemList),继续追踪TfsItemList类,TfsItemList = class(TObject),作者特别声明,这个类跟TList不同,在自己释放的同时将释放自己存储的所有类。
下面看看传说中的类吧
FGlobalUnit := TfsScript.Create(nil);追踪TfsScript类,TfsScript = class(TComponent),噢,原来定义成一个组件了,那么那些各种语法的脚本都是继承自他咯。
这个单元的类很多,而且关系复杂,为了简便起见,本人使用了MM7来查看类关系图,先不看聚合的关系,只看继承。
首先弄懂几个基类,TfsItemList,包含四个直系子类(TfsEventList,TfsCustomVariable,TfsStatement,TfsDesignatorItem),
TfsDesignatorItem直系自类=TfsDesignator,TfsDesignator类包含三个直系子类=(TfsArrayDesignator,TfsStringDesignator,TfsVariableDesignator)
TfsCustomVariable直系子类=(TfsParamItem,TfsTypeVariable,TfsProcVariable<被类TfsCustomEvent聚合>,TfsCustomExpression,TfsClassVariable,TfsVariable),TfsVariable直系子类=TfsStringVariable
TfsCustomVariable直系子类=(TfsCustomHelper,TfsSetExpression),
TfsCustomHelper直系子类=(TfsMethodHelper,TfsComponentHelper,TfsArrayHelper,TfsPropertyHelper,TfsStringHelper,TfsEventHelper)
TfsStatement直系子类=(TfsExitStmt,TfsContinueStmt,TfsCallStmt,TfsWithStmt,TfsRepeatStmt,TfsBreakStmt,TfsCppForStmt,TfsWhileStmt,TfsIfStmt,TfsCaseSelector,TfsForStmt,TfsTryStmt,TfsCaseStmt,TfsVbForStmt,TfsAssignmentStmt)
TfsAssignmentStmt直系子类=(TfsAssignDivStmt,TfsAssignMinusStmt,TfsAssignMulStmt,TfsAssignPlusStmt)
脚本
本想在这里写一个感悟之类的东东,但最近理性思维转型到感性思维还没好,想写一些感性的文字,每每下笔,却不知从何说起。不如就随着心意写一些想些的东东吧。
最近在研究规则库的东东,发现为了让规则库脱离程序设计期,能够在运行期更好的合作,只有运用脚本。但目前主流的脚本机制跟业务逻辑无法挂钩,而且还跟win32系统紧密绑定,这是一个很要命的弱点,那些所谓的VBScripte,JS都是紧密的绑定在Application Script Host上。一直在寻找一种自然的、轻松的绑定机制,一直未果。
昨晚,在看fr源代码的时候,发现了Fast Script这个东东,其实fr公司为了让报表更强大,很久之前就使用了自定义脚本。那么fs内部究竟如何实现的呢?百闻不如一见,打开代码看看就知道了。以下是阅读笔记,发布出来跟大家共享。
单元功能简介:
fs7:包文件而已
fs_xml:定义了fr自己的xml解析器,包括读写机制在里面。其中特别要注意的是,他把xml的一些关键字给替换了。包含的类有TfsXMLDocument,TfsXMLItem,TfsXMLReader,TfsXMLWriter。
fs_tree:定义了一个fr风格的树。继承自一个Panle,但内部聚合了TTreeView、TfsScript和TfsXMLDocument,可以猜测其功能应该是从一个xml配置文件中加载并显示。
fs_synmemo:定义了类似Memo的东东,支持语法高亮。包含的类TfsSyntaxMemo = class(TCustomControl)//为了支持跨平台,TfsSynMemoSearch,THackScrollBar = class(TScrollBar)//直接继承;
fs_itools:属于公共函数单元了。里面包含了一些公用函数。详细如下
procedure fsRegisterLanguage(const Name, Grammar: String);//注册语言
function fsGetLanguage(const Name: String): String;//获取语言
procedure fsGetLanguageList(List: TStrings);//获取语言列表
procedure GenerateXMLContents(Prog: TfsScript; Item: TfsXMLItem;
FunctionsOnly: Boolean = False);
function StrToVarType(const TypeName: String; Script: TfsScript): TfsVarType;
function TypesCompatible(Typ1, Typ2: TfsTypeRec; Script: TfsScript): Boolean;
function AssignCompatible(Var1, Var2: TfsCustomVariable; Script: TfsScript): Boolean;
function VarRecToVariant(v: TVarRec): Variant;
procedure VariantToVarRec(v: Variant; var ar: TVarRecArray);
procedure ClearVarRec(var ar: TVarRecArray);
function ParserStringToVariant(s: String): Variant;
function ParseMethodSyntax(const Syntax: String; Script: TfsScript): TfsCustomVariable;
function fsPosToPoint(const ErrorPos: String): TPoint;
fs_ipascal:pascal语法描述,以xml的形式。在这里面为了兼容fr2也进行了一个转换。
fs_ijs:JS语法描述,同上。
fs_icpp:C++语法。同上
fs_ibasic:VB语法。同上。
fs_iparser:为了支持语法高亮而引入的一个单元,定义了TfsParser类,专门用来做这个事情。
fs_iilparser:这个一个语法分析的单元,支持以上所说的几种语法。TfsILParser专门用来进行语法分析并进行执行,但真正执行的地方在哪里呢?没有细细研读,但初步发现,变量的定义和函数的执行都在这个类中实现了。
fs_iconst:常量定义单元。
fs_isysrtti:TFunctions函数注册的一个类,通过定义了7种类型的方法,将一些常见的方法注册到系统中,内部其实就是将这些函数名词和函数参数保存在一个List中,在以后程序过程中进行遍历。里面用到了一个很重要的类fsGlobalUnit,这个东东是整个脚本能转起来的根本所在。待会细细讲述。
fs_igraphicsrtti:定义了有关图形的一些类和函数。通过注册机制,注册了一些几本的图形函数。TfsGraphicsRTTI,THackGraphic = class(TGraphic),TFunctions=函数注册过程。
fs_iformsrtti:定义并注册有关窗体的一些函数。TfsFormsRTTI,TFunctions=注册过程。依然跟fsGlobalUnit有关,再次体现了这个类的重要性。
fs_iextctrlsrtti:定义了一些常见控件的方法,TfsExtCtrlsRTTI,TFunctions=注册过程。
fs_idialogsrtti:定义了对话框的方法。TfsDialogsRTTI,THackDialog,TFunctions。
fs_iclassesrtti:定义了对象有关的方法。TfsClassesRTTI,TFunctions。
fs_ichartrtti:定义了图表有关的方法。TfsChartRTTI,TFunctions。
fs_idisp:一个无关紧要的单元,但这个单元将引出很重要的类TfsOLEHelper = class(TfsCustomHelper),名义上是支持OLE,实际上只是将IDispatch接口进行方法转发。
fs_ievents:定义了事件函数。TfsCanResizeEvent,TfsCloseEvent,TfsCloseQueryEvent,TfsKeyEvent,TfsKeyPressEvent,TfsMouseEvent,TfsMouseMoveEvent,TfsNotifyEvent。这些类都是继承自TfsCustomEvent。而且每个类都覆盖了function GetMethod: Pointer; override;可以推断这个方法是父类要调用的。
fs_iexpression:表达式。类太多就一一表示了,但有一个共同的特征,就是全部继承自TfsOperatorNode,可以推断出,每种类表达一个操作符,当然也就进行一种运算。
fs_iinterpreter:这是脚本的核心单元,连作者自己在注释中都写道"Main module ",呵呵。这个单元将近3k行,我们慢慢品位。
进入单元初始化部分
fsGlobalUnit;//创建传说中那个重要的类
fsEventList;//创建事件列表
FGlobalUnitDestroyed := False;//标记未释放
好了,先从简单的地方入手,事件列表吧。TfsEventList = class(TfsItemList),继续追踪TfsItemList类,TfsItemList = class(TObject),作者特别声明,这个类跟TList不同,在自己释放的同时将释放自己存储的所有类。
下面看看传说中的类吧
FGlobalUnit := TfsScript.Create(nil);追踪TfsScript类,TfsScript = class(TComponent),噢,原来定义成一个组件了,那么那些各种语法的脚本都是继承自他咯。
这个单元的类很多,而且关系复杂,为了简便起见,本人使用了MM7来查看类关系图,先不看聚合的关系,只看继承。
首先弄懂几个基类,TfsItemList,包含四个直系子类(TfsEventList,TfsCustomVariable,TfsStatement,TfsDesignatorItem),
TfsDesignatorItem直系自类=TfsDesignator,TfsDesignator类包含三个直系子类=(TfsArrayDesignator,TfsStringDesignator,TfsVariableDesignator)
TfsCustomVariable直系子类=(TfsParamItem,TfsTypeVariable,TfsProcVariable<被类TfsCustomEvent聚合>,TfsCustomExpression,TfsClassVariable,TfsVariable),TfsVariable直系子类=TfsStringVariable
TfsCustomVariable直系子类=(TfsCustomHelper,TfsSetExpression),
TfsCustomHelper直系子类=(TfsMethodHelper,TfsComponentHelper,TfsArrayHelper,TfsPropertyHelper,TfsStringHelper,TfsEventHelper)
TfsStatement直系子类=(TfsExitStmt,TfsContinueStmt,TfsCallStmt,TfsWithStmt,TfsRepeatStmt,TfsBreakStmt,TfsCppForStmt,TfsWhileStmt,TfsIfStmt,TfsCaseSelector,TfsForStmt,TfsTryStmt,TfsCaseStmt,TfsVbForStmt,TfsAssignmentStmt)
TfsAssignmentStmt直系子类=(TfsAssignDivStmt,TfsAssignMinusStmt,TfsAssignMulStmt,TfsAssignPlusStmt)