パーサーの代わりに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マーケティングのように見えても、最初から最高のソリューションまで、私が試したすべては実際にはそうではありません(ネチケットに何かが正しくないと思われる場合は、遠慮なく教えてください)。
プロトタイプ継承を使用して、Plain Old JavaScriptでPythonセマンティックを実装する:AFAIK JSプロトタイプオブジェクトシステムを使用してPython多重継承を実装することは不可能です。私は後で他のトリックを使ってそれをやろうとしました(cf. getattribute)。JavaScriptでPythonの多重継承が実装されていないことを知っている限り、存在する最良のものは単一の継承+ミックスインであり、ダイヤモンドの継承を処理するかどうかはわかりません。Skulptに似ていますが、Google clojureがありません。
実際にSkulptコード#failを読み取る代わりに、Sculpt(コンパイラー)と同じように、Googleのclojureを試してみました。とにかく、JSプロトタイプベースのオブジェクトシステムのためにまだ不可能です。バインディングの作成は非常に困難でした。JavaScriptと多くのボイラープレートコードを記述する必要があります(https://github.com/skulpt/skulpt/issues/50私が幽霊である場合を参照)。当時、ビルドシステムにバインディングを統合する明確な方法はありませんでした。Skulptはライブラリであり、.pyファイルをhtmlに含めるだけで実行できると思います。開発者がコンパイルフェーズを実行する必要はありません。
pyjaco(コンパイラ)を試しましたが、バインディングの作成(PythonコードからJavascriptコードを呼び出す)は非常に難しく、毎回作成するボイラープレートコードが多すぎました。今、私はpyjacoがPythoniumに近いものだと思います。pyjacoはPython(ast.parseも)で書かれていますが、多くはJavaScriptで書かれており、プロトタイプ継承を使用しています。
私は実際にパジャマを実行することに#failを成功させることはなく、コード#failを再度読み取ろうとはしませんでした。しかし私の頭の中では、パジャマはPythonからJavaScriptへの変換ではなく、APIからAPIへの変換(またはフレームワークからフレームワークへの変換)を行っていました。JavaScriptフレームワークは、すでにページにあるデータまたはサーバーからのデータを使用します。Pythonコードは「配管」のみです。その後、私はパジャマが実際には本物のpython-> jsトランスレーターであることを発見しました。
それでも、API-> API(またはフレームワーク->フレームワーク)の変換を行うことは可能だと思います。それは、基本的にはPythoniumで行うことですが、より低いレベルで行います。おそらくパジャマはPythoniumと同じアルゴリズムを使用しています...
その後、SkulptのようなJavascriptで完全に記述されたbrythonを発見しました。コンパイルの必要はなく、綿毛もたくさんありますが、JavaScriptで記述されています。
このプロジェクトの過程で書かれた最初の行以来、PyPy、さらにはPyPyのJavaScriptバックエンドについても知っていました。うん、見つけたら、JavaScriptでPyPyから直接Pythonインタープリターを生成できます。人々は、それは災害であったと言います。どこで読めないのか。しかし、その理由は、インタープリターを実装するためにRPythonが使用する中間言語は、C(そしておそらくasm)に翻訳するように調整されたPythonのサブセットであるためだと思います。Ira Baxterは、何かをビルドするときは常に仮定を行い、おそらくそれをPyPy:Python-> C変換の場合に意図されていることで最高になるように微調整すると言います。これらの仮定は、別のコンテキストでは適切ではない可能性があり、オーバーヘッドを推測する可能性があります。
インタープリターをPythonで作成することは、(非常に)良いアイデアのように思えました。しかし、パフォーマンス上の理由からコンパイラに興味がありましたが、実際には、PythonをJavaScriptにコンパイルする方が解釈するよりも簡単です。
私は簡単にJavaScriptに変換できるPythonのサブセットをまとめるという考えでPythonJSを始めました。最初は、過去の経験から、OOシステムを実装することすらしませんでした。JavaScriptに変換するために達成したPythonのサブセットは次のとおりです。
- 定義と呼び出しの両方で完全なパラメータセマンティックを持つ関数。これは私が最も誇りに思っている部分です。
- while / if / elif / else
- Pythonの型がJavaScriptの型に変換されました(いかなる種類のpythonの型もありません)
- for JavaScript配列のみを反復できます(配列内)
- JavaScriptへの透過的なアクセス:Pythonコードで配列を作成すると、JavaScriptで配列に変換されます。これは、競合他社に対するユーザビリティの点で最大の成果です。
- 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のこの部分の直接の子孫は、Pythonium Veloceモードです。完全な実装は、https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/veloce/veloce.py?at = masterにあります。 //bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/veloce/veloce.py at = master 793 SLOC +他のトランスレーターとの共有コードの約100 SLOCで。
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で記述されたアルゴリズムを使用していても、それをPython Veloce互換コードに変換するのは大変な作業でした。
- getattributre:実際のgetattribute解決アルゴリズムは少しトリッキーであり、それでもデータ記述子をサポートしていません
- メタクラスクラスベース:コードをどこに接続するか知っていますが、それでも...
- 最後の注意点:some_callable(...)は常に "call(some_callable)"に変換されます。AFAIKトランスレータは推論をまったく使用しないため、呼び出しを行うたびに、どのような種類のオブジェクトが呼び出されるかを確認する必要があります。
この部分は、https: //bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/compatible/runtime.py ? at = masterで考慮されますと互換性のあるPythonで記述。
実際の準拠トランスレータhttps://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/plied/compliant.py?at=masterは、JavaScriptコードを直接生成せず、最も重要なことに、ast-> ast変換を行いません。私はast-> astを試しましたが、ast.NodeTransformerを使用してもcstよりも優れているとうまく機能しない場合でも、astを実行する必要はありません。さらに重要なのは、ast-> astを実行する必要がないことです。
私の場合、少なくともpython astからpython astを実行すると、関連するコードを生成する前にブロックのコンテンツを検査することがあるため、パフォーマンスが向上する可能性があります。たとえば、次のようになります。
- var / global:何かをvarできるようにするには、varではなく、何をする必要があるかを知っている必要があります。特定のブロックで作成された変数を追跡するブロックを生成し、生成された関数ブロックの上に挿入する代わりに、関連するコードを生成するために子ノードを実際に訪問する前にブロックに入るときに、変数の割り当てを探します。
- 収量、ジェネレーターにはまだJSの特別な構文があるので、「var my_generator = function」を記述したい場合、どのPython関数がジェネレーターであるかを知る必要があります。
そのため、翻訳の各フェーズで各ノードに一度アクセスすることはありません。
全体的なプロセスは次のように説明できます。
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/compliant/builtins/?at=master
pythonium準拠から生成されたJSコードの読み取りは理解できますが、ソースマップは非常に役立ちます。
この経験に照らして私があなたに与えることができる貴重なアドバイスは、親切で古いおならです:
- 文献と既存のプロジェクトの両方で、クローズドソースまたは無料の両方で主題を広範囲にレビューします。既存のさまざまなプロジェクトをレビューしたとき、もっと時間と動機を与えるべきでした。
- 質問をする!C / Javascriptのセマンティックの不一致によるオーバーヘッドのため、PyPyバックエンドが役に立たないことを事前に知っていた場合。私はおそらく6か月前、おそらく3年前にPythoniumのアイデアを持っていたでしょう。
- あなたが何をしたいかを知っている、目標を持っています。このプロジェクトでは、私はさまざまな目的を持っていました。少しJavaScriptを練習し、Pythonの詳細を学び、ブラウザーで実行されるPythonコードを作成できるようにする(詳細は以下を参照)。
- 失敗は経験です
- 小さなステップはステップです
- 小さく始める
- 大きな夢
- デモをする
- 繰り返す
Python Veloceモードのみで、とても嬉しいです!しかし、その過程で、私が本当に探しているのは、私や他の人たちをJavascriptから解放することでしたが、さらに重要なことに、快適な方法で作成することができました。これにより、Scheme、DSL、モデル、そして最終的にはドメイン固有のモデル(http://dsmforum.org/を参照))。
Ira Baxterの対応について:
見積もりはまったく役に立ちません。私は、PythonJSとPythoniumの両方に多かれ少なかれ6か月の自由時間を費やしました。だからフルタイムの6ヶ月からもっと期待できます。私たちは皆、企業のコンテキストで100人年が何を意味し、何を意味しないのかを知っていると思います...
誰かが何かが難しい、またはより頻繁に不可能であると言うとき、私は「不可能である問題の解決策を見つけるのに時間がかかるだけだ」と答えます。
それが不可能であることが証明されていない場合、想像力の余地があります:
そして
- それが不可能な場合は、「劣った」問題があり、解決策がある可能性があります。
または
それは楽観的な考え方だけではありません。私がPython-> Javascriptを始めたとき、誰もがそれは不可能だと言っていました。PyPyは不可能です。メタクラスが難しい。etc ... PyPyをScheme-> C論文(25年前)にもたらした唯一の革命は、自動JIT生成(RPythonインタープリターで書かれたベースのヒントだと思います)だと思います。
物事が「難しい」または「不可能」であると言うほとんどの人は理由を提供しません。C ++は解析が難しいですか?私は知っていますが、それでも(無料の)C ++パーサーです。悪は詳細にありますか?そんなこと知ってる。単独では不可能だと言っても役に立たない、「役に立たなかった」よりもさらに悪いことです。私は/programming/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変換は、生成されたコードを改善する方法として覚えておく必要があるかもしれません。例:プロローグは非常に具体的な構文ですが、Pythonで同じグラフを記述することでプロローグのような計算を行うことができます...プロローグからPythonへのトランスレータを実装する場合、Pythonでは統合を実装せず、Cライブラリで実装します。 Pythonistにとって非常に読みやすい「Python構文」を作成します。結局のところ、構文は私たちが意味を与える "ペイント"にすぎません(そのため、私はスキームを開始しました)。悪は言語の詳細にあり、私は構文について話していません。言語で使用される概念 getattributeでフック(あなたはそれなしで生きることができます)が、末尾再帰最適化のような必要なVM機能は対処するのが難しい場合があります。初期プログラムが末尾再帰を使用していないかどうかは関係ありません。ターゲット言語に末尾再帰がない場合でも、greenlet /イベントループを使用してエミュレートできます。
ターゲット言語とソース言語については、以下を探します。
これから出てきます:
また、何が高速コードと低速コードに変換されるかを知ることもできます。
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/