Jak podejść do tworzenia języka programowania JVM?

93

Stworzyłem kompilator w C (używając Lex & Bison) dla dynamicznego języka programowania, który obsługuje pętle, deklaracje funkcji wewnątrz funkcji, wywołania rekurencyjne itp. Stworzyłem również maszynę wirtualną, która uruchamia kod pośredni utworzony przez kompilator.

Myślałem o skompilowaniu go do kodu bajtowego Java zamiast własnego kodu pośredniego.

Widziałem, że pytanie o stworzenie języka JVM zostało już zadane , ale nie uważam odpowiedzi za zbyt pouczającą.

Oto moje pytania:

  1. Myślę, że aby stworzyć język dla JVM, koniecznością jest przeczytanie książki specyfikacji JVM , jakie inne książki możesz zasugerować (oprócz oczywiście Dragon Book)? Najbardziej niepokoją mnie książki lub samouczki dotyczące tworzenia języka JVM, a nie kompilator w ogóle.
  2. Istnieje wiele bibliotek Java do odczytu, zapisu i zmiany .classplików, takich jak jclasslib , bcel , kod bajtowy gnu itp. Którą z nich byś zaproponował? Czy wiesz również o bibliotekach C, które wykonują tę samą pracę?
  3. Zastanawiałem się, czy przyjrzeć się innemu językowi, który jest przeznaczony dla JVM, takim jak Clojure, Jython lub JRuby. Ale wszystkie te języki są na bardzo wysokim poziomie i są skomplikowane (aby stworzyć dla nich kompilator). Szukałem prostszego (nie mam nic przeciwko, jeśli jest nieznany lub nieużywany), który jest przeznaczony dla JVM, a jego kompilator jest open source. Jakieś pomysły?
sprawnych
źródło

Odpowiedzi:

63

Poleciłbym również ASM, ale spójrz na Jasmin , użyłem go (a raczej musiałem go użyć) do projektu uniwersyteckiego i zadziałał całkiem dobrze. Napisałem kombinację lekser-parser-analizator-optymalizator-generator dla języka programowania przy użyciu Javy i Jasmin, więc generował kod JVM. Wrzuciłem kod tutaj ; interesującą częścią powinien być sam kod źródłowy . W folderze bytecode/InsanelyFastByteCodeCreator.javaznajduje się fragment kodu, który przekształca drzewo AST w format wejściowy asemblera Jasmin. Jest to całkiem proste.

Język źródłowy (który został przekształcony na AST przez analizator leksera-parsera) jest podzbiorem języka Java o nazwie MiniJava. Brakuje pewnych „skomplikowanych” funkcji, takich jak dziedziczenie, konstruktory, metody statyczne, pola i metody prywatne. Żadna z tych funkcji nie jest trudna do zaimplementowania, ale było jeszcze jedno zadanie polegające na napisaniu zaplecza x86 (tak, aby wygenerować asembler maszynowy), a te rzeczy stają się trudne, jeśli nie masz maszyny JVM, która obsługuje niektóre z tych rzeczy.

Jeśli zastanawiasz się nad dziwną nazwą klasy: Zadaniem projektu uniwersyteckiego było przekształcenie AST w wykres SSA (reprezentujący kod wejściowy), zoptymalizowanie wykresu, a następnie przekształcenie go w kod bajtowy Java. To około ¾ pracy w ramach projektu i InsanlyFastByteCodeCreatorbył to tylko skrót do przetestowania wszystkiego.

Zajrzyj do książki „Java Virtual Machine” Jona Meyera i Troya Downinga. Ta książka mocno nawiązuje do Jasmin Assembler; jest to bardzo pomocne w zrozumieniu wewnętrznych elementów JVM.

