Başka bir programlama diline çevirmeyi kolaylaştırmak için koda ne tür kalıplar uygulayabilirim? [kapalı]


95

Kodu bir programlama dilinden diğerine çevirmeyi amaçlayan bir yan proje yapmak için yola çıkıyorum. Başladığım diller PHP ve Python'dur (Python'dan PHP'ye başlamak daha kolay olmalıdır), ancak ideal olarak diğer dilleri (göreceli) kolaylıkla ekleyebilirim. Plan şudur:

  • Bu, web geliştirmeye yöneliktir. Orijinal ve hedef kod, çerçevelerin üstünde olacak (benim de yazmam gerekecek). Bu çerçeveler bir MVC tasarım modelini benimseyecek ve katı kodlama kurallarını izleyecektir. Bu, çeviriyi biraz daha kolaylaştırmalıdır.

  • Ayrıca, çeviri sürecini daha kolay ve hataya daha az eğilimli hale getirebilecekleri için IOC ve bağımlılık enjeksiyonuna da bakıyorum.

  • Soyut Sözdizimi Ağacı ile uğraşmama izin veren Python'un ayrıştırıcı modülünü kullanacağım . Görünüşe göre PHP ile elde edebileceğim en yakın şey bir başlangıç ​​olan token_get_all () .

  • O andan itibaren AST, sembol tabloları oluşturabilir ve akışı kontrol edebilirim.

O zaman kod çıkarmaya başlayabileceğime inanıyorum. Mükemmel bir çeviriye ihtiyacım yok . Yine de oluşturulan kodu gözden geçirip sorunları düzeltmem gerekecek. İdeal olarak, çevirmen sorunlu çevirileri işaretlemelidir.

"Bunun anlamı ne?" Diye sormadan önce Cevap ... İlginç bir öğrenme deneyimi olacak. Bunu nasıl daha az göz korkutucu hale getirebileceğiniz konusunda herhangi bir fikriniz varsa lütfen bana bildirin.


DÜZENLE:

Kodu çevirmeyi (yani: IoC, SOA?) Çevirmeyi nasıl yapacağımdan daha kolay hale getirmek için koda ne tür kalıplar uygulayabileceğimi bilmekle daha çok ilgileniyorum.


6
.NET CLR veya Perl6's Parrot gibi sistemlere baktınız mı? Ortak bir yorumlayıcı tarafından çalıştırılabilen ara temsile kadar bir dizi dil derlerler. Orta düzey temsilden bir dile geri dönebiliyorsanız, bir çevirmeniniz var.
Borealid

1
@Borealid AFAIK .NET CIL (nispeten) kolay derlemek için içine , ama iyi şanslar bundan okunabilir kod geri alma. Parrot'a bakıyorum şimdi.
NullUserException

Diğer diller için benzer projeler var; Yazarlarının ne kadar zengin olduğundan emin değilim. Ve aslında burada bir çerçeveye ihtiyaç duyarak ve katı kodlama kurallarına bağlı kalarak kendimi çok kısıtlıyorum.
NullUserException

2
Belirli bir bilgi ekleyemem ama pijamalara ( pyjs.org ), özellikle de translator.py'ye baktınız mı? Bu, javascript derleyicisine bir python.
stephan

3
Yeniden DÜZENLEME: Çevrilecek kod üzerinde kontrolünüz varsa, yapılacak en bariz şey, çevrilmesi zor yapılardan kaçınmaktır! Örneğin, işaretçi aritmetiği yoksa C'yi Java'ya çevirmek çok daha kolaydır. Python için muhtemelen kapanışlardan uzak dururdum. Yapabileceğiniz diğer bir şey de, kaynak kodunu, çevrilmesi daha zor olan kısımların her zaman deyimsel olarak kodlanacağı şekilde yazmaktır, bu da onları tanımayı ve özel durumları işlemeyi kolaylaştırır.
Ira Baxter

Yanıtlar:


122

Ben oldum araçları (DMS Yazılım Değişim Mühendisliği Toolkit) bina bilgisayar bilim adamlarının güçlü bir ekip tarafından desteklenen, 1995 yılından bu yana (dil çeviri özel bir durum olmakla) genel amaçlı bir program manipülasyon yapmak. DMS genel ayrıştırma, AST oluşturma, sembol tabloları, kontrol ve veri akışı analizi, çeviri kurallarının uygulanması, kaynak metnin yorumlarla yeniden oluşturulması, vb. Sağlar ve bunların tümü bilgisayar dillerinin açık tanımlarıyla parametreleştirilir.

Bunu iyi yapmak için ihtiyacınız olan makine miktarı çok fazladır (özellikle bunu genel bir şekilde birden çok dil için yapabilmek istiyorsanız) ve o zaman güvenilmez tanımlara sahip diller için güvenilir ayrıştırıcılara ihtiyacınız var (PHP bunun mükemmel bir örneğidir ).

Dilden dile çevirmen oluşturmayı veya onu denemeyi düşünmenizde yanlış bir şey yok, ama bence bunu gerçek diller için beklediğinizden çok daha büyük bir görev bulacaksınız. Sadece DMS'ye yaklaşık 100 adam yıl yatırım yaptık ve her "güvenilir" dil tanımında (PHP için acı verici bir şekilde oluşturduğumuz dahil) 6-12 ay daha yatırım yaptık, C ++ gibi kötü diller için çok daha fazlası. "Cehennem bir öğrenme deneyimi" olacak; bizim için oldu. (Öğrenmeye hemen başlamak için yukarıdaki web sitesindeki teknik Makaleler bölümünü ilginç bulabilirsiniz).

