国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

輕量級腳本引擎的設(shè)計(jì)與實(shí)現(xiàn)

2011-05-14 11:58張貝克符盛寶
關(guān)鍵詞:堆棧腳本字節(jié)

張貝克,符盛寶

(北京化工大學(xué) 安全科學(xué)與監(jiān)控工程中心,北京 100029)

腳本語言憑借強(qiáng)大的描述能力和靈活的語法結(jié)構(gòu),使得為應(yīng)用程序提供腳本支持從而進(jìn)行混合語言開發(fā)成為實(shí)現(xiàn)可擴(kuò)展和可定制的有效方案[1]。出于穩(wěn)定性和開發(fā)時間限制的考慮,開發(fā)人員傾向于嵌入現(xiàn)有腳本引擎的方法為應(yīng)用程序提供腳本支持,如嵌入Python引擎為應(yīng)用程序提供Python腳本支持,或使用Microsoft提供的ActiveX Scripting技術(shù)為應(yīng)用程序嵌入VBScript引擎或JavaScript引擎提供相應(yīng)的腳本支持。但是這樣方法靈活性較差,應(yīng)用程序必須接受現(xiàn)有腳本引擎的體積和性能要求,這對運(yùn)行在低硬件條件下的應(yīng)用程序,或者是只要求進(jìn)行簡單規(guī)則計(jì)算的小型應(yīng)用程序來說,這種方法在效率上沒有優(yōu)勢[2]。而且有些現(xiàn)有腳本語言比較難學(xué),使得用戶把太多時間花在語言的學(xué)習(xí)上。因此,需要一個輕型的腳本引擎,能夠解釋運(yùn)行一門語法簡單易學(xué)的腳本語言,該腳本語言對于工程應(yīng)用領(lǐng)域的非正式程序員,可以經(jīng)過短時間的學(xué)習(xí)培訓(xùn)或者不經(jīng)過學(xué)習(xí)就能掌握并使用。

針對以上問題,本文在自行設(shè)計(jì)的腳本語言Vblet的基礎(chǔ)上,開發(fā)實(shí)現(xiàn)了Vblet的輕型腳本引擎,支持腳本引擎被嵌入在C++實(shí)現(xiàn)的應(yīng)用程序上。Vblet語言語法簡單,繼承了在非專業(yè)程序員中具有較高聲譽(yù)的VBA語言,并且借鑒了Python語言的部分功能,使得用戶能夠?qū)W⒂趩栴}的解決而不是語法的學(xué)習(xí)上。

1 腳本引擎概述

腳本引擎[3]是一個加載、解釋執(zhí)行腳本,并負(fù)責(zé)與外界進(jìn)行交互的程序。腳本引擎一般很少獨(dú)立存在,而是要嵌入應(yīng)用程序中以擴(kuò)展應(yīng)用程序的行為,這個被嵌入腳本引擎的應(yīng)用程序稱為宿主程序。

嵌入的腳本引擎如圖1所示。圖1中,腳本引擎通過某種交互接口,根據(jù)腳本源程序描述的邏輯來控制應(yīng)用系統(tǒng)。根據(jù)宿主程序和腳本引擎之間的緊密層次不同,可將通信方式分為:(1)基于二進(jìn)制接口的通信。(2)基于公共運(yùn)行時環(huán)境的通信。(3)基于源碼接口的通信。本文實(shí)現(xiàn)的基于源碼的交互接口,即通信雙方基于共同的實(shí)現(xiàn)語言,在源代碼級上相互調(diào)用。

圖1 嵌入的腳本引擎

除了交互接口,作為腳本的解釋運(yùn)行平臺,腳本引擎包含了一個編譯器前端程序,前端程序負(fù)責(zé)將腳本源代碼經(jīng)過詞法分析、語法語義分析后生成字節(jié)碼格式的指令序列,然而這些指令序列是不能在目標(biāo)機(jī)器上執(zhí)行的。因此,在腳本引擎的最底層還要一個執(zhí)行字節(jié)碼指令的程序,這個程序即稱為虛擬機(jī)。

