Napisz tłumacza dla 2B

12

Napisz tłumacza dla 2B

Lubię ezoteryczny język Davida Catt'a 2B, mając pamięć zapisaną na taśmie, gdzie każda komórka jest oddzielną taśmą bajtów („taśma podrzędna”). Napisz do niego tłumacza!

Specyfikacja języka

Oficjalna specyfikacja znajduje się tutaj . W tej specyfikacji "oznacza liczbę z zakresu 0-9( 0jest interpretowana jako 10) i _oznacza ciąg dowolnej długości. Każda komórka przechowuje wartość z zakresu 0-255, a przepełnienie / niedomiar zawija się, tak jak w przypadku BF. (Dzięki @ MartinBüttner). Aby przekonwertować tekst na liczby 0-255, użyj kodów ASCII . Ponieważ nie mogę znaleźć żadnych szczegółów na ten temat, powiem, że długość taśmy powinna być 255minimalna, ale jeśli wiesz inaczej, edytuj.

+-------------+----------------------------------------------------------------------------------------------------------------------------------------+
| Instruction |                                                              Description                                                               |
+-------------+----------------------------------------------------------------------------------------------------------------------------------------+
| 0           | Zeroes the current cell and clears the overflow/underflow flag.                                                                        |
| {           | If the current cell is zero, jump to the matching }.                                                                                   |
| }           | A placeholder for the { instruction.                                                                                                   |
| (           | Read a byte from the input stream and place it in the current cell.                                                                    |
| )           | Write the value of the current cell to the console.                                                                                    |
| x           | Store the value of the current cell in a temporary register.                                                                           |
| o           | Write the value of the temporary register to the console.                                                                              |
| !           | If the last addition overflowed, add one to the current cell. If the last subtraction underflowed, subtract one from the current cell. |
| ?           | Performs a binary NOT on the current cell.                                                                                             |
| +"          | Adds an amount to the current cell.                                                                                                    |
| -"          | Subtracts an amount from the current cell.                                                                                             |
| ^"          | Moves the subtape up a number of times.                                                                                                |
| V"          | Moves the subtape down a number of times.                                                                                              |
| <"          | Moves the tape left a number of times.                                                                                                 |
| >"          | Moves the tape right a number of times.                                                                                                |
| :_:         | Defines a label of name _.                                                                                                             |
| *_*         | Jumps to a label of name _.                                                                                                            |
| ~_~         | Defines a function of name _.                                                                                                          |
| @_@         | Calls a function of name _.                                                                                                            |
| %           | Ends a function definition.                                                                                                            |
| #_#         | Is a comment.                                                                                                                          |
| [SPACE]     | Is an NOP.                                                                                                                             |
| [NEWLINE]   | Is treated as whitespace and removed.                                                                                                  |
| [TAB]       | Is treated as whitespace and removed.                                                                                                  |
+-------------+----------------------------------------------------------------------------------------------------------------------------------------+

Testy

+0+0+0+0+0+0+0+2)+0+0+9)+7))+3)-0-0-0-0-0-0-0-9)+0+0+0+0+0+0+0+0+7)-8)+3)-6)-8)-7-0-0-0-0-0-0)

Powinien wyjść Hello world!


+1:i:{()*i*}

Coś w rodzaju catprogramu, tylko bez nowej linii.


+1:loop:{@ReadChar@*loop*}@PrintHello@@WriteAll@(~ReadChar~(x-0-3<2o^1>1+1>1%~PrintHello~+0+0+0+0+0+0+0+2)-1+0+0+0)+7))+3)+1-0-0-0-0-0-0-0-0)%~WriteAll~<1x:reverse:{<1v1>1-1*reverse*}o-1:print:{-1<1)^1>1*print*}%

Powinieneś najpierw zaakceptować nazwę, a następnie, po naciśnięciu Return, powinien wypisać Hello name(gdzie nazwa jest to, co zostało wprowadzone).

Podziękowania dla tego programu należą się Davidowi Cattowi .


Pracuję nad pełnym programem testowym.

Zasady

  • Standardowe luki są zabronione
  • Twój tłumacz musi spełniać wszystkie specyfikacje, z wyjątkiem komentarzy, które nie są wymagane.

Punktacja

  • To jest , więc wygrywa najmniej bajtów!
  • -10 bajtów, jeśli Twój tłumacz obsługuje komentarze.

Tabela liderów

Oto fragment kodu, który pozwala wygenerować zarówno zwykłą tabelę wyników, jak i przegląd zwycięzców według języka.

Aby upewnić się, że twoja odpowiedź się pojawi, zacznij od nagłówka, korzystając z następującego szablonu Markdown:

# Language Name, N bytes

gdzie Njest rozmiar twojego zgłoszenia. Jeśli poprawić swój wynik, to może zachować stare porachunki w nagłówku, uderzając je przez. Na przykład:

# Ruby, <s>104</s> <s>101</s> 96 bytes

JimBobOH
źródło
4
Świetny pomysł! Oto kilka przemyśleń: Proszę zdefiniować liczbę komórek na podtape i liczbę podtape'ów, których powinniśmy użyć w naszych implementacjach (lub określić, czy powinna to być adaptacja / nieskończoność). Jak konwertować ciąg wejściowy na liczby 0-255? Może kody ASCII?
flawr

Odpowiedzi:

4

Python2, 748 736 731 709 704 691 bajtów

To było zabawne, małe wyzwanie, jestem pewien, że mogę skrócić ten kod (może zrobię to w pewnym momencie później).

