from .trinario import * class Macchina: def esegui(self, programma): """Esegue il programma Malbolge fornito come stringa.""" #Accumulatore self.a = trin(0) #Registri self.d = trinlist() self.c = trinlist() #Puntatori self.puntatore_c = trin(0) self.puntatore_d = trin(0) istruzioni = { "j": self.__scambia_d, "i": self.__scambia_c, "*": self.__ruota, "p": self.__pazza, "<": self.__leggi, "/": self.__stampa, "v": self.__esci, "o": self.__nulla, } #Controllo lunghezza massima if len(programma) > 3 ** 10: raise MemoryError("Memoria esaurita. Limite di 3^10 word superato.") #Copia il programma nel registro c for indice, word in enumerate(programma): if word not in ("\n", " "): if trinord(word) not in range(32, 127): raise SyntaxError("Carattere non consentito nel programma:\ '%c' a %d." % (word, indice) ) else: self.c[indice] = trinord(word) #Esecuzione del programma while self.puntatore_c < len(programma): #Calcola ed esegue l'istruzione istruzione = self.__calcola_istruzione(trinchr(self.c[self.puntatore_c])) try: istruzioni[istruzione]() except KeyError: istruzioni["o"]() #Operazioni per ogni istruzione self.c[self.puntatore_c] -= 33 self.__traduci() self.puntatore_c += 1 self.puntatore_d += 1 def __calcola_istruzione(self, carattere): """ Calcola l'istruzione da eseguire in base al carattere presente nel puntatore. """ tabella = "+b(29e*j1VMEKLyC})8&m#~W>qxdRp0wkr \ Uo[D7,XTcA\"lI.v%{gJh4G\-=O@5`_3i< \ ?Z';FNQuY]szf$!BS/|t:Pn6^Ha" istruzione = (trinord(carattere) - 33 + self.puntatore_c) % 94 return tabella[istruzione.decimale] def __traduci(self): """ Trascive l'istruzione nel registro del codice seguendo la tavola di conversione. """ trascrizione = str.maketrans( '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN \ OPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~', '5z]&gqtyfr$(we4{WP)H-Zn,[%\\3dL+Q;>U!pJS72FhOA1 \ CB6v^=I_0/8|jsb9m<.TVac`uY*MK\'X~xDl}REokN:#?G"i@' ) istruzione = str.translate(trinchr(self.c[self.puntatore_c]), trascrizione) self.c[self.puntatore_c] = trinord(istruzione) #Istruzioni def __scambia_d(self): """ Istruzione Malbolge "j" Assegna al data pointer il valore a cui punta. """ self.puntatore_d = self.d[self.puntatore_d] def __scambia_c(self): """ Istruzione Malbolge "i" Assegna al code pointer il valore puntato dal data pointer. """ self.puntatore_c = self.d[self.puntatore_d] def __ruota(self): """ Istruzione Malbolge "*" Ruota la word puntata dal data pointer di un trit verso destra. """ self.d[self.puntatore_d] = trin(self.a[-1] + self.a[0:-1]) def __pazza(self): """ Istruzione Malbolge "p" Esegue l'operazione pazza con il valore nell'accumulatore e il valore puntato dal data pointer. Poi salva il risultato nell'accumulatore e nel registro dei dati. """ operazione = [[1, 0, 0], [1, 0, 2], [2, 2, 1]] risultato = [] for i, j in zip(self.a, self.d[self.puntatore_d]): risultato += operazione[i][j], self.d[self.puntatore_d] = trin(risultato) self.a = trin(risultato) def __leggi(self): """ Istruzione Malbolge "<" Legge un carattere dallo stdin e lo registra nell'accumulatore. """ carattere = input() if len(carattere) > 1: raise TypeError("Si attendeva un carattere: letta una stringa.") elif len(carattere) == 0: raise TypeError("Si attendeva un carattere: letta una stringa nulla.") else: self.a = trinord(carattere) def __stampa(self): """ Istruzione Malbolge "/" Stampa il carattere presente nell'accumulatore. """ print(trinchr(self.a), end="") def __esci(self): """ Istruzione Malbolge "v" Termina l'esecuzione del programma. """ exit() def __nulla(self): """ Istruzione Malbolge "o" Esegue l'operazione nulla. """ pass