Na podstawie komentarza George'a Edisona do tego pytania napisz najmniejszego tłumacza.
- Możesz użyć wybranego przez siebie języka.
- Puste języki się nie liczą. Twój program musi mieć co najmniej dwa znaki.
- Program nie musi interpretować całego języka, a jedynie kompletny zestaw funkcji językowych Turinga (zawierający tłumacza).
- Quines się nie liczy.
- Nie używaj wbudowanej
eval
funkcji języka lub jej odpowiednika. To samo dotyczyapply
itp.
code-golf
interpreter
Hoa Long Tam
źródło
źródło
/usr/bin/cat
) co z kompletnością Turinga?sexp
analizator składni.Odpowiedzi:
CI - 260
320 → 260: Wciśnij proste odwzorowania znaków na instrukcje, a następnie złóż je. Zmniejsza to o połowę rozmiar kodu na skrzynkę (jest 18 skrzynek), ale składanie kosztuje 30 znaków.
To kolejny z moich skonstruowanych języków (bazowy tłumacz hostowany na Gist ). Jest wyjątkowy, ponieważ język realizuje fragmenty kodu. Oznacza to, że ciągi instrukcji w tym języku opartym na stosie są używane z takim samym skutkiem, jak struktury danych lub zamknięcia w innych językach:
Interpreter buduje fragment kodu całego programu przed jego uruchomieniem, więc można go również uznać za kompilator. Z tego powodu układanie interpretera w stos nie powoduje wykładniczego obciążenia w czasie wykonywania.
Tłumacz tłumaczy wszystkich swoich operatorów bezpośrednio od tłumacza hosta. Jednak sam analizuje, więc większość kodu to tylko sekwencje, które tłumaczą znaki na odpowiadające im literały kodu. Nie jest to to samo, co używanie
eval
, ale pokazuje, jak zależna jest implementacja dowolnego języka programowania od semantyki języka / architektury hosta.Odniesienie językowe:
Uzyskaj tłumacza tutaj
Bloki
(
...)
Utwórz „blok”, który jest faktycznie listą instrukcji bez kontekstu. Wewnętrznie może to być nawet kod maszynowy.
blok
$
Zadzwoń na blok. Odbiorca otrzymuje globalny stos, który zawiera wywoływany blok.
wartość
^
Podnieś wartość. Mianowicie, zamień go w blok, który wypycha tę wartość.
Przykład :
blok1 blok2
&
Połącz dwa bloki, tworząc jeden, który będzie działał oba kolejno.
Przykład :
Manipulacja stosami
n
c
Skopiuj n-tą wartość stosu.
Przykład :
n
p
Podnieś n-tą wartość stosu (usuń ją i przenieś na przód).
Przykład :
n
d
Upuść n wartości ze stosu.
0d
jest zakazem.Przykład :
Operatorzy relacyjni
ab (on_true) (on_false)
=
Sprawdź, czy a jest równe b. Zużyj wszystkie argumenty oprócz pierwszego i wywołaj komendę on_true lub on_false. Jeśli jeden argument jest równy zero, a drugi jest innego typu, wynik będzie fałszywy. W przeciwnym razie aib muszą być liczbami całkowitymi.
Przykład :
ab (on_true) (on_false)
<
Sprawdź, czy a jest mniejsze niż b. aib muszą być liczbami całkowitymi.
Przykład :
ab (on_true) (on_false)
>
Sprawdź, czy a jest większe niż b. aib muszą być liczbami całkowitymi.
Przykład :
a lo hi (on_true) (on_false)
~
Sprawdź, czy lo <= a <= hi. a, lo i hi muszą być liczbami całkowitymi.
Przykład :
I / O
do
.
Umieść postać c (zużywając ją ze stosu).
,
Zdobądź postać i wepchnij ją na stos. Po osiągnięciu końca pliku wypychane jest -1.
do
!
Unget postaci. Podobnie jak ungetc w C, dozwolona jest tylko jedna odpowiedź zwrotna.
Literały całkowite
'c
Naciśnij znak c.
[0–9] +
Naciśnij liczbę całkowitą dziesiętną.
Arytmetyka
+
-
ab
*
Dodaj / odejmij / pomnóż dwie liczby.
Przykład :
ab
/
ab
%
Podział i moduł. W przeciwieństwie do C, zaokrąglają się w kierunku ujemnej nieskończoności.
Różne
#
komentarz do kodu#
Charakter komentuje się wszystko do końca linii.)
Służy do zakończenia bloków. Można go również użyć do zakończenia całego programu.
Wszystkie pozostałe znaki są ignorowane.
źródło
Binary Lambda Calculus, 232 bity (29 bajtów)
0101000110100000000101011000000000011110000101111110011110000101110011110000001111000010110110111001111100001111100001011110100111010010110011100001101100001011111000011111000011100110111101111100111101110110000110010001101000011010
Szczegółowe informacje można znaleźć na stronie http://en.wikipedia.org/wiki/Binary_lambda_calculus#Lambda_encoding
źródło
Nie mogę przypisać sobie tego , ale pomyślałem, że podzielę się tym niesamowitym:
Brainf *** (423)
źródło
BlockScript - 535
BlockScript to trywialny język oparty na stosach spaghetti , który stworzyłem specjalnie na to wyzwanie. Podstawowym tłumaczem jest blockcript.c .
Przykładowy program (drukuje pierwsze 15 liczb Fibonacciego):
Interpreter odczytuje zarówno kod źródłowy, jak i program z standardowego wejścia, w tej kolejności. Oznacza to, że aby uruchomić tłumacza w tłumaczu, po prostu skopiuj i wklej:
Podobnie jak w filmie Incepcja , nie można zejść głębiej niż trzy poziomy. To nie jest kwestia czasu, ale przestrzeni. BlockScript obficie wycieka pamięć, a to ma związek ze sposobem zaprojektowania samego języka.
Odniesienie językowe:
Uzyskaj tłumacza tutaj
W BlockScript „stos” nie jest tablicą, która jest zastępowana kolejnymi operacjami, do których możesz być przyzwyczajony. W rzeczywistości jest on implementowany jako niezmienna lista połączona, a stos utrzymuje się przez cały czas trwania programu. Ponadto żaden operator (oprócz
@
) nie usuwa wartości ze stosu. Jednak modyfikacje stosu wpływają tylko na blok, w którym występują.Wybór wartości
a
przezz
Weź 0-25 przedmiot ze stosu i pchnij go na stos.
a
odnosi się do głowy lub ostatnio pchanego przedmiotu stosu.A
przezZ
Pobierz 0-25 pozycję bieżącej klatki i pchnij ją na stos.
[
Otwórz „ramkę”, aby wybrać elementy z odnośnika stosu (patrz poniżej) na szczycie stosu.
[
nie wymaga dopasowania]
, ale ramki mają zasięg leksykalny. W BlockScript „zakres” jest określany przez nawiasy klamrowe ({
...}
), które tworzą bloki. Zatem otwarcie ramki wewnątrz bloku nie będzie miało wpływu na kod poza blokiem.]
Zamknij bieżącą ramkę, wracając do poprzedniej ramki (jeśli istnieje).
Bloki
{
...}
Utwórz „blok” i wepchnij go na stos. Wewnątrz bloku stos zacznie się od tego, co było przed blokiem, z wyjątkiem tego, że stos wywołującego zostanie przesunięty na wierzch. Stosy są trwałe i niezmienne w BlockScript, więc bloki są zamknięciami. Ten idiom
{[
oznacza otwórz blok, a następnie otwórz ramkę, aby rozpocząć wybieranie argumentów (zaA
pomocąZ
). Zwracana wartość bloku jest szczytem stosu, gdy}
zostanie osiągnięta.Przykład:
To drukuje
123BCD123DCB123BCD123DCB…
. Małe litery odnoszą się do wartości stosu, podczas gdy duże litery odnoszą się do argumentów (ponieważ ramka jest ustawiona na stos wywołującego).A!
przejmuje głowę dzwoniącego (co z pewnością jest wywoływanym blokiem) i dzwoni do niego. Jeśli zastanawiasz się, dlaczego odwraca się zaBCD
każdym razem, to dlatego, żeB. C. D.
wypycha te argumenty w odwrotnej kolejności tuż przed wywołaniem samego bloku.!
Zadzwoń na blok. Wciśnij wartość zwracaną na stos.
Referencje stosu
&
Utwórz odniesienie do stosu i popchnij je do stosu. Potraktuj to jako „super-przeciw”, ponieważ skutecznie bierze każdy przedmiot ze stosu i tworzy z niego „krotkę”. Idiomu
&[
środki, niezależniea
,b
,c
określone wcześniej mogą być dostępne zA
,B
,C
(w dalszej części bloku, aż]
spotyka).Po części dlatego, że
&
przechwytuje więcej wartości, niż zwykle potrzebuje, BlockScript przecieka pamięć z założenia.@
Przełącz się na stos wskazywany przez odniesienie do stosu
a
. Ten operator jest dość dziwny, ale interpreter BlockScript korzysta z niego kilka razy, aby uniknąć konieczności dwukrotnego przekazywania tych samych argumentów. Efekty@
(lub dowolnej operacji stosu, jeśli o to chodzi) są ograniczone do bloku, w którym są wywoływane. Ramka pozostaje nienaruszona@
, więc można jej użyć do przechwytywania potrzebnych wartości po zmianie stosów.Wyrażenie warunkowe
?
<on true>:
<on false>Wyrażenie warunkowe, podobnie jak operator trójskładnikowy w C. To znaczy, jeśli
a
jest „prawda” (to znaczy, że nie jest równe zeru całkowitemu), to wykonaj <na true> , w przeciwnym razie <na false> .I / O
Uwaga: Wprowadzanie i wysyłanie odbywa się w UTF-8. „Znak” to liczba całkowita odpowiadająca indeksowi Unicode.
,
Zdobądź następny znak wejścia i pchnij go na stos. Po osiągnięciu końca wprowadzania naciśnij zamiast tego -1.
.
Wyprowadź postać na wierzch stosu.
Liczby całkowite / literowe
Uwaga: Liczby całkowite i znaki są takie same w BlockScript.
'c
Naciśnij znak c.
[0–9] +
Naciśnij liczbę całkowitą dziesiętną.
Arytmetyka
Te operatory działają tylko na wartościach całkowitych.
+
Obliczb
+a
(wypychając wynik, ale nie odrzucając żadnej wartości).-
Obliczb
-a
.*
Obliczb
*a
./
Obliczb
/a
(dzielenie liczb całkowitych; zaokrągla w kierunku ujemnej nieskończoności).%
Obliczb
%a
(moduł całkowity; zaokrągla w kierunku ujemnej nieskończoności).Operatorzy relacyjni
Te operatory działają tylko na wartościach całkowitych.
<
Jeślib
jest mniejsze niża
, naciśnij 1, w przeciwnym razie naciśnij 0.>
=
Różne
#
Komentarz do końca linii;
źródło
Zozotez LISP : 414
dodawanie linii w celu uzyskania ładnego bloku nie jest potrzebne i nie jest liczone.
Teoretycznie powinien być w stanie uruchomić się sam, ale ponieważ oryginalny interpreter jest plikiem binarnym BrainFuck, a sam interpreter, mogłem przetestować tylko każdą część. Po otrzymaniu samego i prostego wyrażenia
(p p)
myślę, że potrzebuje więcej czasu niż 40 minut, na które czekałem do tej pory i używam mojego szybkiego,jitbf
aby go uruchomić, który (źle) używa Perla Inline-C do uruchomienia kodu C w locie.Niemożliwe jest zaimplementowanie całego Zozoteza w Zozotezie, ponieważ nie ma on możliwości mutowania wad i
:
(setq / defin) potrzebuje tego do aktualizacji powiązań. Nie wdrożyłem również wyraźnego argumentu start / progn lub & rest, makr i specjalnych argumentów drukowania, ponieważ nie użyłem go w tłumaczu. Uwzględniłemp
(drukuję), mimo że go nie używam, więc programy muszą jawnie wydrukować swoje obliczenia, tak jak oryginalny tłumacz.To samo bez golfa:
źródło
CHIQRSX9 + (prawdopodobnie niekonkurencyjny), 2 bajty
Nie ma sposobu, aby napisać interpretera samo-tłumaczącego w tym języku opartym na HQ9 + bez użycia
I
, który uruchamia wbudowany interpreter przetwarzający STDIN.źródło
eval
, co dotyczy wyrażeń, a nie programów.X
ma sprawić, że język Turinga będzie kompletny (a tym samym będzie w stanie obliczyć liczby pierwsze) w sposób zależny od implementacji.X
polecenie interpretera Perla losowo zaburza program i wykonuje go, co oznacza, że nie można używać poleceń do deterministycznego obliczania liczb pierwszych. Czy możesz podać przykład tłumacza, który pozwala korzystać z niegoX
w sposób określony przez Ciebie?Współbieżny system plików Befunge 98 - 53 \ 18 bajtów (prawie na pewno oszukiwanie)
Pełny 53 bajtowy interpreter bez ograniczeń (chociaż nie testowałem skomplikowanych interakcji czasowych obejmujących dzielenie i zawijanie adresów IP):
Odczytuje dane wejściowe z pliku o nazwie
a
i wykonuje go. Nie jest to określone w regułach, że nie możemy używać kodu modyfikującego.18-bajtowy interpreter, który nie pozwala na owijanie (przesunięcie IP jednej krawędzi kodu i rozpoczęcie od drugiej krawędzi):
źródło