2 腳本語言的設(shè)計(jì)

在開發(fā)實(shí)現(xiàn)腳本引擎之前,先要確定引擎要解釋執(zhí)行的對象,即腳本語言。本文設(shè)計(jì)的腳本語言Vblet是VBA(Visual Basic for Applications)的子集,而 VBA的語法簡單易學(xué),在非專業(yè)程序員中有很大的用戶量,享有很高的聲譽(yù)。Vblet簡化了VBA語法,去掉了VBA語法中的一些限制,此外還根據(jù)需要擴(kuò)展了部分功能。下面是Vblet不同于VBA的一些重要的語法特性:

(1)交互執(zhí)行。這是借鑒了Python語言交互執(zhí)行的語法特點(diǎn),使得程序員可以單行執(zhí)行語句或計(jì)算表達(dá)式,而不限于一定要把代碼封裝在代碼塊中。

(2)不需要變量和參數(shù)聲明。VBlet是動態(tài)語言,變量的類型由腳本引擎從上下文中確定,變量可以不經(jīng)過聲明就可以使用。

(3)去掉了部分運(yùn)算符,比如冒號運(yùn)算符和逗號運(yùn)算符。

為了提高性能,Vblet去除了VBA中一些庫函數(shù)的支持,只保留一些在工程應(yīng)用領(lǐng)域比較常用的數(shù)學(xué)計(jì)算函數(shù)。

3 腳本引擎實(shí)現(xiàn)方案

Vblet引擎除了IDE的開發(fā)使用了MFC類庫之外,其他模塊的實(shí)現(xiàn)都是使用標(biāo)準(zhǔn)C++編寫的,這使得Vblet引擎只需要重新編寫IDE,或者修改小部分的核心代碼就能夠移植到其他平臺上。

3.1 前端編譯程序的實(shí)現(xiàn)

前端編譯程序?qū)⒛_本源程序的字符流經(jīng)過詞法分析、語法分析和語義分析后,生成字節(jié)碼表示的指令流,同時進(jìn)行語法檢查,對語法錯誤給出提示信息。另外,為了支持?jǐn)帱c(diǎn)調(diào)試和異常信息顯示,每行源程序和生成的字節(jié)碼指令的對應(yīng)關(guān)系也要在這里建立。

前端編譯器一般可以通過一些自動生成工具生成,但是這些自動生成的代碼效率都不夠高或者不好閱讀,因此本文采用手寫的方式實(shí)現(xiàn)前端編譯程序。前端程序由Scanner類和Compiler類兩大主要模塊組成。Scanner類主要負(fù)責(zé)源程序的詞法分析,它根據(jù)規(guī)定的詞法規(guī)則把源程序拆分成詞法單元,并進(jìn)行詞法檢查。Compiler類則充當(dāng)語法分析、語義分析和字節(jié)碼生成,而且這三者一步完成,中間不產(chǎn)生任何數(shù)據(jù)。另外,語法分析和語義分析出現(xiàn)的錯誤由類Parse_error負(fù)責(zé)處理。前端編譯器序列圖如圖2所示。

圖2 前端編譯器序列圖

Vblet語法分析采用自頂向下的預(yù)測分析法,驅(qū)動Scanner對象的token()成員函數(shù)為其產(chǎn)生一個詞法單元,當(dāng)需要后退時使用Scanner對象的stoken()方法保存一個不符合當(dāng)前產(chǎn)生式規(guī)則的詞法單元,以便下一個產(chǎn)生式規(guī)則的分析。類Compiler只包含一個public權(quán)限的成員函數(shù) Compile(),當(dāng) Compile()被調(diào)用時,將生成的對應(yīng)編譯單元的字節(jié)碼序列和符號信息、常量數(shù)據(jù)封裝在ByteCode對象中,并返回給被調(diào)用者。

3.2 虛擬機(jī)的實(shí)現(xiàn)

