日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

gophp解释器_【干货】Gisp 解释器 Golang 辅助开发工具

發布時間:2023/12/3 php 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 gophp解释器_【干货】Gisp 解释器 Golang 辅助开发工具 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Gisp 是一個提供給 golang 使用的 Lisp 類 DSL 解釋器。在 Lisp 的基本語法基礎上,針對 go 環境稍作了一點語法糖。主要目標是提供一個盡可能便于與 golang 互操作的微型DSL工具。

簡介

Gisp用go語言編寫,是一個DSL 解釋器,這個 DSL 基本上就是 LIsp 的基礎語法,針對go程序的互操作需要稍微做了一點擴展。它的主要設計目標是盡可能方便的在 go 程序中調用 gisp 解釋器,執行 dsl。

我們的項目,目前后臺主要用 golang 開發。開發過程中,golang 確實達到了我們期待的易用、易維護。但是有幾個具體的問題阻礙了我們更好的使用它。這是我們開發一個內嵌解釋器的基本動機。我們希望用這種方式提升編程效率,更快的推進工作。

golang 使用過程中的問題

Golang 是一門很好的工程語言,整合了幾十年來工程界一些已被證明行之有效的經驗。成為一門非常適合網絡服務開發的后端工程語言。但是 golang 也存在一些具體的問題,影響了我們團隊的工作效率。

在 golang 中,沒有異常拋出和捕獲的機制,通常通過函數返回多個參數的方式,在 error 返回值中傳遞錯誤狀態。這樣的好處是錯誤不中斷程序,對于一些連續處理的程序邏輯非常方便。但是相應的,沒有強制中斷機制,對于一些依賴程序狀態,出錯需要跳出流程,但是不中斷整個程序進程的場合,就無能為力了。典型的,當我們需要組合大量的小函數調用的時候,幾乎每一步都要寫一個狀態判斷。

if err != nil {

return nil, err

}

在類似 parsec 解析這樣密集使用自定義 Parser、用 Bind 組合子傳遞狀態時,這種固定的錯誤處理代碼可以超過程序代碼行數的一半以上。這浪費了開發人員的工作,也影響代碼閱讀,提高了維護難度。

另一個問題是類型推導過于簡單。缺少泛型和 overload 機制。這樣固然學習簡單,編譯器的性能和質量容易有保障,但是代價是一些編程需求比較難實現。例如我們需要實現帶單位的商用數據的統計計算,就要處理非數值類型的累加。在我們的項目中,我們期望這個邏輯可以在運行期間不修改程序代碼,穩定可靠的適應,這對于golang比較困難。

要在不修改 golang 編譯器和語法的前提下,緩解這些由 golang 語法限制的問題,就要提供一個可以方便調用的 DSL 環境。這里我們選擇實現一個基本的 Lisp 解釋器。

安裝和環境構造

gisp依賴 github.com/Dwarfartisan/goparsec 。使用 gisp 前需要安裝 goparsec 和 gisp 。

go get github.com/Dwarfartisan/gisp

go get github.com/Dwarfartisan/goparsec

導入gisp時引用:

import (

"github.com/Dwarfartisan/gisp"

)

上面這個示例代碼只傳入了基本的公理操作。其中包括了 Lisp 七公理中的六個(cons 在這個環境中沒有實用的價值,直接實現為 append的封裝 concat)。當然我們甚至可以連公理體系都不加入,那時 gisp 仍可以作為一個詞法解析工具使用。

技術選擇與設計

選擇 Lisp ,主要是考慮兩個方面。

Lisp 的前端容易實現。之前為了業務后臺,我們在 golang 中實現了文本解析工具 parsec 。這里可以復用。

另一方面,Lisp 的程序即數據結構,這對于我們處理混合編程非常方便,可以將數據和程序調用在外部組裝后傳入解釋器環境。

調用接口

我們為 gisp 提供兩個執行程序的接口,Parse 接受代碼文本:

pi, err := gisp.Parse("box[\"c\"]")

if err != nil {

t.Fatalf("except got pi is 3.14 but error: %v", err)

}

而Eval是傳遞golang對象:

func TestMulAutoOverload(t *testing.T) {

in := Float(30.9)

ratio := Float(0.8)

out := in * ratio

g := NewGisp(map[string]Toolbox{

"axioms": Axiom,

"props": Propositions,

})

g.Defun("*", mrmul())

mulx, ok := g.Lookup("*")

if !ok {

t.Fatalf("except got overloaded function *")

}

ret, err := g.Eval(List{mulx, in, ratio})

if err != nil {

t.Fatalf("except %v * %v is %v but error %v", in, ratio, out, err)

}

if !reflect.DeepEqual(ret, out) {

t.Fatalf("except %v * %v is %v but %v", in, ratio, out, ret)

}

}

看起來我們仍然要處理 Parse 和 Eval 中傳遞出來的 error 狀態,但是 gisp 會自動監測每一個代碼語句的執行結果,一旦有錯誤就跳出,我們只需要在每次調用 Parse 或 Eval 后監測一次。

上例中的代碼我們后面再做進一步講解。這里我們可以看到,代碼中演示了乘法運算符重載。

gisp 運行機制

1.環境

首先,這里介紹 Gisp 環境的概念,Gisp 文本代碼或者 gisp 代碼序列,都執行在解釋器對象中,而解釋器解釋代碼序列,需要使用環境(gisp.Env)。一個 gisp.Env ,需要實現 Lookup,Local、Global、Set、Defvar、Defun 方法。

Local 方法查找本地是否有給定命名,這要求實現 gisp.Env 時應自己實現一個命名管理機制。

Global 方法查找當前環境的外部環境是否有給定命名。這要求實現 gisp.Env 時應實現外部環境的引用管理。

Set 實現賦值操作,被賦值的命名必須已經存在(已定義)。

Defvar 聲明一個變量

Defun 聲明一個函數,因為需要實現函數重載,這里將函數和變量命名區分開。

2.解析和求值

Gisp 遵循一個簡單的機制。通過文本分析過后,代碼解析成一組 gisp 值,到此為止是 Parse 特有的過程。此后進入 Eval,對每一個解析結果順序求值。

各長度整數一律解析為 gisp.Int

各長度浮點數一律解析為 gisp.Float

如果是 Lisp 接口對象,將當前環境(初始是 gisp 解析器對象)傳入,返回求值結果。特別的,如果是 List ,首先將第一個元素求值,然后將后續元素作為參數,嘗試傳遞給第一個元素的求值結果,將其作為一個函數執行,返回求值結果。如果解釋器不知道如何調用這個元素,返回錯誤;如果是 Quote ,返回其包含的元素,這是常見的傳遞數據的封裝方法;gisp 不支持標準的 Lisp (a . b)語法,形如 a.b 的表達式被解析為 gisp.Dot 表達式。該表達式求值遵循以下方式:1)首先,將 a 視作一個 Atom,對 a 求值2)如果a的值是 reflect.Value,嘗試獲取名為 b 的 method 或 field3)如果是 map ,嘗試獲取其鍵值(這里的行為類似 javascript)4)如果是gisp模塊(即 toolkit ,其實其內容基于 map[string]interface{} ),嘗試獲取對應的成員。5)如果不屬于任何 gisp 可解析的類型,返回原值。gisp 將中括號 [] 用于一個語法糖——引入 golang 的索引操作:1)它可以對List、map[string]interface{} 做普通的索引操作;2)對List,支持負索引和切片3)對于其它 reflect.Kind 為 array, slice 和 map 的數據結構,用反射嘗試進行索引操作,這部分還沒有經過充分的測試;未來希望可以支持對嵌套的 List/[]interface{} 和 map[string]interface{} 支持連續索引操作,這樣可以方便的處理 JSON;3)如果僅給出 [...] ,中括號表達式左邊沒有給出對象,則解析為一個 brackets 函數,它接受一個容器類型作為參數,對其進行前述的索引操作。即 x[...] 等同于 ([...] x)。

