@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.egg
Python'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/