İnsanlar genellikle aşina oldukları, işin bir bölümünü yapan bir teknoloji parçasıyla başlayarak bir tür genelleştirilmiş makine inşa etmeye çalışırlar. (Python AST'leri harika bir örnektir). İyi haber, işin bu kısmının tamamlanmasıdır. Kötü haber şu ki, makinenin içinde milyonlarca varsayım var, bunların çoğunu başka bir şey yapmaya çalışana kadar keşfedemeyeceksiniz. Bu noktada, makinenin başlangıçta yaptığı şeyi yapmaya hazır olduğunu ve gerçekten, gerçekten, onu başka bir şey yapma girişiminize direneceğini anlarsınız. (Python AST'yi PHP'yi modellemek için almaya çalışmanın çok eğlenceli olacağından şüpheleniyorum).

Başlangıçta DMS'yi kurmaya başlamamın nedeni, bu tür varsayımların çok az olduğu temeller inşa etmekti. Bazıları başımızı ağrıtıyor. Şimdiye kadar kara delik yok. (Son 15 yıldır işimin en zor kısmı, bu tür varsayımların devreye girmesini önlemeye çalışmaktır).

Pek çok insan, ayrıştırabilirse (ve belki bir AST alabilirlerse), karmaşık bir şey yapma yolunda iyi olduklarını varsayma hatasına da düşer. Zor derslerden biri, iyi bir program analizi veya dönüşümü yapmak için sembol tablolarına ve akış analizine ihtiyaç duymanızdır. AST'ler gereklidir ancak yeterli değildir. Aho & Ullman'ın derleyici kitabının 2. bölümde bitmemesinin nedeni budur (OP, AST'nin ötesinde ek makineler yapmayı planladığı için bu hakka sahiptir). Bu konu hakkında daha fazla bilgi için bkz . Ayrıştırmadan Sonra Yaşam .

"Kusursuz bir çeviriye ihtiyacım yok" sözü can sıkıcı. Zayıf çevirmenlerin yaptığı şey, kodun "kolay"% 80'ini dönüştürerek, zor olan% 20'yi elle yapmaktır. Dönüştürmeyi düşündüğünüz uygulama oldukça küçükse ve yalnızca bir kez iyi bir şekilde dönüştürmeyi düşünüyorsanız, o zaman% 20 tamamdır. Birçok uygulamayı (hatta zaman içinde küçük değişikliklerle aynı uygulamayı) dönüştürmek istiyorsanız, bu hiç hoş değil. 100K SLOC'yi dönüştürmeye çalışırsanız,% 20, zaten anlamadığınız başka bir 80.000 satırlık çevrilmiş program bağlamında çevrilmesi, anlaşılması ve değiştirilmesi zor olan 20.000 orijinal kod satırıdır. Bu çok fazla çaba gerektirir. Milyon satırı seviyesinde, bu pratikte imkansızdır.daha zor ve normalde uzun zaman gecikmeleriyle, yüksek maliyetlerle ve genellikle doğrudan başarısızlıkla acı verici bir şekilde öğrenirler.)

Büyük ölçekli sistemleri çevirmek için uğraşmanız gereken şey, doksanların yüksek yüzdeli dönüşüm oranlarıdır veya çeviri faaliyetinin manuel kısmını tamamlayamamanız olasıdır.

Dikkate alınması gereken bir diğer önemli nokta, çevrilecek kodun boyutudur. İyi araçlarla bile çalışan, sağlam bir çevirmen oluşturmak çok fazla enerji gerektirir. Sadece manuel bir dönüştürme yapmak yerine bir çevirmen oluşturmak seksi ve havalı görünse de, küçük kod tabanları için (örneğin, deneyimlerimize göre yaklaşık 100K SLOC'ye kadar) ekonomi bunu haklı çıkarmaz. Kimse bu cevabı sevmez, ancak gerçekten sadece 10K SLOC kodunu çevirmeniz gerekiyorsa, muhtemelen sadece mermiyi ısırıp bunu yapmaktan daha iyi olursunuz. Ve evet, bu acı verici.

Araçlarımızın son derece iyi olduğunu düşünüyorum (ama o zaman oldukça önyargılıyım). Ve hala iyi bir çevirmen oluşturmak çok zor; 1,5-2 adam-yılı alıyor ve araçlarımızı nasıl kullanacağımızı biliyoruz. Aradaki fark, bu kadar çok makineyle, başarısız olduğumuzdan çok daha fazla başarılı oluyoruz.


8
Hiç "zahmetli bir şekilde oluşturulmuş" PHP tanımınıza, genel olarak PHP topluluğuna katkıda bulunmayı ya da bunu mümkün kılmak için kendi gelir akışınızla çok yakından ilişkili olduğunu düşündünüz mü?
TML

53
Bir gelir akışına katkıda bulunmak istemeyen ve işi yapacak ve işi kendileri yapacak enerjiye sahip olmayan birçok kişi tarafından yaptığımız her şeyi "açık kaynak" yapmam istendi. Çok büyük bir projeye sadece küçük bir bölümle katkıda bulunuyorsanız ve / veya başka bir gelir kaynağınız varsa, "açık kaynak" iyi görünüyor. Tüm işi kendiniz yaptıysanız ve tek gelir kaynağınızsa, bu çok daha az caziptir. ["Özgür yazılım" felsefesinin göreceli yararları hakkında bir tartışmaya girmek istemiyorum, bu yüzden bu satırdaki başka yorumlara katılmayacağım]
Ira Baxter

9
Burada söylediklerinize katılıyorum, bu yüzden soruyu yaptığım gibi ifade ettim. Sanırım bu yanıttan, bunun gelirinize çok yakından bağlı olduğunu düşündüğünüzü ve bunda kesinlikle yanlış bir şey olmadığını anlamalıyız - sadece sormaya değer olduğunu düşündüm.
TML

3
@IraBaxter Bilgisayarla ilgili uygulamalar hakkında diğer birçok uygulamaya uygulanabilecek yaygın deyimler söylüyorsunuz. Yazdığınız her
şeyde ilginç

1
Cevaplarınızda genellikle Clang ile ilgili sayfalara bağlantılar sağlarsınız. Bu sadece başka birinin web sayfası yapabileceğini kanıtlıyor. Çoğumuz, iyi yazılmış bir web sayfasının, cevabınızda ima ettiğiniz gibi okuyucuyu aldatmak için sadece bazı hileli girişimlerin arkasında ciddi, gerçek bir çalışma olduğunu ima ettiğini varsayıyoruz. Web sayfasının sahtekarlık olduğuna gerçekten inanıyor musunuz? Sayfa, "ilgili" kaynağa referans bilgileri içerir; iş için sözleşme gerektirdiği için anonomize edildi. Ben yardım edemem.
Ira Baxter

13

Cevabım, Ira'nın cevabında iyi değindiği üst düzey yönleri değil, onu başka bir dile çevirmek için Python'u ayrıştırma görevine değinecek.

Kısacası: ayrıştırıcı modülünü kullanmayın, daha kolay bir yolu var.

astPython 2.6'dan beri mevcut olan modül, size çalışmanız için hazır bir AST verdiğinden ihtiyaçlarınıza çok daha uygundur. Geçen yıl bununla ilgili bir makale yazdım , ancak kısaca Python kaynak kodunu bir AST'ye ayrıştırma parseyöntemini kullanın ast. parserModül size çözümleme ağacı değil, bir AST verecektir. Farka karşı dikkatli olun .

Şimdi, Python'un AST'leri oldukça ayrıntılı olduğundan, bir AST verildiğinde ön uç işi çok zor değil. Sanırım işlevselliğin bazı bölümleri için oldukça hızlı bir şekilde hazır olan basit bir prototipe sahip olabilirsiniz. Bununla birlikte, tam bir çözüme ulaşmak daha fazla zaman alacaktır, çünkü dillerin anlambilimleri farklıdır. Dilin basit bir alt kümesi (işlevler, temel türler vb.) Kolayca çevrilebilir, ancak daha karmaşık katmanlara girdiğinizde, bir dilin özünü diğerinde taklit etmek için ağır makinelere ihtiyacınız olacak. Örneğin Python'un PHP'de bulunmayan üreteçlerini ve liste anlamalarını düşünün (en iyi bilgime göre, PHP söz konusu olduğunda kuşkusuz zayıftır).

Size son bir ipucu vermek için 2to3, Python geliştiricileri tarafından Python 2 kodunu Python 3 koduna çevirmek için oluşturulan aracı düşünün . Ön uç olarak, Python'u bir şeye çevirmek için ihtiyaç duyduğunuz öğelerin çoğuna sahiptir . Bununla birlikte, Python 2 ve 3'ün çekirdekleri benzer olduğundan, orada herhangi bir öykünme makinesi gerekmez.


Weeeell. 2to3sadece AST'den AST'ye. astModülün yeteneklerinin ötesine geçen hiçbir şeyi desteklemez . Çevirilerin hepsi gitmek Bildirimi gelen konak piton işlemiyle desteklenen sözdizimi için konak piton süreci desteklediği sözdizimi. Diyelim ki, fonksiyon ek açıklamaları ekleyen bir çevirmen yok çünkü 2.6 bunu desteklemiyor.
habnabit

... ve OP'nin sorusu çerçeveli olabilir, kısa vadeli, Python 2.6 AST'den PHP'deki bir şeye nasıl gidilir. Ast modülü büyük olasılıkla PHP sözdizimini iyi temsil etmek istemeyecektir, bu yüzden ast için ast bile değildir.
Ira Baxter

2
@Aaron: 2to3tarafından oluşturulan AST kullanımına bir örnek olarak görülebilir ast.
Eli Bendersky

AFAIK, 2'ye 3, tartışmalı olarak Python'dan PHP'ye daha kolay bir çeviridir (sonuçta, Python'dan Python'a, değil mi? Ve hatta pek iyi çalışmıyor. Henüz 2'ye 3'e geçmemiş büyük miktarda Python 2.6'ya dikkat edin ... çünkü görünüşe göre hala yapılması gereken bir dizi çeviri sonrası el yaması var. % 100 otomatik olsaydı, Python 2.6 ölürdü.
Ira Baxter

5

Bir çevirmen yazmak imkansız değil, özellikle Joel'in Stajyerinin bunu bir yaz boyunca yaptığı düşünüldüğünde.

Tek bir dil yapmak istiyorsanız, bu kolaydır. Daha fazlasını yapmak istiyorsanız, biraz daha zordur, ama çok fazla değil. En zor yanı, herhangi bir eksiksiz dil, başka bir tam dilin yaptığını yapabilirken, yerleşik veri türlerinin bir dilin olağanüstü şekilde yaptığını değiştirebilmesidir.

Örneğin:

word = 'This is not a word'
print word[::-2]

çoğaltmak için çok fazla C ++ kodu alır (tamam, bazı döngü yapılarıyla bunu oldukça kısa yapabilirsiniz, ancak yine de).

Sanırım bu biraz yanıltıcı.

Dil gramerine dayalı bir belirteç / ayrıştırıcı yazdınız mı? Yapmadıysanız, muhtemelen bunu nasıl yapacağınızı öğrenmek isteyeceksiniz, çünkü bu projenin ana kısmı budur. Yapacağım şey, temel bir Turing tam sözdizimi bulmaktır - Python bayt koduna oldukça benzer bir şey . Daha sonra bir dil grameri (belki BNF kullanarak ) alan ve dilbilgisine dayalı olarak, dili sizin ara dilinize derleyen bir sözcük / ayrıştırıcı oluşturursunuz . O zaman yapmak isteyeceğiniz şey tersini yapmaktır - dilbilgisine bağlı olarak dilinizden hedef dillere bir ayrıştırıcı oluşturun.

Gördüğüm en bariz sorun, ilk başta , özellikle Python gibi daha güçlü * dillerde muhtemelen korkunç derecede verimsiz kod yaratacağınızdır .

Ancak bunu bu şekilde yaparsanız, muhtemelen ilerledikçe çıktıyı optimize etmenin yollarını bulabileceksiniz. Özetlemek:

  • sağlanan grameri oku
  • programı orta (aynı zamanda Turing tamamlandı) sözdizimine derleyin
  • ara programı son dilde derleyin (sağlanan dilbilgisine göre)
  • ...?
  • Kar! (?)

* güçlü derken bunun 4 satır sürdüğünü söylüyorum:

myinput = raw_input("Enter something: ")
print myinput.replace('a', 'A')
print sum(ord(c) for c in myinput)
print myinput[::-1]

Bana 4 satırda böyle bir şey yapabilen başka bir dil gösterin, size Python kadar güçlü bir dil göstereceğim.


"Dil gramerine dayalı bir belirteç / ayrıştırıcı yazdınız mı?" Bunu JavaCC kullanarak yaptım.
NullUserException

2
Joel'in stajyeri bir yaz boyunca kısmi bir iş yaptı. Kaynak dili, mevcut bir dilin bir alt kümesiydi ve muhtemelen bu alt küme bir şekilde ayarlanabilirdi. Bu, işi çok daha kolaylaştırır. Benzer şekilde, NullPointerException Python'un daha kolay kısımlarıyla başlamak isteyebilir, belki manuel dönüştürme için daha zor kısımlardan geçebilir (sorularda belirtildiği gibi).
David Thornley

@NullUserException: Biraz maruz kalacaksınız, ancak temelde JavaCC'nin yeniden uygulamasını yapacaksınız, yalnızca çıktı dili olarak Java yerine <langauge buraya girin> yapacaksınız. @David, oldukça. Thistle'ın bile bazı dil yapılarında yardıma ihtiyacı var. OP olsaydım, önce işlevselliğe gider, sonra optimize ederdim, aksi takdirde sonsuza kadar dize dilimleme (adımlarla) yapmak için C ++ almaya çalışırken
Wayne Werner

@WayneWerner Kayıt için, C # gibi diller hiçbir şekilde satırsonu gerektirmez. (En azından, tek satırlı açıklamaları çıkardıktan sonra değil.) Böylece herhangi bir C # programını tek satırda yazabilirsiniz. Ama elbette ne yaptığını anlıyorum.
leviathanbadger

@ aboveyou00: Bunun doğru olduğunu düşünmüyorum. Önişlemci koşullara izin vermezseniz, haklı olabilirsiniz.
Ira Baxter

3

Rahatsız etmemenizi söyleyen birkaç cevap var. Peki, bu ne kadar yardımcı oluyor? Öğrenmek ister misin? Öğrenebilirsin. Bu derlemedir. Öyle ki, hedef diliniz makine kodu değil, başka bir yüksek seviyeli dildir. Bu her zaman yapılır.

Başlamanın nispeten kolay bir yolu var. Öncelikle http://sourceforge.net/projects/lime-php/ (PHP'de çalışmak istiyorsanız) veya bunun gibi bazılarını alın ve örnek kodu gözden geçirin. Daha sonra, oluşturduğunuz ayrıştırıcıya bir dizi normal ifade ve belirteçleri besleyerek bir sözcük analizörü yazabilirsiniz. Anlamsal eylemleriniz, kodu doğrudan başka bir dilde çıkarabilir veya çıktı kodu oluşturmak için masaj yapabileceğiniz ve üzerinde ilerleyebileceğiniz bazı veri yapıları (nesneleri düşünün, adam) oluşturabilir.

PHP ve Python konusunda şanslısınız çünkü birçok yönden birbirleriyle aynı dildir, ancak farklı sözdizimine sahiptir. Zor kısım, dilbilgisi formları ve veri yapıları arasındaki anlamsal farklılıkların üstesinden gelmektir. Örneğin, Python'da listeler ve sözlükler varken, PHP yalnızca assoc dizilerine sahiptir.

"Öğrenci" yaklaşımı, dilin kısıtlı bir alt kümesi için (yalnızca basılı ifadeler, basit matematik ve değişken atama gibi) iyi çalışan bir şey oluşturmak ve ardından sınırlamaları aşamalı olarak kaldırmaktır. Bu, temelde sahadaki "büyük" adamların yaptığı şeydi.

Oh, ve Python'da statik türleriniz olmadığından, Python'un yaptığı gibi sayılar, dizeler veya nesneler ekleyen "python_add" gibi PHP işlevlerini yazmak ve bunlara güvenmek en iyisi olabilir.

Açıkçası, izin verirseniz bu daha da büyüyebilir.


3
Aslında "zahmet etme" demedim. Dediğim şey, "dilleri genel olarak çevirmek çok zor" oldu. OP, PHP'yi denemek ve oluşturmak için Python ağaçlarını kullanma yolunda ilerlerse, çok şey öğrenecek ve ben öğrenme deneyiminden yanayım; Ben de oradan başladım. Yeni dilleri kolayca ekleyemeyecek.
Ira Baxter

@IraBaxter İfadenizi destekleyemiyorum, Python-> PHP ve PHP-> Javascript yapmak çok kolay olurdu. cf. stackoverflow.com/a/22850139/140837'nin son kısmı cevabın ortasında "argümantasyonunuz" ile de ilgileniyorum
amirouche

2

@EliBendersky'nin ayrıştırıcı yerine (daha önce bilmediğim) ast.parse kullanımıyla ilgili bakış açısını ikinci olarak alacağım. Ayrıca blogunu incelemenizi de şiddetle tavsiye ediyorum. Python-> JavaScript çevirmeni (@ https://bitbucket.org/amirouche/pythonium ) yapmak için ast.parse kullandım . Pythonium tasarımını bir şekilde diğer uygulamaları gözden geçirip kendi başıma deneyerek buldum. Pythonium'u https://github.com/PythonJS/PythonJS'den çatalladım ki bu da başlattım, aslında tam bir yeniden yazma. Genel tasarım PyPy ve http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-89-1.pdf kağıdından esinlenmiştir .

En başından en iyi çözüme kadar denediğim her şey, Pythonium pazarlaması gibi görünse bile, gerçekten öyle değil (bir şey ağ etiğine uygun görünmüyorsa bana söylemekten çekinmeyin):

  • Prototip kalıtım kullanarak Python semantikini Düz Eski JavaScript'te uygulayın: AFAIK, JS prototip nesne sistemini kullanarak Python çoklu kalıtımını uygulamak imkansızdır. Daha sonra başka hileler kullanarak yapmayı denedim (cf. getattribute). JavaScript'te Python çoklu kalıtım uygulamasının olmadığını bildiğim kadarıyla, var olan en iyisi Tek kalıtım + karışımlarıdır ve bunların elmas kalıtımı işlediğinden emin değilim. Skulpt'a benzer, ancak google clojure olmadan.

  • Skulpt kodunu #fail okumak yerine, tıpkı Skulpt (derleyici) gibi Google clojure ile denedim. Zaten JS prototip tabanlı nesne sistemi nedeniyle hala imkansız. Bağlama oluşturmak çok çok zordu, JavaScript ve çok sayıda standart kod yazmanız gerekiyor (bkz. Https://github.com/skulpt/skulpt/issues/50 burada hayaletim). O zamanlar, bağlama sistemini derleme sistemine entegre etmenin net bir yolu yoktu. Skulpt'un bir kütüphane olduğunu düşünüyorum ve sadece .py dosyalarınızı yürütülecek html'ye dahil etmeniz gerekiyor, geliştirici tarafından derleme aşamasına gerek yok.

  • Pyjaco (derleyici) denendi, ancak bağlamalar oluşturmak (Python kodundan Javascript kodunu çağırmak) çok zordu, her seferinde yaratılması gereken çok fazla standart kod vardı. Şimdi bence pyjaco, Pythonium'a daha yakın olanı. pyjaco Python (ast.parse) ile yazılmıştır, ancak çoğu JavaScript ile yazılmıştır ve prototip kalıtım kullanır.

Pajamas #fail'i çalıştırmayı asla başaramadım ve bir daha #fail kodunu okumayı denemedim. Ama benim aklımda pijamalar, Python'dan JavaScript'e çeviri yapmak yerine API-> API çevirme (veya çerçeveden çerçeveye) yapıyordu. JavaScript çerçevesi, sayfada zaten bulunan verileri veya sunucudaki verileri kullanır. Python kodu yalnızca "sıhhi tesisattır". Bundan sonra, pijamaların aslında gerçek bir python-> js çevirmeni olduğunu keşfettim.

Yine de API-> API (veya çerçeve-> çerçeve) çevirisi yapmanın mümkün olduğunu düşünüyorum ve temelde Pythonium'da ancak daha düşük seviyede yaptığım şey bu. Muhtemelen Pijama, Pythonium ile aynı algoritmayı kullanıyor ...

Sonra brython'u tamamen Javascript ile Skulpt gibi, derlemeye ve çok fazla kabartmaya gerek yok ... ama JavaScript ile yazılmış keşfettim.

Bu proje sırasında yazılan ilk satırdan beri, PyPy'yi, hatta PyPy için JavaScript arka ucunu biliyordum. Evet, bulursanız, doğrudan PyPy'den JavaScript'te bir Python yorumlayıcısı oluşturabilirsiniz. İnsanlar bunun bir felaket olduğunu söylüyor. Hiçbir yerde neden okumadım. Ancak bunun nedeninin yorumlayıcıyı uygulamak için kullandıkları ara dil olan RPython'un Python'un C'ye (ve belki de asm'ye) çevrilmek üzere uyarlanmış bir alt kümesi olması olduğunu düşünüyorum. Ira Baxter, bir şey inşa ederken her zaman varsayımlar yaptığınızı ve muhtemelen PyPy: Python-> C çevirisi durumunda yapılması gereken şeyde en iyisi olması için ince ayar yaptığınızı söylüyor. Bu varsayımlar başka bir bağlamda alakalı olmayabilir, daha kötüsü ek yüke neden olabilir, aksi takdirde doğrudan çeviri büyük olasılıkla her zaman daha iyi olacaktır.

Tercümanın Python'da yazılması (çok) iyi bir fikir gibi geldi. Ancak performans nedenlerinden ötürü bir derleyiciyle daha çok ilgileniyordum, ayrıca Python'u JavaScript'e derlemek onu yorumlamaktan daha kolaydır.

PythonJS'ye, kolayca JavaScript'e çevirebileceğim bir Python alt kümesini bir araya getirme fikriyle başladım. İlk başta geçmiş deneyimlerimden dolayı OO sistemini uygulamaya zahmet etmedim bile. JavaScript'e çevirmeyi başardığım Python alt kümesi:

  • hem tanımda hem de çağrıda tam parametreli anlamsal işlev. En gurur duyduğum kısım bu.
  • while / if / elif / else
  • Python türleri JavaScript türlerine dönüştürüldü (hiçbir tür python türü yoktur)
  • için yalnızca Javascript dizileri üzerinde yineleme yapabilir (dizideki bir dizi için)
  • JavaScript'e şeffaf erişim: Python kodunda Array yazarsanız, javascript'te Array'e çevrilecektir. Bu, rakiplerine göre kullanılabilirlik açısından en büyük başarıdır.
  • Python kaynağında tanımlanan işlevi javascript işlevlerine geçirebilirsiniz. Varsayılan argümanlar dikkate alınacaktır.
  • Eklenti, yeni olarak adlandırılan ve JavaScript'e çevrilen özel bir işleve sahiptir; örneğin: new (Python) (1, 2, spam, "egg") "new Python (1, 2, spam," egg ") olarak çevrilir.
  • "var", çevirmen tarafından otomatik olarak ele alınır. (Brett'ten çok güzel bir bulgu (PythonJS katılımcısı).
  • genel anahtar kelime
  • kapanışlar
  • Lambdas
  • liste anlayışları
  • ithalatlar, requirejs aracılığıyla desteklenir
  • classyjs aracılığıyla tek sınıf miras + mixin

Bu çok gibi görünüyor, ancak Python'un tam anlamıyla anlamsallığına kıyasla aslında çok dar. Python sözdizimine sahip gerçekten JavaScript.

Oluşturulan JS mükemmel, yani. ek yük yoktur, daha fazla düzenlenerek performans açısından iyileştirilemez. Üretilen kodu geliştirebilirseniz, bunu Python kaynak dosyasından da yapabilirsiniz. Ayrıca derleyici, http://superherojs.com/ tarafından yazılan .js dosyasında bulabileceğiniz herhangi bir JS numarasına güvenmedi , bu yüzden çok okunabilir.

PythonJS'nin bu bölümünün doğrudan soyundan gelen Pythonium Veloce modudur. Tam uygulama @ https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/veloce/veloce.py?at=master 793 SLOC + diğer çevirmenle paylaşılan yaklaşık 100 SLOC paylaşımlı kodda bulunabilir.

Pystones.py'nin uyarlanmış bir sürümü Veloce modunda çevrilebilir, bkz. https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pystone/?at=master

Temel Python-> JavaScript çevirisini kurduktan sonra, tam Python'u JavaScript'e çevirmek için başka bir yol seçtim. Glib'in hedef dil dışında nesne yönelimli sınıf tabanlı kod yapmanın yolu JS'dir, böylece dizilere, harita benzeri nesnelere ve diğer birçok numaraya erişebilirsiniz ve tüm bu kısım Python'da yazılmıştır. IIRC Pythonium tercümanı tarafından yazılmış bir javascript kodu yoktur. Pythonium'u Python ile tamamen uyumlu kılan zor kısımlar burada tek kalıtım almak zor değildir:

  • spam.eggPython'da her zaman için çevrilir getattribute(spam, "egg")Ben özellikle bunun profilini çıkarmadım, ancak çok zaman kaybettiği ve asm.js veya başka bir şeyle onu geliştirebileceğimden emin değilim.
  • yöntem çözümleme sırası: Python'da yazılan algoritma ile bile, onu Python Veloce uyumlu koda çevirmek büyük bir çabaydı.
  • getattributre : gerçek getattribute çözümleme algoritması biraz zor ve hala veri tanımlayıcıları desteklemiyor
  • metasınıf sınıfı temelli: Kodu nereye koyacağımı biliyorum, ama yine de ...
  • son bu en az değil: some_callable (...) her zaman "call (some_callable)" olarak dönüştürülür. AFAIK, çevirmen hiçbir şekilde çıkarım kullanmaz, bu yüzden her arama yaptığınızda, ne tür bir nesnenin çağrılması gerektiği gibi adlandırılacağını kontrol etmeniz gerekir.

Bu bölüm, https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/compliant/runtime.py?at=master içinde belirtilmiştir Python Veloce ile uyumlu Python ile yazılmıştır.

Gerçek uyumlu çevirmen https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/compliant/compliant.py?at=master doğrudan JavaScript kodu oluşturmaz ve en önemlisi ast-> ast dönüşümü yapmaz . Ben ast-> ast'ı denedim ve cst'den daha iyi olsa bile ast.NodeTransformer ile çalışmak hoş değil ve daha da önemlisi ast-> ast yapmama gerek yok.

Benim durumumda python ast'ı python ast'a yapmak, en azından bir performans artışı olabilir, çünkü bazen bir bloğun içeriğini, kendisiyle ilişkili kodu oluşturmadan önce inceliyorum, örneğin:

  • var / global: bir şeyi değiştirebilmek için neye ihtiyacım olduğunu ve neye ihtiyacım olduğunu bilmem gerekir. Belirli bir blokta hangi değişkenin yaratıldığı bir blok izleme oluşturmak ve onu oluşturulan fonksiyon bloğunun üstüne eklemek yerine, ilgili kodu oluşturmak için alt düğümü ziyaret etmeden önce bloğa girdiğimde sadece açığa çıkan değişken atamasını ararım.
  • verim, üreteçlerin şimdiye kadar JS'de özel bir sözdizimi var, bu yüzden "var my_generator = function" yazmak istediğimde hangi Python işlevinin bir oluşturucu olduğunu bilmem gerekiyor

Dolayısıyla, çevirinin her aşaması için her düğümü bir kez ziyaret etmiyorum.

Genel süreç şu şekilde tanımlanabilir:

Python source code -> Python ast -> Python source code compatible with Veloce mode -> Python ast -> JavaScript source code

Python yerleşikleri Python kodu (!), IIRC ile yazılmıştır, önyükleme türleri ile ilgili birkaç kısıtlama vardır, ancak Pythonium'u uyumlu modda çevirebilen her şeye erişebilirsiniz. Https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/compliant/builtins/?at=master adresine bir göz atın

Pythonium uyumludan üretilen JS kodunu okumak anlaşılabilir, ancak kaynak haritaları büyük ölçüde yardımcı olacaktır.

Bu deneyimin ışığında size verebileceğim değerli tavsiyeler, yaşlı osuruklardır:

  • Konuyu hem literatürde hem de mevcut projeler kapalı kaynak veya ücretsiz olarak kapsamlı bir şekilde gözden geçirin. Mevcut farklı projeleri gözden geçirdiğimde, ona daha fazla zaman ve motivasyon vermeliydim.
  • sorular sor! PyPy arka ucunun C / Javascript anlamsal uyumsuzluğu nedeniyle ek yükten dolayı işe yaramadığını önceden bilseydim. Pythonium fikrimi 6 ay önce, belki 3 yıl önce almıştım.
  • ne yapmak istediğinizi bilin, hedef alın. Bu proje için farklı hedeflerim vardı: biraz javascript uygulamak, Python hakkında daha fazla bilgi edinmek ve tarayıcıda çalışacak Python kodu yazabilmek (daha fazlası ve aşağıda).
  • başarısızlık deneyimdir
  • küçük bir adım bir adımdır
  • küçük başla
  • büyük düşün
  • demolar yapmak
  • yinelemek

Yalnızca Python Veloce modu ile çok mutluyum! Ama yol boyunca gerçekten aradığım şeyin beni ve diğerlerini Javascript'ten özgürleştirmek, daha da önemlisi rahat bir şekilde yaratabilmek olduğunu keşfettim . Bu beni Scheme, DSL, Models ve nihayetinde alana özgü modellere götürür (cf. http://dsmforum.org/ ).

Ira Baxter'ın cevabı hakkında:

Tahminler hiç yardımcı olmuyor. Hem PythonJS hem de Pythonium için 6 ay kadar boş zamanımı aldım. Yani tam zamanlı 6 aydan daha fazlasını bekleyebilirim. Sanırım hepimiz bir işletme bağlamında 100 adam yılının ne anlama geldiğini ve hiç bir anlam ifade etmediğini biliyoruz ...

Birisi bir şeyin zor ya da çoğu zaman imkansız olduğunu söylediğinde, "imkansız olan bir soruna çözüm bulmak sadece zaman alır" diye cevaplıyorum, aksi takdirde hiçbir şeyin imkansız olmadığını söylemiştim, bu durumda imkansız olduğu kanıtlanmışsa bir matematik kanıtı ...

İmkansız olduğu kanıtlanmadıysa, hayal gücüne yer bırakır:

  • imkansız olduğunu kanıtlayan bir kanıt bulmak

ve

  • İmkansızsa, çözümü olabilecek "alt düzey" bir sorun olabilir.

veya

  • imkansız değilse bir çözüm bulmak

Bu sadece iyimser düşünce değil. Python-> Javascript'e başladığımda herkes bunun imkansız olduğunu söylüyordu. PyPy imkansız. Metasınıflar çok zor. vs ... PyPy'yi Scheme-> C kağıdına (25 yıllık) getiren tek devrimin bazı otomatik JIT üretimi olduğunu düşünüyorum (sanırım RPython yorumlayıcısıyla yazılmış ipuçları).

Bir şeyin "zor" veya "imkansız" olduğunu söyleyen çoğu insan bunun nedenlerini sunmaz. C ++ 'nın ayrıştırılması zor mu? Biliyorum, hala (ücretsiz) C ++ ayrıştırıcısı. Kötülük ayrıntıda mı gizlidir? Bunu biliyorum. Tek başına imkansız demek yardımcı olmaz, "yardımcı olmamaktan" daha kötüdür, cesaret kırıcıdır ve bazı insanlar diğerlerini caydırmak ister. Bu soruyu /programming/22621164/how-to-automatically-generate-a-parser-code-to-code-translator-from-a-corpus aracılığıyla duydum .

Mükemmellik ne olurdu sizin için ? Bir sonraki hedefi bu şekilde tanımlarsınız ve belki genel hedefe ulaşırsınız.

Kodu çevirmeyi (yani: IoC, SOA?) Çevirmeyi nasıl yapacağımdan daha kolay hale getirmek için koda ne tür kalıplar uygulayabileceğimi bilmekle daha çok ilgileniyorum.

En azından mükemmelden daha az bir şekilde bir dilden başka bir dile çevrilemeyen hiçbir kalıp görmüyorum. Dilden dile çeviri mümkün olduğundan, önce bunu hedeflemelisiniz. Bence http://en.wikipedia.org/wiki/Graph_isomorphism_problem'e göre , iki bilgisayar dili arasındaki çevirinin bir ağaç veya DAG izomorfizmi olduğunu düşünüyorum. Her ikisinin de tamamlandığını bilsek bile, bu yüzden ...

API-> API çevirisi olarak daha iyi görselleştirdiğim Framework-> Framework, oluşturulan kodu iyileştirmenin bir yolu olarak hala aklınızda tutabileceğiniz bir şey olabilir. Örneğin: Prolog çok özel bir sözdizimi olarak ama yine de Python'da aynı grafiği açıklayarak Prolog gibi hesaplama yapabilirsiniz ... Eğer bir Prolog'u Python çevirmenine uygulayacak olsaydım, Python'da birleştirme yapmazdım ama bir C kütüphanesinde gelirim Bir Pythonist için çok okunabilir bir "Python sözdizimi" hazırlayın. Sonunda, sözdizimi sadece bir anlam verdiğimiz "resim" dir (bu yüzden şemaya başladım). Kötülük, dilin detayındadır ve sözdiziminden bahsetmiyorum. Getattribute dilinde kullanılan kavramlarhook (onsuz yaşayabilirsiniz) ancak kuyruk özyineleme optimizasyonu gibi gerekli VM özellikleriyle uğraşmak zor olabilir. İlk programın kuyruk özyinelemeyi kullanmaması umrunda değil ve hedef dilde kuyruk özyinelemesi olmasa bile, yeşillikler / olay döngüsü kullanarak onu taklit edebilirsiniz.

Hedef ve kaynak diller için şunları arayın:

  • Büyük ve özel fikirler
  • Küçük ve ortak paylaşılan fikirler

Bundan ortaya çıkacak:

  • Tercüme etmesi kolay şeyler
  • Tercüme etmesi zor şeyler

Ayrıca neyin hızlı ve yavaş koda çevrileceğini de muhtemelen bileceksiniz.

Ayrıca stdlib veya herhangi bir kütüphane sorusu var ama net bir cevap yok, hedeflerinize bağlı.

Deyimsel kod veya okunabilir üretilen kodun da çözümleri var ...

PHP gibi bir platformu hedeflemek, tarayıcıları hedeflemekten çok daha kolaydır çünkü yavaş ve / veya kritik yolun C-uygulamasını sağlayabilirsiniz.

İlk proje Python'u PHP'ye çevirmek olduğunu düşünürsek, en azından bildiğim PHP3 alt kümesi için veloce.py'yi özelleştirmek en iyi seçeneğinizdir. Veloce.py'yi PHP için uygulayabilirseniz, muhtemelen uyumlu modu çalıştırabilirsiniz ... Ayrıca PHP'yi PHP'nin alt kümesine çevirebiliyorsanız, php_veloce.py ile üretebilirsiniz bu, PHP'yi şu dile çevirebileceğiniz anlamına gelir: veloce.py'nin kullanabileceği Python alt kümesi, bu da PHP'yi Javascript'e çevirebileceğiniz anlamına gelir. Sadece söylüyorum...

Ayrıca şu kitaplıklara da bakabilirsiniz:

Ayrıca şu blog gönderisiyle (ve yorumlarla) ilgilenebilirsiniz: https://www.rfk.id.au/blog/entry/pypy-js-poc-jit/



Veri türleri hakkında diğer yanıtı ikinci olarak veriyorum. Pythonium'da, asm.js olmadan uyumlu modda doğru bir tamsayı ve kayan türü desteklemeyi planlamıyordum bile.
amirouche

Tamam, size 100K SLOC içeren bir Python paketi verirsem ve bunu "çevirmen" üzerinden çalıştırırsanız, çalışan bir program alır mıyım? Bunu düzeltmek için çeviri sonrası el işi ne kadar sürer? Burada söylediniz, "AST'leri oluşturan Python için zaten var olan iyi bir ayrıştırıcı göz önüne alındığında, 6 ay içinde kısmi bir çevirmen oluşturabilirim". Kimse şaşırmaz. 6 ay çoğu insanın standartlarına göre "kolay" değildir (başka bir yorumunuzdan alıntı yaparak). Kalan sorunları çözmek daha fazla çaba gerektirecektir. Cevabım temelde "bunu yapmak kolay değil" ve "bunu genel bir şekilde yapmak zor" dedi.
Ira Baxter

... OP'nin orijinal arzusuna yanıt olarak son nokta: "ideal olarak (göreceli) kolaylıkla başka diller ekleyebilirim.", cevabımın özel olarak hitap ettiği.
Ira Baxter

Katılmamak için yalvarıyorum, özellikle ne yaptığınızı bildiğinizde, kolaydır ve ardından gelenler zor değildir, sadece işleri halletme meselesidir. Soruya özgü herhangi bir şeyle nerede uğraştığınızdan emin değilim. 4 veya 5 paragrafta şirketinizin yaptığını söylüyorsunuz ve bu zor. Ancak aksi takdirde, stackoverflow.com/questions/22621164/… adresindeymişsiniz gibi konu dışı bir şekilde konu hakkında FUD yayıyorsunuz . Tam zamanlı 6 ayda tam bir tercüman yazardım.
amirouche

0

Vala'yı (C # benzeri bir dil) C'ye çeviren Vala derleyicisine bir göz atabilirsiniz .


C'ye çevrilmesi ve gnome kitaplıkları ile geliştirmeyi kolaylaştırması Vala'nın tasarım hedefiydi.
amirouche
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.