• <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
                以前為了開發(fā)KFP,特別學(xué)習(xí)了一下lambda calculus(也就是我的博客的標(biāo)題啦)。lanbda calculus是一門神奇的語(yǔ)言,在計(jì)算機(jī)出現(xiàn)之前就已經(jīng)被搞出來了。這門語(yǔ)言只有三種語(yǔ)法,然后可以用這個(gè)語(yǔ)法來構(gòu)造整數(shù)(!!!)、布爾型和很多遞歸數(shù)據(jù)結(jié)構(gòu)等。

                首先介紹一下語(yǔ)法。
                1、func arg代表一個(gè)函數(shù)調(diào)用,func是函數(shù)表達(dá)式,arg是參數(shù)。
                2、\param.value代表一個(gè)函數(shù)定義,參數(shù)是param,返回結(jié)果value。
                3、(expr)代表expr的優(yōu)先級(jí)較高。

                上面就是所有的語(yǔ)法了。乍一看好像什么都沒有,其實(shí)不然。我們現(xiàn)在先看一個(gè)東西:函數(shù)定義。
                為一個(gè)函數(shù)定義一個(gè)名稱是很簡(jiǎn)單的:
                let double = \num.inc (inc num)) in ...
                代碼“...”可以訪問到函數(shù)double,但是函數(shù)定義的內(nèi)部卻不行。不過這并不會(huì)帶來什么問題(其實(shí)是可以遞歸的,有辦法)。當(dāng)然let-in不是一個(gè)合法的lambda calculus程序,不過可以被翻譯為:
                (\double. ...) (\num.inc (inc num))
                根據(jù)語(yǔ)法規(guī)則1,可以將后面的整個(gè)函數(shù)當(dāng)作實(shí)參傳入形參,將所有的double都替換成后面的那個(gè)東西,于是double的名稱就被定下來了。

                遞歸怎么辦呢?譬如說要寫個(gè)函數(shù)sum n來計(jì)算1+2+...+n的值:
                let sum n = if (n==0) 0 (n+(sum (n-1))) in ...
                這里為了方便,我們假設(shè)所有的運(yùn)算符都是存在的。其實(shí)a op b可以看成函數(shù)調(diào)用op a b,如果我們給每一個(gè)運(yùn)算符都分配一個(gè)名字,實(shí)際上就可以用正確的lambda calculus語(yǔ)法來說明了。所以這里為了方便先這么干。

                sum內(nèi)部是看不見sum的,因?yàn)榉g了之后變成:
                (\sum. ...) (if (n==0) 0 (n+(sum (n-1))))
                那怎么辦呢?既然看不見自己,我可以讓調(diào)用者再外部把它自己傳進(jìn)去當(dāng)參數(shù)總可以吧:
                let sum n = \SELF. if (n==0) 0 (n + (SELF (n-1))) in ...
                但是我們不能用(sum sum)的方法來調(diào)用,因?yàn)榈搅俗詈?SELF (n-1))變成(sum (n-1)),下一步就錯(cuò)了。所以我們?cè)炝藗€(gè)Y函數(shù):
                let Y = \f.(\t.f (t t)) (\t.f (t t)) in
                let sum = Y (\SELF. if (n==0) 0 (n + (SELF (n-1)))) in ...
                這樣函數(shù)\SELF. if (n==0) 0 (n+(SELF (n-1))))就被Y變成了一個(gè)真正的遞歸函數(shù)了。不過在這里我不想花很大篇幅解釋Y是怎么來的,有興趣的讀者看這里

                于是我們可以這么定義數(shù)字:
                zero = \s.\z.z
                one = \s.\z.s z
                two = \s.\z.s (s z)
                three = \s.\z.s (s (s z))
                four = \s.\z.s (s (s (s z)))
                數(shù)字n是一個(gè)函數(shù),這個(gè)函數(shù)接受兩個(gè)參數(shù)s和z,返回結(jié)果是拿s在z上應(yīng)用n次的結(jié)果。所以我們可以很方便的實(shí)現(xiàn)乘法:拿“加法”函數(shù)當(dāng)成第一個(gè)參數(shù)傳進(jìn)a,然后去應(yīng)用b,就變成乘法了。我們首先創(chuàng)造一個(gè)加1函數(shù):
                inc = \a.\s.\z.a s (s z)
                然后是加法和乘法:
                add = \a.\b.\s.\z.a s (b s z)
                mul = \a.\b.\s.\z.a (b s) z
                所以對(duì)代碼mul (add (one two)) (add (three four))進(jìn)行求值的時(shí)候,我們得到(1+2)*(3+4)=21:\s.\z.(s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s z)))))))))))))))))))))。

                布爾值也是一樣的。我們讓true接受兩個(gè)參數(shù)返回第一個(gè),false接受兩個(gè)參數(shù)返回第二個(gè):
                true = \a.\b.a
                false = \a.\b.b
                那么and or xor not可以分別寫成:
                and = \a.\b.a b false
                or = \a.\b.a true b
                not = \a.a false true
                xor = \a.\b.a (not b) b
                函數(shù)if cond t f跟cond t f等價(jià),所以我們不需要if函數(shù)。

                接下來怎么實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)呢?假設(shè)我們實(shí)現(xiàn)一個(gè)pair,讓pair 1 2將數(shù)字保存起來,讓first(pair 1 2)返回1,second(pair 1 2)返回2:
                pair = \a.\b.\c.c a b
                first = \p.p true
                second = \p.p false
                我們舉一個(gè)例子,讓p=pair 1 (pair 2 3),然后求first (second p):
                first (second p) =
                first (second (pair 1 (pair 2 3))) =
                first ((pair 1(pair 2 3)) false) =
                first (false 1 (pair 2 3)) =
                first (pair 2 3) =
                (pair 2 3) true =
                true 2 3 =
                2
                是不是很神奇捏,lambda calculus僅需那么幾條語(yǔ)法就可以實(shí)現(xiàn)所有東西了。將pair嵌套在一起可以構(gòu)成一個(gè)列表。下面我們來寫一個(gè)完整的程序,構(gòu)造列表[1,2,3,4,5],然后對(duì)每一個(gè)元素求平方后相加:1*1 + 2*2 + 3*3 + 4*4 + 5*5 = 55:

                下面是完整的程序:
             1 let Y = \f.(\t.f (t t)) (\t.f (t t)) in
             2 
             3 let true = \a.\b.a in
             4 let false = \a.\b.b in
             5 let and = \a.\b.a b false in
             6 let or = \a.\b.a true b in
             7 let not = \a.a false true in
             8 let xor = \a.\b.a (not b) b in
             9 
            10 let zero = \s.\z.z in
            11 let inc = \a.\s.\z.a s (s z) in
            12 let one = inc zero in
            13 let two = inc one in
            14 let three = inc two in
            15 let four = inc three in
            16 let five = inc four in
            17 let six = inc five in
            18 let seven = inc six in
            19 let eight = inc seven in
            20 let nine = inc eight in
            21 let ten = inc nine in
            22 let add = \a.\b.\s.\z.a s (b s z) in
            23 let mul = \a.\b.\s.\z.a (b s) z in
            24 let sqr = \a.mul a a in
            25 
            26 let pair = \a.\b.\c.c a b in
            27 let first = \p.p true in
            28 let second = \p.p false in
            29 let empty = pair false false in
            30 let list = \a.\b.pair true (pair a b) in
            31 let head = \xs.(first xs) (first (second xs)) ERROR in
            32 let tail = \xs.(first xs) (second (second xs)) ERROR in
            33 let join = Y \SELF.\xs.\ys.(first xs) (list (head xs) (SELF (tail xs) ys)) ys in
            34 let trans = Y \SELF.\f.\xs.(first xs) (list (f (head xs)) (SELF f (tail xs))) empty in
            35 
            36 let foldl = Y \SELF.\op.\init.\xs.(first xs) (SELF op (op init (head xs)) (tail xs)) init in
            37 let foldr = Y \SELF.\op.\init.\xs.(first xs) (op (head xs) (SELF op init (tail xs))) init in
            38 let length = foldl (\a.\b.inc a) zero in
            39 let sum = foldl add zero in
            40 
            41 let long_list = list one (list two (list three (list four (list five empty)))) in
            42 
            43 sum (trans sqr long_list)

                然后是結(jié)果。首先我的lambda calculus虛擬機(jī)把let-in按照上面的方法重新轉(zhuǎn)換為標(biāo)準(zhǔn)的lambda calculus程序,最后求值:


                數(shù)一數(shù)吧,上面有55個(gè)"(s",所以結(jié)果就是55了。

                我們添加一個(gè)計(jì)算a的b次方的函數(shù):pow = \a.\b.b (mul a) one,將最后幾行改成:
                let one_to_five = list one (list two (list three (list four (list five empty)))) in
                let one_to_ten = join one_to_five (trans (add five) one_to_five) in
                let long_list = trans (pow two) one_to_ten in
                sum long_list
                這計(jì)算2^1 + 2^2 + ... + 2^9 + 2^10。結(jié)果太長(zhǎng),不截屏幕了,直接復(fù)制出來:

              1 (\Y.(\true.(\false.(\and.(\or.(\not.(\xor.(\zero.(\one.(\two.(\three.(\four.(\fi
              2 ve.(\six.(\seven.(\eight.(\nine.(\ten.(\inc.(\add.(\mul.(\pow.(\sqr.(\pair.(\fir
              3 st.(\second.(\empty.(\list.(\head.(\tail.(\join.(\trans.(\foldl.(\foldr.(\length
              4 .(\sum.(\one_to_five.(\one_to_ten.(\long_list.(sum long_list) ((trans (pow two))
              5  one_to_ten)) ((join one_to_five) ((trans (add five)) one_to_five))) ((list one)
              6  ((list two) ((list three) ((list four) ((list five) empty)))))) ((foldl add) ze
              7 ro)) ((foldl \a.\b.(inc a)) zero)) (Y \SELF.\op.\init.\xs.(((first xs) ((op (hea
              8 d xs)) (((SELF op) init) (tail xs)))) init))) (Y \SELF.\op.\init.\xs.(((first xs
              9 ) (((SELF op) ((op init) (head xs))) (tail xs))) init))) (Y \SELF.\f.\xs.(((firs
             10 t xs) ((list (f (head xs))) ((SELF f) (tail xs)))) empty))) (Y \SELF.\xs.\ys.(((
             11 first xs) ((list (head xs)) ((SELF (tail xs)) ys))) ys))) \xs.(((first xs) (seco
             12 nd (second xs))) ERROR)) \xs.(((first xs) (first (second xs))) ERROR)) \a.\b.((p
             13 air true) ((pair a) b))) ((pair falsefalse)) \p.(p false)) \p.(p true)) \a.\b.
             14 \c.((c a) b)) \a.((mul a) a)) \a.\b.((b (mul a)) one)) \a.\b.((b (add a)) zero))
             15  \a.\b.((b inc) a)) \a.\s.\z.((a s) (s z))) \s.\z.(s (s (s (s (s (s (s (s (s (s
             16 z))))))))))) \s.\z.(s (s (s (s (s (s (s (s (s z)))))))))) \s.\z.(s (s (s (s (s (
             17 s (s (s z))))))))) \s.\z.(s (s (s (s (s (s (s z)))))))) \s.\z.(s (s (s (s (s (s
             18 z))))))) \s.\z.(s (s (s (s (s z)))))) \s.\z.(s (s (s (s z))))) \s.\z.(s (s (s z)
             19 ))) \s.\z.(s (s z))) \s.\z.(s z)) \s.\z.z) \a.\b.((a (not b)) b)) \a.((a false)
             20 true)) \a.\b.((a true) b)) \a.\b.((a b) false)) \a.\b.b) \a.\b.a) \f.(\t.(f (t t
             21 )) \t.(f (t t))))
             22 最終結(jié)果:
             23 \s.\z.(s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             24  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             25 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             26 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             27  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             28 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             29 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             30  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             31 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             32 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             33  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             34 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             35 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             36  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             37 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             38 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             39  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             40 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             41 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             42  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             43 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             44 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             45  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             46 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             47 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             48  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             49 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             50 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             51  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             52 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             53 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             54  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             55 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             56 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             57  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             58 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             59 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             60  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             61 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             62 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             63  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             64 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             65 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             66  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             67 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             68 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             69  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             70 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             71 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             72  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             73 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             74 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             75  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             76 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             77 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             78  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             79 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             80 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             81  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             82 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             83 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             84  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             85 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             86 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             87  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             88 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             89 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             90  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             91 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             92 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             93  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             94 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             95 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             96  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (
             97 s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             98 (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s
             99  (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s (s z)))))))))))))))
            100 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            101 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            102 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            103 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            104 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            105 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            106 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            107 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            108 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            109 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            110 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            111 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            112 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            113 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            114 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            115 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            116 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            117 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            118 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            119 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            120 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            121 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            122 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            123 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            124 ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
            125 )))))))))))))))))))))))))))))))


                下面是lambda calculus虛擬機(jī)的C++代碼。代碼使用了Vczh Combinator Parser組裝編譯器,然后用一個(gè)池來存放運(yùn)行時(shí)需要的東西,速度很快:

              1 #include "..\..\..\..\VL++\Library\Platform\VL_Console.h"
              2 #include "..\..\..\..\VL++\Library\Data\Data\VL_Data_Map.h"
              3 #include "..\..\..\..\VL++\Library\Data\Data\VL_Data_Pool.h"
              4 #include "..\..\..\..\VL++\Library\Data\VL_Stream.h"
              5 #include "..\..\..\..\VL++\Library\Data\VL_System.h"
              6 #include "..\..\..\..\VL++\Library\Data\Grammar2\Combinator\VL_CpKernel.h"
              7 #include "..\..\..\..\VL++\Library\Data\Grammar2\Combinator\VL_CpLexer.h"
              8 
              9 using namespace vl;
             10 using namespace vl::platform;
             11 using namespace vl::stream;
             12 using namespace vl::system;
             13 using namespace vl::pool;
             14 using namespace vl::grammar;
             15 
             16 /*********************************************************************************************************
             17 運(yùn)行時(shí)表達(dá)式
             18 *********************************************************************************************************/
             19 
             20 enum LambdaRuntimeKind
             21 {
             22     lrkPrimitive,
             23     lrkClosure,
             24     lrkInvoke
             25 };
             26 class LambdaRuntime
             27 {
             28 public:
             29     typedef VL_Pool<LambdaRuntime>            RuntimePool;
             30 
             31     RuntimePool*                Pool;
             32     LambdaRuntimeKind            Kind;
             33     VInt                        ID;
             34     LambdaRuntime*                Closure;
             35     LambdaRuntime*                Expression;
             36 
             37     void SetPrimitive(RuntimePool* aPool , VInt aID)
             38     {
             39         Pool=aPool;
             40         Kind=lrkPrimitive;
             41         ID=aID;
             42         Closure=0;
             43         Expression=0;
             44     }
             45 
             46     void SetClosure(RuntimePool* aPool , VInt aID , LambdaRuntime* aExpression)
             47     {
             48         Pool=aPool;
             49         Kind=lrkClosure;
             50         ID=aID;
             51         Closure=0;
             52         Expression=aExpression;
             53     }
             54 
             55     void SetInvoke(RuntimePool* aPool , LambdaRuntime* aClosure , LambdaRuntime* aExpression)
             56     {
             57         Pool=aPool;
             58         Kind=lrkInvoke;
             59         ID=-1;
             60         Closure=aClosure;
             61         Expression=aExpression;
             62     }
             63 
             64     LambdaRuntime* Alpha(VInt ExpID , LambdaRuntime* Code)
             65     {
             66         switch(Kind)
             67         {
             68         case lrkPrimitive:
             69             return (ID==ExpID)?Code:this;
             70         case lrkClosure:
             71             if(ID==ExpID)
             72             {
             73                 return this;
             74             }
             75             else
             76             {
             77                 LambdaRuntime* NewExpression=Expression->Alpha(ExpID,Code);
             78                 if(Expression==NewExpression)
             79                 {
             80                     return this;
             81                 }
             82                 else
             83                 {
             84                     LambdaRuntime* AlphaTransformed=Pool->Alloc();
             85                     AlphaTransformed->SetClosure(Pool,ID,NewExpression);
             86                     return AlphaTransformed;
             87                 }
             88             }
             89         case lrkInvoke:
             90             {
             91                 LambdaRuntime* NewClosure=Closure->Alpha(ExpID,Code);
             92                 LambdaRuntime* NewExpression=Expression->Alpha(ExpID,Code);
             93                 if(Closure==NewClosure && Expression==NewExpression)
             94                 {
             95                     return this;
             96                 }
             97                 else
             98                 {
             99                     LambdaRuntime* AlphaTransformed=Pool->Alloc();
            100                     AlphaTransformed->SetInvoke(Pool,NewClosure,NewExpression);
            101                     return AlphaTransformed;
            102                 }
            103             }
            104         default:
            105             return 0;
            106         }
            107     }
            108 
            109     LambdaRuntime* Evaluate(VBool EvaluatingRoot)
            110     {
            111         switch(Kind)
            112         {
            113         case lrkPrimitive:
            114             return this;
            115         case lrkClosure:
            116             if(EvaluatingRoot)
            117             {
            118                 Expression=Expression->Evaluate(true);
            119                 return this;
            120             }
            121             else
            122             {
            123                 return this;
            124             }
            125         case lrkInvoke:
            126             {
            127                 Closure=Closure->Evaluate(false);
            128                 if(Closure->Kind==lrkClosure)
            129                 {
            130                     *this=*Closure->Expression->Alpha(Closure->ID,Expression)->Evaluate(EvaluatingRoot);
            131                     return this;
            132                 }
            133                 else
            134                 {
            135                     Expression=Expression->Evaluate(EvaluatingRoot);
            136                     return this;
            137                 }
            138             }
            139         default:
            140             return 0;
            141         }
            142     }
            143 };
            144 
            145 class LambdaEnvironment
            146 {
            147 public:
            148     LambdaRuntime::RuntimePool    Pool;
            149 
            150     LambdaEnvironment():Pool(65536)
            151     {
            152     }
            153 };
            154 
            155 /*********************************************************************************************************
            156 語(yǔ)法樹
            157 *********************************************************************************************************/
            158 
            159 class LambdaError
            160 {
            161 public:
            162     VUnicodeString Message;
            163 
            164     LambdaError(VUnicodeString aMessage)
            165     {
            166         Message=aMessage;
            167     }
            168 };
            169 
            170 class LambdaIdentifier
            171 {
            172 public:
            173     typedef VL_ListedMap<VUnicodeString , VInt>        TokenMap;
            174     typedef VL_ListedMap<VInt , VUnicodeString>        TokenMapRev;
            175 
            176     VUnicodeString            Token;
            177     VInt                    ID;
            178 
            179     LambdaIdentifier()
            180     {
            181         ID=-1;
            182     }
            183 
            184     VBool operator==(const LambdaIdentifier& Identifier)
            185     {
            186         return ID==Identifier.ID;
            187     }
            188 
            189     VBool operator!=(const LambdaIdentifier& Identifier)
            190     {
            191         return ID!=Identifier.ID;
            192     }
            193 
            194     void Initialize(TokenMap& Tokens)
            195     {
            196         VInt Index=Tokens.IndexOfKey(Token);
            197         if(Index==-1)
            198         {
            199             ID=Tokens.KeyCount();
            200             Tokens.Add(Token,ID);
            201         }
            202         else
            203         {
            204             ID=Tokens.ValueOfIndex(Index);
            205         }
            206     }
            207 
            208     void Initialize(TokenMapRev& Tokens)
            209     {
            210         Token=Tokens[ID];
            211     }
            212 
            213     void Collect(TokenMapRev& Tokens)
            214     {
            215         Tokens.Add(ID,Token);
            216     }
            217 };
            218 
            219 class LambdaCode : public VL_Base
            220 {
            221 public:
            222     typedef VL_AutoPtr<LambdaCode>                            Ptr;
            223 
            224     friend LambdaCode::Ptr        CreateCode(LambdaRuntime* Runtime);
            225 
            226     virtual void                Initialize(LambdaIdentifier::TokenMap& Tokens)=0;
            227     virtual void                Initialize(LambdaIdentifier::TokenMapRev& Tokens)=0;
            228     virtual void                Collect(LambdaIdentifier::TokenMapRev& Tokens)=0;
            229     virtual VUnicodeString        ToString()=0;
            230     virtual LambdaRuntime*        CreateRuntime(LambdaEnvironment* Environment)=0;
            231 
            232     LambdaCode::Ptr Evaluate()
            233     {
            234         LambdaEnvironment Environment;
            235         LambdaRuntime* Runtime=CreateRuntime(&Environment);
            236         LambdaRuntime* Evaluated=Runtime->Evaluate(true);
            237         LambdaCode::Ptr Code=CreateCode(Evaluated);
            238         LambdaIdentifier::TokenMapRev Tokens;
            239         Collect(Tokens);
            240         Code->Initialize(Tokens);
            241         return Code;
            242     }
            243 };
            244 
            245 class LambdaCodePrimitive : public LambdaCode
            246 {
            247 public:
            248     LambdaIdentifier        Name;
            249 
            250     void Initialize(LambdaIdentifier::TokenMap& Tokens)
            251     {
            252         Name.Initialize(Tokens);
            253     }
            254 
            255     void Initialize(LambdaIdentifier::TokenMapRev& Tokens)
            256     {
            257         Name.Initialize(Tokens);
            258     }
            259 
            260     void Collect(LambdaIdentifier::TokenMapRev& Tokens)
            261     {
            262         Name.Collect(Tokens);
            263     }
            264 
            265     VUnicodeString ToString()
            266     {
            267         return Name.Token;
            268     }
            269 
            270     LambdaRuntime* CreateRuntime(LambdaEnvironment* Environment)
            271     {
            272         LambdaRuntime* Runtime=Environment->Pool.Alloc();
            273         Runtime->SetPrimitive(&Environment->Pool,Name.ID);
            274         return Runtime;
            275     }
            276 };
            277 
            278 class LambdaCodeClosure : public LambdaCode
            279 {
            280 public:
            281     LambdaIdentifier        Parameter;
            282     LambdaCode::Ptr            Expression;
            283 
            284     void Initialize(LambdaIdentifier::TokenMap& Tokens)
            285     {
            286         Parameter.Initialize(Tokens);
            287         Expression->Initialize(Tokens);
            288     }
            289 
            290     void Initialize(LambdaIdentifier::TokenMapRev& Tokens)
            291     {
            292         Parameter.Initialize(Tokens);
            293         Expression->Initialize(Tokens);
            294     }
            295 
            296     void Collect(LambdaIdentifier::TokenMapRev& Tokens)
            297     {
            298         Parameter.Collect(Tokens);
            299         Expression->Collect(Tokens);
            300     }
            301 
            302     VUnicodeString ToString()
            303     {
            304         return L"\\"+Parameter.Token+L"."+Expression->ToString();
            305     }
            306 
            307     LambdaRuntime* CreateRuntime(LambdaEnvironment* Environment)
            308     {
            309         LambdaRuntime* Runtime=Environment->Pool.Alloc();
            310         Runtime->SetClosure(&Environment->Pool,Parameter.ID,Expression->CreateRuntime(Environment));
            311         return Runtime;
            312     }
            313 };
            314 
            315 class LambdaCodeInvoke : public LambdaCode
            316 {
            317 public:
            318     LambdaCode::Ptr            Function;
            319     LambdaCode::Ptr            Argument;
            320 
            321     void Initialize(LambdaIdentifier::TokenMap& Tokens)
            322     {
            323         Function->Initialize(Tokens);
            324         Argument->Initialize(Tokens);
            325     }
            326 
            327     void Initialize(LambdaIdentifier::TokenMapRev& Tokens)
            328     {
            329         Function->Initialize(Tokens);
            330         Argument->Initialize(Tokens);
            331     }
            332 
            333     void Collect(LambdaIdentifier::TokenMapRev& Tokens)
            334     {
            335         Function->Collect(Tokens);
            336         Argument->Collect(Tokens);
            337     }
            338 
            339     VUnicodeString ToString()
            340     {
            341         return L"("+Function->ToString()+L" "+Argument->ToString()+L")";
            342     }
            343 
            344     LambdaRuntime* CreateRuntime(LambdaEnvironment* Environment)
            345     {
            346         LambdaRuntime* Runtime=Environment->Pool.Alloc();
            347         Runtime->SetInvoke(&Environment->Pool,Function->CreateRuntime(Environment),Argument->CreateRuntime(Environment));
            348         return Runtime;
            349     }
            350 };
            351 
            352 LambdaCode::Ptr CreateCode(LambdaRuntime* Runtime)
            353 {
            354     switch(Runtime->Kind)
            355     {
            356     case lrkPrimitive:
            357         {
            358             LambdaCodePrimitive* Primitive=new LambdaCodePrimitive;
            359             Primitive->Name.ID=Runtime->ID;
            360             return Primitive;
            361         }
            362     case lrkClosure:
            363         {
            364             LambdaCodeClosure* Closure=new LambdaCodeClosure;
            365             Closure->Parameter.ID=Runtime->ID;
            366             Closure->Expression=CreateCode(Runtime->Expression);
            367             return Closure;
            368         }
            369     case lrkInvoke:
            370         {
            371             LambdaCodeInvoke* Invoke=new LambdaCodeInvoke;
            372             Invoke->Function=CreateCode(Runtime->Closure);
            373             Invoke->Argument=CreateCode(Runtime->Expression);
            374             return Invoke;
            375         }
            376     default:
            377         return 0;
            378     }
            379 }
            380 
            381 /*********************************************************************************************************
            382 語(yǔ)法分析器
            383 *********************************************************************************************************/
            384 
            385 enum LambdaTokenID
            386 {
            387     ltiLet,
            388     ltiIn,
            389     ltiClosure,
            390     ltiName,
            391     ltiLeft,
            392     ltiRight,
            393     ltiDot,
            394     ltiEqual,
            395 };
            396 
            397 LambdaCode::Ptr ToPrimitive(VL_CpToken Token)
            398 {
            399     LambdaCodePrimitive* Primitive=new LambdaCodePrimitive;
            400     Primitive->Name.Token=VUnicodeString(Token.Start,Token.Length);
            401     return Primitive;
            402 }
            403 
            404 LambdaCode::Ptr ToInvoke(const VL_CpList<LambdaCode::Ptr>& Input)
            405 {
            406     LambdaCode::Ptr Code=Input.Head->Data;
            407     VL_CpList<LambdaCode::Ptr>::Node::Ptr Current=Input.Head->Next;
            408     while(Current)
            409     {
            410         LambdaCodeInvoke* Invoke=new LambdaCodeInvoke;
            411         Invoke->Function=Code;
            412         Invoke->Argument=Current->Data;
            413         Code=Invoke;
            414         Current=Current->Next;
            415     }
            416     return Code;
            417 }
            418 
            419 LambdaCode::Ptr ToClosure(const VL_CpPair<VL_CpToken , LambdaCode::Ptr>& Input)
            420 {
            421     LambdaCodeClosure* Closure=new LambdaCodeClosure;
            422     Closure->Parameter.Token=VUnicodeString(Input.First.Start,Input.First.Length);
            423     Closure->Expression=Input.Second;
            424     return Closure;
            425 }
            426 
            427 LambdaCode::Ptr ToLetIn(const VL_CpPair<VL_CpPair<VL_CpToken , LambdaCode::Ptr> , LambdaCode::Ptr>& Input)
            428 {
            429     LambdaCodeInvoke* Invoke=new LambdaCodeInvoke;
            430     Invoke->Function=ToClosure(VL_CpPair<VL_CpToken , LambdaCode::Ptr>(Input.First.First,Input.Second));
            431     Invoke->Argument=Input.First.Second;
            432     return Invoke;
            433 }
            434 
            435 LambdaCode::Ptr Parse(VUnicodeString Code)
            436 {
            437     VL_CpLexer Lexer;
            438     Lexer
            439         <<Token(false,L"let",ltiLet)
            440         <<Token(false,L"in",ltiIn)
            441         <<Token(false,L"\\",ltiClosure)
            442         <<Token(false,L"(",ltiLeft)
            443         <<Token(false,L")",ltiRight)
            444         <<Token(false,L".",ltiDot)
            445         <<Token(false,L"=",ltiEqual)
            446         <<Token(false,_Name,ltiName)
            447         <<Token(true,_Blank,-1)
            448         <<Token(true,_CComment,-1)
            449         <<Token(true,_CppComment,-1)
            450         ;
            451 
            452     typedef _Wrapper<VL_CpTokenNodePtr , LambdaCode::Ptr> CodeRule;
            453     typedef _Terminal<VL_CpTokenNodePtr , LambdaCode::Ptr> CodeTerminal;
            454 
            455     CodeRule Unit,Expr;
            456 
            457     CodeTerminal Primitive =
            458         (ToPrimitive <<= Token(ltiName));
            459 
            460     CodeTerminal Closure = 
            461         (ToClosure <<= ((Toks(L"\\"> Token(ltiName) < Toks(L".")) + Expr));
            462 
            463     CodeTerminal Bracket = 
            464         (Toks(L"("> Expr < Toks(L")"));
            465 
            466     CodeTerminal InExpr =
            467         Toks(L"in"> Expr;
            468 
            469     Unit=
            470         Primitive || Closure || Bracket;
            471 
            472     CodeTerminal Invoke=
            473         (ToInvoke <<= ++Unit);
            474 
            475     CodeTerminal LetIn=
            476         (ToLetIn <<=((Toks(L"let"> Token(ltiName) < Toks(L"=")) + Expr + InExpr));
            477 
            478     Expr=
            479         Invoke || LetIn;
            480 
            481     VL_CpParser<VL_CpTokenNodePtr , LambdaCode::Ptr> Parser=Expr;
            482 
            483     LambdaCode::Ptr Lambda=Parser.Parse(Lexer.Parse(Code.Buffer()).First.Head).Head->Data.First;
            484 
            485     LambdaIdentifier::TokenMap Tokens;
            486     Lambda->Initialize(Tokens);
            487     return Lambda;
            488 }
            489 
            490 /*********************************************************************************************************
            491 主程序
            492 *********************************************************************************************************/
            493 
            494 void vlmain()
            495 {
            496     GetConsole()->SetTitle(L"Vczh Lambda Evaluator");
            497     GetConsole()->SetTestMemoryLeaks(true);
            498     GetConsole()->SetPauseOnExit(true);
            499 
            500     VUnicodeString WorkSpace=VFileName(GetConsole()->GetAppPath()).MakeAbsolute(L"..\\TestData\\").GetStrW();
            501     VUnicodeString Code;
            502     {
            503         VL_FileStream Stream(WorkSpace+L"Program_01.txt",VL_FileStream::vomRead);
            504         Code=ReadText(&Stream);
            505     }
            506 
            507     try
            508     {
            509         LambdaCode::Ptr Lambda=Parse(Code);
            510         GetConsole()->WriteLine(Lambda->ToString());
            511         try
            512         {
            513             LambdaCode::Ptr Evaluated=Lambda->Evaluate();
            514             GetConsole()->WriteLine(L"最終結(jié)果:");
            515             GetConsole()->WriteLine(Evaluated->ToString());
            516         }
            517         catch(const LambdaError& Error)
            518         {
            519             GetConsole()->WriteLine(Error.Message);
            520         }
            521     }
            522     catch(const VL_CpException<VL_CpTokenNodePtr>& e)
            523     {
            524         if(e.Input)
            525         {
            526             GetConsole()->WriteLine(L""+VUnicodeString(e.Input->Data.Line+1)+L"行,記號(hào)\""+VUnicodeString(e.Input->Data.Start,e.Input->Data.Length)+L"\"附近有語(yǔ)法錯(cuò)誤。");
            527         }
            528         else
            529         {
            530             GetConsole()->WriteLine(L"程序末尾附近出現(xiàn)語(yǔ)法錯(cuò)誤。");
            531         }
            532     }
            533 }

            posted on 2009-05-11 04:30 陳梓瀚(vczh) 閱讀(5416) 評(píng)論(7)  編輯 收藏 引用 所屬分類: 啟示

            評(píng)論:
            # re: 丘奇數(shù)(Church Numerals)和lambda calculus 2009-05-11 05:54 | cy
            500幾行就誕生了一門語(yǔ)言.......  回復(fù)  更多評(píng)論
              
            # re: 丘奇數(shù)(Church Numerals)和lambda calculus 2009-05-11 06:32 | suxiaojack
            牛!
            這個(gè)語(yǔ)法太酷了。
            to cy :加上頭文件不只500多行。
              回復(fù)  更多評(píng)論
              
            # re: 丘奇數(shù)(Church Numerals)和lambda calculus 2009-05-11 08:21 | cy
            那些頭文件屬于這個(gè)語(yǔ)言的“設(shè)計(jì)支持”部分,暫時(shí)不算進(jìn)去~~

            感覺這樣的語(yǔ)言到達(dá)了電路設(shè)計(jì)級(jí)別  回復(fù)  更多評(píng)論
              
            # re: 丘奇數(shù)(Church Numerals)和lambda calculus 2009-05-12 06:28 | yindf
            127 行的Evaluate 參數(shù)是false,
            236 行的Evaluate 參數(shù)是true,

            可能會(huì)造成不一致吧?

            236行的true表示應(yīng)用序求值(先求值,后代換),但是127行的false表示不對(duì)前面的閉包求值,所以這個(gè)閉包是正則序求值的(先代換,后求值)。于是就可能造成不一致。

            不知道我理解的對(duì)不對(duì),請(qǐng)指教。  回復(fù)  更多評(píng)論
              
            # re: 丘奇數(shù)(Church Numerals)和lambda calculus 2009-05-13 00:53 | 陳梓瀚(vczh)
            @yindf
            不是這個(gè)意思,Evaluate=false指的是盡可能少求值,譬如對(duì)于一個(gè)函數(shù)表達(dá)式來說,(\x.(\y.y) x) 1和(\x.x) 1在對(duì)被調(diào)用函數(shù)的處理上是沒區(qū)別的,但是對(duì)于程序的結(jié)果來說,(\x.(\y.y) x)和(\x.x)是有區(qū)別的。所以Evaluate的意思其實(shí)是【正在求值的表達(dá)式是否根表達(dá)式】。如果\x.y是根表達(dá)式,那么y也是。如果\x.y z是跟表達(dá)式,那么y和z不算根表達(dá)式。  回復(fù)  更多評(píng)論
              
            # re: 丘奇數(shù)(Church Numerals)和lambda calculus 2009-05-13 01:29 | yindf
            @陳梓瀚(vczh)

            其實(shí)問題是一樣的,主要是你對(duì)表達(dá)式怎么求值的問題,比如:

            \x.x 1+2 這個(gè)式子,你是要
            先算1+2=3呢, (1)
            還是把\x.x 1+2直接替換成1+2? (2)

            如果你想做(1)的話,那么在(\x.(\y.y) x) 1中,(\x.(\y.y) x)就應(yīng)該先被計(jì)算成 (\y.y),然后再\y.y 1

            如果(2)的話,那么在(\x.(\y.y) x) 1中,先把x換成1,變成(\y.y) 1

            (1)表示對(duì)所有函數(shù),先求出參數(shù)表達(dá)式,然后再帶入。
            (2)表示先把參數(shù)直接帶入展開,展開到最底層,最后一起求值。

            在函數(shù)式編程里面,比如一個(gè)函數(shù)接受另一個(gè)函數(shù)做參數(shù),那么你是要先計(jì)算參數(shù)的值呢,還是直接把參數(shù)帶進(jìn)去?

            因?yàn)槲腋杏X你在用(1)方法,所以我覺得函數(shù)在使用前應(yīng)該求值。

            其實(shí)問題的本質(zhì)是函數(shù)在使用前應(yīng)不應(yīng)該被化簡(jiǎn),對(duì)于采用應(yīng)用序的語(yǔ)言來說,應(yīng)該。  回復(fù)  更多評(píng)論
              
            # re: 丘奇數(shù)(Church Numerals)和lambda calculus 2009-05-13 07:00 | 陳梓瀚(vczh)
            @yindf
            函數(shù)使用前不簡(jiǎn)化(只需要變成一個(gè)lambda表達(dá)式即可,lambda里面的內(nèi)容不理),不然你無(wú)法對(duì)那個(gè)傳說中的Y函數(shù)求值,會(huì)死循環(huán)的。你可以去學(xué)習(xí)一下惰性求值。  回復(fù)  更多評(píng)論
              
            久久精品国产亚洲AV嫖农村妇女| 亚洲精品国产美女久久久| 韩国三级大全久久网站| 青青草国产精品久久| 久久久久婷婷| 亚洲αv久久久噜噜噜噜噜| 久久免费高清视频| 久久香综合精品久久伊人| 久久国产精品99国产精| 久久久久久噜噜精品免费直播| 久久久久久综合网天天| 久久99国产精品99久久| 热久久最新网站获取| 青青青伊人色综合久久| 久久综合九色综合网站| 青青青伊人色综合久久| 亚洲欧洲日产国码无码久久99| 国产午夜精品久久久久九九电影| 亚洲午夜无码久久久久| 久久青青国产| 国产精品成人无码久久久久久| 77777亚洲午夜久久多人| 久久久久无码中| 国产亚洲成人久久| 国产精品天天影视久久综合网| 久久久黄色大片| 久久WWW免费人成—看片| 久久电影网一区| 99久久99这里只有免费的精品| 久久婷婷色综合一区二区| 久久精品亚洲乱码伦伦中文| 亚洲国产成人久久综合一| 99久久99这里只有免费的精品| 久久人人爽人人爽人人AV| 无码任你躁久久久久久久| 人妻丰满?V无码久久不卡| 久久婷婷色综合一区二区| 久久亚洲视频| 亚洲国产香蕉人人爽成AV片久久 | 人妻系列无码专区久久五月天| 93精91精品国产综合久久香蕉 |