• <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  評論-2670  文章-0  trackbacks-0
                說到底Kernel FP是一個腳本引擎,所以是需要API的。接下來的代碼用來加載一些Kernel FP代碼文件,并執行main函數。

                首先,我們讀入的文件是一個目錄,目錄記錄了一個Kernel FP程序所需要的所有代碼文件:Project.txt
            1 Startup.txt
            2 SysUtils.txt
            3 List.txt

                讀入文件之后將文件按行分割:
            1     VUnicodeString TestDataPath=VFileName(GetConsole()->GetAppPath()).MakeAbsolute(L"..\\TestData\\").GetStrW();
            2     VUnicodeString TestOutput;
            3     VL_UniStrings CodeFiles;
            4     {
            5         VL_FileStream Stream(TestDataPath+L"Project.txt",VL_FileStream::vfomRead);
            6         VUnicodeString Project=ReadText(&Stream);
            7         CodeFiles.SetText(Project);
            8     }

                現在CodeFiles已經有3個文件的文件名了,現在需要聲明一些Kernel FP對象,然后加載這些文件。文件在語法分析的時候出錯,程序需要打印出錯誤信息:
             1     VL_KfpSymbol Symbol;
             2     Symbol.AddUnit(CreateConsoleUnit());
             3     VBool ErrorOccurred=false;
             4     for(VInt i=0;i<CodeFiles.GetCount();i++)
             5     {
             6         VL_FileStream Stream(TestDataPath+CodeFiles[i],VL_FileStream::vfomRead);
             7         VUnicodeString TestCode=ReadText(&Stream);
             8 
             9         VL_KfpError::List Errors;
            10         Symbol.AddUnit(TestCode,Errors);
            11         if(Errors.GetCount())
            12         {
            13             TestOutput+=L"文件\""+VUnicodeString(CodeFiles[i])+L"\"含有語法錯誤:\r\n";
            14             TestOutput+=ToString(Errors);
            15             ErrorOccurred=true;
            16         }
            17     }

                收集了所有代碼文件之后,需要先進行一次編譯,在內部生成運行時所需要的assembly。當然,API不允許外部訪問內部信息:
             1     if(!ErrorOccurred)
             2     {
             3         VL_KfpError::List Errors;
             4         Symbol.PreCompile(Errors);
             5         if(Errors.GetCount())
             6         {
             7             TestOutput+=L"生成符號表時發生錯誤\r\n";
             8             TestOutput+=ToString(Errors);
             9             ErrorOccurred=true;
            10         }
            11     }

                如果到這一步仍然沒有問題的話,我們可以創建VL_KfpMachine了。這個Machine提供了訪問程序公布的一些函數和對象。
            1     if(!ErrorOccurred)
            2     {
            3         VL_KfpMachine::Ptr Machine=Symbol.CreateMachine();
            4         RunProgram(Machine);
            5     }
            6     else
            7     {
            8         GetConsole()->Write(TestOutput);
            9     }

                中間有一步出錯的話,控制臺窗口上會顯示所有錯誤信息。在上面我們發現有一個ToString函數將一個錯誤列表轉換成字符串:
             1 VUnicodeString ToString(VL_KfpError::List& Errors)
             2 {
             3     VUnicodeString Result=L"";
             4     for(VInt i=0;i<Errors.GetCount();i++)
             5     {
             6         Result+=L"錯誤["+VUnicodeString(i+1)+L"]\t模塊:"+Errors[i]->Module+L"\t行號:"+VUnicodeString(Errors[i]->Token.LineInFile+1)+L"\r\n";
             7         Result+=L"信息:"+Errors[i]->Message+L"\r\n";
             8     }
             9     return Result;
            10 }

                接下來是RunProgram函數了。這個函數獲得startup.main,我們假設main函數是放在startup命名空間下面的。當然,如果不確定命名空間的話,我們可以通過其他豐富的查詢手段來獲得我們需要的函數:
             1 void RunProgram(VL_KfpMachine::Ptr Machine)
             2 {
             3     ConsolePlugin Plugin;
             4     Machine->AddPlugin(&Plugin,false);
             5 
             6     VInt Index=0;
             7     VInt ID=Machine->GetFunctionFirstIdByName(L"startup.main");
             8     if(ID==-1)
             9     {
            10         break;
            11     }
            12     else
            13     {
            14         VL_KfpValue MainFunction=Machine->CreateFunction(ID);
            15         if(MainFunction.IsInvokable())
            16         {
            17             MainFunction=Machine->CreateEvaluableIO(MainFunction);
            18         }
            19         GetConsole()->Write(L"返回值:"+MainFunction.GetDebugString()+L"\r\n");
            20     }
            21 }

                這里面有兩個問題。控制臺程序是要有read和write的API的。所以我們這里提供了兩個接口。首先,剛才在編譯Kernel FP之前有一句代碼添加read和write的符號:
            1     VL_KfpSymbol Symbol;
            2     Symbol.AddUnit(CreateConsoleUnit());

                CreateConsoleUnit代碼如下:
             1 KfpUnit CreateConsoleUnit()
             2 {
             3     KfpUnit Unit(L"console");
             4     Unit.AddImport(L"system");
             5     //func read :: IO string alias "KfpType::read"
             6     Unit.AddFuncAlias(KfpDecl(L"read"),
             7         KfpType(L"IO")<<KfpType(L"string"),
             8         L"console::read"
             9         );
            10     //func write :: string -> IO void alias "KfpType::write"
            11     Unit.AddFuncAlias(KfpDecl(L"write"),
            12         KfpType(L"string")>>(KfpType(L"IO")<<KfpType(L"void")),
            13         L"console::write"
            14         );
            15     //func writeln :: string -> IO void alias "KfpType::writeln"
            16     Unit.AddFuncAlias(KfpDecl(L"writeln"),
            17         KfpType(L"string")>>(KfpType(L"IO")<<KfpType(L"void")),
            18         L"console::writeln"
            19         );
            20     return Unit;
            21 }

                有了這些符號還是不夠的。程序運行的過程中,調用了這些函數的話,仍然需要我們處理。所以我們還得實現一個插件來執行這三個函數:
             1 class ConsolePlugin : public VL_KfpPlugin
             2 {
             3 protected:
             4     VInt        FuncRead;
             5     VInt        FuncWrite;
             6     VInt        FuncWriteLine;
             7 public:
             8     ConsolePlugin()
             9     {
            10         FuncRead=-1;
            11         FuncWrite=-1;
            12         FuncWriteLine=-1;
            13     }
            14 
            15     void DestroyUserValue(VL_Base* Object)
            16     {
            17     }
            18 
            19     void ConnectMachine()
            20     {
            21         FuncRead        =RegisterExternalFunction(L"console::read",        1);
            22         FuncWrite        =RegisterExternalFunction(L"console::write",    2);
            23         FuncWriteLine    =RegisterExternalFunction(L"console::writeln",    2);
            24     }
            25 
            26     VUnicodeString GetName()
            27     {
            28         return L"Vczh KernelFP Demo Console Plugin";
            29     }
            30 
            31     VLE_KfpPluginResult Invoke(VInt ExternalID , InParams& In , OutParams& Out)
            32     {
            33         if(ExternalID==FuncWrite || ExternalID==FuncWriteLine)
            34         {
            35             if(In.Parameters.GetCount()==2)
            36             {
            37                 VUnicodeString String;
            38                 if(In.Parameters[0].GetString(String))
            39                 {
            40                     if(ExternalID==FuncWrite)
            41                     {
            42                         GetConsole()->Write(String);
            43                     }
            44                     else
            45                     {
            46                         GetConsole()->Write(String+L"\r\n");
            47                     }
            48                     Out.Result=GetMachine()->CreateIOSuccess(GetMachine()->CreateVoid());
            49                     return vkprSuccess;
            50                 }
            51                 else if(In.Parameters[0].GetErrorMessage(Out.ErrorMessage))
            52                 {
            53                     return vkprFail;
            54                 }
            55             }
            56             Out.ErrorMessage=
            57                 (ExternalID==FuncWrite?
            58                 L"write函數的參數必須是一個string和一個IOEnv。":
            59                 L"writeln函數的參數必須是一個string和一個IOEnv。"
            60                 );
            61             return vkprFail;
            62         }
            63         if(ExternalID==FuncRead)
            64         {
            65             if(In.Parameters.GetCount()==1)
            66             {
            67                 VUnicodeString String;
            68                 GetConsole()->Read(String);
            69                 Out.Result=GetMachine()->CreateIOSuccess(GetMachine()->CreateString(String));
            70                 return vkprSuccess;
            71             }
            72             else
            73             {
            74                 Out.ErrorMessage=L"read函數的參數必須是一個IOEnv。";
            75                 return vkprFail;
            76             }
            77         }
            78         return vkprPass;
            79     }
            80 };

                插件在ConnectMachine的時候,注冊函數名和參數個數,然后返回一個ID供Invoke使用。跟IO有關的函數都是IO類型的。譬如read是IO string,而write是string->IO void。IO類型的函數都多了一個參數用于其他用途,所以read、write和writeln的參數個數才會是1、2和2。

                Kernel FP API還提供了一些輔助函數用于創建或訪問IO對象。實際上只要插件的行為與插件所聲明的函數類型一致的話,基本上是不會有問題的。程序到這里就結束了,讓我們看一看system(自動加載)模塊與console(CreateConsoleUnit)模塊生成的代碼:

                首先是system模塊:
              1 module system
              2 
              3 type void
              4 
              5 type int
              6 
              7 type float
              8 
              9 type char
             10 
             11 data bool = (false | true)
             12 
             13 data list T = (empty | (list T (list T)))
             14 
             15 data maybe Ts Tf = ((success Ts) | (fail Tf))
             16 
             17 type string = (list char)
             18 
             19 data pair T1 T2 = (pair T1 T2)
             20 
             21 data IOError = (ioemessage string)
             22 
             23 type IOEnv
             24 
             25 type IO T = (IOEnv -> (maybe (pair T IOEnv) IOError))
             26 
             27 func iadd :: (int -> (int -> int)) alias "kernelfp::iadd"
             28 
             29 func isub :: (int -> (int -> int)) alias "kernelfp::isub"
             30 
             31 func imul :: (int -> (int -> int)) alias "kernelfp::imul"
             32 
             33 func idiv :: (int -> (int -> int)) alias "kernelfp::idiv"
             34 
             35 func imod :: (int -> (int -> int)) alias "kernelfp::imod"
             36 
             37 func igt :: (int -> (int -> bool)) alias "kernelfp::igt"
             38 
             39 func ilt :: (int -> (int -> bool)) alias "kernelfp::ilt"
             40 
             41 func iequ :: (int -> (int -> bool)) alias "kernelfp::iequ"
             42 
             43 func iegt :: (int -> (int -> bool)) alias "kernelfp::iegt"
             44 
             45 func ielt :: (int -> (int -> bool)) alias "kernelfp::ielt"
             46 
             47 func ineq :: (int -> (int -> bool)) alias "kernelfp::ineq"
             48 
             49 func fadd :: (float -> (float -> float)) alias "kernelfp::fadd"
             50 
             51 func fsub :: (float -> (float -> float)) alias "kernelfp::fsub"
             52 
             53 func fmul :: (float -> (float -> float)) alias "kernelfp::fmul"
             54 
             55 func fdiv :: (float -> (float -> float)) alias "kernelfp::fdiv"
             56 
             57 func fmod :: (float -> (float -> float)) alias "kernelfp::fmod"
             58 
             59 func fgt :: (float -> (float -> bool)) alias "kernelfp::fgt"
             60 
             61 func flt :: (float -> (float -> bool)) alias "kernelfp::flt"
             62 
             63 func fequ :: (float -> (float -> bool)) alias "kernelfp::fequ"
             64 
             65 func fegt :: (float -> (float -> bool)) alias "kernelfp::fegt"
             66 
             67 func felt :: (float -> (float -> bool)) alias "kernelfp::felt"
             68 
             69 func fneq :: (float -> (float -> bool)) alias "kernelfp::fneq"
             70 
             71 func isnan :: (float -> bool) alias "kernelfp::isnan"
             72 
             73 func isinf :: (float -> bool) alias "kernelfp::isinf"
             74 
             75 func chr :: (int -> char) alias "kernelfp::chr"
             76 
             77 func ord :: (char -> int) alias "kernelfp::ord"
             78 
             79 func cgt :: (char -> (char -> bool)) alias "kernelfp::cgt"
             80 
             81 func clt :: (char -> (char -> bool)) alias "kernelfp::clt"
             82 
             83 func cequ :: (char -> (char -> bool)) alias "kernelfp::cequ"
             84 
             85 func cegt :: (char -> (char -> bool)) alias "kernelfp::cegt"
             86 
             87 func celt :: (char -> (char -> bool)) alias "kernelfp::celt"
             88 
             89 func cneq :: (char -> (char -> bool)) alias "kernelfp::cneq"
             90 
             91 func ceil :: (float -> float) alias "kernelfp::ceil"
             92 
             93 func floor :: (float -> float) alias "kernelfp::floor"
             94 
             95 func trunc :: (float -> float) alias "kernelfp::trunc"
             96 
             97 func itof :: (int -> float) alias "kernelfp::itof"
             98 
             99 func ftoi :: (float -> int) alias "kernelfp::ftoi"
            100 
            101 func abs :: (float -> float) alias "kernelfp::abs"
            102 
            103 func exp :: (float -> float) alias "kernelfp::exp"
            104 
            105 func ln :: (float -> float) alias "kernelfp::ln"
            106 
            107 func lg :: (float -> float) alias "kernelfp::lg"
            108 
            109 func sqr :: (float -> float) alias "kernelfp::sqr"
            110 
            111 func pow :: (float -> (float -> float)) alias "kernelfp::pow"
            112 
            113 func sin :: (float -> float) alias "kernelfp::sin"
            114 
            115 func cos :: (float -> float) alias "kernelfp::cos"
            116 
            117 func tan :: (float -> float) alias "kernelfp::tan"
            118 
            119 func asin :: (float -> float) alias "kernelfp::asin"
            120 
            121 func acos :: (float -> float) alias "kernelfp::acos"
            122 
            123 func atan :: (float -> float) alias "kernelfp::atan"
            124 
            125 func atan2 :: (float -> (float -> float)) alias "kernelfp::atan2"
            126 
            127 func itoa :: (int -> string) alias "kernelfp::itoa"
            128 
            129 func ftoa :: (float -> string) alias "kernelfp::ftoa"
            130 
            131 func atoi :: (string -> (maybe int string)) alias "kernelfp::atoi"
            132 
            133 func atof :: (string -> (maybe float string)) alias "kernelfp::atof"
            134 
            135 func iovoid :: (IO void) alias "kernelfp::iovoid"
            136 
            137 func (>>>) T1 T2 :: ((IO T1) -> ((IO T2) -> (IO T2))) alias "kernelfp::(>>>)"
            138 
            139 func (>>=) T1 T2 :: ((IO T1) -> ((T1 -> (IO T2)) -> (IO T2))) alias "kernelfp::(>>=)"
            140 

                然后是console模塊:
            1 module console
            2 import system
            3 
            4 func read :: (IO string) alias "console::read"
            5 
            6 func write :: (string -> (IO void)) alias "console::write"
            7 
            8 func writeln :: (string -> (IO void)) alias "console::writeln"
            9 

                一個將Kernel FP代碼當成命令行程序執行的宿主程序已經完成了。現在讓我們看看完整的代碼:
              1 #include "..\..\..\..\VL++\Library\Platform\VL_Console.h"
              2 #include "..\..\..\..\VL++\Library\Script\KernelFP\VL_KFPScript.h"
              3 #include "..\..\..\..\VL++\Library\Data\VL_Stream.h"
              4 #include "..\..\..\..\VL++\Library\Data\VL_System.h"
              5 #include "..\..\..\..\VL++\Library\Data\VL_Uniop.h"
              6 
              7 using namespace vl;
              8 using namespace vl::platform;
              9 using namespace vl::kernalfp;
             10 using namespace vl::stream;
             11 using namespace vl::system;
             12 using namespace vl::uniop;
             13 
             14 VUnicodeString ToString(VL_KfpError::List& Errors)
             15 {
             16     VUnicodeString Result=L"";
             17     for(VInt i=0;i<Errors.GetCount();i++)
             18     {
             19         Result+=L"錯誤["+VUnicodeString(i+1)+L"]\t模塊:"+Errors[i]->Module+L"\t行號:"+VUnicodeString(Errors[i]->Token.LineInFile+1)+L"\r\n";
             20         Result+=L"信息:"+Errors[i]->Message+L"\r\n";
             21     }
             22     return Result;
             23 }
             24 
             25 KfpUnit CreateConsoleUnit()
             26 {
             27     KfpUnit Unit(L"console");
             28     Unit.AddImport(L"system");
             29     //func read :: IO string alias "KfpType::read"
             30     Unit.AddFuncAlias(KfpDecl(L"read"),
             31         KfpType(L"IO")<<KfpType(L"string"),
             32         L"console::read"
             33         );
             34     //func write :: string -> IO void alias "KfpType::write"
             35     Unit.AddFuncAlias(KfpDecl(L"write"),
             36         KfpType(L"string")>>(KfpType(L"IO")<<KfpType(L"void")),
             37         L"console::write"
             38         );
             39     //func writeln :: string -> IO void alias "KfpType::writeln"
             40     Unit.AddFuncAlias(KfpDecl(L"writeln"),
             41         KfpType(L"string")>>(KfpType(L"IO")<<KfpType(L"void")),
             42         L"console::writeln"
             43         );
             44     return Unit;
             45 }
             46 
             47 class ConsolePlugin : public VL_KfpPlugin
             48 {
             49 protected:
             50     VInt        FuncRead;
             51     VInt        FuncWrite;
             52     VInt        FuncWriteLine;
             53 public:
             54     ConsolePlugin()
             55     {
             56         FuncRead=-1;
             57         FuncWrite=-1;
             58         FuncWriteLine=-1;
             59     }
             60 
             61     void DestroyUserValue(VL_Base* Object)
             62     {
             63     }
             64 
             65     void ConnectMachine()
             66     {
             67         FuncRead        =RegisterExternalFunction(L"console::read",        1);
             68         FuncWrite        =RegisterExternalFunction(L"console::write",    2);
             69         FuncWriteLine    =RegisterExternalFunction(L"console::writeln",    2);
             70     }
             71 
             72     VUnicodeString GetName()
             73     {
             74         return L"Vczh KernelFP Demo Console Plugin";
             75     }
             76 
             77     VLE_KfpPluginResult Invoke(VInt ExternalID , InParams& In , OutParams& Out)
             78     {
             79         if(ExternalID==FuncWrite || ExternalID==FuncWriteLine)
             80         {
             81             if(In.Parameters.GetCount()==2)
             82             {
             83                 VUnicodeString String;
             84                 if(In.Parameters[0].GetString(String))
             85                 {
             86                     if(ExternalID==FuncWrite)
             87                     {
             88                         GetConsole()->Write(String);
             89                     }
             90                     else
             91                     {
             92                         GetConsole()->Write(String+L"\r\n");
             93                     }
             94                     Out.Result=GetMachine()->CreateIOSuccess(GetMachine()->CreateVoid());
             95                     return vkprSuccess;
             96                 }
             97                 else if(In.Parameters[0].GetErrorMessage(Out.ErrorMessage))
             98                 {
             99                     return vkprFail;
            100                 }
            101             }
            102             Out.ErrorMessage=
            103                 (ExternalID==FuncWrite?
            104                 L"write函數的參數必須是一個string和一個IOEnv。":
            105                 L"writeln函數的參數必須是一個string和一個IOEnv。"
            106                 );
            107             return vkprFail;
            108         }
            109         if(ExternalID==FuncRead)
            110         {
            111             if(In.Parameters.GetCount()==1)
            112             {
            113                 VUnicodeString String;
            114                 GetConsole()->Read(String);
            115                 Out.Result=GetMachine()->CreateIOSuccess(GetMachine()->CreateString(String));
            116                 return vkprSuccess;
            117             }
            118             else
            119             {
            120                 Out.ErrorMessage=L"read函數的參數必須是一個IOEnv。";
            121                 return vkprFail;
            122             }
            123         }
            124         return vkprPass;
            125     }
            126 };
            127 
            128 void RunProgram(VL_KfpMachine::Ptr Machine)
            129 {
            130     ConsolePlugin Plugin;
            131     Machine->AddPlugin(&Plugin,false);
            132 
            133     VInt Index=0;
            134     VInt ID=Machine->GetFunctionFirstIdByName(L"startup.main");
            135     if(ID==-1)
            136     {
            137         break;
            138     }
            139     else
            140     {
            141         VL_KfpValue MainFunction=Machine->CreateFunction(ID);
            142         if(MainFunction.IsInvokable())
            143         {
            144             MainFunction=Machine->CreateEvaluableIO(MainFunction);
            145         }
            146         GetConsole()->Write(L"返回值:"+MainFunction.GetDebugString()+L"\r\n");
            147     }
            148 }
            149 
            150 void vlmain()
            151 {
            152     GetConsole()->SetTitle(L"Vczh Kernal FP");
            153     GetConsole()->SetPauseOnExit(true);
            154     GetConsole()->SetTestMemoryLeaks(true);
            155 
            156     VUnicodeString TestDataPath=VFileName(GetConsole()->GetAppPath()).MakeAbsolute(L"..\\TestData\\").GetStrW();
            157     VUnicodeString TestOutput;
            158     VL_UniStrings CodeFiles;
            159     {
            160         VL_FileStream Stream(TestDataPath+L"Project.txt",VL_FileStream::vfomRead);
            161         VUnicodeString Project=ReadText(&Stream);
            162         CodeFiles.SetText(Project);
            163     }
            164 
            165     VL_KfpSymbol Symbol;
            166     Symbol.AddUnit(CreateConsoleUnit());
            167     VBool ErrorOccurred=false;
            168     for(VInt i=0;i<CodeFiles.GetCount();i++)
            169     {
            170         VL_FileStream Stream(TestDataPath+CodeFiles[i],VL_FileStream::vfomRead);
            171         VUnicodeString TestCode=ReadText(&Stream);
            172 
            173         VL_KfpError::List Errors;
            174         Symbol.AddUnit(TestCode,Errors);
            175         if(Errors.GetCount())
            176         {
            177             TestOutput+=L"文件\""+VUnicodeString(CodeFiles[i])+L"\"含有語法錯誤:\r\n";
            178             TestOutput+=ToString(Errors);
            179             ErrorOccurred=true;
            180         }
            181     }
            182     if(!ErrorOccurred)
            183     {
            184         VL_KfpError::List Errors;
            185         Symbol.PreCompile(Errors);
            186         if(Errors.GetCount())
            187         {
            188             TestOutput+=L"生成符號表時發生錯誤\r\n";
            189             TestOutput+=ToString(Errors);
            190             ErrorOccurred=true;
            191         }
            192     }
            193     if(!ErrorOccurred)
            194     {
            195         VL_KfpMachine::Ptr Machine=Symbol.CreateMachine();
            196         RunProgram(Machine);
            197     }
            198     else
            199     {
            200         GetConsole()->Write(TestOutput);
            201     }
            202 }
            posted on 2008-12-17 19:15 陳梓瀚(vczh) 閱讀(1634) 評論(1)  編輯 收藏 引用 所屬分類: 腳本技術

            評論:
            # re: 使用Kernel FP API實現一個運行Kernel FP代碼的控制臺程序 2008-12-18 06:29 | dell筆記本
            收藏,謝謝  回復  更多評論
              
            欧美亚洲国产精品久久| 久久久亚洲裙底偷窥综合| jizzjizz国产精品久久| 九九99精品久久久久久| 热综合一本伊人久久精品| 久久亚洲AV成人无码| 狠狠久久亚洲欧美专区| 久久国产福利免费| 久久久久99精品成人片欧美| 久久九九久精品国产| 亚洲第一极品精品无码久久| 国产精品成人无码久久久久久| 一本久久综合亚洲鲁鲁五月天| 精品久久久噜噜噜久久久| 亚洲国产精品嫩草影院久久| 久久ZYZ资源站无码中文动漫| 99久久精品免费看国产一区二区三区 | 久久久久亚洲AV无码专区网站| 久久久午夜精品福利内容| 99国产精品久久久久久久成人热| 欧美大战日韩91综合一区婷婷久久青草 | 久久国产乱子伦精品免费强| 久久人妻AV中文字幕| 国产精品久久久久久久午夜片| 久久久免费精品re6| 久久久国产视频| 欧美午夜A∨大片久久 | 色综合久久中文字幕综合网| 国产精品久久久久久久久免费| 亚洲国产精品无码成人片久久| 女人高潮久久久叫人喷水| 丰满少妇人妻久久久久久4| 99久久免费国产特黄| 久久精品黄AA片一区二区三区| 久久精品中文无码资源站| 欧美亚洲国产精品久久久久| 亚洲国产精品无码久久九九| 久久亚洲视频| 中文字幕久久精品 | 国内精品久久久久久99| A狠狠久久蜜臀婷色中文网|