theomega
źródło
Dzięki za odpowiedź, przyjrzę się Jasmin. Byłbym również zadowolony, gdybyś mógł przesłać źródło, abym mógł rzucić okiem. Jeśli chodzi o książkę, którą zasugerowałeś, wydaje się interesująca, ale wyczerpany i dość stary :(.
Książka jest jednak bardzo tania z drugiej ręki. Znalazłem kopię za kilka dolarów.
namin
Spójrz na moją edycję powyżej, jeśli masz jakieś pytania, chętnie pomogę.
theomega
Link do „samego kodu źródłowego” jest uszkodzony. Chociaż myślę, że można się tego spodziewać po 8 latach.
Llew Vallis
@LlewVallis, jeśli zinterpretuję wszystkie informacje poprawnie, kod wydaje się być tutaj: github.com/replimoc/compiler .
U880D
15

W zeszłym semestrze uczestniczyłem w kursie "Budowa kompilatora". Nasz projekt był dokładnie tym, co chcesz zrobić.

Językiem, którego użyłem do napisania mojego języka, była Scala . Działa na JVM, ale obsługuje wiele zaawansowanych funkcji, których Java nie ma (nadal jest w pełni kompatybilna z czystą Java JVM).

Do wyprowadzenia kodu bajtowego javy użyłem biblioteki Scala CAFEBABE . Dobrze udokumentowane i nie musisz zagłębiać się w klasy Java, aby zrozumieć, co robić.

Oprócz książki myślę, że możesz znaleźć wiele informacji, przeglądając laboratoria , które wykonaliśmy podczas kursu.

Kami
źródło
To brzmi jak świetny kurs. Czy możesz podzielić się swoimi notatkami lub kodem?
Pedro,
1
Nie ma problemu, sprawdzę, gdzie są moje kopie zapasowe i opublikuję tutaj link, abyś mógł je jak najszybciej pobrać.
Kami
1
Schludnie, szukałem praktycznego kursu kompilatora, który jest skierowany do JVM i zawiera cały materiał online do samodzielnej nauki.
namin
5

ASM może być rozwiązaniem do generowania kodu bajtowego. Na początek przejrzyj tematy dotyczące generowania elementów z instrukcji .

h3xStream
źródło
4

Myślałem, żeby rzucić okiem na inny język, który jest przeznaczony dla JVM, taki jak Clojure, Jython lub JRuby. Ale wszystkie te języki są na bardzo wysokim poziomie i są skomplikowane (aby stworzyć dla nich kompilator).

Sugestia: Możesz rzucić okiem na język programowania Lua , istnieją jego implementacje JVM, takie jak LuaJ .

Lekki , szybki, oparty na Javie interpreter Lua napisany dla J2ME i J2SE, z bibliotekami dla pakietów podstawowych, łańcuchowych, tabelowych, pakietowych, matematycznych, io, os, debugowania i coroutine, kompilatorem , powiązaniami luajava i podłączanym silnikiem skryptów JSR-233 wiązania.

(Nie mylić z LuaJava, który używa natywnych bibliotek z podejściem JNI).

bakkal
źródło
Dziękuję Ci. Przyjrzę się
4

W zeszły weekend zadawałem sobie to samo pytanie, aby przenieść język zabawek na JVM.

Spędzam tylko kilka godzin na szukaniu informacji, więc traktuj te odniesienia z przymrużeniem oka.

  • Wzorce implementacji języka . Nienawidzę antlr, ale ta książka wygląda bardzo dobrze. Jeśli nie lubisz antlr, jest bardzo dobre analizowanie „Techniki analizy. Praktyczny przewodnik”.

    Dowiedz się, jak tworzyć czytniki plików konfiguracyjnych, czytniki danych, generatory kodu oparte na modelach, translatory ze źródła do źródła, analizatory źródła i interpretery. Nie potrzebujesz doświadczenia w informatyce - twórca ANTLR Terence Parr demistyfikuje implementację języka, dzieląc ją na najbardziej powszechne wzorce projektowe. Wzór po wzorze, nauczysz się kluczowych umiejętności potrzebnych do wdrożenia własnych języków komputerowych.

    Rozdział 10 obejmuje 30 stron (do szybkiej IMO) tego tematu. Ale jest inny rozdział, który prawdopodobnie Cię zainteresuje.

    • 10 Interpretatorów kodu bajtowego budynku
      • 10.1 Programowanie interpreterów kodu bajtowego. .
      • 10.2 Definiowanie składni języka asemblera
      • 10.3 Architektura maszyny kodu bajtowego. . . . .
      • 10.4 Dokąd się udać z tego miejsca. . . . . . . . . .
      • P.26. Asembler kodu bajtowego. . . . . . . . . . .
      • P.27. Interpreter kodu bajtowego oparty na stosie. . .
      • P.28. Interpreter kodu bajtowego oparty na rejestrze
      http://pragprog.com/titles/tpdsl/language-implementation-patterns
    • Implementacja Lua 5.0 To świetny artykuł o maszynach z kodem bajtowym opartym na rejestrach. Idź i przeczytaj to nawet ze względu na to.

    • Lisp w małych kawałkach. Ta książka uczy, jak napisać 2 podręczniki szkolne, które można skompilować do C. Z tej książki można się wiele nauczyć. Posiadam egzemplarz tej książki i jest naprawdę dobra dla każdego, kto interesuje się seplenieniem, ale może nie twoja filiżanka herbaty.

      To jest wyczerpujące omówienie semantyki i implementacji całej rodziny języków Lisp, a mianowicie Lisp, Scheme i pokrewnych dialektów. Opisuje 11 tłumaczy i 2 kompilatory ...

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

Sprawdź maszynę wirtualną Dalvik7, maszynę wirtualną opartą na rejestrze. DVM działa na kodach bajtowych, które są przekształcane z plików klas Java skompilowanych przez kompilator języka Java.

Istnieje lista dyskusyjna na ten temat, jvm-languages.

Czy planujesz załadować kod w dowolne miejsce? Chciałbym rzucić okiem.

Pedro
źródło
Are you planning to upload the code to anyplace?Nie jestem dumny z tego kodu :( ... może przepisałbym całość. W każdym razie, jeśli to zrobię, dam Ci znać. Dziękuję bardzo za sugestie.
2

Poleciłbym najpierw dowiedzieć się, jak działa asembler JVM, jeśli jeszcze tego nie wiesz.

Wiele instrukcji ma postać ?name, gdzie ?jest, ijeśli instrukcja działa z typem całkowitym i ajeśli działa z typem referencyjnym.

Zasadniczo JVM jest maszyną stosową bez rejestrów, więc wszystkie instrukcje działają z danymi bezpośrednio na stosie. Możesz wypychać / przesuwać dane za pomocą ?push/?popi przenosić dane między zmiennymi lokalnymi (lokalizacjami stosu, do których odnoszą się przesunięcia), a szczytem stosu za pomocą ?store/?load. Inne ważne instrukcje to invoke???i if_???.

Podczas kursu kompilatora na moim uniwersytecie użyliśmy Jasmin do złożenia programów. Nie wiem, czy to najlepszy sposób, ale przynajmniej jest to łatwe miejsce do rozpoczęcia.

Oto lista instrukcji dla starej wersji maszyny JVM, która może zawierać mniej instrukcji niż nowa.

Jørgen Fogh
źródło
0

Najpierw wycofałem się, zmodyfikowałem kompilator tak, aby wyświetlał rzeczywistą Javę zamiast kodów bajtowych Javy (co oznacza tworzenie więcej translatora niż kompilatora) i kompilowałem dane wyjściowe Java z dowolnym wygodnym środowiskiem Java (które prawdopodobnie wygenerowałoby lepszy kod obiektowy niż mój własny kompilator).

Możesz użyć tej samej techniki (np. Skompilować do C #), aby wygenerować kody bajtowe CLI lub skompilować do Pascala, aby wygenerować kod P itp.

Nie jest jasne, dlaczego rozważasz użycie kodów Java zamiast używania własnej maszyny wirtualnej, ale jeśli chodzi o wydajność, oczywiście powinieneś również rozważyć kompilację do rzeczywistego kodu maszynowego.

joe snyder
źródło
Kompilowanie dla JVM pozwoli na szersze uruchomienie kodu niż w przypadku kompilacji do kodu natywnego. Co więcej, kompilacja do kodu bajtowego umożliwi kodowi wykonanie pewnych rzeczy, które nie są możliwe w samym języku Java.
supercat
0

Oczywiście kiedyś można było użyć Javy do napisania nowego języka. Dzięki API Refleksji w Javie możesz uzyskać plik llot. Jeśli prędkość nie ma większego znaczenia, preferowałbym Javę zamiast ASM. Programowanie w Javie (IMHO) jest łatwiejsze i mniej podatne na błędy . Spójrz na 7. język RPN . Jest w całości napisany w Javie.

Kaplan
źródło