Kernel FP的虛擬機(jī)設(shè)計(jì)起來比較別扭,主要還是因?yàn)閘aziness的問題。不過現(xiàn)在已經(jīng)有了一個(gè)能用的想法了。
第一個(gè)需要確定的是assembly。當(dāng)然,這個(gè)assembly只是概念上的,現(xiàn)在并沒有什么確定的形式。一個(gè)assembly需要一些函數(shù)的結(jié)構(gòu)以及名表。名表的作用是減少特化模板函數(shù)所需要的內(nèi)存空間。一個(gè)函數(shù)總是可以被分解成一個(gè)模板以及對于每一種類型需求下所做出的一些改變。例如:
現(xiàn)在有代碼:
1 def inc a = iadd a 1
2
3 def inc s = concat a (list ' ')
4
5 def inc2 x = inc (inc x)
在調(diào)用inc2的時(shí)候,會(huì)根據(jù)x的類型確定所需要的inc究竟是什么。這個(gè)時(shí)候,inc2僅僅依賴于inc,所以在生成assembly的時(shí)候可以為這段指令的inc留一個(gè)自定義的位置,然后記錄當(dāng)x為string的時(shí)候調(diào)用第二個(gè),當(dāng)x為int的時(shí)候調(diào)用第一個(gè)。這個(gè)時(shí)候inc2的定義就被完整的保留了下來,而且也不需要在運(yùn)行的時(shí)候才判斷重載。
事實(shí)上,函數(shù)應(yīng)當(dāng)屬于值。而且有了laziness,代碼也應(yīng)當(dāng)屬于值。所以實(shí)際上運(yùn)行的時(shí)候只需要一種數(shù)據(jù)結(jié)構(gòu),也就是值了。值有以下幾種:
1、整數(shù)和字符(浮點(diǎn)數(shù)以后再加)
2、類型構(gòu)造(譬如list a b)
3、表達(dá)式樹(譬如\a->imul a a)
在Kernel FP運(yùn)行的任意一個(gè)階段,所產(chǎn)生的中間結(jié)果會(huì)這最終結(jié)果都只能是這三種類型的其中一種。而且這三種類型還是互相嵌套的。那么在什么時(shí)候開始運(yùn)算呢?實(shí)際上我們一貫來需要的首先是判斷一個(gè)值得類型,也就是將值轉(zhuǎn)換成1或者2。Kernel FP里面的select-case表達(dá)式也需要這種功能。至此什么時(shí)候該laziness已經(jīng)非常清楚了。一個(gè)表達(dá)式來了,我們首先獲得它的類型(從而獲得其結(jié)構(gòu)),這個(gè)時(shí)候就一直運(yùn)行到知道整數(shù)的內(nèi)容、字符的內(nèi)容或者得到類型構(gòu)造的構(gòu)造符號(譬如list)的時(shí)候暫停。當(dāng)結(jié)果為類型構(gòu)造的時(shí)候,讀到了內(nèi)容的時(shí)候繼續(xù)遞歸。這樣就可以保證一個(gè)值無論在Kernel FP,或者在一個(gè)使用Kernel FP的虛擬機(jī)的C++程序里面,不需要執(zhí)行的Kernel FP代碼一定不會(huì)被執(zhí)行。
Kernel FP的表達(dá)式一共有primitive表達(dá)式(整數(shù)或者字符)、函數(shù)調(diào)用表達(dá)式、let-in的局部名稱定義表達(dá)式、lambda表達(dá)式以及select-case表達(dá)式。其中,運(yùn)行的時(shí)候let-in表達(dá)式可以轉(zhuǎn)化為lambda表達(dá)式,函數(shù)定義也可以轉(zhuǎn)換為lambda表達(dá)式,所以運(yùn)行時(shí)所需的表達(dá)式結(jié)構(gòu)也就很容易確定下來了:
1、值(整數(shù)常量或字符常量)
2、名引用(引用到一個(gè)局部的或全局的名稱并提供相應(yīng)的名表,并且保證對同一個(gè)名稱在不同的地方求值不會(huì)導(dǎo)致重復(fù)的代碼執(zhí)行)
3、函數(shù)調(diào)用
4、lambda表達(dá)式(用于積累到所有參數(shù)足夠的時(shí)候,獲得表達(dá)式以及局部的名引用對象表)
5、select-case表達(dá)式(用于讓laziness的代碼開始運(yùn)轉(zhuǎn)所需的部分)
那么,當(dāng)需要知道一個(gè)表達(dá)式的值的時(shí)候需要做什么事情呢?
首先,對于值來說,因?yàn)槭浅A?,所以不需要進(jìn)行更多的運(yùn)算。
第二,對于名引用來說,因?yàn)閳?zhí)行的是名引用的表達(dá)式,因此不需要什么特殊的動(dòng)作,只需要按照這里定義的策略執(zhí)行。
第三,對于函數(shù)調(diào)用,我們需要將函數(shù)的參數(shù)傳入lambda表達(dá)式的第一個(gè)參數(shù),生成一個(gè)新的名引用對象并將lambda表達(dá)式的內(nèi)容提上來。
第四、lambda表達(dá)式,不需計(jì)算,因?yàn)楹瘮?shù)本身就是一個(gè)值。
第五、select-case表達(dá)式,對被判斷的表達(dá)式本身的類型進(jìn)行判斷,運(yùn)行最少的代碼之后,生成case所需要的名引用對象并將case的結(jié)果表達(dá)式的內(nèi)容提上來。
至此,運(yùn)行帶有l(wèi)aziness的Kernel FP代碼所需要的數(shù)據(jù)結(jié)構(gòu)以及策略都定下來了。
posted on 2008-10-18 23:29
陳梓瀚(vczh) 閱讀(1550)
評論(1) 編輯 收藏 引用 所屬分類:
腳本技術(shù)