Vblet虛擬機(jī)是一個模擬的運(yùn)行時環(huán)境,是對Vblet腳本邏輯做出響應(yīng)的地方。根據(jù)體系結(jié)構(gòu)的不同,虛擬機(jī)分為如下兩種類型:(1)寄存器虛擬機(jī);(2)堆棧虛擬機(jī)。寄存器虛擬機(jī)具有相對較高的執(zhí)行效率,但實(shí)現(xiàn)機(jī)制復(fù)雜。而堆棧虛擬機(jī)實(shí)現(xiàn)起來則相對比較簡單,但是需要付出一定的性能代價(jià)。堆棧虛擬機(jī)由于Java和Python的成功而被證明它在模擬計(jì)算平臺上的優(yōu)勢[4-5]。因此,本文也將采用堆棧虛擬機(jī)作為Vblet腳本引擎的計(jì)算平臺。

圖3 Vblet虛擬機(jī)的體系結(jié)構(gòu)

如圖3所示,除了模擬處理器執(zhí)行字節(jié)碼指令外,Vblet虛擬機(jī)還包含了1個堆棧和 PC、SP、FP 3個寄存器。堆棧是虛擬機(jī)的運(yùn)行時棧,是函數(shù)調(diào)用和保存中間變量的地方,是整個虛擬機(jī)最核心的數(shù)據(jù)結(jié)構(gòu)。程序計(jì)數(shù)器寄存器PC是記錄下一條要執(zhí)行指令的序號;棧頂寄存器SP是在堆棧變化的過程中保存堆棧的頂部位置;幀指針寄存器FP則相當(dāng)于真實(shí)處理機(jī)的基址寄存器BX,保存當(dāng)前函數(shù)工作棧的棧底位置。這些數(shù)據(jù)結(jié)構(gòu)表示了整個Vblet虛擬機(jī)的運(yùn)行時環(huán)境。

Vblet是一種動態(tài)語言,所有數(shù)據(jù)類型的數(shù)據(jù)值在Vblet虛擬機(jī)中只以一種數(shù)據(jù)結(jié)構(gòu)VALUE存在,VALUE的定義如下:

在VALUE結(jié)構(gòu)體中,成員v_type表示了當(dāng)前VALUE對象保存的數(shù)據(jù)類型。VALUE不僅封裝了Vblet的所有基本數(shù)據(jù)類型,也封裝了數(shù)組和字節(jié)碼指令流等。實(shí)際上,虛擬機(jī)的堆棧和SP、FP寄存器所保存的就是VALUE對象或是VALUE對象的引用。

Vblet虛擬機(jī)在執(zhí)行字節(jié)碼指令的過程中,要經(jīng)常讀寫堆棧數(shù)據(jù)。因此,為了提高堆棧讀寫操作的速度,從而提高虛擬機(jī)性能,在實(shí)現(xiàn)過程中,定義了如下宏來進(jìn)行堆棧操作:

Vitual虛擬機(jī)指令系統(tǒng)共有16條數(shù)據(jù)傳輸指令、21條運(yùn)算指令、5條轉(zhuǎn)移指令和5條支持調(diào)試、異常和錯誤處理的指令,而執(zhí)行指令的機(jī)構(gòu)——處理器則由函數(shù)interpret()來模擬。interpret()函數(shù)從指令序列中逐條取得操作碼指令,根據(jù)操作碼的不同調(diào)用各自的處理函數(shù)。整個虛擬機(jī)的實(shí)現(xiàn)封裝在VVM類中。

3.3 集成接口的實(shí)現(xiàn)

腳本引擎的集成接口是指將腳本引擎嵌入應(yīng)用程序中擴(kuò)展后者功能時,負(fù)責(zé)兩者之間通信的API。所謂腳本引擎與應(yīng)用程序的通信,是指腳本引擎以動態(tài)庫或靜態(tài)庫的形式被加載進(jìn)應(yīng)用程序中,應(yīng)用程序向腳本引擎開放特定的全局函數(shù)和類及其屬性、方法,使腳本引擎可以調(diào)用這些全局函數(shù)、創(chuàng)建這些類的實(shí)例,并且通過該實(shí)例實(shí)現(xiàn)屬性的訪問和方法的調(diào)用。