from sys import*
w=stdout.write
p=open(argv[1],'r').read()
c,r,s,x,y,t,o=0,0,256,0,0,0,0
g=[[0]*s]*s
e=lambda d:p.find(d,c+1)
def h(i,j=0,k=0):global c,x,y;c+=1;n=1+(int(p[c])-1)%10;l=g[x][y]+n*i;g[x][y]=l%s;o=l/s;x=(x+n*j)%s;y=(y+n*k)%s
a="g[x][y]"
b="[p[c+1:i]]"
l={}
f={}
d={'0':a+"=0",'{':"if "+a+"<1:c=e('}')",'(':"i=stdin.read(1);"+a+"=ord(i)if i else 0",')':"w(chr("+a+"))",'x':"t="+a,'o':"w(chr(t))",'!':a+"+=o",'?':a+"=0if "+a+"else 1",'+':"h(1)",'-':"h(-1)",'^':"h(0,1)",'V':"h(0,-1)",'<':"h(0,0,-1)",'>':"h(0,0,1)",':':"i=e(':');l"+b+"=i;c=i",'*':"i=e('*');c=l"+b,'~':"i=e('~');f"+b+"=i;c=e('%')",'@':"i=e('@');r=i;c=f"+b,'%':"c=r"}
while c<len(p):
    if p[c]in d:exec d[p[c]]
    c+=1

Ta implementacja wymaga deklaracji (implementacji) etykiet i funkcji przed ich wywołaniem. Działa idealnie z dwoma podanymi testami, ale niestety nie działa z programem „SayHi.2b” napisanym przez autora języka (nawet po zmianie kolejności deklaracji funkcji). Myślę, że ten problem może mieć związek ze sposobem, w jaki rozumiałem system taśm i podtap. Czy przesuwając się wzdłuż głównej taśmy, pozycja na odpowiedniej podtapie jest resetowana do 0? W tej chwili utrzymuję pozycję na taśmie podrzędnej, nawet gdy poruszam się po głównej taśmie.

Oto bardziej czytelna wersja:

#!/usr/bin/python

import sys
w=sys.stdout.write
p=open(sys.argv[1],'r').read()
c,r,s,x,y,t,o=0,0,256,0,0,0,0
# c is the current index in the program string
# r is the return index (for functions)
# s is the size of the tape, subtapes and modulo for ints (max int will be 255)
# x and y are the coordinates in the grid
# t is the temporary register
# o is overflow
g=[[0]*s]*s # initialise a grid 256x256 with 0

e=lambda d:p.find(d,c+1)
def n():global c;c+=1;i=int(p[c]);return i if i>0 else 10 # get the number specified
def h(i):j=g[x][y]+i;g[x][y]=j%s;o=j/s # handle addition and substraction
def m(i,j):global x,y;x=(x+i)%s;y=(y+j)%s # move current cell

a="g[x][y]" # string of current cell
b="[p[c+1:i]]" # key for label or function
l={} # dictionary of labels
f={} # dictionary of functions
d={'0':a+"=0",
   '{':"if "+a+"<1:c=e('}')",
   '(':"i=sys.stdin.read(1);"+a+"=ord(i)if i else 0",
   ')':"w(chr("+a+"))",
   'x':"t="+a,
   'o':"w(chr(t))",
   '!':a+"+=o",
   '?':a+"=0if "+a+"else 1",
   '+':"h(n())",
   '-':"h(-n())",
   '^':"m(n(),0)",
   'V':"m(-n(),0)",
   '<':"m(0,-n())",
   '>':"m(0,n())",
   ':':"i=e(':');l"+b+"=i;c=i",
   '*':"i=e('*');c=l"+b,
   '~':"i=e('~');f"+b+"=i;c=e('%')",
   '@':"i=e('@');r=i;c=f"+b,
   '%':"c=r",
   '#':"c=e('#')"
   }

while c<len(p): # loop while c is not EOF
    # print c, p[c]
    if p[c]in d:exec d[p[c]] # execute code kept as a string
    c+=1 # increment index

Edycja: Weź pod uwagę obsługę komentarzy (-10 bajtów), naprawiając jeden błąd. Ta implementacja nie obsługuje zagnieżdżonych wywołań funkcji (mógłbym ją zaimplementować, jeśli jest to wymagana funkcja)

Edycja2: Zmieniono funkcję modułu obsługi, aby dodawała, odejmowała i przemieszczała komórkę. Więcej lambdów! : D („Bardziej czytelna wersja” może być teraz niezsynchronizowana)

Edycja3: Właśnie zdałem sobie sprawę, że obsługa komentarzy kosztuje mnie 5 bajtów (biorąc pod uwagę -10). Więc właśnie go usunąłem, szkoda, że ​​teraz wydaje się niekompletny.

Edycja4: przeniesiono definicję n z lambda do var w module obsługi h ()

basile-henry
źródło
z tak wieloma +a+może lepiej dołączyć a? Pozbędzie się również konieczności przypisania go do var.
Maltysen,
No cóż, z wyjątkiem tego, że nie mogę dołączyć do ciągów w słowniku jako całości i nie warto tego robić dla każdego łańcucha osobno. Przypisanie ciągu do a jest tylko sztuczką, aby uzyskać jakieś bajty, nic tak naprawdę nie jest przydatne dla kodu.
basile-henry,
Chyba nie mogę narzekać na kolejność funkcji, ponieważ tak naprawdę tego nie określiłem, ale spróbuj uruchomić SayHi.2bplik. Co się stanie, jeśli zostanie zmieniony, aby zresetować podtapę do zera podczas zmiany?
JimBobOH