如果不屬于任何 gisp 可解析的類型,返回原值。

基本概念和主要數據類型

Atom

List

Quote

函子、函數和 Lambda

內置模塊和功能

gisp 公理

公理(axioms)模塊主要用于實現 Lisp 語系必須的幾個基本操作。這里沒有完整的實現 Lisp 公理,因為 gisp 的語義和實現內核都不是基于完整的 Lisp ,而是 golang runtime 。這是出于實用的考慮而非優雅。

quote

quote 操作接受任意的數據,將其封裝為一個 Quote。Quote 在 Eval的時候返回其內部保存的數據。它常用于 Lisp 的數據傳遞,在 gisp 的內部也經常用個類型直接封裝數據用于傳遞。在golang中可以調用 gisp.Q(x itnerface{}) 函數,得到一個 Quote{x} 。(quote x) 等價于 'x 。

var

var 在最里的一個 Env 中定義一個命名。它可以使用以下幾種形式:

(var x)

(var x::type) 這里需要注意的是,一般來說 Lisp 是弱類型的,而 gisp 其實是強類型的,而且是靜態類型。不過gisp并不能在解釋器中直接用 gisp 腳本定義新類型,它只能在 golang 環境中擴展,這是為了讓 gisp 解釋器盡可能保持簡單。

(var x value) 在定義的時候可以給出 x 的值,這里其實內部是順序作了 def 和 set 操作

定義x的時候,如果同名的變量或函數已經存在于當前環境,就會報錯。

set

set 操作比較好理解, (set x value) 就是對x進行賦值,x需要預先已經存在。在 gisp 環境內部,def 會生成一個 gisp.Var 接口的 slot 對象,這個對象內部通過反射管理賦值,如果 x 和value 類型不匹配,會導致panic。

equal

euqal 內部其實調用的是 reflect.DeepEqual 。

cond

cond 就是普通的 lisp cond 操作符,相當于 golang 的 value switch case 。gisp 沒有實現 type switch。而且目前使用的案例中其實沒有用到過 cond ,這部分沒有經過充分的測試。

car

car 取給定 list 的第一個元素,類似于 haskell 的 head 操作。等價于 Lisp 通常意義上的 car 操作符。

cdr

cdr 取 List 除了第一個以外剩下的元素,等同于通常意義的 cdr 操作符,也就是 Haskell 的 tail操作。即 list[1:] 。由于實際使用中還沒有遇到,這里也沒有經過充分的測試,從代碼中看對空列表做 cdr 會 panic。

atom

atom 等同于通常意義的 Lisp atom 操作符,如果給定的參數是 List ,返回false,否則返回true。這個操作符也沒有經過充分的測試。

concat

Lisp 的公理 cons ,用于將 head 和 (tail.()) 結合成一個 list。但是這個功能在 gisp 面向 golang 做互操作的需求前提下沒有存在意義,這里 gisp 實現了一個 concat 操作,內部調用 append,將給定的參數連接成一個 gisp.List 。

Gisp 定理

定理(propositions)其實是一些基礎操作,主要是比較操作和數學運算。這個可以參見其定義代碼:

var Propositions Toolkit = Toolkit{

Meta: map[string]interface{}{

"name": "propositions",

"category": "package",

},

Content: map[string]interface{}{

"lambda": BoxExpr(LambdaExpr),

"let": BoxExpr(LetExpr),

"+": EvalExpr(ParsexExpr(addx)),

"add": EvalExpr(ParsexExpr(addx)),

"-": EvalExpr(ParsexExpr(subx)),

"sub": EvalExpr(ParsexExpr(subx)),

"*": EvalExpr(ParsexExpr(mulx)),

"mul": EvalExpr(ParsexExpr(mulx)),

"/": EvalExpr(ParsexExpr(divx)),

"div": EvalExpr(ParsexExpr(divx)),

"cmp": EvalExpr(cmpExpr),

"less": EvalExpr(lessExpr),

"": EvalExpr(greatExpr),

">?": EvalExpr(gtoExpr),

">=": EvalExpr(geExpr),

">=?": EvalExpr(geoExpr),

"==": EvalExpr(eqsExpr),

"==?": EvalExpr(eqsoExpr),

"!=": EvalExpr(neqsExpr),

"!=?": EvalExpr(neqsoExpr),

},

}

這里有兩個函數單獨拿出來討論一下,一個是let ,一個是lambda。

let

Let 在 lisp 中構造一個封閉的環境,可以指定若干初始化變量,其作用域僅限于let內。

func TestParsecBasic(t *testing.T) {

g := NewGispWith(

map[string]Toolbox{

"axiom": Axiom, "props": Propositions, "time": Time},

map[string]Toolbox{"time": Time, "p": Parsec})

digit := p.Bind(p.Many1(p.Digit), p.ReturnString)

data := "344932454094325"

state := p.MemoryParseState(data)

pre, err := digit(state)

if err != nil {

t.Fatalf("except \"%v\" pass test many1 digit but error:%v", data, err)

}

src := "(let ((st (p.state \"" + data + `")))

(var data ((p.many1 p.digit) st))

(p.s2str data))

`

gre, err := g.Parse(src)

if err != nil {

t.Fatalf("except \"%v\" pass gisp many1 digit but error:%v", src, err)

}

t.Logf("from gisp: %v", gre)

t.Logf("from parsec: %v", pre)

if !reflect.DeepEqual(pre, gre) {

t.Fatalf("except got \"%v\" from gisp equal \"%v\" from parsec", gre, pre)

}

}

通常來講,在實用項目中使用 gisp 解釋器,可以用let得到一個比較干凈和安全的沙箱環境,用let隔離每一次腳本的運行,使之不會互相干擾。

lambda

lambda 的含義和用法不用太多介紹,就是 Lisp 實現中通常的形式。不過有幾點需要注意:

gisp 中變量可以附帶類型,這是定義函數重載的方式,但是實踐上我目前為止都是在 go 中構造函子。所以這部分沒有經過充分測試。原理上,gisp函數是各種同名但不同類型的 lambda 的集合容器。

lambda 一般來講可以不攜帶類型直接使用,在ginq等工具應用場合,lambda往往是用來封裝一段規則,不需要復雜的約束。

func TestGinqWhereSelect(t *testing.T) {

data := QL(

L(0, 1, 2, 3, 4, 5),

L(1, 2, 3, 4, 5, 6),

L(2, 3, 4, 5, 6, 7),

L(3, 4, 5, 6, 7, 8))

g := NewGispWith(

map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils},

map[string]Toolbox{"time": Time})

g.DefAs("data", data)

ginq, err := g.Parse(`

(ginq

(where (lambda (r) (< 1 r[0])))

(select (fs [1] [2] [4]))

)

`)

if err != nil {

t.Fatalf("except got a ginq query but error %v ", err)

}

re, err := g.Eval(L(ginq, data))

if err != nil {

t.Fatalf("except got columns from data but error %v", err)

}

t.Logf("ginq select got %v", re)

}

常用工具

Parsec

Parsec是我們項目中使用到的重要工具之一。它用于文本和規則解析。目前 goparsec 的表現尚可,基本完成了預期目標。但是限于go的語法,有一些地方并不盡如人意。

go 的強類型靜態檢查,使得 parsec 的 Parser 構造能夠基于一個比較嚴謹的輸入約束。但是因為go沒有泛型。文本和[]interface{} 的解析器只能各自實現,而在 Haskell 中這些只需要寫一次。

由于沒有泛型,為了讓 goparsec 能夠適用各種不同的解析場合,每個 Parser 的返回值只能寫成 interface{} 。

