• <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
                為了讓更高級(jí)的語言可以編譯到Vczh Library++ 3.0上面的NativeX語言,原生的泛型支持是必須有的。泛型不僅僅是一堆代碼的填空題那么簡(jiǎn)單,因?yàn)榫幾g之后的Assembly(dll)必須可以容納泛型聲明,而且其他的Assembly可以實(shí)例化包含在其他Assembly里面的泛型聲明。這是非常麻煩的(被.net搞定了,jvm則由于種種原因搞不定,大概是因?yàn)閖vm對(duì)assembly version的支持太差導(dǎo)致的,你知道.net 2.0的東西是不能引用4.0的dll的……)。不過先拋開這個(gè)不講,雖然如何在Assembly里面實(shí)現(xiàn)泛型我已經(jīng)心里有數(shù)了,但是這里還是從語義的層面上來考慮泛型的設(shè)計(jì)。

                在討論之前還是要強(qiáng)調(diào)一下一個(gè)大前提:NativeX基本上就是一個(gè)語法更加容易看懂的C語言而已,功能完全是等價(jià)的。于是我要在NativeX上加泛型,其實(shí)也就是等于在C上面加泛型。我們使用泛型完成的事情可以有很多,譬如說定義泛型的結(jié)構(gòu)體,定義泛型的函數(shù),還有泛型的存儲(chǔ)空間等等。首先讓我們討論泛型的結(jié)構(gòu)體。最終的語法可能會(huì)跟現(xiàn)在不一樣,因?yàn)镹ativeX的使命是作為一棵語法樹出現(xiàn)的,所以做得太漂亮的價(jià)值其實(shí)不是很大。

                一、泛型結(jié)構(gòu)體

                泛型的結(jié)構(gòu)體還是比較容易理解的,舉個(gè)小例子:
            1 generic<type T>
            2 structure Vector
            3 {
            4   T x;
            5   T y;
            6 }

                這樣子我們就創(chuàng)建了一個(gè)泛型的結(jié)構(gòu)體。任何熟悉C++或C#的人都知道這是什么意思,我就不做解釋了。使用的時(shí)候跟我們的習(xí)慣是一樣的:
            1 Vector<double> v;
            2 v.x = 1.0;
            3 v.y = 2.0;

                于是我們創(chuàng)建了一個(gè)泛型的變量,然后修改了它的成員。

                二、泛型全局存儲(chǔ)空間

                其實(shí)泛型的全局存儲(chǔ)空間基本上等于編譯器替你做好的一個(gè)key為類型的大字典。有些時(shí)候我們需要給類型加上一些附加的數(shù)據(jù),而且是按需增長的。這就代表在編譯的時(shí)候提供泛型全局存儲(chǔ)空間的Assembly并不知道將來有多少個(gè)key要提供支持,所以創(chuàng)建它們的工作應(yīng)該是虛擬機(jī)在鏈接一個(gè)想使用其他Assembly提供的全局空間的新Assembly的時(shí)候創(chuàng)建的。這里帶來了一個(gè)問題是不同的Assembly使用相同的類型可以訪問相同的全局存儲(chǔ)空間,這里先不討論具體實(shí)施的手段。

                語法上可能比較混淆:
            1 generic<type T>
            2 structure TypeStorage
            3 {
            4   wchar* name;
            5   function T() builderFunction;//這是函數(shù)指針
            6 }
            7 
            8 generic<type T>
            9 TypeStorage<T> typeStorage;

                在一個(gè)變量上面加泛型可能會(huì)有點(diǎn)奇怪,不過這里的定義還是很明確的。typeStorage是全局變量的泛型,因此typeStorage<int>、typeStorage<double>甚至typeStorage<Vector<Vector<wchar*>>>等等(啊,>>問題)是代表不同的全局變量。不同的Assembly訪問的typeStorage<int>都是相同的全局變量。

                三、泛型函數(shù)

                泛型函數(shù)我們也都很熟悉了。一個(gè)簡(jiǎn)單的例子可以是:
            1 generic<type T>
            2 T Copy(T* pt)
            3 {
            4   result = *pt;
            5 }

                需要指出的是,NativeX并沒有打算要支持泛型結(jié)構(gòu)、全局存儲(chǔ)和函數(shù)的特化或偏特化。因此我們會(huì)很驚訝的發(fā)現(xiàn)這樣的話泛型函數(shù)唯一能做的就是復(fù)制東西了,因?yàn)樗{(diào)用不了其他的非泛型函數(shù)(跟C++不一樣,NativeX的泛型函數(shù)更接近于C#:編譯的時(shí)候進(jìn)行完全的語義分析)。雖然泛型函數(shù)可以調(diào)用其他的泛型函數(shù),但是最終也只能做復(fù)制。因此我們要引入一個(gè)新的(其實(shí)是舊的)概念,才可以避免我們?yōu)榱颂峁└鞣N操作在泛型函數(shù)的參數(shù)上傳入一大堆的函數(shù)指針:“概念”。

                四、泛型concept

                泛型結(jié)構(gòu)體和全局存儲(chǔ)僅僅用來保存數(shù)據(jù),所以泛型concept只能在泛型函數(shù)上面使用。這個(gè)concept跟C++原本打算支持的concept還是很接近的,只是NativeX沒有class,因此只好做一點(diǎn)小修改。

                泛型concept主要是為了指定一套操作的接口,然后讓編譯器可以完成比調(diào)用函數(shù)指針更加高效的代碼。偷偷告訴大家,把他叫concept只是因?yàn)镹ativeX跟C很像,但其實(shí)這個(gè)概念是從Haskell來的……我們還是來看看concept怎么寫吧。
             1 generic<type T>
             2 concept Addable
             3 {
             4   operation T add(T a, T b);
             5   operation T sub(T a, T b);
             6   constant T zero;
             7 }
             8 
             9 generic<type T>
            10 concept Multible : Addable<T>
            11 {
            12   operation T mul(T a, T b);
            13   operation T div(T a, T b);
            14   constant T one;
            15 }

                這里定義了加法和乘法的兩個(gè)concept。我們可以看出concept是可以繼承的,其實(shí)也是可以多重繼承的。concept里面可以放操作(operation),也可以放常數(shù)(constant)。這里的常數(shù)跟全局存儲(chǔ)的機(jī)制不同,全局存儲(chǔ)可以自動(dòng)為新類型產(chǎn)生可讀寫的空間,而concept的常數(shù)不僅是只讀的,而且還不可自動(dòng)產(chǎn)生空間。之前考慮到的一個(gè)問題就是,我們可能需要把外界提供的某個(gè)concept的operation的函數(shù)指針提取出來,有這種需要的operation可以把這個(gè)關(guān)鍵字替換成function,這樣在實(shí)例化concept的時(shí)候,那個(gè)標(biāo)記了function的操作就只能綁定一個(gè)函數(shù)而不是一個(gè)表達(dá)式了。我們可以嘗試為int創(chuàng)建一個(gè)Multible的concept:
            1 concept instance IntMultible : Multible<int>
            2 {
            3   operation T add(T a, T b) = a+b;
            4   operation T sub(T a, T b) = a-b;
            5   operation T mul(T a, T b) = a*b;
            6   operation T div(T a, T b) = a/b;
            7   constant T zero = 0;
            8   constant T one = 1;
            9 }

                于是我們可以寫一個(gè)函數(shù)計(jì)算a+b*c:
            1 generic<type T, concept Multible<T> multible>
            2 function T AddMul(T a, T b, T c)
            3 {
            4   return multible.add(a, multible.mul(b, c));
            5 }

                然后調(diào)用它:
            1 int r = AddMul<int, IntMultible>(345);

                五、另一種concept instance

                雖然我們不允許泛型的結(jié)構(gòu)體、全局存儲(chǔ)和函數(shù)進(jìn)行特化,但是因?yàn)樘鼗瘜?shí)在是一個(gè)好東西。上面的concept instance是沒有彈性的,因?yàn)槟悴豢赡芡ㄟ^一個(gè)concept instance拿到另外一個(gè)concept instance。考慮一下delphi的帶引用計(jì)數(shù)的嵌套數(shù)組,如果我們想讓delphi可以編譯到NativeX上,則勢(shì)必要支持那種東西。主要的困難在于delphi支持的帶有引用計(jì)數(shù)的數(shù)組和字符串,因此在對(duì)array of array of string進(jìn)行釋放的時(shí)候,我們首先要拿到array of array of string的concept instance,其次在釋放函數(shù)里面要拿到array of string的concept instance,最后還要拿到string的concept instance。這個(gè)用上面所提出來的方法是做不了的。因此我們引進(jìn)了一種新的concept instance:叫concept series。這個(gè)跟haskell的東西又更接近了一步了,因?yàn)閔askell的concept instance其實(shí)是匿名但是可特化的……

                于是現(xiàn)在讓我們來實(shí)現(xiàn)Array和String,并寫幾個(gè)類型的Increase和Decrease的函數(shù)(函數(shù)體一部分會(huì)被忽略因?yàn)檫@里只是為了展示concept):
             1 structure String
             2 {
             3   int reference;
             4   wchar* content;
             5 }
             6 
             7 generic<type T>
             8 structure Array
             9 {
            10   int reference;
            11   int length;
            12   T* items;
            13 }

                我們從這里可以看出,string跟array的區(qū)別就是在于長度上面,string有0結(jié)尾而array只能通過記錄一個(gè)長度來實(shí)現(xiàn)。現(xiàn)在我們來寫一個(gè)用于構(gòu)造缺省數(shù)值、增加引用計(jì)數(shù)和減少引用計(jì)數(shù)的concept series:
             1 generic<type T>
             2 concept Referable
             3 {
             4   operation T GetDefault();
             5   operation void Increase(T* t);
             6   operation void Decrease(T* t);
             7 }
             8 
             9 generic<type T>
            10 concept series DelphiTypeReferable : Referable<T>
            11 {
            12 }

                concept series其實(shí)就是專門用來特化的concept instance。但是為了防止不同的Assembly特化出同一個(gè)concept series所帶來的麻煩,我可能會(huì)規(guī)定允許特化concept series的地方,要么是在聲明該concept series的Assembly,要么是聲明涉及的類型的Assembly。因?yàn)槲业腁ssembly不允許循環(huán)引用,因此對(duì)于同一個(gè)concept series C<T,U>來講,就算T和U分別在不同的Assembly出現(xiàn),那么也只能有一個(gè)有權(quán)限特化出它。下面來看特化具體要怎么做。首先我們特化一個(gè)簡(jiǎn)單的,string的DelphiTypeReferable:
            1 concept series DelphiTypeReferable<String>
            2 {
            3   operation GetDefault = StringGetDefault;
            4   operation Increase = StringIncrease;
            5   operation Decrease = StringDecrease;
            6 }

                StringGetDefault、StringIncrease和StringDecrease都是一些普通的函數(shù),內(nèi)容很簡(jiǎn)單,不用寫出來。現(xiàn)在讓我們來看看Array應(yīng)該怎么做:
            1 generic<type T>
            2 concept series DelphiTypeReferable<Array<T>>
            3 {
            4   operation Array<T> GetDefault() = ArrayGetDefault<T>;
            5   operation Increase = ArrayIncrease<T>;
            6   operation Decrease = ArrayDecrease<T>;
            7 }

                看起來好像沒什么特別,不過只要想一想ArrayDecrease的實(shí)現(xiàn)就知道了,現(xiàn)在我們需要在ArrayDecrease里面訪問到未知類型T的DelphiTypeReferable<T>這個(gè)concept instance。因?yàn)楫?dāng)自己要被干掉的時(shí)候,得將引用到的所有對(duì)象的引用計(jì)數(shù)都減少1:
             1 generic<type T>
             2 function void ArrayDecrease(Array<T>* array)
             3 {
             4   if(array->reference<=0)exit;
             5   if(--array->reference==0)
             6   {
             7     for int i = 0
             8       when i < array->length
             9       with i--
            10       do DelphiTypeReferable<T>.Decrease(&array->items[i]);
            11     free(array->items);
            12     array->length=-1;
            13     array->items=null;
            14   }
            15 }

                這樣一大堆concept series的特化組合在一起就成為會(huì)根據(jù)類型的變化而采取不同行為的concept instance了。于是我們還剩下最后的一個(gè)問題,那么其他類型的DelphiTypeReferable應(yīng)該怎么寫呢?其實(shí)只需要玩一個(gè)小技巧就行了,不過在這里將會(huì)看到NativeX支持泛型的最后一個(gè)功能:
             1 generic<type T>
             2 concept series DelphiTypeReferable<T>
             3 {
             4   operation GetDefault = GenericGetDefault<T>;
             5   operation Increase = null;
             6   operation Decrease = null;
             7 }
             8 
             9 generic<type T>
            10 T GenericGetDefault()
            11 {
            12 }

                返回null的operation可以賦值成null以表示不需要執(zhí)行任何東西。如果你將一個(gè)有副作用的表達(dá)式傳進(jìn)去當(dāng)參數(shù)的話,副作用會(huì)保證被執(zhí)行。

                關(guān)于語義上的泛型就講到這里了。
            posted on 2010-06-12 23:58 陳梓瀚(vczh) 閱讀(2532) 評(píng)論(2)  編輯 收藏 引用 所屬分類: VL++3.0開發(fā)紀(jì)事

            評(píng)論:
            # re: Vczh Library++ 3.0之NativeX語言泛型草稿 2010-06-13 00:46 | radar
            仰望!!!  回復(fù)  更多評(píng)論
              
            # re: Vczh Library++ 3.0之NativeX語言泛型草稿 2010-06-15 03:40 | mm
            仰望!!!  回復(fù)  更多評(píng)論
              
            麻豆成人久久精品二区三区免费 | 综合久久国产九一剧情麻豆| 久久精品无码一区二区WWW| 久久人人爽爽爽人久久久| 99久久免费只有精品国产| 亚洲精品午夜国产va久久| 国产精品99久久精品| 亚洲精品NV久久久久久久久久| 久久亚洲精品人成综合网| 国产三级精品久久| 欧洲人妻丰满av无码久久不卡| 久久se精品一区二区影院| 色欲久久久天天天综合网| 久久高清一级毛片| 97久久精品国产精品青草| 久久婷婷国产剧情内射白浆| 国产成人综合久久久久久| 狠狠色丁香久久婷婷综合五月| 婷婷久久综合九色综合九七| 久久不射电影网| 久久精品人人槡人妻人人玩AV | 久久精品人人槡人妻人人玩AV | 久久久久久毛片免费看| 欧美精品一区二区精品久久| 丁香色欲久久久久久综合网| 久久综合视频网站| 久久精品成人| 久久国产精品免费一区| 久久久综合九色合综国产| 久久久久无码精品国产不卡| 亚洲精品无码久久一线| 狠狠色丁香久久婷婷综合| 久久青青草原精品国产软件| 久久九九久精品国产| 久久国产精品视频| 国内精品久久久久久久影视麻豆 | 久久精品亚洲日本波多野结衣| 久久亚洲国产精品成人AV秋霞| 性做久久久久久免费观看| 日日狠狠久久偷偷色综合0| 模特私拍国产精品久久|