パーサーの代わりにast.parseを使用することに関して@EliBenderskyの観点を2番目にします(これは以前は知りませんでした)。また、彼のブログを確認することを強くお勧めします。ast.parseを使用してPython->JavaScriptトランスレータ(@ https://bitbucket.org/amirouche/pythonium)を実行しました。Pythoniumの設計は、他の実装をいくらか見直して、自分で試してみました。私も始めたhttps://github.com/PythonJS/PythonJSからPythoniumをフォークしました。これは実際には完全な書き直しです。全体的なデザインは、PyPyとhttp://www.hpl.hp.com/techreports/Compaq-DEC/WRL-89-1.pdfの論文から着想を得ています。
最初から最良の解決策まで、Pythoniumのマーケティングのように見えても、実際にはそうではありません(ネチケットに正しくないように思われる場合は、遠慮なく教えてください)。
プロトタイプ継承を使用してプレーンオールドJavaScriptでPythonセマンティックを実装する:AFAIKは、JSプロトタイプオブジェクトシステムを使用してPython多重継承を実装することは不可能です。私は後で他のトリックを使ってそれをやろうとしました(getattributeを参照)。JavaScriptにPythonの多重継承の実装がないことを私が知っている限り、存在する最良のものは単一継承+ミックスインであり、それらがダイヤモンド継承を処理するかどうかはわかりません。Skulptに似ていますが、googleclojureはありません。
実際にSkulptコード#failを読み取る代わりに、Skulpt(コンパイラ)のようにGoogleclojureを試してみました。とにかくJSプロトタイプベースのオブジェクトシステムのためにまだ不可能です。バインディングの作成は非常に困難でした。JavaScriptと多くの定型コードを作成する必要があります(私が幽霊であるhttps://github.com/skulpt/skulpt/issues/50を参照)。当時、ビルドシステムにバインディングを統合する明確な方法はありませんでした。Skulptはライブラリであり、実行するhtmlに.pyファイルを含めるだけでよく、開発者がコンパイルフェーズを実行する必要はないと思います。
pyjaco(コンパイラ)を試しましたが、バインディングの作成(PythonコードからJavascriptコードを呼び出す)は非常に困難で、毎回作成するには定型コードが多すぎました。今、私はpyjacoがPythoniumにもっと近いものだと思います。pyjacoはPython(ast.parseも)で書かれていますが、多くはJavaScriptで書かれており、プロトタイプの継承を使用しています。
私は実際にパジャマ#failの実行に成功したことはなく、コード#failを再度読み取ろうとしたこともありません。しかし、私の考えでは、パジャマはAPI-> API変換(またはフレームワークからフレームワーク)を実行しており、PythonからJavaScriptへの変換は実行していませんでした。JavaScriptフレームワークは、すでにページにあるデータまたはサーバーからのデータを消費します。Pythonコードは「配管」にすぎません。その後、私はパジャマが実際には本当のpython->jsトランスレーターであることを発見しました。
それでも、API-> API(またはフレームワーク->フレームワーク)の翻訳を行うことは可能だと思います。それは基本的に私がPythoniumで行うことですが、より低いレベルです。おそらくパジャマはPythoniumと同じアルゴリズムを使用しています...
それから私はSkulptのようにJavascriptで完全に書かれたbrythonを発見しました。コンパイルの必要はなく、多くの綿毛があります...しかしJavaScriptで書かれています。
このプロジェクトの過程で書かれた最初の行以来、私はPyPyについて、さらにはPyPyのJavaScriptバックエンドについても知っていました。はい、見つかった場合は、PyPyからJavaScriptでPythonインタープリターを直接生成できます。人々はそれが災害だったと言います。なぜどこにも読まない。しかし、その理由は、インタプリタを実装するために使用する中間言語であるRPythonが、C(およびおそらくasm)に変換されるように調整されたPythonのサブセットであるためだと思います。Ira Baxterは、何かを構築するときは常に仮定を立て、おそらくPyPy:Python->C変換の場合に意図されていることで最高になるように微調整すると言います。これらの仮定は、別のコンテキストでは関連性がない可能性があり、オーバーヘッドを推測する可能性があります。そうでない場合、直接翻訳の方が常に優れている可能性があります。
Pythonでインタプリタを作成することは、(非常に)良い考えのように思えました。しかし、パフォーマンス上の理由からコンパイラーに興味がありました。また、PythonをJavaScriptにコンパイルする方が、解釈するよりも実際には簡単です。
私は、JavaScriptに簡単に変換できるPythonのサブセットをまとめることを考えてPythonJSを開始しました。最初は、過去の経験から、オブジェクト指向システムを実装することすらしませんでした。JavaScriptに翻訳するために私が達成したPythonのサブセットは次のとおりです。
- 定義と呼び出しの両方でセマンティックな完全なパラメーターを持つ関数。これは私が最も誇りに思っている部分です。
- while / if / elif / else
- PythonタイプはJavaScriptタイプに変換されました(どのような種類のPythonタイプもありません)
- forはJavascript配列のみを反復できます(in配列の場合)
- JavaScriptへの透過的なアクセス:PythonコードでArrayを記述すると、javascriptでArrayに変換されます。これは、競合他社に対する使いやすさの点で最大の成果です。
- Pythonソースで定義された関数をjavascript関数に渡すことができます。デフォルトの引数が考慮されます。
- 追加には、JavaScript newに変換されるnewという特別な関数があります。例:new(Python)(1、2、spam、 "egg")は "new Python(1、2、spam、" egg ")に変換されます。
- 「var」は翻訳者によって自動的に処理されます。(Brett(PythonJS寄稿者)からの非常に素晴らしい発見。
- グローバルキーワード
- クロージャ
- ラムダ
- リスト内包
- インポートはrequirejsを介してサポートされています
- classyjsを介した単一クラスの継承+ミックスイン
これは多くのように見えますが、Pythonの本格的なセマンティクスと比較すると実際には非常に狭いです。これは、実際にはPython構文を使用したJavaScriptです。
生成されたJSは完璧です。オーバーヘッドはなく、さらに編集してもパフォーマンスを向上させることはできません。生成されたコードを改善できる場合は、Pythonソースファイルからも改善できます。また、コンパイラはhttp://superherojs.com/によって記述された.jsにあるJSトリックに依存していなかったため、非常に読みやすくなっています。
PythonJSのこの部分の直接の子孫は、PythoniumVeloceモードです。完全な実装は、@ https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced3 92f1c369afd746c25d7/pythonium/veloce/veloce.py?at= master 793SLOC+他のトランスレータとの共有コードの約100SLOCにあります。
pystones.pyの適応バージョンは、Veloceモードで翻訳できます。https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pystone/?at=master
基本的なPython->JavaScriptの翻訳を設定した後、完全なPythonをJavaScriptに翻訳するための別のパスを選択しました。ターゲット言語を除くオブジェクト指向のクラスベースのコードをglibが実行する方法はJSであるため、配列、マップのようなオブジェクト、およびその他の多くのトリックにアクセスでき、そのすべての部分はPythonで記述されています。IIRCは、Pythoniumトランスレータで記述されたjavascriptコードはありません。ここで単一継承を取得することは難しくありません。PythoniumをPythonに完全に準拠させるための難しい部分は次のとおりです。
spam.egg
Pythonで常に翻訳されているのでgetattribute(spam, "egg")
、特にこれをプロファイリングしませんでしたが、多くの時間が失われ、asm.jsなどで改善できるかどうかわからないと思います。
- メソッドの解決順序:Pythonで記述されたアルゴリズムを使用しても、PythonVeloce互換コードに変換することは大きな努力でした。
- getattributre:実際のgetattribute解決アルゴリズムはちょっとトリッキーですが、それでもデータ記述子をサポートしていません
- メタクラスクラスベース:コードをどこにプラグインするかはわかっていますが、それでも...
- 最後になりましたが、some_callable(...)は常に「call(some_callable)」に変換されます。AFAIKトランスレータは推論をまったく使用しないため、呼び出しを行うたびに、呼び出されるオブジェクトの種類を確認する必要があります。
この部分はhttps://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced3 92f1c369afd746c25d7/pythonium/compatible/runtime.py?at=masterで考慮されていますPythonVeloceと互換性のあるPythonで書かれています。
実際の準拠トランスレータhttps://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced3 92f1c369afd746c25d7/pythonium/compatible/compatible.py?at=masterはJavaScriptコードを直接生成せず、最も重要なのは、ast->ast変換を実行しないことです。 。私はast->astを試しましたが、cstよりも優れている場合でもast.NodeTransformerを使用してもうまく機能しません。さらに重要なことに、ast->astを実行する必要はありません。
私の場合、少なくともpythonastからpythonastを実行すると、ブロックに関連付けられたコードを生成する前にブロックのコンテンツを検査することがあるため、パフォーマンスが向上する可能性があります。
- var / global:何かをvarできるようにするには、varではなく必要なことを知っている必要があります。特定のブロックで作成された変数を追跡するブロックを生成し、生成された関数ブロックの上に挿入する代わりに、子ノードに実際にアクセスして関連コードを生成する前に、ブロックに入るときに関連する変数の割り当てを探します。
- イールド、ジェネレーターはまだJSで特別な構文を持っているので、「var my_generator = function」を書きたいときは、どのPython関数がジェネレーターであるかを知る必要があります。
そのため、翻訳の各フェーズで各ノードに1回アクセスすることはありません。
全体的なプロセスは次のように説明できます。
Python source code -> Python ast -> Python source code compatible with Veloce mode -> Python ast -> JavaScript source code
PythonビルトインはPythonコード(!)で記述されており、IIRCにはブートストラップタイプに関連するいくつかの制限がありますが、Pythoniumを準拠モードで変換できるすべてのものにアクセスできます。https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/compatible/builtins/? at =masterをご覧ください
pythonium準拠から生成されたJSコードを読むことは理解できますが、ソースマップは非常に役立ちます。
この経験に照らして私があなたに与えることができる貴重なアドバイスは親切な古いオナラです:
- 文献と既存のプロジェクトの両方で、クローズドソースまたは無料で主題を広範囲にレビューします。さまざまな既存のプロジェクトをレビューしたとき、私はそれにもっと多くの時間とモチベーションを与えるべきでした。
- 質問をする!C / Javascriptのセマンティックの不一致によるオーバーヘッドのために、PyPyバックエンドが役に立たないことを事前に知っていた場合。私はおそらく6か月前か3年前にPythoniumのアイデアを持っていたでしょう。
- あなたが何をしたいのかを知って、目標を持ってください。このプロジェクトでは、さまざまな目的がありました。少しJavaScriptを練習し、Pythonについて詳しく学び、ブラウザーで実行されるPythonコードを記述できるようにすることです(詳細は以下を参照)。
- 失敗は経験です
- 小さな一歩は一歩です
- 小さく始める
- 大きな夢
- デモを行う
- 繰り返す
Python Veloceモードのみで、私はとても幸せです!しかし、その過程で、私が本当に探していたのは、私や他の人をJavascriptから解放することであり、さらに重要なことに、快適な方法で作成できることであることに気付きました。これにより、Scheme、DSL、Models、そして最終的にはドメイン固有のモデルにつながりました(http://dsmforum.org/を参照)。
アイラ・バクスターの反応について:
見積もりはまったく役に立ちません。PythonJSとPythoniumの両方で、多かれ少なかれ6か月の自由時間がかかりました。だから私はフルタイムの6ヶ月からもっと期待することができます。私たちは皆、企業の文脈で100工数が何を意味するのか、まったく意味しないのかを知っていると思います...
誰かが何かが難しい、またはより多くの場合不可能であると言うとき、私は「不可能な問題の解決策を見つけるのに時間がかかるだけです」と答えます。
それが不可能であることが証明されていない場合、それは想像の余地を残します:
と
- それが不可能な場合は、解決策となる可能性のある「劣った」問題がある可能性があります。
また
楽観的な考え方だけではありません。私がPython->Javascriptを始めたとき、誰もがそれは不可能だと言っていました。PyPyは不可能です。メタクラスが難しすぎる。など...Scheme->Cペーパー(25年前)にPyPyをもたらす唯一の革命は、自動JIT生成(RPythonインタープリターで記述されたヒントに基づく)だと思います。
物事が「難しい」または「不可能」であると言うほとんどの人は理由を提供しません。C ++は解析が難しいですか?それでも、それらは(無料の)C++パーサーであることを私は知っています。悪は詳細にありますか?そんなこと知ってる。一人では不可能だと言っても役に立たない、「役に立たない」よりもさらに悪いことは落胆し、ある人は他の人を落胆させるつもりです。この質問については、 https://stackoverflow.com/questions/22621164/how-to-automatically-generate-a-parser-code-to-code-translator-from-a-corpusで聞いたことがあります。
あなたにとって完璧なものは何ですか?これが次の目標を定義し、おそらく全体的な目標を達成する方法です。
変換方法よりも、コードの変換(IoC、SOA?など)を容易にするために、コードにどのようなパターンを適用できるかを知りたいと思っています。
少なくとも完璧とは言えない方法で、ある言語から別の言語に翻訳できないパターンは見当たりません。言語から言語への翻訳が可能であるため、最初にこれを目指す方がよいでしょう。http://en.wikipedia.org/wiki/Graph_isomorphism_problemによると、2つのコンピューター言語間の翻訳はツリーまたはDAG同型であると思います。両方ともチューリング完全であることをすでに知っているとしても、それで...
フレームワーク->API->API変換としてより適切に視覚化できるフレームワークは、生成されたコードを改善する方法として、まだ覚えておくべきものかもしれません。例:非常に特殊な構文としてのPrologですが、Pythonで同じグラフを記述することで、Prologのような計算を行うことができます... PrologからPythonへのトランスレーターを実装する場合、PythonではなくCライブラリで統合を実装します。 Pythonistにとって非常に読みやすい「Python構文」を考え出します。結局のところ、構文は私たちが意味を与える「絵画」にすぎません(それが私がスキームを始めた理由です)。悪は言語の詳細にあり、私は構文について話していません。言語getattributeで使用される概念フック(それがなくても生きることができます)が、末尾再帰の最適化などの必要なVM機能を処理するのは難しい場合があります。最初のプログラムが末尾再帰を使用していないかどうかは関係ありません。ターゲット言語に末尾再帰がない場合でも、グリーンレット/イベントループを使用してエミュレートできます。
ターゲット言語とソース言語については、以下を探してください。
- 大きくて具体的なアイデア
- 小さくて一般的な共有アイデア
これから明らかになります:
また、高速コードと低速コードに何が変換されるかを知ることもできるでしょう。
stdlibまたは任意のライブラリの質問もありますが、明確な答えはありません。それはあなたの目標によって異なります。
慣用的なコードまたは読み取り可能な生成されたコードにも解決策があります...
PHPのようなプラットフォームをターゲットにすることは、ブラウザをターゲットにするよりもはるかに簡単です。これは、低速および/またはクリティカルパスのC実装を提供できるためです。
最初のプロジェクトがPythonをPHPに変換していることを考えると、少なくとも私が知っているPHP3サブセットでは、veloce.pyをカスタマイズするのが最善の策です。PHP用にveloce.pyを実装できれば、おそらく準拠モードを実行できるでしょう...また、PHPをPHPのサブセットに変換できれば、php_veloce.pyで生成できます。つまり、PHPをveloce.pyが消費できるPythonのサブセット。これは、PHPをJavascriptに変換できることを意味します。ただ言って...
これらのライブラリもご覧ください。
また、このブログ投稿(およびコメント)に興味があるかもしれません:https ://www.rfk.id.au/blog/entry/pypy-js-poc-jit/