[compiler-construction] JVM 프로그래밍 언어 만들기

루프, 함수 내부 함수 선언, 재귀 호출 등을 지원하는 동적 형식 프로그래밍 언어를 위해 C (lex & bison 사용)로 컴파일러를 만들었습니다. 또한 컴파일러에서 만든 중간 코드를 실행하는 가상 머신을 만들었습니다.

나는 이제 내 자신의 중간 코드로 컴파일하는 대신 자바 바이트 코드로 컴파일하는 것을 생각하고 있었다.

JVM 언어 생성에 대한 질문은 이미 것을 보았지만 그에 대한 답은 그리 유익하지 않습니다.

그래서 여기 내 질문이 있습니다.

  1. JVM에 대한 언어를 작성하려면 반드시 읽어야합니다. JVM 사양서 하다고 생각합니다. 다른 책을 제안 할 수 있습니까 (물론 Dragon Book 제외)? 저는 일반적으로 컴파일러가 아닌 JVM 언어를 만드는 방법에 대한 책이나 자습서에 주로 관심이 있습니다.
  2. jclasslib , bcel , gnu bytecode 등과 같은 .class 파일을 읽고, 쓰고, 변경할 수있는 많은 Java 라이브러리 가 있습니다. 어떤 것을 제안 하시겠습니까? 또한 동일한 작업을 수행하는 C 라이브러리를 알고 있습니까?
  3. Clojure, Jython 또는 JRuby와 같은 JVM을 대상으로하는 다른 언어를 살펴볼 생각이었습니다. 그러나 이러한 모든 언어는 매우 수준이 높고 복잡합니다. JVM을 대상으로하는 더 간단한 프로그래밍 언어 (알 수 없거나 사용되지 않은 경우 상관 없음)를 찾고 있었으며 컴파일러는 오픈 소스입니다. 어떤 아이디어?



답변

나는 또한 ASM을 추천하고 싶지만 Jasmin을 살펴 보았고 대학 프로젝트에 사용했고 (또는 사용해야했고) 꽤 잘 작동했고, Java와 jasmin을 사용하는 프로그래밍 언어이므로 JVM 코드를 생성합니다. 여기 에 코드를 업로드했는데 흥미로운 부분은 소스 코드 자체 여야합니다. . “bytecode / InsanelyFastByteCodeCreator.java”폴더에서 AST 트리를 재스민 어셈블러의 입력 형식으로 변환하는 코드를 찾을 수 있습니다. 아주 간단합니다.

소스 언어 (Lexer + Parser + Analyzer에 의해 AST로 변환 됨)는 MiniJava라는 Java의 하위 집합입니다. 상속, 생성자, 정적 메서드, 개인 필드 / 메서드와 같은 일부 “복잡한”기능이 없습니다. 이러한 기능 중 구현하기 어려운 것은 없지만 X86 백엔드를 작성하는 또 다른 작업이있었습니다 (따라서 머신 어셈블러를 생성하기 위해). 이러한 기능은 일부 작업을 처리하는 JVM이 없으면 어려워지는 경향이 있습니다.

이상한 클래스 이름이 궁금한 경우 : 대학 프로젝트의 작업은 AST를 SSA 그래프 (입력 코드를 나타내는 그래프)로 변환 한 다음 그래프를 최적화 한 다음 그래프를 자바 바이트 코드로 바꾸는 것이 었습니다 . 이것은 프로젝트 작업의 약 3/4이었고 InsanlyFastByteCodeCreator는 모든 것을 테스트하는 지름길이었습니다.

Jon Meyer와 Troy Downing의 “Java Virtual Machine”책을 살펴보십시오. 이 책은 Jasmin-Assembler를 많이 참조하므로 JVM 내부를 이해하는 데 매우 유용합니다.


답변

지난 학기에 “컴파일러 구성”과정에 참석했습니다. 우리 프로젝트는 정확히 당신이하고 싶은 일이었습니다.

제 언어를 작성하는 데 사용한 언어는 Scala 입니다. JVM에서 실행되지만 Java가 지원하지 않는 많은 고급 기능을 지원합니다 (여전히 순수 Java JVM과 완전히 호환 됨).

Java 바이트 코드를 출력하기 위해 Scala CAFEBABE 라이브러리를 사용했습니다 . 잘 문서화되어 있으며 수행 할 작업을 이해하기 위해 Java 클래스에 깊이 들어갈 필요가 없습니다.

책 이외에도 우리가 과정 중에 수행 한 실습 을 통해 많은 정보를 찾을 수 있다고 생각합니다 .


답변

ASM 은 바이트 코드 생성을위한 솔루션이 될 수 있습니다. 시작하려면 매뉴얼 에서 요소 생성에 대한 주제를 확인하십시오 .


답변

Clojure, Jython 또는 JRuby와 같은 JVM을 대상으로하는 다른 언어를 살펴볼 생각이었습니다. 그러나 이러한 모든 언어는 매우 수준이 높고 복잡합니다.

제안 : Lua Programming Language를 살펴볼 수 있으며 LuaJ 와 같은 JVM 구현이 있습니다 .

기본, 문자열, 테이블, 패키지, 수학, io, os, 디버그 및 코 루틴 패키지, 컴파일러 , luajava 바인딩 및 JSR-233 플러그 형 스크립팅 엔진을 위한 라이브러리를 포함하여 J2ME 및 J2SE 용으로 작성된 가볍고 빠른 Java 중심 Lua
인터프리터 바인딩.

