파서 대신 ast.parse를 사용하는 것과 관련하여 @EliBendersky 관점에서 두 번째로 볼 것입니다 (이전에 알지 못했던). 또한 그의 블로그를 검토 할 것을 적극 권장합니다. 저는 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 다중 상속을 구현하는 것은 불가능합니다. 나중에 다른 트릭을 사용하여 시도했습니다 (getattribute 참조). 내가 아는 한 JavaScript에서 Python 다중 상속을 구현하지 않는 한, 존재하는 최고는 단일 상속 + 믹스 인이며 다이아몬드 상속을 처리하는지 확실하지 않습니다. Skulpt와 비슷하지만 Google clojure가 없습니다.
실제로 Skulpt 코드 #fail을 읽는 대신 Skulpt (컴파일러)처럼 Google clojure를 사용해 보았습니다. 어쨌든 JS 프로토 타입 기반 객체 시스템 때문에 여전히 불가능합니다. 바인딩을 만드는 것은 매우 어려웠습니다. JavaScript와 많은 상용구 코드를 작성해야합니다 (참고 : 내가 유령 인 경우 https://github.com/skulpt/skulpt/issues/50 ). 그 당시에는 빌드 시스템에 바인딩을 통합하는 명확한 방법이 없었습니다. Skulpt는 라이브러리이고 html에 .py 파일을 포함하면 실행되며 개발자가 컴파일 단계를 수행 할 필요가 없습니다.
pyjaco (컴파일러)를 시도했지만 바인딩 생성 (Python 코드에서 자바 스크립트 코드 호출)은 매우 어려웠으며 매번 생성하기에는 너무 많은 상용구 코드가있었습니다. 이제 나는 pyjaco가 Pythonium에 더 가깝다고 생각합니다. pyjaco는 Python (ast.parse도 마찬가지)으로 작성되었지만 JavaScript로 작성되었으며 프로토 타입 상속을 사용합니다.
나는 실제로 Pajamas #fail 실행에 성공한 적이 없으며 코드 #fail을 다시 읽지 않았습니다. 그러나 내 마음에 잠옷은 Python에서 JavaScript 로의 번역이 아닌 API-> API 변환 (또는 프레임 워크에서 프레임 워크로)을 수행하고있었습니다. JavaScript 프레임 워크는 이미 페이지에있는 데이터 또는 서버의 데이터를 사용합니다. 파이썬 코드는 단지 "배관"입니다. 그 후 나는 잠옷이 실제로 진짜 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 번역의 경우에 의도 한 바에 따라 최선을 다하도록 미세 조정한다고 말합니다. 이러한 가정은 다른 맥락에서 더 나쁘게 관련되지 않을 수 있으며 오버 헤드를 추론 할 수 있습니다. 그렇지 않으면 직접 번역이 항상 더 좋을 것이라고 말했습니다.
인터프리터를 파이썬으로 작성하는 것은 (아주) 좋은 생각처럼 들렸습니다. 하지만 성능상의 이유로 컴파일러에 더 관심이 많았습니다. 실제로 파이썬을 해석하는 것보다 자바 스크립트로 컴파일하는 것이 더 쉽습니다.
저는 JavaScript로 쉽게 번역 할 수있는 Python의 하위 집합을 모으는 아이디어로 PythonJS를 시작했습니다. 처음에는 과거의 경험으로 인해 OO 시스템을 구현하는 데 신경 쓰지 않았습니다. JavaScript로 번역하기 위해 얻은 Python의 하위 집합은 다음과 같습니다.
- 정의와 호출 모두에서 의미론적인 전체 매개 변수를 가진 함수. 이것이 제가 가장 자랑스럽게 생각하는 부분입니다.
- while / if / elif / else
- Python 유형이 JavaScript 유형으로 변환되었습니다 (어떤 종류의 Python 유형도 없음).
- for Javascript 배열 만 반복 할 수 있음 (in 배열의 경우)
- JavaScript에 대한 투명한 액세스 : Python 코드로 Array를 작성하면 javascript의 Array로 변환됩니다. 이것은 경쟁사보다 유용성 측면에서 가장 큰 성과입니다.
- Python 소스에 정의 된 함수를 javascript 함수로 전달할 수 있습니다. 기본 인수가 고려됩니다.
- new (Python) (1, 2, spam, "egg")는 "new Python (1, 2, spam,"egg ")로 번역됩니다.
- "var"는 번역기에 의해 자동으로 처리됩니다. (Brett (PythonJS 기고자)의 아주 좋은 결과입니다.
- 글로벌 키워드
- 폐쇄
- 람다
- 목록 이해
- import는 requirejs를 통해 지원됩니다.
- 단일 클래스 상속 + classyjs를 통한 믹스 인
이것은 많이 보이지만 실제로 파이썬의 완전한 의미에 비해 매우 좁습니다. 실제로 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 793 SLOC + 약 100 SLOC의 공유 코드를 다른 번역자와 함께 찾을 수 있습니다 .
pystones.py의 개조 된 버전은 Veloce 모드 cf. https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pystone/?at=master
기본 Python-> JavaScript 번역을 설정 한 후 전체 Python을 JavaScript로 번역하는 다른 경로를 선택했습니다. 대상 언어를 제외한 객체 지향 클래스 기반 코드를 수행하는 glib 방법은 JS이므로 배열, 맵과 같은 객체 및 기타 많은 트릭에 액세스 할 수 있으며 해당 부분은 모두 Python으로 작성되었습니다. IIRC에는 Pythonium 번역기로 작성된 자바 스크립트 코드가 없습니다. 단일 상속을 얻는 것은 어렵지 않습니다. 여기에 Pythonium이 Python과 완전히 호환되는 어려운 부분이 있습니다.
spam.egg
파이썬에서는 항상 getattribute(spam, "egg")
이것을 특별히 프로파일 링하지는 않았지만 많은 시간을 잃어버린 곳에서 asm.js 또는 다른 것으로 향상시킬 수 있는지 확신하지 못합니다.
- 메서드 해결 순서 : Python으로 작성된 알고리즘을 사용하더라도 Python Veloce 호환 코드로 번역하는 것은 큰 노력이었습니다.
- getattributre : 실제 getattribute 해결 알고리즘은 다소 까다 롭고 여전히 데이터 설명자를 지원하지 않습니다.
- 메타 클래스 클래스 기반 : 코드를 연결할 위치를 알고 있지만 여전히 ...
- 마지막으로, some_callable (...)은 항상 "call (some_callable)"로 변환됩니다. AFAIK 번역자는 추론을 전혀 사용하지 않으므로 호출을 할 때마다 어떤 종류의 객체를 호출 할 것인지 확인해야합니다.
이 부분은 https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/compliant/runtime.py?at=master 에서 고려됩니다 . Python Veloce와 호환되는 Python으로 작성되었습니다.
실제 호환 번역기 https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/compliant/compliant.py?at=master 는 JavaScript 코드를 직접 생성하지 않으며 가장 중요한 것은 ast-> ast 변환을 수행하지 않습니다. . 나는 ast-> ast 일을 시도했고 cst보다 좋더라도 ast.NodeTransformer와 함께 작업하는 것이 좋지 않더라도 ast-> ast를 할 필요가 없습니다.
내 경우에는 python ast를 python ast로 수행하는 것이 적어도 성능 향상이 될 수 있습니다. 예를 들어 관련 코드를 생성하기 전에 언젠가 블록의 내용을 검사하기 때문입니다.
- var / global : 무언가를 var로 만들 수 있으려면 var가 아닌 내가 무엇을해야하는지 알아야합니다. 주어진 블록에 생성 된 변수를 추적하는 블록을 생성하고 생성 된 펑션 블록 위에 삽입하는 대신, 실제로 하위 노드를 방문하여 관련 코드를 생성하기 전에 블록에 들어갈 때 눈에 띄는 변수 할당을 찾습니다.
- yield, generators는 아직 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 아이디어를 가지고 있었을 것입니다.
- 무엇을하고 싶은지 알고 목표를 정하십시오. 이 프로젝트에서 저는 다른 목표를 가지고있었습니다. 자바 스크립트를 조금 연습하고, Python에 대해 더 배우고, 브라우저에서 실행되는 Python 코드를 작성할 수 있다는 것입니다.
- 실패는 경험이다
- 작은 발걸음은 발걸음
- 작게 시작하다
- 큰 꿈
- 데모를하다
- 반복하다
Python Veloce 모드 만 사용하면 매우 기쁩니다! 그러나 그 과정에서 내가 정말로 찾고 있던 것이 자바 스크립트로부터 나와 다른 사람들을 해방시키는 것이었지만 더 중요한 것은 편안한 방식으로 만들 수 있다는 것을 발견했습니다 . 이것은 나를 Scheme, DSL, Models 그리고 결국 도메인 특정 모델 (참조 : http://dsmforum.org/ )로 이끌었습니다 .
Ira Baxter의 답변 :
추정치는 전혀 도움이되지 않습니다. PythonJS와 Pythonium 모두에 대해 6 개월 정도의 자유 시간을 가졌습니다. 그래서 나는 풀 타임 6 개월에서 더 많은 것을 기대할 수 있습니다. 저는 우리 모두가 기업 맥락에서 100 인년이 의미하는 것이 무엇인지 전혀 알고 있다고 생각합니다.
누군가가 어렵거나 더 자주 불가능하다고 말하면 "불가능한 문제에 대한 해결책을 찾는 데 시간이 걸린다"고 대답하고 그렇지 않으면 불가능하다는 것이 증명 된 경우를 제외하고는 불가능한 것이 없다고 대답합니다.
불가능하다고 증명되지 않았다면 상상의 여지가 남습니다.
과
- 불가능하다면 해결책을 가질 수있는 "열등한"문제가있을 수 있습니다.
또는
단지 낙관적 인 생각이 아닙니다. 내가 Python-> Javascript를 시작했을 때 모두가 불가능하다고 말했습니다. PyPy는 불가능합니다. 메타 클래스가 너무 어렵습니다. 등 ... 저는 Scheme-> C 논문 (25 년 된)보다 PyPy를 가져 오는 유일한 혁명은 자동 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 에 따르면 두 컴퓨터 언어 간의 번역은 트리 또는 DAG 동형 이라고 생각 합니다. 둘 다 튜링이 완료되었다는 것을 이미 알고 있더라도 ...
API-> API 번역으로 더 잘 시각화하는 프레임 워크-> 프레임 워크는 생성 된 코드를 개선하기위한 방법으로 여전히 염두에 두어야 할 것입니다. 예 : Prolog는 매우 구체적인 구문이지만 여전히 Python에서 동일한 그래프를 설명하여 계산과 같은 Prolog를 수행 할 수 있습니다. Prolog를 Python 변환기로 구현하려면 Python에서 통합을 구현하지 않고 C 라이브러리에서 올 수 있습니다. Pythonist가 매우 읽기 쉬운 "Python 구문"을 사용합니다. 결국 구문은 의미를 부여하는 "그림"일뿐입니다 (그래서 제가 계획을 시작한 이유입니다). 악은 언어의 세부 사항에 있으며 구문에 대해 말하는 것이 아닙니다. 언어에서 사용되는 개념getattribute후크 (이 없이도 살 수 있음)이지만 꼬리 재귀 최적화와 같은 필수 VM 기능은 처리하기 어려울 수 있습니다. 초기 프로그램이 꼬리 재귀를 사용하지 않는지 상관하지 않으며 대상 언어에 꼬리 재귀가 없더라도 greenlets / event 루프를 사용하여 에뮬레이트 할 수 있습니다.
대상 및 소스 언어의 경우 다음을 찾으십시오.
- 크고 구체적인 아이디어
- 작고 일반적인 공유 아이디어
이것으로부터 나타날 것입니다 :
또한 빠르고 느린 코드로 변환되는 내용을 알 수있을 것입니다.
stdlib 또는 라이브러리에 대한 질문도 있지만 명확한 대답은 없으며 목표에 따라 다릅니다.
관용적 코드 또는 읽을 수있는 생성 코드에도 솔루션이 있습니다.
느린 경로 및 / 또는 중요한 경로의 C 구현을 제공 할 수 있으므로 PHP와 같은 플랫폼을 대상으로하는 것이 브라우저를 대상으로하는 것보다 훨씬 쉽습니다.
첫 번째 프로젝트가 Python을 PHP로 번역하고 있다는 점을 감안할 때 적어도 내가 아는 PHP3 하위 집합의 경우 veloce.py를 사용자 정의하는 것이 가장 좋습니다. PHP 용 veloce.py를 구현할 수 있다면 호환 모드를 실행할 수있을 것입니다. 또한 PHP를 PHP의 하위 집합으로 변환 할 수 있다면 php_veloce.py로 생성 할 수 있습니다. veloce.py가 사용할 수있는 Python의 하위 집합입니다. 즉, PHP를 Javascript로 번역 할 수 있습니다. 그냥 ...
해당 라이브러리를 살펴볼 수도 있습니다.
또한이 블로그 게시물 (및 의견)에 관심이있을 수 있습니다. https://www.rfk.id.au/blog/entry/pypy-js-poc-jit/