• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-341  評(píng)論-2670  文章-0  trackbacks-0
             
            花了兩天時(shí)間,集成了以前開發(fā)的山寨Office2007的Ribbon框架,和之前開發(fā)的Intellisense算法和控件,打算做一個(gè)可以點(diǎn)擊Run之后出一只小烏龜畫圖的小demo哇哈哈。然后以此作為Vczh Library++ 3.0的第一個(gè)Release的Demo。

            vle.exe大概已經(jīng)做完了,現(xiàn)在checkin了一個(gè)vlscript.dll的框架,但是還沒有實(shí)現(xiàn)里面的具體的函數(shù)。到時(shí)候這個(gè)用C#寫的demo就會(huì)調(diào)用C++寫的vlscript.dll,來(lái)實(shí)現(xiàn)烏龜畫圖功能。

            這個(gè)破IDE的代碼在“Tools\Release\VleSource\VlTurtle\VlTurtle.csproj”,大家有興趣的話可以去下載。打開那個(gè)solution,然后用release編譯,然后再release目錄下執(zhí)行Deploy.bat之后,就可以F5看到效果了。

            此時(shí)的心情簡(jiǎn)直無(wú)以倫比。

            posted @ 2011-02-24 08:54 陳梓瀚(vczh) 閱讀(25338) | 評(píng)論 (26)編輯 收藏
                Vczh Library++ 3.0這破東西也做了一年半了,因此打算給它制作第一個(gè)Release。這個(gè)Release將計(jì)劃包含下面的東西:

                1、vle.exe。這是一個(gè)編譯器和虛擬機(jī)的命令行程序。通過這個(gè)程序可以把NativeX程序編譯成assembly、可以執(zhí)行基于控制臺(tái)的assembly程序、以及運(yùn)行我為這個(gè)平臺(tái)開發(fā)的一個(gè)單元測(cè)試工具。這些是已經(jīng)開發(fā)完成的了。接下來(lái)還要給vle.exe添加鏈接功能。所謂的鏈接功能是指將多個(gè)assembly合并成一個(gè),并且預(yù)先展開所有模板函數(shù)、模板變量和concept mapping等等。雖然NativeX程序跟C語(yǔ)言很像(多了泛型和concept mapping),也需要頭文件,不過其機(jī)制并不像#include那樣把文件復(fù)制進(jìn)去,而是類似pascal。為了調(diào)用另一個(gè)assembly而必須的頭文件可以讓編譯器在編譯的過程中產(chǎn)生,不需要人去維護(hù)。

                2、vlscript.dll。這是一個(gè)編譯器和虛擬機(jī)的函數(shù)庫(kù)。這個(gè)函數(shù)庫(kù)將會(huì)制作成C而不是C++的格式。我在盡可能讓vlscript.dll包含vle.exe所具有的全部功能以外,還要添加一些其他的譬如可以遍歷一個(gè)assembly里面各種聲明什么的的一些功能,以便二次開發(fā)的時(shí)候可以利用vlscript.dll完成很多有趣的事情。

                3、TurtleDotNet.exe。這暫時(shí)還是一個(gè)設(shè)想。還記得舊社會(huì)的LOGO語(yǔ)言吧?最近新出的Microsoft Small Basic也跟LOGO一樣可以使用烏龜畫圖。這是一個(gè)很好的教程式的函數(shù)庫(kù),因此我也打算做一個(gè)。因?yàn)闀r(shí)間的關(guān)系,我并不會(huì)在第一個(gè)Release里面包含一個(gè)NativeX的IDE,而只是包含一個(gè)C#寫的窗口程序,可以讀取assembly并提供烏龜畫圖的功能。這也同時(shí)展示了C#如何跟C的dll進(jìn)行互操作。

                4、各種NativeX的demo?,F(xiàn)在已經(jīng)開發(fā)好的demo包含一個(gè)四則運(yùn)算分析器的程序。這個(gè)程序從字符串生成語(yǔ)法樹(NativeX也可以利用虛函數(shù)表來(lái)模擬多態(tài),雖然這需要人肉完成而不是語(yǔ)法完成),然后做各種事情。我還附帶一個(gè)四則運(yùn)算分析庫(kù)的單元測(cè)試程序。另一個(gè)開發(fā)好的demo是一個(gè)猜數(shù)字游戲。程序隨機(jī)產(chǎn)生4個(gè)0-9范圍內(nèi)的數(shù)字,然后讓你也輸入4個(gè),告訴你命中了多少,半命中(數(shù)字對(duì)位置不對(duì))了多少,然后一直到你放棄或者猜中為止,程序結(jié)束。

                上面已經(jīng)開發(fā)好的東西已經(jīng)check in在codeplex里面了,感興趣的話可以自行下載。不過那個(gè)vle.exe是以源代碼的形式存放的(不像Release,都是編譯好的東西),因此如果想要看到效果的話,需要裝有Visual Studio 2010。編譯完之后,在Tools\Release\Vlpp\和Tools\Release\Vlpp\ScriptSample\CrossAssemblyInvoking\Binary\下面有Readme.txt,會(huì)告訴你在編譯完vle.exe之后如何部署他們,使得上述的兩個(gè)NativeX demo可以編譯和運(yùn)行。

                拭目以待吧,哇哈哈。
            posted @ 2011-02-19 23:29 陳梓瀚(vczh) 閱讀(3479) | 評(píng)論 (1)編輯 收藏

            流水賬。

            今年春節(jié)回家的時(shí)候帶了三本書。去年中秋節(jié)的時(shí)候外服發(fā)了200塊錢的卓越卡(啊,不是公司的,啊,說出來(lái)沒人信),我覺得自己還是個(gè)看書的人,因此買了8本書。不過我覺得自己大概不是個(gè)做文學(xué)的人,所以買的都是些什么數(shù)學(xué)啊物理的民科書。里面有本講時(shí)間的,原本以為是物理,結(jié)果是本哲學(xué)書,堅(jiān)持到看完了才知道。之后8本只看了1/4本,于是到了春節(jié)。家里的電腦是02年買的,到現(xiàn)在就跟屎一樣,因此給家里添置了一臺(tái)。不過在這之前的三天,只能把上網(wǎng)的時(shí)間用來(lái)看書了,然后把這本書給解決掉了。接下來(lái)解決了那本哲學(xué)的,現(xiàn)在在看一本我也不知道他在說什么的。

            我是懷著一種什么心情來(lái)看書的呢?覺得不看書就如同有負(fù)罪感一般,因此總是千方百計(jì)想把它們看完??赐甑臅r(shí)候是什么感覺呢?除了接收到了知識(shí)感到欣喜以外,還有一種神奇的感覺類似“如釋重負(fù)”的感覺。我覺得很不舒服。

            對(duì)比起自己更加喜愛的編程,我突然想起在大學(xué)的時(shí)候,不寫程序也是有負(fù)罪感的,不過現(xiàn)在沒有了。當(dāng)時(shí)其實(shí)我也很坦白,說不寫程序會(huì)有負(fù)罪感,并且引以為豪,以此證明自己是一個(gè)愛寫程序的人?,F(xiàn)在想起來(lái)是有點(diǎn)滑稽。人每天都說話,說話就是生活,但有一兩天你沒說話,你有沒有負(fù)罪感呢?想必是沒有的。沒有人會(huì)覺得一兩天不說話會(huì)對(duì)不起自己或者對(duì)不起別人。當(dāng)然吃飯是不一樣的,不吃飯是會(huì)死的。寫程序?qū)τ诂F(xiàn)在的我來(lái)說就如同說話。寫程序就是生活,但是有一兩天你沒寫程序,其實(shí)也覺得沒什么,這種事常有。但是自己是不會(huì)因此就再也不寫程序的,就如同你自己不會(huì)因?yàn)橐粌商觳徽f話就永遠(yuǎn)不說話一樣。當(dāng)然如果你一兩天不吃飯,估計(jì)就永遠(yuǎn)不吃飯了……

            那寫程序?qū)τ谖沂鞘裁茨??初中的時(shí)候,覺得寫程序很有意思,自己搞著搞著總能擺弄出一點(diǎn)事情來(lái),沒有理過微軟的fellow們。高中的時(shí)候,覺得寫程序是一種追求,很有遠(yuǎn)大理想,看到了微軟主頁(yè)上的那三十多個(gè)fellow,覺得自己將來(lái)就是想成為他們一樣的人。大學(xué)的時(shí)候,覺得寫程序是一種義務(wù),雖然自己再也不拿fellow當(dāng)終極目標(biāo)了,覺得修煉自己就是一種快樂,覺得反正自己的目標(biāo)大概是要成為一個(gè)厲害的人的,不管將來(lái)是不是fellow都無(wú)所謂。到了現(xiàn)在,寫程序儼然變成了生活的一部分。自己仍然對(duì)自己有嚴(yán)厲的要求,寫出來(lái)的代碼要高性能要好改還要富有藝術(shù)感,但已經(jīng)不覺得厲害不厲害是一件多么大不了的事情了。我就是寫程序,寫程序就是我,反正遲早是要厲害的,那只是時(shí)間問題,也就不執(zhí)著于那個(gè)了。

            因此我現(xiàn)在沒有宣稱自己是喜歡寫程序的人了,而宣稱我自己就是寫程序的人。想必當(dāng)年覺得“喜歡寫程序”就是自己身份的一個(gè)標(biāo)簽,認(rèn)為只要不寫程序,我也就不成為我,而且對(duì)不起貼在身上的標(biāo)簽了。如今,程序還是在寫,但標(biāo)簽已經(jīng)沒了。激情在,理想在,功夫也在,程序也一直在寫。只是寫程序已經(jīng)變成了自己想寫就寫,不想寫就不寫,隨心所欲的狀態(tài)了。

            因此對(duì)比起看書,說不定自己仍然很在意“喜歡看民科書”的標(biāo)簽。實(shí)際上我也是這么做的,對(duì)外宣稱自己是喜歡看民科書的人,而不是看民科書的人,跟寫程序相反。所以大概會(huì)有這種感覺罷。

            想想以前也有過不少愛好,譬如4歲的時(shí)候開始的鋼琴,8歲的時(shí)候開始的看民科書。10歲的時(shí)候開始的糊變形金剛,14歲的時(shí)候開始的寫程序。堅(jiān)持下來(lái)的也就是看民科書跟寫程序了。然后經(jīng)歷都是差不多的,一個(gè)事情自己做得好,然后就慢慢有了追求,然后就變成了標(biāo)簽,如果順利的話那個(gè)事情也就成為了生活了。

            什么時(shí)候看民科書能成為生活呢?我想能看的民科書的數(shù)量也是有限的,大概也只能當(dāng)個(gè)標(biāo)簽吧,說不定哪天自己寫程序?qū)懰?,也寫寫跟編程相關(guān)的民科書,然后就貼上了個(gè)“喜歡寫民科書”的標(biāo)簽了。

            posted @ 2011-02-08 09:09 陳梓瀚(vczh) 閱讀(4235) | 評(píng)論 (13)編輯 收藏
                今天做了一整天終于優(yōu)化了kd-tree和Ambient Occlusion。先上代碼,后上圖。

                首先是做了一個(gè)kd-tree,渲染一幅有一千三百多萬(wàn)個(gè)三角形的圖僅需要0.4秒。


                其次是Ambient Occlusion


                第三幅是對(duì)比圖。上圖有Ambient Occlusion,下圖沒有。
             

                再加兩張(博客發(fā)布后才添加的)。算法沒變,只不過多了模型,就暫時(shí)不更新代碼了:


            posted @ 2011-01-21 22:45 陳梓瀚(vczh) 閱讀(11470) | 評(píng)論 (11)編輯 收藏
                最近休了幾天假玩一玩所以進(jìn)展比較慢。直到今天我做了高亮、4*4全屏幕消鋸齒、圓柱體和三角形模型。不過目前三角形我沒有用kd-tree,所以巨慢。在i7上做一個(gè)36096個(gè)面的Menger Sponge再加上全屏幕消鋸齒花掉了20分鐘……

                點(diǎn)擊這里下載當(dāng)前進(jìn)度的代碼。

                下面開始貼圖:

                Blinn Specular:


                全屏幕消鋸齒:


                傳說中三萬(wàn)多個(gè)三角形的Menger Sponge


                無(wú)聊做的圓柱體求交函數(shù):
            posted @ 2011-01-20 09:10 陳梓瀚(vczh) 閱讀(5188) | 評(píng)論 (9)編輯 收藏

                每年總有那么幾個(gè)星期不想寫編譯器,這個(gè)時(shí)候做做ray tracing就變成一件很美妙的事情了。因此這個(gè)星期重寫了當(dāng)年那個(gè)超爛的光線追蹤,然后加上了貼圖的功能。當(dāng)然圖是可以直接貼在物體上的,還支持了法線貼圖,譬如說下面做的地球在不同方向的光線的照射下顯得有立體效果:


                之所以FPS有16是因?yàn)槲乙呀?jīng)不再當(dāng)年那個(gè)破thinkpad上渲染,而在一個(gè)i7四核超線程三通道的CPU上做了。渲染的時(shí)候?yàn)榱撕?jiǎn)單,把屏幕等分成了八行,然后創(chuàng)建八個(gè)線程分別綁定到八個(gè)CPU上面去(SetThreadAffinityMask),最后渲染完出來(lái)。當(dāng)然比起那些專業(yè)的還是顯得相當(dāng)慢,現(xiàn)在很多光線追蹤軟件都用了GPU來(lái)做,不過我GPU也沒用,SSE指令也沒用,就純粹C++寫。如今也懶得用C++做GUI了,所以把核心用C++做成了之后,export幾個(gè)函數(shù)出來(lái),用C#的P/Invoke直接調(diào)用。C++渲染完以后給一個(gè)HBITMAP,C#拿過來(lái)就往窗口上畫,還是十分方便的哈。多語(yǔ)言開發(fā)萬(wàn)歲。

                重寫了光線追蹤之后仍然把折射和反射給做了,因此可以做出個(gè)類似凸透鏡一樣的東西:


                需要提一下的是,做貼圖的時(shí)候?qū)崿F(xiàn)了nearest、linear和bicubic三種插值方法。nearest基本上就是不插值,所以放大了之后會(huì)有馬賽克效果。linear是線性插值,如果放得太大還是能看出一點(diǎn)模糊的馬賽克。bicubic效果就好很多了,如果大家有興趣的話可以到這里去看。為了達(dá)到更好的效果,后面還有計(jì)劃做ray differential和各向異性過濾。ray differential之后就可以做photon mapping(一種比較高效的全局光照模型)了。做完photon mapping之后,無(wú)聊的心情大概就結(jié)束了,可以繼續(xù)寫編譯器了吧。

                嗯嗯,雖然ray differential和photon mapping還沒做,我就先把代碼丟上啦,不僅可以做備份,大家也能搞下來(lái)看一看。當(dāng)然需要有Visual Studio 2010才能編譯的。選擇release編譯之后到release文件夾下去啟動(dòng),debug的話慢的不能忍。而且我的多線程模型是一個(gè)核(超線程的話算兩個(gè))一個(gè)線程,那些古老的雙核CPU大概性能會(huì)很慘不忍賭吧……

             

            posted @ 2011-01-08 23:54 陳梓瀚(vczh) 閱讀(6968) | 評(píng)論 (15)編輯 收藏
                根據(jù)之前的計(jì)劃,讓Vczh Library++3.0的編譯器變成語(yǔ)言的公共后端的同時(shí),開放幾乎所有層的API讓人們可以從各種基礎(chǔ)上開發(fā)自己的DSL,所以在做完NativeX之后,接下來(lái)的事情就是寫必要程度的庫(kù)之后,做一些基礎(chǔ)設(shè)施讓托管語(yǔ)言可以被編譯到NativeX上面去。因此現(xiàn)在需要完成的東西有:
                1、內(nèi)存池,用來(lái)實(shí)現(xiàn)NativeX的new和delete。這個(gè)已經(jīng)做完了。下一篇文章將詳細(xì)描述這個(gè)內(nèi)存池的結(jié)構(gòu)。
                2、線程和同步對(duì)象。這個(gè)很快就做完了。NativeX的線程不僅需要有基本的功能,還需要做一個(gè)內(nèi)置的消息循環(huán)。當(dāng)一部分線程選擇使用消息循環(huán)作為它的結(jié)構(gòu)的時(shí)候,其他線程就可以把一些代碼片段發(fā)送給這個(gè)線程執(zhí)行了。并且要做到跟C#一樣,當(dāng)線程被外部強(qiáng)行中止的時(shí)候,線程內(nèi)部會(huì)拋出一個(gè)異常,然后讓線程自己去處理。
                3、基本的字符串和數(shù)學(xué)函數(shù)庫(kù)
                4、垃圾收集器。這個(gè)垃圾收集器是不屬于NativeX的語(yǔ)法的。這個(gè)垃圾收集器將被開發(fā)成一個(gè)NativeX的函數(shù)庫(kù),用于支持更高層次語(yǔ)言的編譯。

                當(dāng)然為了完成這個(gè)目標(biāo),我給NativeX加上了一些無(wú)關(guān)痛癢但是卻會(huì)帶來(lái)方便的語(yǔ)法:
                1、#public編譯選項(xiàng)。只要在structure、function或者variable上面標(biāo)記了#public的話,這個(gè)特殊的標(biāo)志就會(huì)被記錄在編譯后的二進(jìn)制文件的元數(shù)據(jù)里面。NativeX現(xiàn)在的元數(shù)據(jù)分為兩種。第一種是運(yùn)行時(shí)元數(shù)據(jù)。之前的文章提到NativeX的模板函數(shù)和其他模板的東西都是可以直接編譯進(jìn)二進(jìn)制文件的,因此模板函數(shù)的實(shí)例化實(shí)際上是在運(yùn)行是的時(shí)候做的。不過現(xiàn)在我也實(shí)現(xiàn)了一個(gè)編譯選項(xiàng)(不屬于NativeX,需要用C++去控制),可以在編譯完所有二進(jìn)制文件之后,將他們合并成一個(gè)大的二進(jìn)制文件并且預(yù)先展開所有需要的模板函數(shù)。這一步可以用于加快運(yùn)行速度,還可以為將來(lái)運(yùn)行時(shí)編譯成x86或者x64做準(zhǔn)備。當(dāng)#public被記錄到元數(shù)據(jù)里面之后,編譯器就可以從編譯好的二進(jìn)制文件里面重新還原出該二進(jìn)制文件的頭文件。
                2、sizeof(type)、offsetof(type::member)、typeof(expression)和typeof(type::member)。這個(gè)純粹是為了配合內(nèi)存池和未來(lái)的垃圾收集器而做出來(lái)的。當(dāng)你需要alloc一個(gè)東西的時(shí)候,你顯然需要知道一個(gè)類型的尺寸,而這個(gè)是會(huì)跟隨著不同的情況而變化的,所以就給出了這些東西,讓編譯器幫助你計(jì)算各種跟類型相關(guān)的數(shù)字。
                3、常量定義。這個(gè)還沒實(shí)現(xiàn),到時(shí)候的語(yǔ)法可能會(huì)是constant type name = value;。而且當(dāng)他被標(biāo)記上#public之后,就可以在生成頭文件的時(shí)候包含該常量了。

                為了讓C++可以給NativeX添加外部函數(shù),我做了一個(gè)輔助類用來(lái)簡(jiǎn)化這個(gè)過程。舉個(gè)例子,我們需要實(shí)現(xiàn)一個(gè)叫做MemCreate的創(chuàng)建內(nèi)存池的函數(shù)。首先我們需要在NativeX里面聲明它:
            1 structure __ForeignHandle
            2 {
            3 }
            4 
            5 foreign function __ForeignHandle* __MemCreate()
            6     alias SystemCoreForeignFunctions.MemCreate;

                這里的alias后面的一大串是外部函數(shù)的名稱,而__MemCreate則是他對(duì)于NativeX的名稱。接下來(lái)我們就得在C++實(shí)現(xiàn)這個(gè)函數(shù)了:
              1 #include "ScriptingUtilityForeignFunctions.h"
              2 #include "..\Languages\LanguageRuntime.h"
              3 #include "..\..\Entity\GeneralObjectPoolEntity.h"
              4 #include "..\..\Threading.h"
              5 
              6 namespace vl
              7 {
              8     namespace scripting
              9     {
             10         namespace utility
             11         {
             12             using namespace basicil;
             13             using namespace entities;
             14             using namespace collections;
             15 
             16             class SystemCoreMemoryManagerPlugin : public LanguagePlugin
             17             {
             18             public:
             19                 struct PoolPackage
             20                 {
             21                     GeneralObjectPool                    pool;
             22                     CriticalSection                        cs;
             23 
             24                     PoolPackage(vint poolUnitSize, vint poolUnitCount)
             25                         :pool(poolUnitSize, poolUnitCount)
             26                     {
             27                     }
             28                 };
             29 
             30                 List<Ptr<PoolPackage>>                    pools;
             31                 CriticalSection                            pluginCs;
             32 
             33                 class MemCreate : public Object, public IBasicILForeignFunction
             34                 {
             35                 protected:
             36                     SystemCoreMemoryManagerPlugin*        plugin;
             37                 public:
             38                     MemCreate(SystemCoreMemoryManagerPlugin* _plugin)
             39                         :plugin(_plugin)
             40                     {
             41                     }
             42 
             43                     void Invoke(BasicILInterpretor* interpretor, BasicILStack* stack, void* result, void* arguments)
             44                     {
             45                         LanguageArgumentReader reader(result, arguments, stack);
             46                         Ptr<PoolPackage> pool=new PoolPackage(1048576256);
             47 
             48                         CriticalSection::Scope scope(plugin->pluginCs);
             49                         plugin->pools.Add(pool);
             50                         reader.Result<PoolPackage*>()=pool.Obj();
             51                     }
             52                 };
             53 
             54                 static vint MemAlloc(void* result, void* arguments)
             55                 {
             56                     LanguageArgumentReader reader(result, arguments);
             57                     PoolPackage* pool=reader.NextArgument<PoolPackage*>();
             58                     vint size=reader.NextArgument<vint>();
             59 
             60                     CriticalSection::Scope scope(pool->cs);
             61                     reader.Result<char*>()=pool->pool.Alloc(size);
             62                     return reader.BytesToPop();
             63                 }
             64 
             65                 static vint MemFree(void* result, void* arguments)
             66                 {
             67                     LanguageArgumentReader reader(result, arguments);
             68                     PoolPackage* pool=reader.NextArgument<PoolPackage*>();
             69                     char* pointer=reader.NextArgument<char*>();
             70                     
             71                     CriticalSection::Scope scope(pool->cs);
             72                     reader.Result<bool>()=pool->pool.Free(pointer);
             73                     return reader.BytesToPop();
             74                 }
             75 
             76                 static vint MemIsValidHandle(void* result, void* arguments)
             77                 {
             78                     LanguageArgumentReader reader(result, arguments);
             79                     PoolPackage* pool=reader.NextArgument<PoolPackage*>();
             80                     char* pointer=reader.NextArgument<char*>();
             81                     
             82                     CriticalSection::Scope scope(pool->cs);
             83                     reader.Result<bool>()=pool->pool.IsValid(pointer);
             84                     return reader.BytesToPop();
             85                 }
             86 
             87                 static vint MemGetHandleSize(void* result, void* arguments)
             88                 {
             89                     LanguageArgumentReader reader(result, arguments);
             90                     PoolPackage* pool=reader.NextArgument<PoolPackage*>();
             91                     char* pointer=reader.NextArgument<char*>();
             92                     
             93                     CriticalSection::Scope scope(pool->cs);
             94                     reader.Result<vint>()=pool->pool.GetSize(pointer);
             95                     return reader.BytesToPop();
             96                 }
             97 
             98                 static vint MemGetOwnerHandle(void* result, void* arguments)
             99                 {
            100                     LanguageArgumentReader reader(result, arguments);
            101                     PoolPackage* pool=reader.NextArgument<PoolPackage*>();
            102                     char* pointer=reader.NextArgument<char*>();
            103                     
            104                     CriticalSection::Scope scope(pool->cs);
            105                     reader.Result<char*>()=pool->pool.GetHandle(pointer);
            106                     return reader.BytesToPop();
            107                 }
            108             protected:
            109                 bool RegisterForeignFunctions(BasicILRuntimeSymbol* symbol)
            110                 {
            111                     return
            112                         symbol->RegisterForeignFunction(L"SystemCoreForeignFunctions", L"MemCreate"new MemCreate(this)) &&
            113                         symbol->RegisterLightFunction(L"SystemCoreForeignFunctions", L"MemAlloc", MemAlloc) &&
            114                         symbol->RegisterLightFunction(L"SystemCoreForeignFunctions", L"MemFree", MemFree) &&
            115                         symbol->RegisterLightFunction(L"SystemCoreForeignFunctions", L"MemIsValidHandle", MemIsValidHandle) &&
            116                         symbol->RegisterLightFunction(L"SystemCoreForeignFunctions", L"MemGetHandleSize", MemGetHandleSize) &&
            117                         symbol->RegisterLightFunction(L"SystemCoreForeignFunctions", L"MemGetOwnerHandle", MemGetOwnerHandle);
            118                 }
            119             };
            120 
            121             Ptr<LanguagePlugin> CreateMemoryManagerPlugin()
            122             {
            123                 return new SystemCoreMemoryManagerPlugin();
            124             }
            125         }
            126     }
            127 }

                外部函數(shù)分兩種,一種是需要全局狀態(tài)的,而另一種不需要。在不需要的時(shí)候,我提供了一個(gè)不會(huì)跟虛函數(shù)打交道的接口來(lái)加快(雖然其實(shí)可以忽略,只是為了滿足那些有畸形性能欲望的人的心理而已)運(yùn)行時(shí)的性能。

                就先說到這里了。NativeX函數(shù)庫(kù)的測(cè)試用例已經(jīng)開始在做了,可以去Vczh Library++3.0下載最新代碼之后,在下面的目錄找到:
                Library\Scripting\Utility\:這里是外部函數(shù)的實(shí)現(xiàn)。
                UnitTest\Binary\ScriptCoreLibrary\:這里是NativeX將外部函數(shù)簡(jiǎn)單的封裝起來(lái)之后的函數(shù)庫(kù),以及他們的測(cè)試用例。我為NativeX實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的單元測(cè)試框架。
                UnitTest\UnitTest\TestScripting_Utility_System_CoreNative.cpp:這個(gè)是NativeX單元測(cè)試框架的host。
            posted @ 2011-01-01 05:14 陳梓瀚(vczh) 閱讀(3884) | 評(píng)論 (7)編輯 收藏

            距離元旦也就十幾天了,2010就要過去了。從第一行Hello World到現(xiàn)在,已經(jīng)有10年了,所幸從未中斷,因此從某種意義上來(lái)講,我已經(jīng)寫了10年的程序了。每個(gè)人回顧以往走過的路的時(shí)候,往往會(huì)發(fā)現(xiàn)今天的結(jié)果來(lái)源于之前的一些“關(guān)鍵步驟”。顯然我也是一樣的,所以這次的總結(jié)跟以往不同,就不列出之前做過的種種程序,而是聊一聊這些關(guān)鍵步驟和影響我的人給我?guī)?lái)的影響。當(dāng)然算得上關(guān)鍵步驟的,只能是那些能夠左右人生軌跡的事情。

            老爸、外婆和爺爺
            這倒不是說老爸老媽把我生下來(lái)了怎么樣怎么樣。老爸在我幼小的時(shí)候教我一些簡(jiǎn)單的數(shù)學(xué),給了我很多書,還有外婆教我識(shí)字,結(jié)果就是我從大概二年級(jí)開始就能夠閱讀老爸留給我的一些科普讀物了。這些科普讀物是他小的時(shí)候看的,上面還有語(yǔ)錄,每一篇的幾位都是偉大的思想指引我們前進(jìn)云云。當(dāng)然這并不妨礙書本的內(nèi)容的質(zhì)量。老爸的書也都一直保存得很好,后來(lái)我爺爺也給我弄了一套科普的啟蒙讀物,現(xiàn)在還保留著,只不過很多翻爛了。這套書是翻譯的,小日本寫的,不過內(nèi)容卻十分豐富。里面包含了數(shù)學(xué)、物理、生物、手工和一些其他的很多東西,甚至連汽車和飛機(jī)的結(jié)構(gòu)都有。加上外婆也十分贊成并且指引我看這些書,其結(jié)果就是從小就對(duì)一些科學(xué)的事情感興趣——當(dāng)然也包括數(shù)學(xué)。從三年級(jí)開始到中學(xué),老爸就給我買一些數(shù)學(xué)奧林匹克的書。當(dāng)然這并不是讓我去參加競(jìng)賽用的,只是他覺得既然他小時(shí)候也喜歡搞數(shù)學(xué)那我也應(yīng)該繼承這個(gè)優(yōu)點(diǎn),從而就讓我去弄那些東西了。在五年級(jí)的時(shí)候,那次全市的數(shù)學(xué)競(jìng)賽老爸也幫了我很多,我也拿了很好的成績(jī)。維持了那么多年從不間斷的強(qiáng)大的自信心和信念就是從這個(gè)時(shí)候開始的。人喜歡搞一些事情很大程度上都是因?yàn)槟切┦虑樵?jīng)被搞得很好,因此我也就喜歡上數(shù)學(xué)了,后來(lái)有機(jī)會(huì)體驗(yàn)到了數(shù)學(xué)的定理和公式的美妙之處,讓我一發(fā)不可收拾。

            汕頭市華僑中學(xué)的領(lǐng)導(dǎo)們
            這是個(gè)好學(xué)校。我整個(gè)讀書的生涯,唯一一次體驗(yàn)到什么是素質(zhì)教育就是在這里??墒呛髞?lái)由于各種微妙的問題導(dǎo)致這所學(xué)校的競(jìng)爭(zhēng)力下降,這從某種程度上來(lái)說算是悲哀吧。我第一次接觸到編程就是在這里。初中二年級(jí)的時(shí)候,學(xué)校開Basic的課,但是并沒有試圖讓我們參加競(jìng)賽——其實(shí)連提都沒提,只是就這么當(dāng)成正常的課來(lái)上。把編程學(xué)得好,滿足下面兩個(gè)條件的話基本上可以說就是在走捷徑,第一個(gè)是會(huì)從心底里對(duì)公式和定理產(chǎn)生美的感覺,第二個(gè)就是要持續(xù)不斷地在編程上體會(huì)到成就感。這也是我為什么在一篇寫給師弟師妹的文章里面提到剛開始的時(shí)候?qū)W習(xí)制作軟件界面也是十分重要的,因?yàn)檫@會(huì)讓你產(chǎn)生源源不斷的動(dòng)力,好讓你給以后學(xué)習(xí)算法打下精神基礎(chǔ)。QBasic教完自然就教Visual Basic了,當(dāng)然都是很淺的內(nèi)容。不過我由于受到吸引,從那以后就一直往書店里面跑,去掃蕩各種跟Visual Basic有關(guān)的書,后來(lái)學(xué)到了不少。我初二在新華書店很偶然的發(fā)現(xiàn)了那本《Visual Basic高級(jí)圖形程序設(shè)計(jì)教程》,不過坦白說我其實(shí)是被插圖吸引的。那個(gè)時(shí)候發(fā)現(xiàn)Visual Basic竟然可以僅憑代碼繪制出那么漂亮的圖形,從而興趣提高了不少。不過學(xué)習(xí)這個(gè)也是很辛苦的,這導(dǎo)致我不得不在初三的時(shí)候就去尋找并學(xué)習(xí)立體解析幾何,高中的時(shí)候提前學(xué)習(xí)數(shù)學(xué)分析,都是為了看懂這本書啊。這本書我從初二一直看到上了大學(xué),還帶去宿舍看,看了好多年才把它每一頁(yè)都琢磨透。這從某種程度上來(lái)說也算是緣分吧。

            英語(yǔ)補(bǔ)習(xí)老師李培濤
            初中的英語(yǔ)被我一不小心搞的一塌糊涂,甚至到了快不及格的地步了,所幸當(dāng)時(shí)我媽(特別感謝)非得讓我找一個(gè)英語(yǔ)的補(bǔ)習(xí)老師,所以就遇到了李老師了。雖然說補(bǔ)習(xí)課是要交錢的,不過李老師人倒是很好,不是為了收錢而收錢,還是花了很大精力實(shí)踐了因材施教的。我的英語(yǔ)就被他給搞好了。我們知道英語(yǔ)對(duì)于編程來(lái)說是不可或缺的一個(gè)重要條件,因?yàn)橹形牡馁Y料從數(shù)量或者質(zhì)量上來(lái)說,都遠(yuǎn)遠(yuǎn)比不上英文的資料。如果英語(yǔ)不好,這除了阻止知識(shí)到達(dá)你的大腦里面以外,沒有好處。

            汕頭市第一中學(xué)的張朝陽(yáng)老師
            高一的時(shí)候是張老師給我們上的計(jì)算機(jī)課,這個(gè)時(shí)候他告訴我們有NOI這種東西,不過我著實(shí)對(duì)算法沒什么興趣,因?yàn)槟莻€(gè)時(shí)候我對(duì)圖形更感興趣,而且絕大多數(shù)圖形的算法都不是搜索算法,而是跟數(shù)學(xué)知識(shí)有著更直接的聯(lián)系。因此我就沒有花多少時(shí)間在算法上面了。不過其實(shí)什么時(shí)候?qū)W習(xí)算法并不重要,只要你在工作之前學(xué)了就好了。原本那個(gè)時(shí)候也想靠NOI看看能不能混個(gè)保送什么的,由于我其實(shí)也不太認(rèn)真做這個(gè),因此只好親自高考了。但是在這里我并不是說張老師教給了我什么知識(shí),其實(shí)那段時(shí)間我都是靠自學(xué)。只不過因?yàn)槲以诜荖OI的編程競(jìng)賽里面的成績(jī)很好,所以他給我大開方便之門,讓我可以利用學(xué)校的各種資源。我們都知道萬(wàn)惡的學(xué)校經(jīng)常會(huì)不知不覺做出一些扼制青少年素質(zhì)全面發(fā)展的事情,因此張老師給我的方便是十分重要的,包括我可以擁有機(jī)房的鑰匙以便我在任何時(shí)候可以進(jìn)去使用計(jì)算機(jī)寫程序。課還是要上的,但是由于我每一年都參加NOI,所以自習(xí)課我就可以跑去機(jī)房了,寫代碼的時(shí)間也就大大增加了,這著實(shí)是十分有好處。

            CSTC的同僚們
            CSTC我現(xiàn)在也搞不清楚究竟他們的使命是干啥,不過印象里面就是北京工業(yè)大學(xué)的幾個(gè)寫代碼比較厲害的人搞起來(lái)的。我有幸在上高中的時(shí)候接觸到了他們,其中曾毅和唐良兩個(gè)人對(duì)我的幫助很大。曾毅告訴我為了將來(lái)的前途也好,為了自己編程能力的發(fā)展也好,搞一個(gè)好學(xué)校總是必須的。唐良是在我上了大學(xué)之后告訴我這個(gè)世界上還有《算法導(dǎo)論》這本書,讓我的數(shù)據(jù)結(jié)構(gòu)和算法知識(shí)有了十分穩(wěn)固的基礎(chǔ)。當(dāng)然其實(shí)不會(huì)數(shù)據(jù)結(jié)構(gòu)和算法并不是說你就寫不了什么復(fù)雜的程序,而只是導(dǎo)致你寫出來(lái)的復(fù)雜的程序質(zhì)量很差性能比較低而已。在高中的時(shí)候我已經(jīng)做出了一個(gè)pascal的無(wú)指針版本的解釋程序了,不過在這個(gè)時(shí)候我說實(shí)話除了鏈表以外,什么都不知道,編譯原理也不知道,所有的東西都是硬湊出來(lái)的。當(dāng)然程序還是能運(yùn)行的,就是寫好之后就無(wú)法再修改了,實(shí)在改不下去。

            華南理工大學(xué)的陳健老師
            高三的時(shí)候?qū)懗鰜?lái)的pascal解釋器實(shí)在是讓我十分興奮,所以在剛?cè)雽W(xué)不久聽說我們的班主任陳建老師教編譯原理的,我就跟她說我對(duì)這方面有興趣了,而且當(dāng)時(shí)還為我的下一個(gè)解釋器寫了一個(gè)很長(zhǎng)的設(shè)計(jì)文檔。這份文檔一開始只是寫給我自己的,后來(lái)順便就給她看了。陳老師倒是沒說什么,過了許久,給了我一本《編譯原理》。當(dāng)然這不是龍書,說實(shí)話那本課本也非常糟糕,只是這讓我知道這個(gè)世界上還有這種東西,也就足夠了。大一的時(shí)候迅速看完了這本書,覺得很不爽,就把龍書搞到手,然后看了一部分。大一結(jié)束的時(shí)候就做出一個(gè)面向?qū)ο髱0搴屠占撵o態(tài)類型腳本語(yǔ)言了,陳老師實(shí)在是功不可沒。作為老師,能教你什么是不重要的,告訴你你還有什么不會(huì)才是最重要而且最有用的。

            華南理工大學(xué)的陳天老師
            這位老師給我們上了大一的C++課,不僅功底扎實(shí),而且可以課也講得很好,無(wú)奈在我大三的時(shí)候說是實(shí)在不行了,跑去做程序員了。我就不對(duì)這件事情作評(píng)論了。陳天老師不僅告訴了我《設(shè)計(jì)模式》是十分重要的,而且也經(jīng)常鼓勵(lì)我進(jìn)行更加深入的學(xué)習(xí),對(duì)我?guī)椭艽蟆?/p>

            g9yuayon
            這是個(gè)人才啊,而且編程水平也十分地令人嘆為觀止。不過他對(duì)我?guī)椭畲蟮哪^于告訴我這個(gè)世界上還存在著《Parsing Techniques》了。這是世界上最好的描述語(yǔ)法分析的書,連龍書的前幾個(gè)章節(jié)都不如這本書講得好。當(dāng)然龍書還是包含了后端的,而《Parsing Techniques》是只有前端的。不僅如此,他還給了我不少論文看。其實(shí)如果看得下去的話,論文帶來(lái)的幫助遠(yuǎn)比算法要大得多。因?yàn)閿?shù)據(jù)結(jié)構(gòu)和算法真正普遍實(shí)用的也就那么幾種,其實(shí)知識(shí)量是十分少的,還比不上數(shù)學(xué)分析。既然數(shù)學(xué)分析一年就可以上完,那實(shí)用數(shù)據(jù)結(jié)構(gòu)和算法其實(shí)是不需要花那么久的。不過那些更加深刻的數(shù)據(jù)結(jié)構(gòu)和算法當(dāng)然不在此列了——還是很多的。但是論文,是方向性十分強(qiáng),而且解決的問題其實(shí)范圍更狹窄的東西。只不過如果認(rèn)真研讀論文的話,可以學(xué)到很多知識(shí)以外的東西,譬如說作者是如何整理他們的結(jié)果的。遇到好心的作者的話你連他們?cè)趺窗l(fā)現(xiàn)這個(gè)事情都可以知道。由于從小就喜歡數(shù)學(xué),所以看論文的時(shí)候看得十分入迷,也就看得更加認(rèn)真仔細(xì)了。g9yuayon介紹給我的論文的確都是十分漂亮的,在我掌握了知識(shí)的同時(shí),又讓我的基礎(chǔ)變得更扎實(shí),并且對(duì)編程也更加喜愛了。

            龔敏敏一伙
            這倒是一個(gè)共同作用的結(jié)果,也是我第一個(gè)聯(lián)系比較緊密的圈子。群里面的人都分布在各大公司,而且水平都不錯(cuò),并且都是在研究圖形學(xué)的。至于說為什么會(huì)跟他們接觸,當(dāng)然是因?yàn)楦咧械臅r(shí)候?qū)D形學(xué)特別熱衷的關(guān)系了。雖然后來(lái)轉(zhuǎn)去做編譯器了,不過學(xué)習(xí)圖形學(xué)并不是一個(gè)浪費(fèi),因?yàn)檫@個(gè)漫長(zhǎng)的過程讓我的數(shù)學(xué)知識(shí)變的扎實(shí),而且也產(chǎn)生了很多題目讓我練習(xí)編寫一些至少有點(diǎn)小規(guī)模的程序。實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn),這話是不錯(cuò)的。

            我還要提一下LYT同學(xué)。LYT并沒有在編程上幫助我,其實(shí)是我在教LYT寫代碼,只是LYT肯讓我教那么久著實(shí)也不容易。為了教LYT學(xué)會(huì)寫簡(jiǎn)單的編譯器,讓我不得不將我學(xué)過的知識(shí)從頭到尾整理了一遍,而且還讓我思考如何使得一個(gè)人在學(xué)會(huì)編程的同時(shí)可以保持樂趣、自信心和良好的習(xí)慣。這個(gè)過程十分有意義,不僅讓我有一個(gè)機(jī)會(huì)可以從頭整理我學(xué)會(huì)的知識(shí),思考一些更加深刻的東西,讓自己對(duì)知識(shí)的掌握更加深刻和牢固,而且其實(shí)對(duì)被教也是有幫助的。利己利人,何樂不為。LYT經(jīng)過了我三年的精心指導(dǎo),從對(duì)編程什么都不知道開始,最終順利拿到了網(wǎng)易的offer,而且工資也沒比我低多少,實(shí)在是讓我感到十分高興。

            在我2009年7月份畢業(yè)之后就去了Microsoft而且尚未跳槽。從畢業(yè)后開始到現(xiàn)在這段時(shí)間現(xiàn)任女朋友2A同學(xué)給了我很大的支持,并沒有覺得整天宅在電腦前寫代碼看動(dòng)畫片很沒前途,而且還幫忙尋找各種書帶我去書店鼓勵(lì)我等等,對(duì)此十分感謝。

            當(dāng)然這并不是說其他人就對(duì)我沒有幫助,而只是沒有滿足文章一開始提出來(lái)的“左右人生軌跡”的條件而已。因?yàn)閷?duì)我有幫助的人其實(shí)非常多,志同道合的朋友也不少,在這里我就不一一列舉了。

            祝各位讀者們也能夠?qū)幊谈信d趣而且在這個(gè)道路上不斷堅(jiān)持越走越遠(yuǎn)。

            <><><><><><><><><><>
            后記。突然想起來(lái)我忘記寫上,其實(shí)小日本的動(dòng)畫片都是一些非常具有教育意義的東西,這讓我學(xué)會(huì)了很多黑暗的社會(huì)沒有任何機(jī)會(huì)讓我知道的人生的道理。大家一定要看啊。

            <><><><><><><><><><>
            后記2。今天空明流產(chǎn)說他是搞圖形那一群人里面為數(shù)不多的還做做shader前端的,所以我再提一下,啊哈哈哈。

            posted @ 2010-12-18 09:17 陳梓瀚(vczh) 閱讀(10613) | 評(píng)論 (33)編輯 收藏
                時(shí)隔一個(gè)月,終于在Vczh Library++ 3.0的IDE工程里實(shí)現(xiàn)了用戶自定義類型變綠(抄C#的娃哈哈)鼠標(biāo)移動(dòng)到對(duì)象上會(huì)出tooltip、顯示函數(shù)參數(shù)提示和Code snippet的功能了。由于我的語(yǔ)法樹的每一個(gè)節(jié)點(diǎn)都包含了它在源代碼中的位置,所以鼠標(biāo)指向一個(gè)字符的時(shí)候,可以計(jì)算出他在語(yǔ)法樹的位置,從而可以查到他的聲明的語(yǔ)法樹節(jié)點(diǎn),再用聲明節(jié)點(diǎn)的位置就可以把聲明的代碼復(fù)制出來(lái)顯示在tooltip上面了:

                同樣的方法可以用來(lái)實(shí)現(xiàn)顯示函數(shù)參數(shù)。這個(gè)比tooltip要復(fù)雜一點(diǎn),因?yàn)橐烧Z(yǔ)法樹的聲明重新組織成代碼才能顯示出來(lái),而且還有模板函數(shù)的類型問題。不過現(xiàn)在有兩個(gè)小功能還沒實(shí)現(xiàn),第一個(gè)是在沒輸入的時(shí)候移動(dòng)光標(biāo)不會(huì)更新參數(shù),這只是個(gè)小問題。另一個(gè)是對(duì)一個(gè)函數(shù)指針調(diào)用的時(shí)候做提示,這個(gè)還要進(jìn)一步考慮。下圖顯示的是對(duì)一個(gè)模板函數(shù)做參數(shù)提示的時(shí)候,參數(shù)的類型會(huì)自動(dòng)特化:

                接下來(lái)就是code snippet了。Code snippet是一個(gè)強(qiáng)大的功能,可以讓你免除一些無(wú)謂的手指的勞動(dòng)。Visual Studio里面提供了大量的code snippet,不過在這里我暫時(shí)只提供for和forr兩種,用來(lái)輸入for循環(huán)。下面是使用code snippet輸入一個(gè)for循環(huán)的全過程:











                Code snippet是一個(gè)比較復(fù)雜的功能,在這里我只實(shí)現(xiàn)了上下文無(wú)關(guān)的一些特性。Visual Studio里面的就更為高級(jí)了,他在插入一個(gè)類名的時(shí)候,可以根據(jù)上下文來(lái)判斷是否需要出現(xiàn)完整的namespace。當(dāng)然由于現(xiàn)在我用來(lái)做intellisense的語(yǔ)言還沒有這么復(fù)雜的元素,所以也就無(wú)從做起了。

                所有的代碼可以在Vczh Library++ 3.0里面找到。這篇文章的代碼跟(十)的時(shí)候的代碼已經(jīng)大為不同了。經(jīng)過一系列的重構(gòu),intellisense功能最終被做成一個(gè)靈活的插件形式,所有的細(xì)節(jié)都可以更改,甚至連code snippet那個(gè)黃色的輸入位置都可以再往上畫東西。因?yàn)樵陂_發(fā)intellisense的時(shí)候發(fā)現(xiàn)了NativeX語(yǔ)言語(yǔ)法上一個(gè)二義性,因此NativeX的語(yǔ)法也做了一處小修改。而且我趁著這個(gè)時(shí)候重構(gòu)了所有NativeX的測(cè)試用例,把在C++里面構(gòu)造語(yǔ)法樹改成了用一系列make file和反射函數(shù)并運(yùn)行的方式直接使用NativeXProvider編譯、運(yùn)行main函數(shù)并與記錄在index文件中的結(jié)果進(jìn)行比較的方法。

                接下來(lái)可以做的事情就比較多了。首先我要開始完成NativeX的調(diào)試功能,其次我要拿Microsoft SQL Server那個(gè)超級(jí)復(fù)雜的T-SQL來(lái)研究一個(gè)從文法產(chǎn)生intellisense代碼(是的,你沒看錯(cuò),是intellisense代碼)的方法,最后要在intellisense上實(shí)現(xiàn)NativeX的重構(gòu)。對(duì)于那個(gè)自動(dòng)生成intellisense代碼的算法,目前還僅僅出于YY階段,當(dāng)然生成出來(lái)的也只能是上下文無(wú)關(guān)的intellisense。譬如說幫你列出數(shù)據(jù)庫(kù)里面的所有表啦,或者幫你列出前面聲明過的變量啦,不屬于自動(dòng)生成的范圍。不過自動(dòng)生成的intellisense還是會(huì)告訴你“現(xiàn)在需要彈出變量列表,需要提供內(nèi)容”的這樣一種信息來(lái)讓你可以往里面添加一些不能自動(dòng)生成的東西。當(dāng)然做不做得出來(lái)那是另外一回事了,先研究研究。
            posted @ 2010-12-04 18:59 陳梓瀚(vczh) 閱讀(13365) | 評(píng)論 (16)編輯 收藏

                有兩個(gè)星期沒有更新博客了,主要是最近在研究一種更靈活的代碼編輯框的框架設(shè)計(jì),修了很多bug,還有公司的事情多了起來(lái)?,F(xiàn)在全部都解決了,因此開始寫這一篇博客。上一篇文章提到了我搞定了一個(gè)智能提示的原型,當(dāng)然現(xiàn)在已經(jīng)在Vczh Library++ 3.0上面添加了鼠標(biāo)指向一個(gè)對(duì)象顯示聲明代碼和打括號(hào)的時(shí)候提示函數(shù)參數(shù)(部分完成)的功能了。今天來(lái)說一下我是如何實(shí)現(xiàn)這些功能的。當(dāng)然我不會(huì)講所有細(xì)節(jié),只會(huì)講重點(diǎn),如何實(shí)現(xiàn)那個(gè)界面也不包括在這里。我要說的是,如何立刻知道任意一個(gè)位置所在的代碼究竟是什么東西。

                如果你沒有讀過之前的幾篇文章的話,建議去翻一翻,因?yàn)槲抑疤岬搅艘恍┍尘?,還有我實(shí)現(xiàn)的C#版yacc(當(dāng)然只是指功能,并不兼容),IDE和編譯器的語(yǔ)法分析器的異同和實(shí)現(xiàn)一個(gè)IDE用的語(yǔ)法分析器要注意的地方。

                語(yǔ)法分析總是產(chǎn)生語(yǔ)法樹或者分析樹的,無(wú)論開發(fā)什么能夠感應(yīng)代碼內(nèi)容的工具,都逃不過語(yǔ)法分析。因此可以肯定的是,在你敲代碼的時(shí)候,IDE真的在背后生成了一棵樹,只不過為了要達(dá)到普通文本框的輸入性能,很多東西都要移動(dòng)到后臺(tái)去做,但是為了瞬間響應(yīng)并作智能提示,有一些東西要移動(dòng)到前臺(tái)做。他們之間的分界線想要界定清楚其實(shí)也不是很難。

                假設(shè)我們要編輯一份超大文件(幾萬(wàn)行吧,再超過要開除的哈),每當(dāng)你打字修改它的時(shí)候,一定會(huì)進(jìn)行語(yǔ)法分析并產(chǎn)生語(yǔ)法樹。對(duì)于這么大規(guī)模的代碼要產(chǎn)生語(yǔ)法樹肯定不是瞬間就能完成的(我那個(gè)東西大概要一秒鐘多一點(diǎn)),因此這一步是在后臺(tái)完成的。但是當(dāng)你打一個(gè)"."的時(shí)候,你肯定希望立刻就要彈出列表的內(nèi)容。為了知道列表的內(nèi)容,你肯定得先知道那個(gè)"."出現(xiàn)在了什么表達(dá)式里面,以及"."前面的那個(gè)表達(dá)式究竟是什么類型,這是離不開全文分析的。但是全文分析又太慢,所以我引入了一個(gè)技術(shù)。

                為了完成這個(gè)技術(shù),你必須在前臺(tái)分析得到那個(gè)表達(dá)式。我們很容易就知道,我們是不可能等待后臺(tái)分析給我們提供數(shù)據(jù)的。所以在這里我們要做的是,緩存當(dāng)前我們感興趣的代碼。在這里簡(jiǎn)單化一下,如果我們只需要提供按"."彈出列表的話,我們只需要緩存語(yǔ)句(statement)就可以了。怎么做呢?假設(shè)我們已經(jīng)可以通過所在的位置得到代碼的內(nèi)容(下面會(huì)講),那么我們顯然可以知道光標(biāo)的位置所在的語(yǔ)句的語(yǔ)法樹對(duì)象究竟是什么。有了這個(gè)語(yǔ)法樹對(duì)象,我們就可以從代碼里面直接把這個(gè)語(yǔ)句的代碼文字復(fù)制出來(lái),然后緩存語(yǔ)句的代碼、語(yǔ)句所在的全文位置和語(yǔ)句所在的作用域。作用域是語(yǔ)法樹的一部分,在做完語(yǔ)法分析之后,只需要做簡(jiǎn)單的語(yǔ)義分析建立作用域就可以計(jì)算很多東西了。這個(gè)緩存會(huì)在光標(biāo)位置移動(dòng)的時(shí)候更新,也會(huì)在當(dāng)前的全文分析結(jié)束的時(shí)候更新

                一旦緩存下來(lái)之后,你往里面打了一個(gè)字符,那我不僅可以更新文本框里面的內(nèi)容,我還可以更新緩存里面的代碼的內(nèi)容,同時(shí)還可以知道新的緩存開始結(jié)束位置。一個(gè)語(yǔ)句通常都是很短的,最多也就一百來(lái)個(gè)字符,因此我們立刻在前臺(tái)對(duì)它做語(yǔ)法分析。而且往一個(gè)語(yǔ)句里面打字的話,99%以上的情況是不會(huì)影響到上下文的,所以這個(gè)語(yǔ)句的舊作用域?qū)ο笕匀豢捎?/strong>。這個(gè)時(shí)候我們用舊的作用域?qū)ο髞?lái)對(duì)新的語(yǔ)句做語(yǔ)義分析,那么就可以知道這個(gè)語(yǔ)句每一個(gè)表達(dá)式的類型了,從而知道了"."前面的表達(dá)式究竟是什么類型。然后利用舊作用域?qū)ο?,我們就可以知道這個(gè)類型包含了多少成員。到了這一步,列表里面的對(duì)象就構(gòu)造完畢了。

                然而后臺(tái)的全文分析總是會(huì)結(jié)束的,所有的信息在這個(gè)時(shí)候就準(zhǔn)備好了,然后發(fā)個(gè)消息給前臺(tái)讓它更新緩存。兩種更新緩存都是用GUI的消息驅(qū)動(dòng)的,所以不可能同時(shí)發(fā)生,只會(huì)先后發(fā)生。之前談到的臨時(shí)更新跟后臺(tái)的全文分析是并行的,不過這個(gè)不會(huì)影響我們。只要我們正確處理后臺(tái)跟前臺(tái)的信息交換,那么整個(gè)智能感應(yīng)的計(jì)算過程就可以做得十分安全,不會(huì)發(fā)生死鎖。我相信這一點(diǎn)應(yīng)該不是很難。

                那么,現(xiàn)在回到了兩個(gè)最原始的問題。第一個(gè)是如何通過位置查找語(yǔ)法樹。這個(gè)很容易解決,只要在語(yǔ)法分析的時(shí)候把所有跟位置有關(guān)的信息都記錄在樹里面就可以了。第二個(gè)問題是我們?nèi)绾翁幚碛脩魧戝e(cuò)的代碼。平時(shí)編譯原理里面所教授的自動(dòng)錯(cuò)誤恢復(fù)其實(shí)是不好用的,你看看VC++的編譯器在你寫錯(cuò)了什么東西之后,大部分的錯(cuò)誤信息基本上都沒法看,因此如何進(jìn)行錯(cuò)誤恢復(fù)肯定要我們自己進(jìn)行精心設(shè)計(jì)。但是問題來(lái)了,我們?nèi)绾螌?shí)現(xiàn)它呢?顯然手寫語(yǔ)法分析器會(huì)讓我們心煩意亂根本做不下去(還要處處記得記錄位置信息……),因此我們需要一個(gè)語(yǔ)法分析器生成器。

                在這里我建議大家去閱讀我博客上的兩篇文章,你可以從這兩篇文章所給的鏈接看到一些其他的東西,講的是如何用組合子開發(fā)語(yǔ)法分析器。我這里給語(yǔ)法樹添加了一個(gè)新屬性,也就是一種組合起來(lái)強(qiáng)大但是又容易指定的錯(cuò)誤恢復(fù)技術(shù)了。這里的錯(cuò)誤恢復(fù)技術(shù)分為兩種,一種是針對(duì)循環(huán)的,這個(gè)大家看代碼就可以了,因?yàn)楦诙N——也就是序列關(guān)系的文法的錯(cuò)誤恢復(fù)——非常相似,只是一個(gè)理論上的變換而已。

                內(nèi)容是這樣的。假設(shè)我們需要分析下面的表達(dá)式:EXPRESSION + "." + MEMBER,那么我們總是希望在殘缺不全的代碼里面恢復(fù)出盡可能正確的信息。我們知道一旦出現(xiàn)了".",用戶想要寫的必然是一個(gè)訪問對(duì)象成員的表達(dá)式,因此我們?cè)?."那里表上記號(hào),變成EXPRESSION + "." + MEMBER。標(biāo)記有一個(gè)副作用,也就是一旦標(biāo)記所包含的語(yǔ)法分析成功了,那么整條語(yǔ)法會(huì)保證產(chǎn)生出指定的語(yǔ)法樹結(jié)構(gòu)。如果用戶出現(xiàn)了錯(cuò)誤,那么所有的錯(cuò)誤都會(huì)被當(dāng)成用戶少輸入了什么東西而引起的。雖然這一個(gè)假設(shè)對(duì)于編譯器來(lái)說不太合適,但是對(duì)于IDE來(lái)說顯然是合適的。但是這種做法很容易在分析列表結(jié)構(gòu)的代碼里引起死循環(huán),所以需要做很多測(cè)試來(lái)保證你的標(biāo)記不會(huì)造成問題。

                下面的例子也可以輔助說明這種方法的有效性。舉個(gè)例子,你需要做一個(gè)函數(shù)。你在寫函數(shù)的過程中顯然會(huì)臨時(shí)或者不小心少些一些東西——有時(shí)候我們并不是把所有的事情都想清楚了才開始寫代碼的。這個(gè)時(shí)候?yàn)榱苏_分析出函數(shù)的結(jié)構(gòu),我們做下面的語(yǔ)法并標(biāo)記:
                FUNCTION_DECLARATION ::= TYPE + NAME + "(" + list<TYPE + NAME, ","> + ")" + COMPOSITE_STATEMENT
                VARIABLE_DECLARATION ::= TYPE + NAME + optional("=" + EXPRESSION) + ";"
                然后總是保證FUNCTION_DECLARATION的優(yōu)先級(jí)比VARIABLE_DECLARATION更高,我們就總是可以恢復(fù)出最正確的語(yǔ)法結(jié)構(gòu)了。這一種做法對(duì)于你在連續(xù)輸入代碼的過程中進(jìn)行正確的提示是相當(dāng)好用而且方便的。

                至于代碼生成器本身怎么實(shí)現(xiàn),還是去Vczh Library++ 3.0下載代碼吧。

            posted @ 2010-11-22 03:29 陳梓瀚(vczh) 閱讀(13606) | 評(píng)論 (14)編輯 收藏
            僅列出標(biāo)題
            共35頁(yè): First 7 8 9 10 11 12 13 14 15 Last 
            久久精品国产精品亚洲人人 | 国内精品九九久久久精品| 久久777国产线看观看精品| 97久久婷婷五月综合色d啪蜜芽| 久久激情五月丁香伊人| 国产99久久久国产精免费| 国产一久久香蕉国产线看观看| 无码伊人66久久大杳蕉网站谷歌| 狠狠色婷婷久久综合频道日韩 | 久久精品无码一区二区三区免费| 777久久精品一区二区三区无码| 亚洲精品乱码久久久久久按摩| 性欧美大战久久久久久久久| 久久国产色AV免费观看| 成人国内精品久久久久一区| 青青草国产精品久久| 久久99精品久久久久久齐齐| 久久人人爽人人精品视频 | 亚洲精品无码久久毛片| 久久婷婷五月综合国产尤物app| 婷婷久久久亚洲欧洲日产国码AV| 色88久久久久高潮综合影院| 久久青草国产精品一区| 亚洲国产成人精品久久久国产成人一区二区三区综 | 久久久久久久91精品免费观看| 亚洲中文久久精品无码| 久久99国产精品一区二区| 久久国产午夜精品一区二区三区| 色青青草原桃花久久综合| 精品久久久久久无码专区不卡| 久久精品国产国产精品四凭| 欧美午夜精品久久久久免费视| 91精品国产91久久久久久青草| 欧美亚洲国产精品久久高清 | 国产情侣久久久久aⅴ免费| 99久久婷婷国产综合精品草原| 国产一区二区久久久| AAA级久久久精品无码区| 亚洲国产欧洲综合997久久| 久久久91人妻无码精品蜜桃HD| 久久综合给久久狠狠97色 |