(JNI 접근 방식으로 네이티브 라이브러리를 사용하는 LuaJava와 혼동하지 마십시오.)


답변

지난 주말, 장난감 언어를 JVM으로 이식하는 것과 같은 질문을했습니다.

정보를 검색하는 데 몇 시간 밖에 걸리지 않으므로이 참고 자료를 염두에 두십시오.

  • 언어 구현 패턴 . 나는 개미를 싫어하지만이 책은 아주 좋아 보인다. antlr도 좋아하지 않는다면 “Parsing Techniques. A Practical Guide”를 구문 분석하는 것이 좋습니다.

    구성 파일 판독기, 데이터 판독기, 모델 기반 코드 생성기, 소스-소스 변환기, 소스 분석기 및 인터프리터를 구축하는 방법을 배웁니다. 컴퓨터 과학에 대한 배경 지식이 필요하지 않습니다. ANTLR 제작자 인 Terence Parr는 언어 구현을 가장 일반적인 디자인 패턴으로 분류하여 설명합니다. 패턴 별 패턴을 통해 자신의 컴퓨터 언어를 구현하는 데 필요한 핵심 기술을 배우게됩니다.

    10 장은이 주제를 30 페이지 (고속 IMO)로 다룹니다. 그러나 아마도 당신이 관심을 가질만한 다른 장이 있습니다.

    • 10 바이트 코드 인터프리터 구축
      • 10.1 바이트 코드 해석기 프로그래밍. .
      • 10.2 어셈블리 언어 구문 정의
      • 10.3 바이트 코드 머신 아키텍처. . . . .
      • 10.4 여기에서 이동할 위치. . . . . . . . . .
      • P.26. 바이트 코드 어셈블러. . . . . . . . . . .
      • P.27. 스택 기반 바이트 코드 인터프리터. . .
      • 28 페이지. 레지스터 기반 바이트 코드 인터프리터

      http://pragprog.com/titles/tpdsl/language-implementation-patterns

    • Lua 5.0의 구현 이것은 레지스터 기반 바이트 코드 기계에 대한 훌륭한 문서입니다. 그것을 위해서도 그것을 읽으십시오.

    • 작은 조각의 Lisp. 이 책은 C로 컴파일되는 2 개의 schme 컴파일러를 작성하는 방법을 알려줍니다.이 책에서 많은 교훈을 배울 수 있습니다. 나는이 책의 사본을 소유하고 있으며 흥미로운 사람에게는 정말 좋은 것이 lisp이지만 아마도 당신의 차 한잔은 아닐 것입니다.

      이것은 의미론과 전체 Lisp 계열 언어, 즉 Lisp, Scheme 및 관련 방언의 구현에 대한 포괄적 인 설명입니다. 11 개의 인터프리터와 2 개의 컴파일러를 설명합니다 …

    http://www.amazon.com/Lisp-Small-Pieces-Christian-Queinnec/dp/0521562473

레지스터 기반 VM 인 Dalvik7 VM을 확인합니다. DVM은 Java 컴파일러에 의해 컴파일 된 Java 클래스 파일에서 변환 된 바이트 코드에서 작동합니다.

주제 jvm-languages에 대한 메일 링리스트가 있습니다.

아무 곳에 나 코드를 업로드 할 계획입니까? 제가 살펴보고 싶습니다.


답변

아직 모르는 경우 JVM 어셈블리의 작동 방식을 먼저 배우는 것이 좋습니다.

많은 지침 양식을 가지고 ?name, 어디 ?이며 i명령이 정수 유형에서 작동하는 경우a 는 참조 형식으로 작동하는 경우입니다.

기본적으로 JVM은 레지스터가없는 스택 머신이므로 모든 명령어는 스택에서 직접 데이터와 함께 작동합니다. 를 사용 ?push/?pop하여 로컬 변수 (오프셋으로 참조되는 스택 위치)와 스택 상단 사이에서 데이터를 푸시 / 팝 하고 이동할 수 있습니다 ?store/?load. 다른 중요한 지침은 다음 invoke???과 같습니다.if_??? 입니다.

들어 내 대학의 컴파일러 물론 우리가 사용 재스민을 프로그램을 조립. 이것이 최선의 방법인지는 모르겠지만 적어도 시작하기 쉬운 곳입니다.

다음은 새 버전보다 적은 수의 명령어를 포함 할 수있는 이전 버전의 JVM에 대한 명령어 참조 입니다.


답변

먼저 저는 뒤로 물러나서 Java 바이트 코드 대신 실제 Java를 출력하도록 컴파일러를 수정하고 (컴파일러보다 변환기를 더 많이 생성 함을 의미 함) 편리한 Java 환경 (더 나은 객체 코드를 생성 할 수 있음)으로 Java 출력을 컴파일합니다. 내 컴파일러보다).

동일한 기술 (예 : C #으로 컴파일)을 사용하여 CLI 바이트 코드를 생성하거나 Pascal로 컴파일하여 P 코드 등을 생성 할 수 있습니다.

자신의 VM을 사용하는 대신 Java 코드를 고려하는 이유는 명확하지 않지만 성능을 고려한다면 물론 실제 기계 코드로 컴파일하는 것도 고려해야합니다.