為了實(shí)現(xiàn)全局函數(shù)和類的注冊,需要一些數(shù)據(jù)結(jié)構(gòu)來表示注冊對象的信息,以便腳本引擎能夠識別并使用注冊對象。相對來說,描述函數(shù)的信息比較簡單,只需要一個函數(shù)名和一個函數(shù)指針,函數(shù)指針的定義如下:

可見,extfuncptr是指向以VALUE數(shù)組為參數(shù)、返回一個VALUE值的函數(shù),extfuncptr函數(shù)指針統(tǒng)一了參數(shù)類型、個數(shù)和返回值類型不同的所有函數(shù)聲明。因此,需要把用一個能夠被extfuncptr指向的全局函數(shù)將注冊函數(shù)“包裝”起來。在包裝函數(shù)中,需要將Vblet腳本傳遞過來的VALUE參數(shù)轉(zhuǎn)換為C++數(shù)據(jù)類型的參數(shù),并調(diào)用注冊函數(shù)取得C++數(shù)據(jù)類型的返回值,再將返回值轉(zhuǎn)換成VALUE值返回給腳本引擎。

一個類的類信息包括類名、大小、初始化函數(shù)指針、類注冊的方法和屬性,用結(jié)構(gòu)體VLEXTCLASSINFO表示,如圖4所示。

圖4 注冊類MyAppExtClass與VlExtObject、VLEXTCLASSINFO三者之間關(guān)系的類圖

此外,還需要一些機(jī)制使得腳本引擎能夠引用腳本創(chuàng)建的注冊類的實(shí)例對象。把這個表示所有注冊類對象的“始祖”稱為 VlExtObject。VlExtObject包含一個表示引用計(jì)數(shù)的成員變量refcnt和兩個純虛函數(shù)GetExtClassInfo()和RegisterConstructor()。任何應(yīng)用程序需要向腳本引擎注冊的自定義類都必須繼承自類VlExtObject,每個注冊類包含一個靜態(tài)的VLEXTCLASSINFO實(shí)例,函數(shù)GetExtClassInfo()返回該VLEXTCLASSINFO實(shí)例,函數(shù)RegisterConstructor()將向該VLEXTCLASSINFO實(shí)例指定類實(shí)例的初始化函數(shù)——構(gòu)造器的包裝函數(shù)。此外,應(yīng)用程序注冊類還可以有自己的函數(shù)來向VLEXTCLASSINFO實(shí)例對象添加自己的方法和屬性。在腳本引擎內(nèi)部,通過使用指針來操作注冊類的實(shí)例。因此,在腳本中當(dāng)這樣的對象被復(fù)制時,實(shí)際上復(fù)制的是對象的指針,并且該對象的引用計(jì)數(shù)refcnt加1,而當(dāng)對象的引用在腳本中離開其作用域時,并不立即銷毀對象,而是將refcnt減1后如果為零才會使用delete將其銷毀。

整個腳本引擎被封裝成單件模式的CVbletEngine類中,該類包含了腳本引擎的啟動、初始化、腳本的運(yùn)行和停止等操作。CVbletEngine和集成接口的聲明對應(yīng)用程序可見,而集成接口始終與腳本引擎的虛擬機(jī)部分連接,在虛擬機(jī)指令集足夠完善的情況下,前端編譯器和集成接口的分離使得前端編譯器對應(yīng)用程序是透明的,這樣,當(dāng)需要增加腳本功能的時候,應(yīng)用程序可以不做修改。

4 與Python的性能比較

為了測試Vblet腳本引擎是否達(dá)到輕量級的要求,在Intel 586 PC機(jī)上用該腳本引擎解釋執(zhí)行如下這段Vblet腳本代碼:

同時在同一平臺上用Cpython2.6解釋執(zhí)行對應(yīng)的Python程序,最后通過對兩者的初始化時間、編譯時間、運(yùn)行時間、內(nèi)存使用量和生成字節(jié)碼個數(shù)進(jìn)行了比較,結(jié)果如表1所示。