go 沒有 throw 和 try catch,每訪問一次 state ,都要檢查返回狀態是否有錯。雖然有大量組合子用于減少這個工作量,例如 Bind_, Bind, ManyTil 都是有力的工具。但是一旦我們需要在狀態傳遞中加入稍復雜一點的業務規則,就要實現自己的 Bind Keep 函數。在這個過程中我們總是要編寫大量的 if err != nil {return nil, err} 。

事實上,在使用 Parsec 的過程中遇到的各種不便,特別是錯誤處理,是我開發 gisp 的最主要動機。

限于 golang 項目在實用中的性能考慮,目前我們仍然將 string 和 List 的 Parsec 分別實現為 parsec 和 parsex 。當前只是對 goparsec 的封裝,未來可能會根據 gisp 的實踐經驗,向 gisp 化改變。

在 gisp 中調用 parsec ,最大的好處是省去錯誤監測(這個工作由 gisp 自然的接管了),于是就可以用類似haskell 版本的風格去自然的編寫解析過程:

func TestParsecRune2(t *testing.T) {

g := NewGispWith(

map[string]Toolbox{

"axiom": Axiom, "props": Propositions, "time": Time},

map[string]Toolbox{"time": Time, "p": Parsec})

//data := "Here is a Rune : 'a' and a is't a rune. It is a word in sentence."

data := "'a' and a is't a rune. It is a word in sentence."

state := p.MemoryParseState(data)

pre, err := p.Between(p.Rune('\''), p.Rune('\''), p.AnyRune)(state)

if err != nil {

t.Fatalf("except found rune expr from \"%v\" but error:%v", data, err)

}

src := `

(let ((st (p.state "` + data + `")))

((p.rune '\'') st)

(var data (p.anyone st))

((p.rune '\'') st)

data)

`

//fmt.Println(src)

gre, err := g.Parse(src)

if err != nil {

t.Fatalf("except \"%v\" pass gisp '' but error:%v", src, err)

}

t.Logf("from gisp: %v", gre)

t.Logf("from parsec: %v", pre)

if !reflect.DeepEqual(pre, gre) {

t.Fatalf("except got \"%v\" from gisp equal \"%v\" from parsec", gre, pre)

}

}

Ginq

Ginq 模塊也是開發 gisp 的動機之一,我們項目中主要使用的是 go-linq ,這個項目質量很高。但是我們需要多步簡單操作的時候,go風格的linq結構仍顯有點笨拙。在 ginq 中可以簡潔很多。

func TestGinqWhereSelect(t *testing.T) {

data := QL(

L(0, 1, 2, 3, 4, 5),

L(1, 2, 3, 4, 5, 6),

L(2, 3, 4, 5, 6, 7),

L(3, 4, 5, 6, 7, 8))

g := NewGispWith(

map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils},

map[string]Toolbox{"time": Time})

g.DefAs("data", data)

ginq, err := g.Parse(`

(ginq

(where (lambda (r) (< 1 r[0])))

(select (fs [1] [2] [4]))

)

`)

if err != nil {

t.Fatalf("except got a ginq query but error %v ", err)

}

re, err := g.Eval(L(ginq, data))

if err != nil {

t.Fatalf("except got columns from data but error %v", err)

}

t.Logf("ginq select got %v", re)

}

Ginq 的機制和使用

Ginq 的結構比較特殊,可以把 ginq 函數看成一個特化的 lambda。它接受一組 ginq 子句,將其串成一個處理序列,生成一個接受 List 參數的lambda函子,我們稱之為 ginq 查詢。給這個查詢傳入一個 List ,它會順序調用每個子句,最終返回結果。

在這個過程中,ginq的一級子句很重要。它們接受List,并將輸出結果返回到 ginq ,ginq 再將其輸出到下一個子句。目前這里沒有做優化,每一步都會生成一個中間 List 。所以使用的時候盡量將 where 這樣的過濾子句放在前面,可以提高效率,節省內存。

select

Select 子句接受一個函數,然后生成一個函數。新的函數接受 ginq 傳入的 list,再返回一個list。特別的,我們提供一個 fs (即 fields)函數,這個函數接受一組函數,生成一個接受單個數據,返回List 的函數。這個函數可以跟 select 組合,形成一個類似 SQL 的列選擇功能。示例如下:

func TestGinqSelectFields(t *testing.T) {

data := QL(

L(0, 1, 2, 3, 4, 5),

L(1, 2, 3, 4, 5, 6),

L(2, 3, 4, 5, 6, 7),

L(3, 4, 5, 6, 7, 8))

g := NewGispWith(

map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils},

map[string]Toolbox{"time": Time})

g.DefAs("data", data)

ginq, err := g.Parse(`

(ginq (select (fs [1] [2] [4])))

`)

if err != nil {

t.Fatalf("except got a ginq query but error %v ", err)

}

re, err := g.Eval(L(ginq, data))

if err != nil {

t.Fatalf("except got columns from data but error %v", err)

}

t.Logf("ginq select got %v", re)

}

where

where 子句接受一個判斷函數為參數,返回一個過濾器。它對傳入的 List 中的元素逐個調用給定的判斷函數,只有返回值為 true 的才放到輸出結果中,最終生成一個 List,其中的內容是所有通過判斷的數據。

func TestGinqWhereSelect(t *testing.T) {

data := QL(

L(0, 1, 2, 3, 4, 5),

L(1, 2, 3, 4, 5, 6),

L(2, 3, 4, 5, 6, 7),

L(3, 4, 5, 6, 7, 8))

g := NewGispWith(

map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils},

map[string]Toolbox{"time": Time})

g.DefAs("data", data)

ginq, err := g.Parse(`

(ginq

(where (lambda (r) (< 1 r[0])))

(select (fs [1] [2] [4]))

)

`)

if err != nil {

t.Fatalf("except got a ginq query but error %v ", err)

}

re, err := g.Eval(L(ginq, data))

if err != nil {

t.Fatalf("except got columns from data but error %v", err)

}

t.Logf("ginq select got %v", re)

}

groupby

groupby 執行分組統計操作。下例為了更清楚的表現Ginq的串行操作,將groupby中的分組子句拆解成一個新的qinq,其實后面的例子我們會看到更簡潔的寫法。

func TestGinqGroupBy(t *testing.T) {

data := QL(

L(0, 1, 2, 3, 4, 5),

L(1, 2, 3, 4, 5, 6),

L(0, 1, 2, 3, 4, 5),

L(1, 2, 3, 4, 5, 6),

L(2, 3, 4, 5, 6, 7),

L(1, 2, 3, 4, 5, 6),

L(2, 3, 4, 5, 6, 7),

L(3, 4, 5, 6, 7, 8))

g := NewGispWith(

map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils},

map[string]Toolbox{"time": Time})

g.DefAs("data", data)

ginq, err := g.Parse(`

(ginq

(groupby [0] (ginq (select [5]) sum))

)

`)

if err != nil {

t.Fatalf("except got a ginq query but error %v ", err)

}

re, err := g.Eval(L(ginq, data))

if err != nil {

t.Fatalf("except got columns from data but error: %v", err)

}

t.Logf("ginq select got %v", re)

}

統計函數

為了更方便的在ginq中對一個 List 進行統計計算,我們實現了對應的一級子句 sums、maxs、mins、avgs。它們接受fs這樣的行處理函數,可以先用行處理函數對單個數據項進行計算后,再做統計。在我們的業務中,典型如訂單,每一個消費項先進行結算,再做總計。

下例演示了groupby、sums、where和中括號表達式的組合。(sums [5]) 隱藏了內部的 select fs 和sum等多步操作。

