Opiera się to na rozmowie na temat kompilatorów, której słuchałem jakiś czas temu, ale niestety nie pamiętam, kiedy i gdzie.
Utwórz najkrótszy kompilator w dowolnym języku, który może się skompilować. Kieruj reklamy na dowolny rozsądny ISA (68K, x86, MIPS, ARM, SPARC, IBM BAL itp.), Który nie ma instrukcji „kompiluj program” (może to wykluczać niektóre wersje VAX). Odczytaj programy źródłowe stdin
i wydrukuj wygenerowany kod stdout
. Możesz użyć standardowej biblioteki C do operacji we / wy i przetwarzania ciągów (np _printf
.). Nie musisz kompilować całego języka, a tylko dowolny podzbiór zawierający kompilator (tzn. Po prostu wydrukowanie języka asemblera, choć imponujące, nie liczy się jako rozwiązanie).
#!/usr/local/bin/tcc -run
w pierwszym wierszu źródła C i uruchom go bezpośrednio z wiersza poleceń.” To fajnie.Odpowiedzi:
Podzbiór Haskell → C - 18926 znaków
To kompiluje mały podzbiór Haskella do C. Obsługiwane funkcje:
Największymi brakującymi cechami są zmienne zagnieżdżone (co oznacza brak lambda / let / where / case), sprawdzanie typów i klasy typów. Powstałe programy przeciekają pamięć, a samokompilacja zajmuje około 200 megabajtów w moim systemie ( moduł zbierający śmieci Boehm pomaga, ale tylko wtedy, gdy kompilator dobrze optymalizuje rekurencję ogona).
Aby uruchomić, odkomentuj pierwsze trzy linie (nie liczone w wyniku) i skompiluj z GHC. Kompilator pobiera kod podzbioru Haskell na standardowe wejście i generuje kod C na standardowe wyjście.
To długo nie dlatego, że język jest złożony, ale dlatego, że jestem leniwy.
Jest to jednak obecnie najkrótsze rozwiązanieJuż nie. Chyba nie będę się nudzić w ten weekend.źródło
Język niestandardowy → C - (7979)
Ponieważ pytanie nie wyklucza stworzenia własnego języka, pomyślałem, że spróbuję.
Środowisko
Język ma dostęp do dwóch stosów, stosu wywołań i stosu danych. Stos wywołań służy do instrukcji skoków
{
i}
, podczas gdy dane Stos jest używany przez większość innych instrukcji. Stos wywołań jest nieprzejrzysty dla aplikacji.Stos danych może przechowywać trzy różne typy wartości: całkowitą, tekstową i pustą. Liczby całkowite są typu intptr_t, a tekst jest przechowywany jako ciągi w stylu C.
The
^
Instrukcja ma dostęp do tablicy. Tablica to stała tablica o długości 17 pozycji tekstowych. Prawdopodobnie powinieneś zobaczyć źródło schematu indeksowania, ponieważ jest ono trochę dziwne.Język
Kompilator
To jest kompilator. Nie jest golfem i spodziewam się, że można go znacznie ograniczyć. Powinno być możliwe bezpośrednie użycie kodu maszynowego i wyprowadzenie pliku COM dos, ale jeszcze się do tego nie przyzwyczaiłem. Wiem, że to wygląda jak program w C, ale rzeczywista implementacja kompilatora jest na końcu.
Obecnie kompilator generuje wiele informacji o debugowaniu na stderr.
Aby skompilować wygenerowany kod C:
Zestaw znaków jest wymagany, ponieważ kompilator unika znaków specjalnych, dodając 128.
Bootstrap
Aby skompilować pierwszy kompilator, napisałem interpreter języka Python.
Kładąc wszystko razem
Zakładając, że zapisałeś kompilator jako
compiler.cmp
i bootstrap jakobootstrap.py
, oto jak zbudować kompilator, a następnie użyć go do samodzielnej kompilacji:Nie jestem więc zbytnio programistą C, ani projektantem języków, więc wszelkie sugestie dotyczące poprawy tego są mile widziane!
Przykładowe programy
Witaj świecie!
źródło
Rozszerzony Brainfuck v0.9: 618 bajtów (nie licząc niepotrzebnych sygnałów liniowych)
To jest gra w golfa mojej pierwszej wersji EBF z usuniętą obsługą komentarzy i martwym kodem do obsługi usuwania zmiennych.
Zasadniczo jest to BrainFuck ze zmiennymi.
:x
tworzy zmienne x. Kompilator wie, gdzie jesteś, więc$y
utworzy <i>, aby dostać się do tej pozycji. Czasami potrzebujesz asymetrycznych pętli, a następnie musisz powiedzieć kompilatorowi, gdzie jesteś@x
. Jako obecny EBF kompiluje się do Brainfuck.Ta pierwsza wersja miała tylko jedną nazwę zmiennej char, ale użyłem tej wersji do skompilowania następnej wersji i tak dalej, aż do obecnej wersji, która ma imponujący zestaw funkcji. Podczas kompilacji ze źródła github pobiera ręcznie skompilowany plik binarny do bootstrap 6 pośrednich wersji ebf w celu utworzenia bieżącej wersji.
Aby go załadować, możesz użyć tego pierwszego i jedynego pliku binarnego w repozytorium git EBF, który został skompilowany ręcznie po kilku próbach.
Brainfuck ma kilka implementacji sprzętowych, np. to , to i to, aby wspomnieć o kilku. Ale przede wszystkim jest tak łatwe do wdrożenia, że praktycznie można zaimplementować tłumacza w dowolnym systemie. Żartuję, że LISP Zozoteza , napisany w EBF, jest prawdopodobnie najbardziej przenośnym LISPem w historii.
źródło
Szesnastkowy, 550 bajtów
Dotyczy to w szczególności systemów x86_64 z systemem Linux.
W tym języku, kod źródłowy składa się z dwóch bajtów reprezentowane małych cyfr szesnastkowych
[0-9a-f][0-9a-f]
. Te bajty mogą mieć dowolną ilość otaczających białych znaków, ale nic nie może wystąpić między cyframi, które tworzą pojedynczy bajt. Ponadto'!'
jest znakiem komentarza liniowego: jest ignorowany, a także wszystko, co znajduje się między nim a następnym'\n'
znakiem.Jeśli rozumiesz zespół x86, oto o wiele bardziej czytelna wersja kodu źródłowego:
Jeśli wyodrębnisz język asemblera z poniższych komentarzy
! Program Code
, możesz skompilować i uruchomić kompilator Hex. Wejścia i wyjścia używają stdin i stdout.źródło
Hex
nie jest językiem.Podzbiór Javascript -> Java, 504 bajty
źródło
05AB1E , 2 bajty (być może niekonkurujące)
Wypróbuj online!
Kod w pierwszym wierszu wejścia, dane wejściowe w kolejnych wierszach.
źródło
Tarcica , 0 bajtów
Lumber to kompletny ezoteryczny język programowania wymyślony przez niepowiązany ciąg napisany w zaledwie 10 liniach kodu Prolog.
Nie możesz w to uwierzyć? W programach tych usunięto komentarze, dzięki czemu źródło tłumacza jest bardziej zwięzłe.
lumber_corefuncs.pl:
lumber_types.pl
lumber_corefuncs.pl przyjmuje bibliotekę lumber_types; z kolei ta biblioteka definiuje moduł, w którym nic nie ma. Dlatego Lumber nic nie robi na arbitralnych danych wejściowych, co z kolei jest samokompilatorem.
źródło
Zero , 0 bajtów
źródło