<cite id="ffb66"></cite><cite id="ffb66"><track id="ffb66"></track></cite>
      <legend id="ffb66"><li id="ffb66"></li></legend>
      色婷婷久,激情色播,久久久无码专区,亚洲中文字幕av,国产成人A片,av无码免费,精品久久国产,99视频精品3
      網易首頁 > 網易號 > 正文 申請入駐

      三天時間,我用這門國產編程語言寫了個編譯器,同事們看后大為震驚!

      0
      分享至

      張大胖很幸運,剛畢業就進入了一家芯片設計公司。

      不過,工作了一個月以后,他就覺得不對勁了。

      原因很簡單,對于公司開發的最新芯片,主流的編程語言還不支持呢!

      無論是驗證特性,還是編寫測試,都不得不用最最古老的形式:匯編!

      張大胖決心改變這種狀況,他找到了梁經理,說出了自己的想法。

      確實是這樣,操作系統、圖形學,編譯器號稱程序員的三大浪漫,但每一項真做起來都讓人頭大。

      張大胖當年的畢業設計,一個極其簡單的編譯器,就讓他做了8個月!

      不過,梁經理似乎發現了一個“秘密武器”。

      MoonBit是一門國產開源編程語言,由 Rescript 作者張宏波(現居深圳)及其團隊打造,它的一些優秀特性,非常適合用來開發編譯器和新編程語言。

      張大胖非常高興,決定利用之前畢業設計的經驗,用MoonBit做個實驗,設計并實現一個新的編程語言!

      為了記錄自己的工作,他用日記的形式記錄下了每天的進展:


      ———日記開始———

      第一天:語言設計與詞法分析

      晚上下班,照常來說,我會打開原神欣賞一下提瓦特的風景。不過今天要用MoonBit實現新編程語言了,游戲就先放到一邊吧。

      1、語言設計

      我打算設計的這門語言叫 TinyMoonBit。它得有常見的數值類型、分支循環、函數、內存管理和 CFFI。語法上,我決定讓它看起來像 MoonBit,但內核更像 C。

      同時,為了體現“現代”語言的優越性,我給它設計了更嚴格的類型系統,比如 1 + 1.0 這種在 C 語言里司空見慣的隱式類型轉換,在 TinyMoonBit 里是不允許的。

      我隨手寫下了一個 TinyMoonBit 的示例程序,用來計算斐波那契數列:

      extern fn print_int(x : Int) -> Unit;
      // 遞歸實現斐波那契數列
      fn fib(n : Int) -> Int {
        if n <= 1 { return n; }
        return fib(n - 1) + fib(n - 2);
      }
      fn main() -> Unit {
        print_int(fib(10));
      }

      2、詞法分析

      第一步是詞法分析。通俗地說,就是把一長串代碼文本,切分成一個個有意義的“單詞”,我們稱之為 Token。比如 let x = 5;,處理后應該變成一個 Token 序列:Keyword("let") -> Identifier("x") -> Operator("=") -> IntLiteral(5) -> Symbol(";")。

      在 MoonBit 里,這件事出奇的簡單。首先,用一個代數數據類型(ADT)來定義所有可能的 Token:

      pub enum Token {
        Bool(Bool)       // 布爾值:true, false
        Int(Int)         // 整數
        Keyword(String)  // 關鍵字:let, if, fn
        Upper(String)    // 類型標識符:Int, Bool
        Lower(String)    // 變量標識符:x, n
        Symbol(String)   // 運算符:+, -, ->
        Bracket(Char)    // 括號:(, ), {, }
        EOF              // 文件結束標記
      } derive(Show, Eq)

      然后,借助 MoonBit 的一大殺器——字符串模式匹配,我們可以像寫詩一樣實現詞法分析器:

      pub fn lex(code: String) -> Array[Token] {
        let tokens = Array::new()
        loop code[:] {
          // 跳過空白字符
          [' ' | '\n' | '\r' | '\t', ..rest] => 
            continue rest
          // 處理單行注釋
          [.."http://", ..rest] =>
            continue loop rest {
              ['\n', ..rest] => break rest
              [_, ..rest] => continue rest
              [] => break ""
            }
          
          // 識別多字符運算符 (順序很重要!)
          [.."->", ..rest] => { tokens.push(Symbol("->")); continue rest }
          [.."<=", ..rest] => { tokens.push(Symbol("<=")); continue rest }
          
          // 識別單字符運算符
          [':' |1 ';' | '+' | '-' | '*' | '/' | '<' | '=' as c, ..rest] => {
            tokens.push(Symbol("\{c}")); continue rest
          }
          
          // 識別標識符和關鍵字
          ['a'..='z', ..] as code => {
            let (tok, rest) = lex_ident(code) // lex_ident 會區分關鍵字和普通變量
            tokens.push(tok)
            continue rest
          }
          // ... 其他匹配,如數字、大寫字母開頭的類型等 ...
          
          [] => { tokens.push(EOF); break tokens }
        }
      }

      MoonBit 特性解讀

      函數式循環 (loop):它不是簡單的重復,而是一個不斷用新狀態(rest)迭代自身的遞歸過程,非常適合處理“吃掉”一部分字符串,然后處理剩余部分的場景。

      強大的模式匹配:[.."->", ..rest] 這樣的語法,可以直觀地匹配字符串前綴,比晦澀的正則表達式清晰百倍。

      只花了大半個小時,詞法分析器就寫完并測試通過了。我暗自竊喜,這要是用別的語言,光是處理各種邊界情況就得焦頭爛額。MoonBit 的 ADT 和模式匹配,寫起來真是既優雅又高效。

      第二天:語法分析與類型檢查

      有了昨晚的順利開局,我信心更足了。我趁著午休和晚上的時間,開始攻克編譯器的第二個難關。

      1、語法分析:從扁平到立體

      詞法分析產生的是一維的 Token 序列,而程序本身是有層次結構的。語法分析的任務,就是將這個扁平的序列,組織成一棵能夠反映代碼結構的抽象語法樹(AST)。

      首先,我定義了 AST 的節點。這就像為程序搭建骨架,每一塊骨骼都代表一種語法結構:

      // 表達式的定義
      pub enum Expr {
        AtomExpr(AtomExpr, mut ty~ : Type?)          // 原子表達式 (變量、字面量等)
        Unary(String, Expr, mut ty~ : Type?)         // 一元運算:-, !
        Binary(String, Expr, Expr, mut ty~ : Type?)  // 二元運算:+, -, *, /
      } derive(Show, Eq, ToJson)
      // 語句的定義
      pub enum Stmt {
        Let(String, Type, Expr)      // 變量聲明:let x : Int = 5;
        If(Expr, Array[Stmt], Array[Stmt])           // 條件分支
        While(Expr, Array[Stmt])     // 循環
        Return(Expr?)                // 返回
        // ... 其他語句 ...
      } derive(Show, Eq, ToJson)
      // 函數和程序的頂層結構
      pub struct Function {
        name : String
        params : Array[(String, Type)]
        ret_ty : Type
        body : Array[Stmt]
      } derive(Show, Eq, ToJson)
      pub type Program Map[String, Function]

      設計巧思:注意到每個表達式節點都有一個 mut ty~ : Type? 字段嗎?這是一個可變的可選類型字段。這樣,我就可以在后續的類型檢查階段,直接把推斷出的類型信息“填”進去,而無需重新構建一棵新樹,非常巧妙。

      有了骨架,接下來就是用 遞歸下降 的方法來填充它。簡單來說,就是為每一種語法結構(如函數、語句、表達式)編寫一個解析函數。在 MoonBit 中,這又成了模式匹配的絕佳舞臺:

      pub fn parse_function(tokens : ArrayView[Token]) -> (Function, ArrayView[Token]) raise {
        // Function一定由fn關鍵字,Lower,左括號開頭
        guard tokens is [Keyword("fn"), Lower(fname), Bracket('('), .. rest_tokens]
        let params : Array[(String, Type)] = Array::new()
        let (tokens, ret_ty) = loop rest_tokens {
          // 參數格式:param_name : Type
          [Lower(param_name), Symbol(":"), Upper(type_name), .. rest] => {
            params.push((param_name, parse_type(type_name)))
            continue rest
          }
          [Symbol(","), .. rest] => continue rest
          [Bracket(')'), Symbol("->"), Upper(ret_ty), .. rest] => 
            break (rest, parse_type(ret_ty))
        }
        // ... 解析函數體
      }

      整個過程就像剝洋蔥,parse_program 調用 parse_function,parse_function 調用 parse_stmt,parse_stmt 調用 parse_expr,層層遞進,直到把所有 Token 都消耗完畢。

      MoonBit 高級特性應用

      derive(Show, Eq, ToJson):這個小小的注解威力巨大。Show 讓我能輕松打印 AST 用于調試,Eq 用于測試,而 ToJson 能一鍵將 AST 序列化為 JSON,方便檢查其結構。

      raise 錯誤處理:通過在函數簽名中標記 raise,我可以優雅地向上拋出解析錯誤,而不用到處傳遞錯誤碼。

      2、類型檢查:確保語義正確

      在代碼生成之前,通常需要實現一個類型檢查階段。一些語句雖然符合語法,但可能不符合語義,例如我有一個foo函數,然后又有了1+foo這樣的代碼,但這是語義不正確的,因為一個整數無法與一個函數相加。

      我設計了一個環境鏈來處理作用域:

      pub struct TypeEnv[K, V] {
        parent : TypeEnv[K, V]?
        data : Map[K, V]
      }
      pub fn TypeEnv::get[K : Eq + Hash, V](self : Self[K, V], key : K) -> V? {
        match self.data.get(key) {
          Some(value) => Some(value)
          None => match self.parent {
            Some(parent_env) => parent_env.get(key)
            None => None
          }
        }
      }

      類型檢查器會自頂向下掃描每個表達式,填充類型信息并驗證類型一致性:

      pub fn Expr::check_type(self : Self, env : TypeEnv[String, Type]) -> Type raise {
        match self {
          Binary("+", lhs, rhs, ..) as node => {
            let lhs_type = lhs.check_type(env)
            let rhs_type = rhs.check_type(env)
            guard lhs_type == rhs_type else {
              raise TypeCheckError("類型不匹配")
            }
            node.ty = Some(lhs_type)
            lhs_type
          }
          // ... 其他表達式類型
        }
      }

      語法分析消耗的時間比預想的多一些,尤其是在處理運算符優先級時頗費腦筋。但在 MoonBit 強大的模式匹配和 AI 助手的幫助下,我還是在深夜前完成了這項工作。萬里長征,只剩下最后一步——代碼生成了。

      第三天:代碼生成,最后的難關

      MoonBit本身語言特性適合編譯器實現之外,也有一個超級好用的LLVM綁定,叫做llvm.mbt。

      1、LLVM:現代編譯器的基石

      LLVM作為現代編譯器基礎設施的集大成者,為我們提供了一個強大而靈活的解決方案。通過將程序轉換為LLVM中間表示(IR),我們可以利用LLVM成熟的工具鏈將代碼編譯到多種目標架構。

      我們先來試用LLVM的經典起手三段式:

      pub fn initialize_llvm() -> (Context, Module, Builder) {
        let ctx = @IR.Context::new()          // LLVM上下文
        let mod = ctx.addModule("demo")       // 模塊容器
        let builder = ctx.createBuilder()     // IR構建器
        (context, module, builder)
      }

      有了這三樣法寶,我們就能像搭積木一樣,一條條地構建出程序的 LLVM IR。比如生成一個計算 a*b+c 的函數:

      pub fn generate_muladd_function() -> String {
        let (ctx, mod, builder) = initialize_llvm()
        // 定義函數簽名:i32 muladd(i32, i32, i32)
        let i32_ty = ctx.getInt32Ty()
        let func_type = ctx.getFunctionType(i32_ty, [i32_ty, i32_ty, i32_ty])
        let func_value = mod.addFunction(func_type, "muladd")
        // 創建函數入口基本塊
        let entry_block = func_value.addBasicBlock(name="entry")
        builder.setInsertPoint(entry_block)
        // 獲取函數參數并生成計算指令
        let arg_a = func_value.getArg(0).unwrap()
        let arg_b = func_value.getArg(1).unwrap()
        let arg_c = func_value.getArg(2).unwrap()
        let mul_result = builder.createMul(arg_a, arg_b)
        let add_result = builder.createAdd(mul_result, arg_c)
        let _ = builder.createRet(add_result)
        mod.dump()
      }

      這會生成非常清晰的 LLVM IR:

      define i32 @muladd(i32 %a, i32 %b, i32 %c) {
      entry:
        %mul_res = mul i32 %a, %b
        %add_res = add i32 %mul_res, %c
        ret i32 %add_res
      }

      看起來很簡單,對吧?但真正的挑戰在于,如何將我們前一天生成的、復雜的 AST,系統性地翻譯成這一條條的 LLVM 指令。

      2、類型系統的映射

      在LLVM中,類型系統相當復雜。llvm.mbt使用Trait Object的概念,&Type可以表示任意LLVM類型。我需要建立TinyMoonBit類型與LLVM類型的映射:

      pub fn CodeGen::convert_type(self : Self, parser_type : Type) -> &@llvm.Type {
        match parser_type {
          Type::Unit => self.ctx.getVoidTy() as &@llvm.Type
          Type::Bool => self.ctx.getInt1Ty()
          Type::Int => self.ctx.getInt32Ty()  
          Type::Double => self.ctx.getDoubleTy()
        }
      }

      然后就是真正的代碼生成。我需要為 AST 中的每一種節點編寫一個 emit 方法。其中最有趣也最關鍵的,是如何處理變量和分支:

      3、變量處理:SSA與可變性的橋梁

      TinyMoonBit支持變量的重新賦值,但LLVM IR采用SSA(Static Single Assignment)形式,每個變量只能賦值一次。我需要采用alloca + load/store模式來處理可變變量:

      // 變量聲明:let x : Int = 5;
      Let(var_name, var_type, init_expr) => {
        let llvm_type = self.convert_type(var_type)
        let alloca = self.builder.createAlloca(llvm_type, name=var_name)
        env.symbols.set(var_name, alloca)
        let init_value = init_expr.emit(env)
        let _ = self.builder.createStore(alloca, init_value)
      }
      // 變量賦值:x = 10;
      Assign(var_name, rhs_expr) => {
        let var_ptr = env.get_symbol(var_name).unwrap()
        let rhs_value = rhs_expr.emit(env)
        let _ = self.builder.createStore(var_ptr, rhs_value)
      }

      4、控制流:基本塊的藝術

      控制流是程序邏輯的骨架。在LLVM IR中,控制流通過基本塊和分支指令來實現。每個基本塊代表一個沒有內部跳轉的指令序列:

      // if-else語句的實現
      If(cond, then_stmts, else_stmts) => {
        let cond_val = cond.emit(env)
        // 創建三個基本塊
        let then_block = func.addBasicBlock(name="if.then")
        let else_block = func.addBasicBlock(name="if.else") 
        let merge_block = func.addBasicBlock(name="if.end")
        // 條件分支
        let _ = builder.createCondBr(cond_val, then_block, else_block)
        // 生成then分支
        builder.setInsertPoint(then_block)
        then_stmts.each(s => s.emit(env))
        let _ = builder.createBr(merge_block)
        // 生成else分支  
        builder.setInsertPoint(else_block)
        else_stmts.each(s => s.emit(env))
        let _ = builder.createBr(merge_block)
        // 繼續在merge塊生成后續代碼
        builder.setInsertPoint(merge_block)
      }

      5、完整的代碼生成

      經過詞法分析、語法分析、類型檢查和代碼生成四個階段,我們的編譯器已經能夠將TinyMoonBit源代碼轉換為完整的LLVM IR。

      對于我們的斐波那契例子:

      fn fib(n : Int) -> Int {
        if n <= 1 { return n; }
        return fib(n - 1) + fib(n - 2);
      }

      最終生成的LLVM IR:

      define i32 @fib(i32 %0) {
      entry:
        %1 = alloca i32, align 4
        store i32 %0, ptr %1, align 4
        %2 = load i32, ptr %1, align 4
        %3 = icmp sle i32 %2, 1
        br i1 %3, label %4, label %6
      4:                                                
        %5 = load i32, ptr %1, align 4
        ret i32 %5
      6:                                                
        %7 = load i32, ptr %1, align 4
        %8 = sub i32 %7, 1
        %9 = call i32 @fib(i32 %8)
        %10 = load i32, ptr %1, align 4
        %11 = sub i32 %10, 2
        %12 = call i32 @fib(i32 %11)
        %13 = add i32 %9, %12
        ret i32 %13
      }

      使用LLC工具鏈,我們可以進一步將LLVM IR編譯成RISC-V匯編代碼,完成整個編譯過程。

      攻克了這些核心難點后,剩下的工作就是水到渠成了。周三深夜,當我看到 fib(10) 的代碼成功生成了復雜的 LLVM IR ,并順利通過llc鏈接編譯成可執行程序并且運行通過時,我知道,我成功了!


      ———日記結束———

      總結

      周四的午休時刻,張大胖向同事們展示了自己三天時間編寫的TinyMoonBit編譯器。

      確實,MoonBit的模式匹配讓詞法分析變得異常簡單,遞歸下降語法分析也很直觀。

      最關鍵的是llvm.mbt這個綁定庫,讓代碼生成變得容易很多。

      有了MoonBit以后,開發新語言就不那么難了,也許你也可以再把編譯原理撿起來,用MoonBit完成自己的年輕時的夢想:實現一個自己的編程語言!

      資源推薦

      對這個項目感興趣的讀者,可以從以下鏈接獲取更多信息:

      TinyMoonBit 完整項目 :


      https://github.com/Kaida-Amethyst/TinyMoonbitLLVM

      MoonBit 官方文檔 :


      https://www.moonbitlang.com/docs/

      llvm.mbt 文檔 :


      https://mooncakes.io/docs/Kaida-Amethyst/llvm

      LLVM 官方教程 :


      https://www.llvm.org/docs/tutorial/

      特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。

      Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

      相關推薦
      熱點推薦
      罕見!女足主帥米利西奇因熱身賽下課:37歲陳婉婷再次落選

      罕見!女足主帥米利西奇因熱身賽下課:37歲陳婉婷再次落選

      邱澤云
      2025-12-14 17:22:22
      澳大利亞邦迪灘槍擊事件已致16死,槍手為一對父子

      澳大利亞邦迪灘槍擊事件已致16死,槍手為一對父子

      觀察者網
      2025-12-15 07:18:04
      王一博海釣釣出帝王鮭!喊 “baby” 道歉,抱魚像年畫笑翻全網

      王一博海釣釣出帝王鮭!喊 “baby” 道歉,抱魚像年畫笑翻全網

      阿廢冷眼觀察所
      2025-12-15 01:12:42
      罰球準絕殺!詹姆斯對噴狄龍完勝!湖人拒絕逆轉,東契奇29+6

      罰球準絕殺!詹姆斯對噴狄龍完勝!湖人拒絕逆轉,東契奇29+6

      體壇小李
      2025-12-15 12:16:40
      生娃基本不花錢!明年力爭全國實現!

      生娃基本不花錢!明年力爭全國實現!

      看看新聞Knews
      2025-12-15 10:28:03
      阿隆索:皇馬需要狀態持續性

      阿隆索:皇馬需要狀態持續性

      體壇周報
      2025-12-15 11:33:13
      朱丹回金華老家,穿水靴割茭白弄一身泥,吃大碗“豬油面”很滿足

      朱丹回金華老家,穿水靴割茭白弄一身泥,吃大碗“豬油面”很滿足

      心靜物娛
      2025-12-15 09:46:52
      寧波通報患兒手術后離世

      寧波通報患兒手術后離世

      新京報
      2025-12-14 20:06:30
      日本記者挑釁:南京30萬你們數了?李連杰當場反問一句,他立馬閉嘴,提到了日本至今都抬不起頭的7萬女人公案

      日本記者挑釁:南京30萬你們數了?李連杰當場反問一句,他立馬閉嘴,提到了日本至今都抬不起頭的7萬女人公案

      歷史回憶室
      2025-12-11 18:47:11
      彩虹-7,首飛成功!

      彩虹-7,首飛成功!

      第一財經資訊
      2025-12-15 09:23:41
      外教杰森告別北京國安:這份情感將永遠存在,國安永遠爭第一

      外教杰森告別北京國安:這份情感將永遠存在,國安永遠爭第一

      懂球帝
      2025-12-15 08:29:03
      常遇春把兵符交予朱元璋,回府對心腹說:帳下四千鐵騎在城郊埋伏

      常遇春把兵符交予朱元璋,回府對心腹說:帳下四千鐵騎在城郊埋伏

      朝暮書屋
      2025-12-12 18:28:28
      就在今天!12月15日凌晨,傳來王曼昱、張本智和、樊振東最新消息

      就在今天!12月15日凌晨,傳來王曼昱、張本智和、樊振東最新消息

      皮皮觀天下
      2025-12-15 04:44:46
      柬埔寨是世界最貧窮的國家之一,但統治該國的洪森家族卻富可敵國

      柬埔寨是世界最貧窮的國家之一,但統治該國的洪森家族卻富可敵國

      大道無形我有型
      2025-09-05 11:31:52
      中國女游客在日本泡溫泉混進偽娘,因沒胸部暴露,酒店的回應讓人氣炸!

      中國女游客在日本泡溫泉混進偽娘,因沒胸部暴露,酒店的回應讓人氣炸!

      日本物語
      2025-12-14 20:43:30
      9000mAh!新機官宣:搭載天璣9500e+1.5K直屏!

      9000mAh!新機官宣:搭載天璣9500e+1.5K直屏!

      科技堡壘
      2025-12-14 12:05:40
      34歲張稀哲將重返國足?主帥邵佳一直接給出回應,球迷直呼意外!

      34歲張稀哲將重返國足?主帥邵佳一直接給出回應,球迷直呼意外!

      羅掌柜體育
      2025-12-15 09:36:04
      土媒:32歲的伊卡爾迪目前年薪1000萬歐元,米蘭難以負擔

      土媒:32歲的伊卡爾迪目前年薪1000萬歐元,米蘭難以負擔

      懂球帝
      2025-12-14 21:30:11
      小泉進次郎與美防長通話照被指“擺拍”,日本網民諷刺:表演也得拿根筆吧

      小泉進次郎與美防長通話照被指“擺拍”,日本網民諷刺:表演也得拿根筆吧

      環球網資訊
      2025-12-13 18:46:46
      曼城3-0輕取水晶宮!福登回暖謝爾基成“新丁丁”,阿森納壓力大

      曼城3-0輕取水晶宮!福登回暖謝爾基成“新丁丁”,阿森納壓力大

      里芃芃體育
      2025-12-15 11:10:15
      2025-12-15 12:28:49
      碼農翻身 incentive-icons
      碼農翻身
      有趣且硬核的技術文章
      207文章數 596關注度
      往期回顧 全部

      科技要聞

      平價數碼產品,要和我們說再見了?

      頭條要聞

      巨頭裁員史無前例 員工發現同事"消失":杯子還在桌上

      頭條要聞

      巨頭裁員史無前例 員工發現同事"消失":杯子還在桌上

      體育要聞

      戰勝完全體雷霆,馬刺“瘋狂動物城”只是半成品

      娛樂要聞

      黃綺珊在何晴去世首發,10年悄悄祈福

      財經要聞

      新會陳皮亂象曝光:產地造假、年份速成

      汽車要聞

      奔馳小G諜照,或搭混動或燃油動力

      態度原創

      房產
      親子
      家居
      旅游
      軍事航空

      房產要聞

      瘋狂拿地290畝!封關在即,又一民企重倉海南!

      親子要聞

      這孩子

      家居要聞

      溫潤質感 打造干凈空間

      旅游要聞

      大明湖雪后初霽,盡顯古韻今風冬日浪漫

      軍事要聞

      澤連斯基稱烏方已妥協不加入北約 俄方發聲

      無障礙瀏覽 進入關懷版 主站蜘蛛池模板: 五月情婷婷| 色综合热无码热国产| 成人在线超碰| 91新视频| 色欲狠狠躁天天躁无码中文字幕| 亚洲中文字幕无码一区日日添| 国模粉嫩小泬视频在线观看| 一本无码中文字幕| 永年县| 国产人妻无套一区二区普通话对白| 久久久久99精品成人片牛牛影视| 精品无码一区二区三区在线| 中文字幕不卡在线播放| 日韩在线视频网| 亚洲欧洲∨国产一区二区三区 | 中文字幕亚洲一区二区va在线| 亚洲国产精品久久一线不卡| 人人凹凸XX凹凸爽凹凸| 中文字幕在线观看亚洲| 高安市| 乱人伦??国语对白| 亚洲人妻av伦理| 亚洲精品欧美综合二区| 国产传媒淫语对白AV| 婷婷五月麻豆| 无码人妻中文字幕| av片在线播放| 老太婆性杂交视频| 国产?日韩?欧美| 长宁县| 日韩美女久久| 日韩精品一区二区三区在线观看| 亚洲av片在线免费观看| 国产精品一亚洲AV日韩AV欧| 亚色天堂| 久久婷婷久久一区二区三区| 又大又硬又爽免费视频| 91视频www| 大荔县| 亚洲电影在线观看| 亚洲综合在线另类色区奇米|