func TestGinqGroupBySumSelectWhere(t *testing.T) {

data := QL(

L(0, 1, 2, 3, 4, 5),

L(1, 2, 3, 4, 5, 6),

L(0, 1, 2, 3, 4, 5),

L(1, 2, 3, 4, 5, 6),

L(2, 3, 4, 5, 6, 7),

L(1, 2, 3, 4, 5, 6),

L(2, 3, 4, 5, 6, 7),

L(3, 4, 5, 6, 7, 8))

g := NewGispWith(

map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils},

map[string]Toolbox{"time": Time})

g.DefAs("data", data)

ginq, err := g.Parse(`

(ginq

(groupby [0] (sums [5]))

(where (lambda (x) (> 10 x[1])))

)

`)

if err != nil {

t.Fatalf("except got a ginq query but error %v ", err)

}

re, err := g.Eval(L(ginq, data))

if err != nil {

t.Fatalf("except got group sum from data but error: %v", err)

}

t.Logf("ginq group sum select got %v", re)

}

而單列的“平凡”數據集,其實groupby sum過程是這樣的:

func TestGinqGroupBy(t *testing.T) {

data := QL(

L(0, 1, 2, 3, 4, 5),

L(1, 2, 3, 4, 5, 6),

L(0, 1, 2, 3, 4, 5),

L(1, 2, 3, 4, 5, 6),

L(2, 3, 4, 5, 6, 7),

L(1, 2, 3, 4, 5, 6),

L(2, 3, 4, 5, 6, 7),

L(3, 4, 5, 6, 7, 8))

g := NewGispWith(

map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils},

map[string]Toolbox{"time": Time})

g.DefAs("data", data)

ginq, err := g.Parse(`

(ginq

(groupby [0] (ginq (select [5]) sum))

)

`)

if err != nil {

t.Fatalf("except got a ginq query but error %v ", err)

}

re, err := g.Eval(L(ginq, data))

if err != nil {

t.Fatalf("except got columns from data but error: %v", err)

}

t.Logf("ginq select got %v", re)

}

這里需要注意的是,sum、max、min、avg、count等函數不同于 sums 這樣的統計組合子函數,它直接構成 List 到 統計結果的函數,不另組合行處理函數。

排序

同樣,ginq也提供了處理簡單序列的sort:

func TestGinqSort(t *testing.T) {

data := QL(

L(0, 1, 2, 3, 4, 5),

L(1, 2, 3, 4, 5, 6),

L(0, 1, 2, 3, 4, 2),

L(1, 2, 3, 4, 5, 6),

L(2, 3, 4, 5, 6, 7),

L(1, 2, 3, 4, 5, 3),

L(2, 3, 4, 5, 6, 4),

L(3, 4, 5, 6, 7, 8))

g := NewGispWith(

map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils},

map[string]Toolbox{"time": Time})

g.DefAs("data", data)

ginq, err := g.Parse(`

(ginq

(select [4])

sort

)

`)

if err != nil {

t.Fatalf("except got a ginq sort but error %v ", err)

}

re, err := g.Eval(L(ginq, data))

if err != nil {

t.Fatalf("except got ginq sort from data but error: %v", err)

}

t.Logf("ginq sort got %v", re)

}

和基于自定義判斷函數的 sortby

func TestGinqSortBy(t *testing.T) {

data := QL(

L(0, 1, 2, 3, 4, 5),

L(1, 2, 3, 4, 5, 6),

L(0, 1, 2, 3, 4, 2),

L(1, 2, 3, 4, 5, 6),

L(2, 3, 4, 5, 6, 7),

L(1, 2, 3, 4, 5, 3),

L(2, 3, 4, 5, 6, 4),

L(3, 4, 5, 6, 7, 8))

g := NewGispWith(

map[string]Toolbox{"axiom": Axiom, "props": Propositions, "utils": Utils},

map[string]Toolbox{"time": Time})

g.DefAs("data", data)

ginq, err := g.Parse(`

(ginq

(select (fs [3] [1] [5]))

(sortby (lambda (x y) (< x[2] y[2])))

)

`)

if err != nil {

t.Fatalf("except got a ginq sortby but error %v ", err)

}

re, err := g.Eval(L(ginq, data))

if err != nil {

t.Fatalf("except got ginq sortby from data but error: %v", err)

}

t.Logf("ginq sort got %v", re)

}

各個ginq子句其實可以作為獨立的函數調用,使用ginq環境主要是它會根據子句判斷求值方式,寫起來可以比較簡潔。提高一致性。我們也可以嘗試定制一些新的ginq子句組合使用。

并發

我們也提供了 go 關鍵字和 chan 關鍵字的封裝,不過目前應用中完全沒有用到,所以沒有經過測試。

擴展

gisp 的擴展主要是兩部分,一個是通過在 gisp 內注冊 go 類型,實現類型擴展。

func TestTypeFound(t *testing.T) {

m := money{9.99, "USD"}

g := NewGisp(map[string]Toolbox{

"axioms": Axiom,

"props": Propositions,

})

g.DefAs("money", reflect.TypeOf(m))

_, err := g.Parse("(var bill::money)")

if err != nil {

t.Fatalf("except define a money var but error: %v", err)

}

g.Setvar("bill", m)

mny, ok := g.Lookup("bill")

if !ok {

t.Fatalf("money var bill as %v not found ", m)

}

if !reflect.DeepEqual(m, mny) {

t.Fatalf("except got money var bill as %v but %v", m, mny)

}

}

上例可以看到,只要定義一個值為reflect.Type 的變量,就可以將其視為一個類型。這里借鑒了一些動態語言的做法。

或者編寫自己的 gisp.Functor 函子實現,作為函數使用:

type Functor interface {

Task(env Env, args ...interface{}) (Lisp, error)

}

在gisp中調用函數時,是從 Task 傳入參數,此時函數可以不執行,只是將要執行的代碼封裝成一個新的 Lisp 返回,這個設計是為了兩方面,一個是在出現函數重載時,先做參數檢查,有錯誤的話及早返回,也可以在不執行代碼的情況下先校驗參數是否匹配。其次將來實現 go 關鍵字時,可以盡可能在異步任務之外先排除一些錯誤,然后讓任務執行在無參數的環境下,理想情況時這可以是一個封閉的沙箱。

自定義函子通常是若干個組成一個模塊,放進gisp調用,示例可以參見 axiom.go 等內部實現。典型的,Axioms模塊實現的非常簡單,而 Gisp 模塊則非常完整和復雜。可以看到兩種不同實現方式的利弊。

解釋器

目前默認的解釋器,設計目標是盡可能輕量。它有buildin的概念,如果將模塊(通常是一個 gisp.Toolkit 實現) 放到 buildin模板,調用它的成員時不需要 m.fun 這樣的dot 表達式,直接給出命名就可以。否則要指定模塊名。構造 Gisp 解釋器對象,有兩個工具方法。NewGisp接受一個map[string]interface{} 作為buildin模塊,而 NewGispWith 則多接受一個ext字典,作為需要顯示引用模塊名的模塊定義。

前面幾個例子中都有引入一些buildin或ext模塊的行為,而下面這個例子甚至沒有引入任何模塊,gisp仍然可以執行一些邏輯。

func TestParseFloat(t *testing.T) {

g := NewGisp(map[string]Toolbox{})

gisp := *g

data := "3.14"

ret, err := gisp.Parse(data)

if err != nil {

t.Fatalf("except Float(3.14) but error: %v", err)

}

if ret.(Float) != Float(3.14) {

t.Fatalf("except got Float(3.14) but %v", ret)

}

}

總結

以上是生活随笔為你收集整理的gophp解释器_【干货】Gisp 解释器 Golang 辅助开发工具的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

