本文關鍵字:DSL架構和自動化生成工具,pypy as dsl framework and jit framework
在《bcxszy》 part2中提到,發明各種DSL一直是軟體工程模式之一,在那裡,我們還一直在找尋某種1ddlang和1dddev方案 --- 更多更好的DSL和統一的語言系統并不沖突,如《程式設計語言選型通史》《程式設計實踐選型通史》所講,問題的根源是不斷出現新的問題域要求語言系統足夠領域通用,最終要導向到語言選型問題,語言選型其實是一個涉及到程式設計所有的領域的活動(不光問題還要平台還有考慮人的入階曲線且能将現有的codebase輕易遷移過來),而理想的狀态是提出一種語言或混合系統language for all,它可以內建一種強大簡便的DSL方案,能勝任其它語言能做的事而不帶有任何先天缺陷,保持同一生态不斷層。關于DSL和這種lang for all的設想,有語言内(langtechs,lib,qtmoc工具鍊+pme)和語言外(方法論,toolset lvl,各種語言标準emscirpt)的一系列手段。
這些在我以前langsys系列文章中都不斷涉及:
在《釋出odoo8》時我們談到主從語言,lua+c,or py+cpp----這也是傳統語言選型的經典标準---也是初級标準,注意到因為大凡腳本語言系統,為了兼顧效率和考慮進通用目的,都是binding c extensions--這也是為新語言快速建庫的方法,不過當這類語言這樣做的時候,它實際上也在承認它是靠更新檔工作的,如果滿足于同時使用二門語言,其實這是完全可以的,不過這像極了學會了使用C還要學會彙編一樣,這樣的轉換始終帶有曆史遺痕和存在斷層,僅支援從庫級和語言技法級,擴充級去擴充DSL支援,這種語言通常用cffi這樣的庫支援,這樣的語言代表是py,php,etc..
而.net,java這樣的語言系統,它提出了統一後端,語言服務也是運作時和庫,可以作為API調用,有DSL支援,即使所有語言可以無縫interspect,且它提倡将原生擴充做進純粹managed runtime,如c#重寫forms而不依賴native forms, 這實際上是要統一clr上的生态使之脫離對本地的依賴,隻是将一切放在虛拟機的運作時裡,明顯效率是個問題。
在上述二種語言生态充分飽和之後,效率和大語言思維終于被提上日程,業界要做的,隻能在上述這二個基礎上改造,這首先是給常見的語言如php,py增加JIT,近年來,JIT發展迅速,為了将上述php,py語言發展為真正的通用語言奮鬥(再在這上面擴充DSL,這就是上面說的langone+dsl化)。就是jit系統+混合語言系統:
在前面《釋出terracling》時,我們提到從CPP到混合語言系統選型出現的曆史現象回顧,且做了一個小型的關于混合語言的綜合。聯系到更早在《釋出qtcling》時我們談到llvm的jit原理和它獨立于傳統編譯器的事實,這裡我們看到LLVM作為一個DSL和JIT工具架構,它的強大實用性,要了解它,可拿它與clr,jvm這樣的東西類比,因為它們都支援多語言前端和統一後端且都有JIT,有強大的可比性,然而他們的差別卻微小不易發現而至關重要,足以影響到他們歸類在不同的流派:
clr,jvm是虛拟機流派,llvm是運作時流派,llvm後端就是一個to native os的運作時沒有VM。它沒有為任何語言設定一個解釋部件隻是一路翻譯,最後僅執行jit後的代碼,這樣的代碼已是jitted to native的,這使得它的效率是很高的。一句話,llvm的統一後端和其運作時就是免虛拟機且JIT的沒有虛拟機和解釋部件,它允許從C系開始制造前端這是它與clr,jvm不一樣的地方(後者如果要寫C擴充是用虛拟機routing原生代碼),它産生的新DSL和語言,可以與原生C語言系統的子產品在IR級互動可直接調用這類子產品無須binding,且由于jit是類解釋系統的線上執行機制,是以可以支援産生qtcling as c++ script這樣的語言。 而jvm,clr無非就是虛拟機+解釋,而jvm,clr同樣有jit,對于中間表示(位元組碼或AST)和執行結果,他們都提供了一個可寫多語言前端為任一語言內建jit的架構,JIT和虛拟機都是黑盒(或者半JIT半解釋,或者純JIT),有沒有黑盒這個是沒有差異的,--------------- 産生差異的,恰恰是這個黑盒内部是如何運作的:llvm是分析位元組碼然後以jit方式快速編譯且執行.新語言不需要VM運作隻須帶LLVM運作時,而clr,jvm的jit預設是解釋系統加jit協同工作的,任何語言結果必須帶虛拟機。llvm是all code defaultly routed to llvm,clr 是一切routed to vm first,then selectively to jit
純走JIT,完全可以使二門語言需要混合的部分走統一的工具鍊流程和開發釋出。不必涉及到專門的binding過程。這就維護了統一生态不必斷層。而統一後端加統一都走jit,可以使得多語言天然可互動。
除了qtcling,在前面《釋出terracling》時,并提到一種原型terracling as toolkit,qtcling和terralang都是典型的llvm based jit mixable langsys,而terracling更先進,因為它提出了用lua metaprogramming terra(c)産生新語言。使得選型二門中心語言,其它DSL都可以以庫的方式被plugin進來,然而其方法主要還是用lua結合編譯原理程式設計産生新的語言parser..
最後,我們來歸納一下開發界對DSL邏輯和dsl語言發明的所有招數:有interlanguage interopt,binding interface tool,Preprocess,template,meta programming,partical evaluation,src2src translator(甚至到支援全部語言的haxe),common runtime,anonation,js functional metaprogramming,regluar compiler和編譯原理,還有jit+mixable mutiple langsys
如果LLVM是這麼好的架構,那麼不出所料,在LLVM上直接做PY,PHP的JIT應該會收到好的效果,然而,事實上llvm被嘗試用于将很多傳統語言如php,py裝配新的jit,然而收到的實際效果卻不好。google的unshadow和dropbox的pyston都反響不佳, 據說它對前端語言的要求最好是非動态類型的,這次我們碰到了pypy, 它不光是更好的LLVM,且它也面向多語言走JIT沒斷層,vs terracling它也有metaprogramming+編譯原理出新語言系統的能力且以語言内機制自動完成jit部分,沒錯,它其實是另外一種更強大的langone+DSL架構,單PYPY是語言實作,整個PyPy語言系統就是一個編譯器架構,完成可以拿來跟llvm+terracling結合效果相比,與llvm這種忠實地從0開始再造輪子的方法相比,pypy似乎更聰明一點,它重用輪子,它極力促成的結果是:使py真正變得通用化且內建DSL開發機制而能使産生的語言巧妙免除binding c的那些場景,因為它走的是更聰明的jit:
pypy:更合理的metaprogramming和auto jitted backend,像terracling一樣裝配了一個語言産生器
在制造DSL和混合語言的手段當中,有一種是語言轉換器,就是src2src translator,pypy的原理:1)The RPython translator takes RPython code and converts it to a chosen lower-level language, most commonly C. 2)Unlike Python, RPython is a statically-typed language,,,,
也即,pypy使用了rpython(rescricted)這門python的子集來自實作,但是要注意rpython其實離python十W八千裡了,與其說它是python,其實不如說它是另外一門語言,它就是實作産生DSL的元語言。類似llvm的前端部分,terralang的lua metaprogramming部分。如支援clang實作的那部分。pypy就是用rpython實作的python語言的前端部分和解析部分,雖然rPython不是完整的Python,但用rPython寫的這個Python實作卻是可以解釋完整的Python語言。,,這句話亮了,作為使用者我們面向的,始終僅是最後一部分,即可以解釋的完整的PY。
這裡的特點在哪裡呢?它有三層,即使有這麼多層,且全程用py或rpy實作,也絲毫不影響性能。注意這裡的1)pypy代碼,2)rpython表示,和3)jit運作代碼。使用者寫的是pypy代碼,不運作,rpython僅用于工具連結清單示,産生的c代碼才進入到運作,而jit過後才實際運作。離線的始終是那些預置化過程和面向使用者代碼的部分。運作的始終是jit過後和優化過程的C代碼部分和原生代碼部分。
然後其它的事就交給rpython強大的工具鍊,這是rpython第二部分,這就是我們說到的DSL産生工具架構和JIT産生器,類似LLVM統一後端。亮點是它是一個src2src 轉換器,目前Pypy隻實作了Python到C的編譯,也就是說編譯器的後端實作了直接轉成了機器碼。然後對這部分代碼作JIT,它的JIT是jitted to c相當于免VM的native code了,邏輯是:PyPy 的編譯工具鏈可以靜態地對 RPython 代碼做類型推導。類型推導是編譯的步驟中相當重要的一步,做了類型推導之後,就可以靜態地把 RPython 的代碼直接翻譯成 C 代碼然後靜態編譯了。 使用者不需要發明JIT,并不需要自己實作JIT編譯器,工具鍊支援自動生成JIT,隻要按照PyPy架構的指引,用RPython實作一個帶有足夠annotation的解釋器,就自動得到了高性能的帶JIT編譯器的實作。
這裡的特點又在哪裡呢?不可忽視的地方在于, 按需執行的JIT - 對特定的函數做修飾,然後動态的把它們編譯成機器碼并切換到使用c擴充。這種做法的好處是,重要的事情說三遍,寫解釋器,得到JIT編譯器。寫解釋器,得到JIT編譯器。寫解釋器,得到JIT編譯器。當有人想寫一個新的程式設計語言的實作時,隻要在PyPy架構下用RPython編寫一個對應上面(2)的語言解釋器,就可以借助作為meta-compiler的(3)的部分,得到一個能支援把(1)JIT編譯到機器碼的高性能實作。
且它還實作了運作時優化器。
PyPy's powerful abstractions make it the most flexible Python implementation. It has nearly 200 configuration options, which vary from selecting different garbage collector implementations to altering parameters of various translation optimizations. ----- 這有點類似kernel的busybox配置過程了。
最後說它的缺點,由于pypy實際上不面向混合來自C語言的擴充,PyPy有很弱的C語言擴充性。它支援C語言擴充,但是比Python本身的速度還慢。但是要說這是PYPY的缺點分明是無理取鬧嘛,直接将邏輯寫在純PYPY上,開啟JIT就好了。
pypy:更合理的斷層,jitted2c使其跨系統和應用二棧,jitted2js使其跨任意全棧
最後,pypy jitted to c的特點使得pypy可以跨系統和應用二棧,因為傳統C系開發釋出的那些領域就代表了整個系統開發棧。而其實rpython可以編譯到js的,這使得py碼代碼遷移到web是一個巨大的幫助,可以将整個pypy編譯為pypy.js放在浏覽器中,如js有asm.js産品,可以将浏覽器中的js+css+html通過模闆程式設計控制手段化為py+css+html,這樣py就web全棧了。
這是我以前在《釋出jupyter》中提出的設想,結合它作為線上IDE,可以完全将所有前後端編碼+邏輯調試放在浏覽器端。
拟下文是《web開發釋出的極大化:一套以浏覽器和paas為中心技術的可視全棧開發調試工具,支援自動适配任何領域demo》,增補《程式設計實踐選型通史》part2 web部分,那文說得不夠透徹,預計深入講解一下,可能自圓其說的往往都會有點玄,抱歉抱歉。。
(此處不設回複,掃碼到微信參與留言,或直接點選到原文)