表1 Vblet腳本引擎和CPython2.6的性能比較

從表1可以看出,雖然Vblet的編譯時間高于CPython,但是初始化時間要遠(yuǎn)遠(yuǎn)優(yōu)于Cpython。這是因?yàn)镻ython包含了強(qiáng)大的功能模塊,引擎運(yùn)行前需要加載這些模塊,并初始化復(fù)雜的運(yùn)行時環(huán)境和類型環(huán)境。另外,由于Vblet的類型機(jī)制比Python簡單,虛擬機(jī)在數(shù)據(jù)的存取上比CPython更快,即使生成的字節(jié)碼個數(shù)略多于CPython,也能達(dá)到更優(yōu)的運(yùn)行時間。再加上Vblet在內(nèi)存上的優(yōu)勢,表明Vblet完全可以作為一個輕型的腳本引擎嵌入在應(yīng)用程序中。

基于嵌入或擴(kuò)展腳本的混合語言編程是實(shí)現(xiàn)可定制工程應(yīng)用系統(tǒng)的有效方法。本文通過借鑒VBA和Python的語法特點(diǎn)設(shè)計(jì)了語法簡單易學(xué)的腳本語言Vblet,設(shè)計(jì)并實(shí)現(xiàn)了Vblet的基于堆棧虛擬機(jī)的輕量級腳本引擎。測試結(jié)果表明,腳本引擎能夠正確運(yùn)行Vblet代碼,占有較小的內(nèi)存空間,在進(jìn)行簡單的規(guī)則計(jì)算時具有明顯的執(zhí)行效率。同時,腳本引擎對被嵌入C++應(yīng)用程序的支持,使得腳本能夠透明地使用應(yīng)用程序注冊的類和函數(shù),從而達(dá)到增強(qiáng)應(yīng)用系統(tǒng)靈活性、可定制性和擴(kuò)展性的目的。

[1]JOHN K.Ousterhout scripting:higher-level programming for the 21st century[J].IEEE Computer Magazine,1998,31(3).

[2]XIE Q, LIU J, CHOU P H.Tapper: a lightweight scripting engine forhighly constrained wireless sensornodes[C].Information Processing in SensorNetworks, 2006.IPSN 2006.The Fifth International Conference on, 2006:342-349.

[3]Alex Varanese.Game Scripting Mastery[M].Premier Press,2003.

[4]LINDHOLM T, YELLIN F.Java virtual machine specification[M].Boston, MA, USA:Addison-Wesley Longman Publishing Co., Inc,1999.

[5]ALFRED R S, AHO V, JEFFREY D.Ullman.compilers:principles, techniques, and tools[M].2rd.Boston: Pearson/Addison Wesley,2007.

猜你喜歡
堆棧腳本字節(jié)
酒駕
基于行為監(jiān)測的嵌入式操作系統(tǒng)堆棧溢出測試*
No.8 字節(jié)跳動將推出獨(dú)立出口電商APP
安奇奇與小cool 龍(第二回)
No.10 “字節(jié)跳動手機(jī)”要來了?
簡談MC7字節(jié)碼
快樂假期
基于堆棧自編碼降維的武器裝備體系效能預(yù)測
小編的新年愿望
一種用于分析MCS-51目標(biāo)碼堆棧深度的方法
惠安县| 南木林县| 治多县| 安达市| 塔城市| 怀集县| 阿鲁科尔沁旗| 临湘市| 昆山市| 西安市| 陆川县| 丰宁| 莱芜市| 隆尧县| 德阳市| 天水市| 南康市| 安义县| 虹口区| 开原市| 抚远县| 明光市| 新巴尔虎右旗| 安图县| 鲜城| 香格里拉县| 惠水县| 黑龙江省| 屏东县| 东阿县| 萨嘎县| 铁岭县| 南召县| 南华县| 乌拉特中旗| 昌都县| 香河县| 靖江市| 淮安市| 西乌珠穆沁旗| 金门县|