diff --git a/666.py b/666.py index f18f08a..a681148 100755 --- a/666.py +++ b/666.py @@ -1,34 +1,27 @@ +import argparse import malbolge -import sys - -istruzioni = [ - "Utilizzo:", - "666 [-f] input", - " * -f: specifica un file.", - " * input: file o codice da eseguire." -] -def utilizzo(): - print(*istruzioni, sep="\n") - exit(1) +def main(): + parser = argparse.ArgumentParser(description="Malbolge interpeter") + parser.add_argument("-f", "--file", + action="store_true", help="specify a file") + parser.add_argument("input", type=str, + help="malbolge program (string or file)") + args = parser.parse_args() -try: - programma = sys.argv[1] -except IndexError: - utilizzo() + if args.file: + try: + program = open(args.input).read() + except FileNotFoundError: + parser.error("File not Found.") + if program == "": + parser.error("File is empty.") + else: + program = args.input -if sys.argv[1] == "-f": - try: - programma = open(sys.argv[2]).read() - except FileNotFoundError: - exit("File non trovato.") - except IndexError: - utilizzo() - if programma == "": - exit("File vuoto.") -else: - programma = sys.argv[1] + machine = malbolge.Machine() + machine.run(program) -macchina = malbolge.Macchina() -macchina.esegui(programma) +if __name__ == "__main__": + main() diff --git a/License.txt b/License.txt deleted file mode 100644 index ac19f84..0000000 --- a/License.txt +++ /dev/null @@ -1,10 +0,0 @@ - * 666 - * - * Macchina virtuale per codice Malbolge. - * - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - * @author Michele Guerini Rocco aka Rnhmjoj - * @since 2013 \ No newline at end of file diff --git a/README.md b/README.md index 55a99f2..9dfb208 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,14 @@ -666 -=== +# 666 -Macchina virtuale per codice Malbolge -------------------------------------- +## Malbolge virtual machine written in python -### Informazioni -Una macchina virtuale per eseguire codice Malbolge in Python. +### Info +A virtual machine to run Malbolge code in python. -### Istruzioni -Lanciare 666.py per le istruzioni. \ No newline at end of file +### Help +Launch `666 -h` for help. + +### License +Dual licensed under the MIT and GPL licenses: +http://www.opensource.org/licenses/mit-license.php +http://www.gnu.org/licenses/gpl.html diff --git a/malbolge/__init__.py b/malbolge/__init__.py index c1668a9..ff2ad7b 100644 --- a/malbolge/__init__.py +++ b/malbolge/__init__.py @@ -1,2 +1,2 @@ -from .trinario import * -from .macchina import * +from .trinary import * +from .machine import * diff --git a/malbolge/macchina.py b/malbolge/macchina.py deleted file mode 100644 index 60ca6f1..0000000 --- a/malbolge/macchina.py +++ /dev/null @@ -1,154 +0,0 @@ -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 diff --git a/malbolge/trinario.py b/malbolge/trinario.py deleted file mode 100644 index 5bf5a55..0000000 --- a/malbolge/trinario.py +++ /dev/null @@ -1,217 +0,0 @@ -class Trinario: - """Word trinaria""" - - def __init__(self, valore, converti): - #Converte da base n a base 3 se necessario - if converti: - valore = self.__converti(valore) - self.valore = valore - - #Controllo lunghezza massima - if self.lunghezza > 10: - raise OverflowError( - "Limite di trit per word superato: massimo 10 (passati %d)" % self.lunghezza - ) - - def __converti(self, decimale): - """Restituisce il valore decimale passato in trinario.""" - trinario = [] - if decimale == 0: - return [0] - while decimale > 0: - trinario += decimale % 3, - decimale //= 3 - return trinario[::-1] - - #Vari override degli operatori - - def __iter__(self): - lista = [int(i) for i in self.valore] - return iter(lista) - - def __str__(self): - return self.valore - - def __repr__(self): - return self.valore - - def __setattr__(self, nome, valore): - """ - Assegna entrambi i valori (decimale e trinario) quando almeno uno - cambia. - """ - if nome == "valore": - if type(valore) is list: - valore = "".join([str(i) for i in valore]) - self.__dict__["valore"] = valore - elif type(valore) is str: - self.__dict__["valore"] = valore - elif type(valore) is int: - self.__dict__["valore"] = str(valore) - self.__dict__["decimale"] = int(self.valore, base=3) - self.__dict__["lunghezza"] = len(self.valore) - elif nome == "decimale": - if type(valore) is int: - self.__dict__["valore"] = str(self.decimale) - self.__dict__["decimale"] = valore - elif type(valore) is list: - valore = "".join([str(i) for i in valore]) - self.__dict__["valore"] = valore - self.__dict__["decimale"] = int(self.valore, base=3) - self.__dict__["lunghezza"] = len(self.valore) - - def __getitem__(self, indice): - return self.valore[indice] - - #Override degli operatori matematici - - def __add__(self, altro): - try: - return Trinario(self.decimale + altro.decimale, True) - except AttributeError: - return Trinario(self.decimale + altro, True) - - def __iadd__(self, altro): - try: - return self + altro - except AttributeError: - return self.decimale + altro - - def __sub__(self, altro): - try: - return Trinario(self.decimale - altro.decimale, True) - except AttributeError: - return Trinario(self.decimale - altro, True) - - def __isub__(self, altro): - return self - altro - - def __mul__(self, altro): - try: - return Trinario(self.decimale * altro.decimale, True) - except AttributeError: - return Trinario(self.decimale * altro, True) - - def __imul__(self, altro): - return self * altro - - def __mod__(self, altro): - try: - return Trinario(self.decimale % altro.decimale, True) - except AttributeError: - return Trinario(self.decimale % altro, True) - - def __imod__(self, altro): - return self % altro - - def __truediv__(self, floor): - try: - return Trinario(self.decimale / altro.decimale, True) - except AttributeError: - return Trinario(self.decimale / altro, True) - - def __itruediv__(self, altro): - return self / altro - - def __floordiv__(self, altro): - try: - return Trinario(self.decimale // altro.decimale, True) - except AttributeError: - return Trinario(self.decimale // altro, True) - - def __ifloordiv__(self, altro): - return self // altro - - def __lt__(self, altro): - try: - return self.decimale < altro.decimale - except AttributeError: - return self.decimale < altro - - def __le__(self, altro): - try: - return self.decimale <= altro.decimale - except AttributeError: - return self.decimale <= altro - - def __eq__(self, altro): - try: - return self.decimale == altro.decimale - except AttributeError: - return self.decimale == altro - - def __ne__(self, altro): - try: - return self.decimale != self.altro - except AttributeError: - return self.decimale != altro - - def __gt__(self, altro): - try: - return self.decimale > altro.decimale - except AttributeError: - return self.decimale > altro - - def __ge__(self, altro): - try: - return self.decimale >= altro.decimale - except AttributeError: - return self.decimale >= altro - -class Trilista: - """Lista per word trinarie""" - - def __init__(self, lista, converti): - """Inizializzazione della lista trinaria.""" - self.valori ={a:trin(b, converti) for a, b in enumerate(lista)} - - #Vari override degli operatori - - def __setitem__(self, indice, valore): - try: - self.valori[indice.decimale] = valore - except AttributeError: - self.valori[indice] = valore - - def __getitem__(self, indice): - try: - return self.valori[indice.decimale] - except AttributeError: - return self.valori[indice] - except KeyError: - return trin(0) - - def __str__(self): - return self.valori.__str__() - - def __repr__(self): - return self.valori - -#Wrappers - -def trin(valore, converti=False): - """ - Restituisce una word trinaria. Fornire converti=True come parametro se - il valore รจ decimale. - """ - return Trinario(valore, converti) - -def trinord(carattere): - """ - Restituisce l'ordinale di un carattere in una word trinaria. - """ - return trin(ord(carattere), True) - -def trinchr(trinario): - """ - Restituisce il carattere ASCII data una wordtrinaria. - """ - return chr(trinario.decimale % 256) - -def trinlist(lista=[], converti=False): - """ - Restituisce una lista accessibile da indici trinari data una lista. - Fornire converti=False come parametro solo se gli elementi della lista - sono trinari.Non usare liste con basi numeriche miste. - """ - return Trilista(lista, converti)