激情综合五月婷婷 | 欧美 亚洲 另类 激情 另类 | 亚洲精品456在线播放第一页 | 免费看的黄色小视频 | 中文视频在线播放 | 中文字幕 国产视频 | 在线观看黄网站 | 精品少妇一区二区三区在线 | 亚洲成成品网站 | 97精品国自产拍在线观看 | 久久在线免费视频 | 国产在线毛片 | 一个色综合网站 | 天天操天天操天天操天天操天天操天天操 | 最近日本韩国中文字幕 | 国产一级黄大片 | av字幕在线 | 亚洲理论电影网 | 99精品视频免费全部在线 | 久久精品日产第一区二区三区乱码 | 亚洲黄色免费电影 | 国产精品视频全国免费观看 | a天堂在线看 | 99热超碰| 黄色avwww | 免费h精品视频在线播放 | 精品一区二区久久久久久久网站 | 高清av网站 | 二区视频在线观看 | 久久狠狠一本精品综合网 | 国内精品中文字幕 | 日韩高清免费无专码区 | 日韩精品视频在线观看网址 | 国产福利一区二区三区视频 | 日韩在线视频线视频免费网站 | 五月天久久综合网 | 日韩a级黄色片 | 天干啦夜天干天干在线线 | 欧美地下肉体性派对 | 97人人人| 国产成人61精品免费看片 | 久久永久免费 | 97精品视频在线 | 最新中文字幕在线播放 | 国产97色 | 亚洲一区二区三区四区在线视频 | 天天爱av导航 | 日本福利视频在线 | 中文字幕在线观看网 | 青青河边草观看完整版高清 | 国产成人精品在线播放 | 国产专区欧美专区 | 日韩中文字幕a | 日韩精品一区二区在线视频 | 免费在线观看日韩欧美 | 麻豆av一区二区三区在线观看 | 免费看片成人 | 日本中文不卡 | 欧美一二三区播放 | 黄色小网站在线观看 | 久久国产精品视频观看 | 9999激情| 综合网成人 | 国产精品99久久免费黑人 | 国产精品久久久久永久免费观看 | 欧美一区二区三区在线 | 一区二区三区国产欧美 | 四虎天堂 | 国产精品私人影院 | 久艹视频在线免费观看 | 国产精品精品久久久久久 | 国产99久久久久久免费看 | www.国产在线 | 欧美一性一交一乱 | 丁香亚洲| 成人黄色大片 | 激情电影在线观看 | 亚州日韩中文字幕 | 99视频免费 | 免费在线观看91 | 亚洲综合在线视频 | 国产美腿白丝袜足在线av | 国产视频一区在线播放 | 久久久久视 | 一区精品久久 | 国语精品久久 | 亚洲精品中文字幕视频 | 99午夜| 天天综合天天做天天综合 | 国产一区在线观看视频 | 日韩精品免费一区二区在线观看 | 99久久精品国产观看 | 麻豆视频国产精品 | 97超碰在线久草超碰在线观看 | 天天插综合网 | 亚洲精品成人 | 色综合久久久久综合体桃花网 | 欧美日本日韩aⅴ在线视频 插插插色综合 | 日韩深夜在线观看 | 国产对白av | 欧美精品久久 | 欧美久久久久久久久久久 | 国产在线欧美日韩 | 天天操导航 | 国产精品女教师 | 特级西西www44高清大胆图片 | 插插插色综合 | 国产亚洲久久 | 香蕉久草 | 激情网婷婷| 在线观看国产成人av片 | 亚洲精品高清在线观看 | 国产精品中文字幕av | 天天插天天操天天干 | 欧美成人精品欧美一级乱 | 日韩高清久久 | 在线天堂视频 | 91入口在线观看 | 91精品国产福利在线观看 | 国产综合小视频 | 久久理论片 | 99色精品视频 | 久久精品小视频 | 久久亚洲私人国产精品 | 香蕉影视在线观看 | 欧美另类xxx | 国产亚洲精品久久网站 | 麻豆一区二区 | 久久人人爽人人爽人人 | 毛片网在线播放 | 九九免费在线观看 | 999国内精品永久免费视频 | 久久人人精品 | 亚洲色图美腿丝袜 | 久久精彩免费视频 | 精品一区二区在线看 | 99r在线视频 | 中文字幕一区二区三区精华液 | 中文字幕黄色 | 人人精品| 一区中文字幕 | 天堂激情网 | 久久久91精品国产一区二区精品 | 国产精品久久久久久久久搜平片 | 成人超碰在线 | 久久久国产在线视频 | 亚洲成人资源在线观看 | 中文字幕视频一区二区 | 亚洲成av片人久久久 | 欧美亚洲精品一区 | 久久精品国产亚洲aⅴ | 国语久久| 日韩网站视频 | 亚洲视频一区二区三区在线观看 | 成人h视频在线 | 免费av片在线 | 在线亚洲成人 | 99精品免费久久久久久日本 | 日韩欧美91 | 丁香婷婷在线 | 精品久久毛片 | 欧美日韩另类在线 | 免费a v网站 | 亚洲国产三级在线 | 超碰在线中文字幕 | 在线免费观看麻豆 | 欧美色综合久久 | 一区二区三区免费在线观看 | 日韩av网站在线播放 | 一本一本久久aa综合精品 | 西西4444www大胆视频 | 99在线免费视频 | 久久天天躁夜夜躁狠狠85麻豆 | 日韩欧美在线视频一区二区 | 亚洲经典精品 | 亚av在线| 国产一卡在线 | 三级大片网站 | 国产精品一区专区欧美日韩 | 日韩精品一区二区三区外面 | 国产美女被啪进深处喷白浆视频 | 国产精品资源网 | 伊人天天狠天天添日日拍 | 国产99久久九九精品 | 人人爽人人搞 | 激情狠狠干 | 国产小视频在线免费观看视频 | 在线观看亚洲国产精品 | 99色在线播放 | 黄色的网站免费看 | 国产美女视频黄a视频免费 久久综合九色欧美综合狠狠 | 国产午夜一区二区 | 国产美女网站在线观看 | a资源在线 | 婷婷亚洲综合 | 天天干天天射天天爽 | 成人app在线播放 | 精品久久一区二区 | 综合久久久久久 | 天堂av在线免费 | 中文字幕在线观看视频一区二区三区 | 99热国产精品 | 国产精品一区二区在线播放 | 久久综合干| 最新国产精品久久精品 | 日韩在线网址 | 91av电影网| 欧美最猛性xxxxx亚洲精品 | 亚洲精品播放 | 国内精品久久久久久中文字幕 | 在线免费观看视频一区二区三区 | 在线视频 成人 | 亚洲欧美国产精品久久久久 | 91看片在线| 美女黄久久 | 国产精品综合久久久久久 | 日日夜夜天天久久 | 91免费国产在线观看 | 国产视频美女 | 欧美日韩视频观看 | 最近最新mv字幕免费观看 | 免费看片亚洲 | 日韩av电影网站在线观看 | 91香蕉视频 | 日韩欧美网址 | 日韩激情视频在线 | 成人四虎| 亚洲久草视频 | 亚洲人成人天堂h久久 | 日韩精品一区二区三区丰满 | 在线观看一级片 | 国产黄网站在线观看 | 天天艹天天干天天 | 欧美一区二区三区在线 | 久久国产精品精品国产色婷婷 | 欧美影院久久 | 狠狠干五月天 | 手机在线视频福利 | 九九久久电影 | 三级av网站 | 日韩精品影视 | 亚洲综合婷婷 | 日韩a在线播放 | 日韩免费观看一区二区三区 | 亚洲最新视频在线 | av不卡免费在线观看 | 欧美一级乱黄 | 午夜.dj高清免费观看视频 | 蜜臀av夜夜澡人人爽人人桃色 | 久久久综合精品 | 亚洲午夜精品在线观看 | 五月婷婷黄色 | 天天搞天天干天天色 | 91精品入口 | 99视频免费观看 | 亚洲成人精品在线观看 | 国产在线观看91 | 99精品一级欧美片免费播放 | 欧洲高潮三级做爰 | 999成人国产| 免费av网址在线观看 | 美女精品 | 91成人天堂久久成人 | 免费国产在线精品 | 亚洲天堂网在线视频 | 91黄色在线观看 | 久久五月网 | 激情五月色播五月 | 久久久高清一区二区三区 | 亚洲精品乱码久久 | av在线免费观看黄 | 91视频免费网站 | 久久精彩视频 | 亚洲精品88欧美一区二区 | 欧美最爽乱淫视频播放 | 日韩网站在线观看 | 国产免费二区 | 亚洲夜夜综合 | 国产福利资源 | 一本一本久久a久久精品综合 | 九九热精品视频在线播放 | 久久婷婷精品视频 | 国产在线观看免费观看 | 日韩美在线观看 | ww亚洲ww亚在线观看 | 亚洲精品一区二区18漫画 | 在线观看色网站 | 国内精品视频免费 | 日日夜夜干 | 丁香午夜婷婷 | 日p在线观看 | 久久免费视频6 | 97超碰成人 | 国产91国语对白在线 | 91精品国自产在线观看 | 欧美久久久一区二区三区 | 久久精品一区二区三区四区 | 日韩欧美视频免费在线观看 | 少妇高潮流白浆在线观看 | 五月婷婷六月丁香激情 | 国产一区视频在线播放 | 国产一区电影在线观看 | 亚洲国产精品推荐 | 欧美色婷婷| 亚洲国产资源 | 视频国产在线观看18 | 免费婷婷 | 狠狠色丁香婷婷综合 | 国产精品久久久久永久免费 | 亚洲一级电影视频 | 日韩在线视频精品 | 免费av视屏 | 狠狠色丁婷婷日日 | 黄色免费观看视频 | 黄色毛片在线看 | 开心色停停 | 色狠狠综合 | 色无五月 | 天天色综合三 | 国产一区二区在线免费视频 | 国产 欧美 在线 | 91字幕 | 有码中文在线 | 9在线观看免费 | 麻豆国产网站入口 | 亚洲作爱 | 久久成人黄色 | 人人讲下载 | 久草在线中文888 | 欧美极品少妇xbxb性爽爽视频 | 日韩v在线 | 激情黄色一级片 | 亚洲1区在线 | 免费看片网站91 | 成人在线视频免费看 | 欧美一级片免费 | 99久久99久久 | 人人爽人人爽人人爽人人爽 | 亚洲国产精品成人va在线观看 | 免费色视频网站 | 久久久96| 欧美人zozo| 日韩精品一区二区三区高清免费 | 香蕉色综合 | 成人毛片100免费观看 | 黄色91在线观看 | av不卡免费看| av再线观看 | 久久视频二区 | 日韩在线观看视频在线 | 五月婷婷视频在线 | 国产91综合一区在线观看 | 久久1电影院 | 久久精品看片 | 五月婷婷一级片 | 色吊丝在线永久观看最新版本 | 999久久国精品免费观看网站 | 欧美午夜寂寞影院 | 免费看一级黄色大全 | 日韩免费福利 | 久久论理 | 69精品人人人人 | 国产艹b视频 | 日韩欧美精品一区二区三区经典 | 日韩一二区在线 | 欧美日韩高清在线一区 | 久久免费视频5 | 亚洲伊人天堂 | 日韩欧美在线观看一区二区 | 激情网色 | 色久网| 456免费视频 | 精品爱爱 | 高清精品在线 | aaa日本高清在线播放免费观看 | 天天干天天操天天爱 | 日韩在线国产精品 | 天天综合在线观看 | 亚洲涩涩网站 | 1024手机看片国产 | 国产大尺度视频 | 日日草天天草 | 免费日韩 精品中文字幕视频在线 | 超碰在线97国产 | 久久国产精品一区二区三区 | 亚洲观看黄色网 | 少妇bbbb搡bbbb搡bbbb | 国产精品久久网站 | 综合激情网 | 国产色婷婷精品综合在线手机播放 | 99视频在线精品国自产拍免费观看 | 992tv成人免费看片 | 日韩美女一级片 | 韩国av免费看 | 久久久久这里只有精品 | 最近中文字幕免费视频 | 久久99精品久久久久久清纯直播 | 成人av资源网站 | 亚洲另类在线视频 | 欧美精品xx | 国产精品免费久久久 | 色成人亚洲网 | 国产99亚洲 | 久久综合久久综合久久综合 | 99热最新在线 | av网站手机在线观看 | 久久免费一 | 免费在线色 | 久久国产欧美日韩精品 | 99视频在线免费看 | 亚洲国产网址 | 99久久久久久国产精品 | 国产中文字幕三区 | 日韩av成人在线观看 | 欧美三级在线播放 | 国内久久视频 | 99re6热在线精品视频 | 久久久久亚洲精品成人网小说 | 在线观看一 | 西西444www大胆无视频 | 视频成人免费 | 精品亚洲一区二区 | 最近日本中文字幕 | 99视频在线免费观看 | 国产精品久久久久高潮 | 欧美 亚洲 另类 激情 另类 | 天天操天天干天天 | 黄色大片日本免费大片 | 午夜免费福利片 | 丁香五月网久久综合 | 97久久精品午夜一区二区 | 免费观看十分钟 | 日本激情视频中文字幕 | 午夜体验区 | 亚洲最大在线视频 | 欧美激情精品久久久久久免费印度 | 嫩小bbbb摸bbb摸bbb | 欧美做受69| 国产亚洲精品bv在线观看 | 欧美日韩免费在线观看视频 | 日韩专区一区二区 | 一区二区高清在线 | 国产女人18毛片水真多18精品 | 国产黄色免费电影 | 亚洲动漫在线观看 | 四虎在线免费观看视频 | 欧美性成人 | 免费观看全黄做爰大片国产 | 国产96视频 | 深爱婷婷激情 | 国内外成人免费在线视频 | 国产伦理剧 | 欧美精品久久久久久久免费 | 最近免费中文视频 | 亚洲国产精品一区二区久久,亚洲午夜 | 天天色天天爱天天射综合 | 亚洲成熟女人毛片在线 | 亚洲欧洲国产日韩精品 | 国产精品自拍av | 一区二区在线影院 | 久久国产精品99久久久久久老狼 | 亚洲精品一区中文字幕乱码 | 欧美 日韩 视频 | 香蕉在线播放 | 国产精品21区 | 91视频在线国产 | 成人黄色电影在线 | 四虎成人精品永久免费av九九 | 黄色免费观看 | 欧美一级视频免费看 | 国产小视频你懂的在线 | 日韩在线中文字幕 | 狠狠色香婷婷久久亚洲精品 | 天天干天天操天天干 | 久久精品一区二区三区中文字幕 | 天天操夜夜操 | 黄色av网站在线免费观看 | 91麻豆精品国产自产在线游戏 | 黄色片网站大全 | 日韩视频在线一区 | 国产精品亚洲片在线播放 | 在线视频一二三 | 亚洲作爱 | 国际av在线 | 国产精品初高中精品久久 | 久久久久在线观看 | 色久天 | 天天操天天色天天 | 久久精品免视看 | 婷婷中文在线 | 香蕉精品视频在线观看 | 国产一级a毛片视频爆浆 | 国产自产在线视频 | 亚洲成a人片在线观看网站口工 | 久久不卡电影 | 欧美综合干| 又黄又色又爽 | 国产精品综合在线 | 国产香蕉视频 | 亚洲精品日韩在线观看 | 欧美性春潮 | 叶爱av在线 | 国产精品18久久久久久久久久久久 | 久久久久久久久国产 | 久久久久99999 | 麻豆国产网站入口 | 9在线观看免费高清完整版在线观看明 | 天天干天天操天天做 | 亚洲电影久久 | 亚洲尺码电影av久久 | 91在线一区二区 | 在线黄色免费av | 亚洲综合小说电影qvod | 精品一二三四五区 | 国产成人久 | 丁香久久五月 | 亚洲精品婷婷 | 婷婷综合成人 | 久久久久久美女 | 亚洲午夜精品电影 | 国产精品激情偷乱一区二区∴ | 天天干天天天天 | 五月综合色 | 中文字幕一区二区三区在线播放 | 天天射天天舔天天干 | 狠狠躁日日躁狂躁夜夜躁 | 五月婷婷丁香色 | 久草在在线视频 | 中文字幕高清在线播放 | 不卡av在线 | 免费成人在线网站 | www,黄视频 | 在线视频日韩欧美 | 亚洲精品乱码久久久久久蜜桃动漫 | 国产精品色视频 | 九九在线视频 | 麻豆视频在线 | 狠狠操天天干 | 999久久久免费精品国产 | 美女视频a美女大全免费下载蜜臀 | 丁香五月亚洲综合在线 | 天天干天天操天天入 | 9999国产精品 | 成人av一区二区三区 | 韩国一区二区三区在线观看 | 黄色免费观看视频 | 日韩欧美高清不卡 | 亚洲涩综合 | 日韩激情免费视频 | 中文字幕亚洲高清 | 日日爽天天| 日本久久成人 | 日日干网 | 色婷婷久久久综合中文字幕 | 日韩理论影院 | 日韩一区二区三区视频在线 | 欧美日韩国产精品一区 | 国产亚洲永久域名 | 国产精品成人久久久久久久 | 午夜精品久久久久久久爽 | 欧美做受高潮1 | 天天干天天操天天拍 | 亚洲国内精品在线 | 久久不射电影院 | 99久高清在线观看视频99精品热在线观看视频 | 久久草草热国产精品直播 | 国产精品国产三级在线专区 | 亚洲国产精品视频在线观看 | 黄色在线免费观看网址 | 国产91综合一区在线观看 | 成人在线一区二区三区 | 久久精品香蕉视频 | 久久精品超碰 | 日韩电影在线视频 | 91网免费观看 | 日韩三级视频在线看 | 免费aa大片 | 日韩欧美视频一区 | 91视频电影 | 成年在线观看 | 最近中文字幕mv免费高清在线 | 欧美激情第十页 | 久精品一区 | 亚洲艳情 | 欧美日韩久久不卡 | 三级黄色理论片 | 五月婷网 | 麻豆观看| 久久精品国产一区二区三 | 在线观看视频99 | 999久久a精品合区久久久 | 欧洲在线免费视频 | 最近中文字幕mv | 日韩欧美一区二区三区在线 | 亚洲精品小视频 | 久久国产精彩视频 | 91在线播放综合 | 亚洲一区视频免费观看 | 中文 一区二区 | 国产亚洲视频在线免费观看 | 在线免费观看av网站 | 欧美一级性生活视频 | 亚洲精品国产精品国自 | 久草在线观看视频免费 | 国产精品综合在线观看 | 久久国产亚洲视频 | 国产精品免费在线 | 手机在线观看国产精品 | 欧美精品久久久久久久久免 | 在线观看免费成人 | 国产一区自拍视频 | 欧美精品999 | 精品人人人 | 日韩精品一区在线播放 | 777xxx欧美 | 欧美国产日韩中文 | 91丨九色丨国产女 | 福利视频网址 | www.天天射| 夜夜躁日日躁狠狠躁 | 国产视频999| 一区二区三区视频 | 午夜视频免费在线观看 | 久久麻豆精品 | 天天曰天天射 | 免费福利在线播放 | 国产精品6999成人免费视频 | 国产黄色理论片 | 色婷婷久久久综合中文字幕 | 国产精品久久久亚洲 | 午夜av免费| 国产精品福利一区 | 亚洲一级性| 国产精品一级视频 | 国产精品久久久久久久久软件 | 亚洲精品大片www | 夜夜操综合网 | 国产一级在线 | 超碰97免费 | 免费在线观看成人 | 欧美无极色 | 欧美一级免费 | 91传媒免费在线观看 | 日韩激情一二三区 | 日韩电影一区二区在线观看 | 国产人成在线观看 | 国产精品一区二区免费 | 成人黄色资源 | 粉嫩av一区二区三区免费 | av线上看 | 激情视频二区 | 日日夜夜免费精品视频 | 国产一区二区在线播放视频 | 中文 一区二区 | 色婷婷97| 九九久久精品视频 | 一区中文字幕电影 | 中文字幕在线专区 | www久久久久 | 91成年人网站 | 日韩精品一区二区三区电影 | 国产99久久久精品 | 福利视频一二区 | 久久久伦理 | 五月天婷婷综合 | 免费av高清| 久艹在线免费观看 | 久久九九影视网 | 四虎在线视频 | 91日韩在线 | 国内精品在线观看视频 | 中日韩欧美精彩视频 | 久久午夜免费视频 | 亚洲国产无 | 99国产情侣在线播放 | 日韩激情小视频 | 日韩黄色中文字幕 | 欧美性久久久 | 亚洲一区二区视频在线播放 | 国产亚洲精品日韩在线tv黄 | 国产精品2019 | 国产五月色婷婷六月丁香视频 | 免费一级特黄录像 | 日韩欧美一区二区三区在线 | 在线看中文字幕 | 激情五月综合网 | 操久久免费视频 | 国产精品日韩久久久久 | a一片一级| 欧美最猛性xxxxx亚洲精品 | 亚洲最大激情中文字幕 | 免费又黄又爽 | 日韩成人在线一区二区 | 久久黄色a级片 | 成人影音av | 久久a级片 | 99热在线免费观看 | 91精品老司机久久一区啪 | 国产精品久久一卡二卡 | 中文字幕中文字幕在线一区 | av在线等| 欧美成人视 | 久草男人天堂 | 国产精品嫩草影院9 | 手机av在线网站 | 国产精品福利在线观看 | 精品免费视频. | 日韩在线不卡视频 | mm1313亚洲精品国产 | 玖玖在线播放 | 久久精品欧美一区二区三区麻豆 | 成人久久18免费网站 | 久久精品中文字幕 | 久久99亚洲精品久久久久 | 日韩中文字幕第一页 | 国产麻豆电影 | 亚洲欧美在线综合 | 国内精品99 | 久久精品在线视频 | 久久er99热精品一区二区 | 亚洲精品1区2区3区 超碰成人网 | 国产第一页精品 | 亚洲精品tv久久久久久久久久 | 911香蕉视频| 美女网站久久 | 欧美日韩中文在线视频 | 91麻豆精品国产91久久久久久久久 | 福利一区在线 | 四虎免费在线观看视频 | 91成人精品在线 | 免费成人av在线看 | 91久久奴性调教 | 国产午夜三级一区二区三桃花影视 | 亚洲天堂毛片 | 国产免费观看高清完整版 | 国产精品午夜av | 亚洲第一中文网 | 天天干,天天插 | 国产美女视频网站 | 亚洲一区久久久 | 一区二区三区在线观看免费视频 | 99视频精品视频高清免费 | 91视频在线国产 | 久久久久久久电影 | 久久久久久免费毛片精品 | 91理论片午午伦夜理片久久 | 久久久久在线观看 | 亚洲午夜精品电影 | av在线免费播放 | 99精品免费久久久久久久久 | 国产精品一区二区美女视频免费看 | 国产精品毛片完整版 | 欧美日韩精品在线一区二区 | 天天综合网久久综合网 | 国产午夜精品一区 | 五月婷婷伊人网 | 欧美韩国日本在线观看 | 精品99免费视频 | 久久99国产精品久久99 | 国产精品乱码一区二区视频 | 高清一区二区三区 | 国产精品久久在线 | 福利一区视频 | 91中文字幕| 欧美性受极品xxxx喷水 | 一区二区精品久久 | 青青久视频 | 精品在线观看一区二区 | 欧美成人h版 | 岛国片在线 | 日韩中文字幕在线观看 | av中文字幕在线观看网站 | 国产小视频在线免费观看 | 欧美在线视频一区二区三区 | 91桃色视频 | 狠狠综合久久 | 夜夜爽88888免费视频4848 | 99色人| av成人在线网站 | 8x成人免费视频 | 九九热只有这里有精品 | 日韩久久精品一区二区 | www.午夜色.com| 麻豆网站免费观看 | 日本久久免费电影 | 99视频在线精品国自产拍免费观看 | 99视频这里只有 | 免费手机黄色网址 | 亚洲精品成人 | 亚洲国产网址 | 天天射天天操天天 | 久久只有精品 | 97国产 | 午夜精品久久久久久久99水蜜桃 | 欧美成人a在线 | 欧美色图东方 | 国产视频日本 | 日韩午夜电影院 | 中国美女一级看片 | av中文字幕网址 | 久久久亚洲国产精品麻豆综合天堂 | 精品亚洲成a人在线观看 | 成人午夜电影久久影院 | 91视频 - v11av | 国产中文字幕三区 | 在线精品视频免费播放 | 日韩欧美高清免费 | 亚洲精品久久久久999中文字幕 | 日本大尺码专区mv | 9999毛片| 国产又粗又长的视频 | 99人成在线观看视频 | 日韩在线中文字幕视频 | 久久久999 | 天天干天天干天天 | 99久久日韩精品视频免费在线观看 | 日韩中文字幕视频在线 | 91九色视频国产 | 成人av片免费看 | 在线看岛国av | 永久免费的av电影 | 国产香蕉97碰碰碰视频在线观看 | 久久人人爽人人爽人人片 | 国产精品视频久久 | 成人午夜在线电影 | 欧美精品在线观看一区 | 国产成人av电影在线观看 | av免费网站观看 | 色欧美成人精品a∨在线观看 | 5月丁香婷婷综合 | 久久99久久久久 | 99精品一区二区三区 | 久久影视中文字幕 | 91日韩在线播放 | 国产乱对白刺激视频在线观看女王 | 国产精品99蜜臀久久不卡二区 | 久久国内免费视频 | 亚洲久草在线视频 | 国产精品地址 | 中文字幕中文字幕在线中文字幕三区 | 波多野结衣电影一区二区三区 | 人人插人人做 | 亚洲理论片在线观看 | 亚洲国产wwwccc36天堂 | 九九九九九九精品任你躁 | 99视频免费| 91av原创| 四虎影院在线观看av | 国产精品久久一区二区三区, | 亚洲黄色app | 国产日韩欧美中文 | 免费福利在线播放 | 国产成人a亚洲精品v | 国产品久精国精产拍 | 亚洲精品在线免费观看视频 | 欧美日韩免费一区二区 | 久久av电影 | 久久久精品久久日韩一区综合 | 中文字幕在线视频一区二区三区 | 99国产精品久久久久久久久久 | 九九久 | 九九热在线精品 | 视频福利在线 | 国产小视频在线免费观看 | 久久综合五月天 | 国产香蕉97碰碰久久人人 | 欧美日韩国产一二三区 | av不卡在线看 | 四虎国产精品永久在线国在线 | 色吊丝在线永久观看最新版本 | 免费久久久久久久 | 97成人免费 | 成人av网站在线观看 | 国产精品女 | 日韩欧美一区二区不卡 | 免费在线观看av不卡 | 欧美专区日韩专区 | 国产精品毛片一区视频 | 欧美精品在线观看一区 | 国产香蕉97碰碰碰视频在线观看 | 四虎影视精品 | a级片韩国 | 日韩a级黄色 | 国产色妞影院wwwxxx | 中文字幕 国产视频 | 国产高清在线一区 | 欧美大香线蕉线伊人久久 | www.五月天| 香蕉视频国产在线观看 | 免费涩涩网站 | 天堂av一区二区 | 亚洲欧美日韩国产精品一区午夜 | www黄| 91日韩免费 | 亚洲精品在线视频网站 | 97国产超碰 | 国产大片免费久久 | 久久99精品久久只有精品 | 高清av中文在线字幕观看1 | 在线免费看黄网站 | 欧美日韩国产一区二区三区在线观看 | 国产录像在线观看 | 黄a网站| 日韩三级.com | 99亚洲精品在线 | 国产精品久久久区三区天天噜 | 日韩草比| 五月婷婷操 | 国产九九精品视频 | 久久久久女人精品毛片 | 91亚洲成人| 狠狠干激情 | 美女免费网站 | 夜夜干天天操 | 日韩久久视频 | 国产精品无av码在线观看 | 91久久精品一区二区三区 | 国产一区二区在线观看免费 | 97超碰资源站 | 色综合久久久久综合99 | 国产在线精品国自产拍影院 | 久久99精品视频 | 奇米网8888| 香蕉精品视频在线观看 | 亚洲做受高潮欧美裸体 | 91亚洲精品视频 | 午夜精品久久久久久久99婷婷 | 日韩有码第一页 | 成人精品在线 | 天天鲁一鲁摸一摸爽一爽 | 国产亚洲精品久久久久久电影 | 69av在线视频 | 日本精品一二区 | 天天爽天天爽夜夜爽 | 久久久资源网 | 天天翘av | 免费视频成人 | 中文亚洲欧美日韩 | 色综合欧洲 | av观看网站 | 中文在线a∨在线 | 黄色字幕网 | 免费高清国产 | 国产美女在线精品免费观看 | 黄网站免费看 | 久久成人亚洲欧美电影 | 天天做日日做天天爽视频免费 | 日韩xxxxxxxxx| 成人网在线免费视频 | 成人小视频在线观看免费 | av色综合网| 99热这里只有精品久久 | 欧美日韩免费网站 | 521色香蕉网站在线观看 | av电影中文字幕 | 五月婷香蕉久色在线看 | 国产精品尤物视频 | 日韩色高清 | 在线免费视频 你懂得 | 国产成人在线观看免费 | 一区二区三区视频网站 | 麻豆系列在线观看 | 亚洲黄电影 | 亚洲第一av在线播放 | 日本精品xxxx| 免费在线观看av网站 | 在线午夜 | 久久久亚洲麻豆日韩精品一区三区 | 人人超碰在线 | 久久国产剧场电影 | 91视频一8mav | 偷拍福利视频一区二区三区 | 91麻豆产精品久久久久久 | 久久久久免费看 | 国产成人精品在线 | 国产精品av免费观看 | 久久人人添人人爽添人人88v | 日本激情动作片免费看 | 国产精品破处视频 | 一区二区高清在线 | 五月婷婷丁香在线观看 | 特黄一级毛片 | 中文字幕精品一区二区三区电影 | 欧美一区免费在线观看 | 天堂v中文| 成人午夜黄色 | 91av视频网| 在线观看精品国产 | 91大神dom调教在线观看 | 国产午夜精品免费一区二区三区视频 | 丁香综合网 | 国产91精品看黄网站在线观看动漫 | 中文字幕在线电影 | 久久久久久精 | av中文国产 | 国产一区二三区好的 | 亚洲精品在线一区二区 | 综合视频在线 |