From 747de71cac5e6210f676c9b6c6ae7e00673804eb Mon Sep 17 00:00:00 2001 From: Rnhmjoj Date: Mon, 13 Jan 2014 23:54:13 +0100 Subject: [PATCH] English translation --- hello.mb | 2 + malbolge/machine.py | 153 +++++++++++++++++++++++++++++++ malbolge/trinary.py | 216 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 371 insertions(+) create mode 100644 hello.mb create mode 100644 malbolge/machine.py create mode 100644 malbolge/trinary.py diff --git a/hello.mb b/hello.mb new file mode 100644 index 0000000..fdd5ea0 --- /dev/null +++ b/hello.mb @@ -0,0 +1,2 @@ +('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}= diff --git a/malbolge/machine.py b/malbolge/machine.py new file mode 100644 index 0000000..9f831ef --- /dev/null +++ b/malbolge/machine.py @@ -0,0 +1,153 @@ +from .trinary import * + + +class Machine: + + def run(self, program): + """Run Malbolge code passed as a string.""" + + #Accumulator + self.a = trin(0) + + #Registers + self.d = trinlist() + self.c = trinlist() + + #Pointers + self.pointer_c = trin(0) + self.pointer_d = trin(0) + + statements = { + "j": self.__swap_d, + "i": self.__swap_c, + "*": self.__rotate, + "p": self.__crazy, + "<": self.__read, + "/": self.__print, + "v": self.__exit, + "o": self.__nop + } + + #Check max lenght + if len(program) > 3 ** 10: + raise MemoryError("Out of memory. 3^10 words limit exceeded.") + + #Copy the program in register c + for index, word in enumerate(program): + if word not in ("\n", " "): + if trinord(word) not in range(32, 127): + raise SyntaxError("Invalid character:'%c' a %d." + % (word, index)) + else: + self.c[index] = trinord(word) + + #Program execution + while self.pointer_c < len(program): + #Calculate current instruction + statement = self.__calculate_statement(trinchr(self.c[self.pointer_c])) + try: + statements[statement]() + except KeyError: + statements["o"]() + + #Operations for each statement + self.c[self.pointer_c] -= 33 + self.__translate() + self.pointer_c += 1 + self.pointer_d += 1 + + def __calculate_statement(self, character): + """ + Calculates the instruction to be executed + based on the character in the pointer. + """ + table = "+b(29e*j1VMEKLyC})8&m#~W>qxdRp0wkr \ + Uo[D7,XTcA\"lI.v%{gJh4G\-=O@5`_3i< \ + ?Z';FNQuY]szf$!BS/|t:Pn6^Ha" + statement = (trinord(character) - 33 + self.pointer_c) % 94 + return table[statement.decimal] + + def __translate(self): + """ + Write the statement in the code register + following the conversion table. + """ + trans = 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@' + ) + statement = str.translate(trinchr(self.c[self.pointer_c]), trans) + self.c[self.pointer_c] = trinord(statement) + + #Statements + + def __swap_d(self): + """ + Malbolge statement "j" + Assign the data pointer the value it points to. + """ + self.pointer_d = self.d[self.pointer_d] + + def __swap_c(self): + """ + Malbolge statement "i" + Assign to the code pointer the value pointed by the data pointer. + """ + self.pointer_c = self.d[self.pointer_d] + + def __rotate(self): + """ + Malbolge statement "*" + Rotate the word pointed by the pointer by a trit to the right. + """ + self.d[self.pointer_d] = trin(self.a[-1] + self.a[0:-1]) + + def __crazy(self): + """ + Malbolge statement "p" + Performs the operation crazy with the value in the accumulator + and the value pointed by the data pointer. Then stores the result + in the accumulator and log data. + """ + operation = [[1, 0, 0], [1, 0, 2], [2, 2, 1]] + result = [] + for i, j in zip(self.a, self.d[self.pointer_d]): + result += operation[i][j], + self.d[self.pointer_d] = trin(result) + self.a = trin(result) + + def __read(self): + """ + Malbolge statement "<" + Reads a character from stdin and stores it in the accumulator. + """ + character = input() + if len(character) > 1: + raise TypeError("Expected a character: read a string.") + elif len(character) == 0: + raise TypeError("Expected a character: read an empty string.") + else: + self.a = trinord(character) + + def __print(self): + """ + Malbolge statement "/" + Print the character present in the accumulator. + """ + print(trinchr(self.a), end="") + + def __exit(self): + """ + Malbolge statement "v" + Terminate the program. + """ + exit() + + def __nop(self): + """ + Malbolge statement "o" + Performs the nop operation. + """ + pass diff --git a/malbolge/trinary.py b/malbolge/trinary.py new file mode 100644 index 0000000..169ea30 --- /dev/null +++ b/malbolge/trinary.py @@ -0,0 +1,216 @@ +class Trinary: + """Trinary word""" + + def __init__(self, value, convert): + #Convert to base 3 if necessary + if convert: + value = self.__converti(value) + self.value = value + + #Check max lenght + if self.lenght > 10: + raise OverflowError("Trit word limit exceeded: max 10 (passed %d)" + % self.lenght) + + def __converti(self, decimal): + """Return decimal value of the passed trinary.""" + trinary = [] + if decimal == 0: + return [0] + while decimal > 0: + trinary += decimal % 3, + decimal //= 3 + return trinary[::-1] + + #Operators override + + def __iter__(self): + trilist = (int(i) for i in self.value) + return iter(trilist) + + def __str__(self): + return self.value + + def __repr__(self): + return self.value + + def __setattr__(self, name, value): + """ + Assegna entrambi i valori (decimal e trinary) quando almeno uno + cambia. + """ + if name == "value": + if type(value) is list: + value = "".join([str(i) for i in value]) + self.__dict__["value"] = value + elif type(value) is str: + self.__dict__["value"] = value + elif type(value) is int: + self.__dict__["value"] = str(value) + self.__dict__["decimal"] = int(self.value, base=3) + self.__dict__["lenght"] = len(self.value) + elif name == "decimal": + if type(value) is int: + self.__dict__["value"] = str(self.decimal) + self.__dict__["decimal"] = value + elif type(value) is list: + value = "".join([str(i) for i in value]) + self.__dict__["value"] = value + self.__dict__["decimal"] = int(self.value, base=3) + self.__dict__["lenght"] = len(self.value) + + def __getitem__(self, index): + return self.value[index] + + #Math operators override + + def __add__(self, other): + try: + return Trinary(self.decimal + other.decimal, True) + except AttributeError: + return Trinary(self.decimal + other, True) + + def __iadd__(self, other): + try: + return self + other + except AttributeError: + return self.decimal + other + + def __sub__(self, other): + try: + return Trinary(self.decimal - other.decimal, True) + except AttributeError: + return Trinary(self.decimal - other, True) + + def __isub__(self, other): + return self - other + + def __mul__(self, other): + try: + return Trinary(self.decimal * other.decimal, True) + except AttributeError: + return Trinary(self.decimal * other, True) + + def __imul__(self, other): + return self * other + + def __mod__(self, other): + try: + return Trinary(self.decimal % other.decimal, True) + except AttributeError: + return Trinary(self.decimal % other, True) + + def __imod__(self, other): + return self % other + + def __truediv__(self, floor): + try: + return Trinary(self.decimal / other.decimal, True) + except AttributeError: + return Trinary(self.decimal / other, True) + + def __itruediv__(self, other): + return self / other + + def __floordiv__(self, other): + try: + return Trinary(self.decimal // other.decimal, True) + except AttributeError: + return Trinary(self.decimal // other, True) + + def __ifloordiv__(self, other): + return self // other + + def __lt__(self, other): + try: + return self.decimal < other.decimal + except AttributeError: + return self.decimal < other + + def __le__(self, other): + try: + return self.decimal <= other.decimal + except AttributeError: + return self.decimal <= other + + def __eq__(self, other): + try: + return self.decimal == other.decimal + except AttributeError: + return self.decimal == other + + def __ne__(self, other): + try: + return self.decimal != self.other + except AttributeError: + return self.decimal != other + + def __gt__(self, other): + try: + return self.decimal > other.decimal + except AttributeError: + return self.decimal > other + + def __ge__(self, other): + try: + return self.decimal >= other.decimal + except AttributeError: + return self.decimal >= other + +class Trilist: + """Trinary word list""" + + def __init__(self, trilist, convert): + """Trinary list inizialization.""" + self.valori ={a:trin(b, convert) for a, b in enumerate(trilist)} + + #Operators override + + def __setitem__(self, index, value): + try: + self.valori[index.decimal] = value + except AttributeError: + self.valori[index] = value + + def __getitem__(self, index): + try: + return self.valori[index.decimal] + except AttributeError: + return self.valori[index] + except KeyError: + return trin(0) + + def __str__(self): + return self.valori.__str__() + + def __repr__(self): + return self.valori + +#Wrappers + +def trin(value, convert=False): + """ + Returns a trinary word. Provide convert=True as a parameter if + the value is decimal. + """ + return Trinary(value, convert) + +def trinord(carattere): + """ + Returns the ordinal value of a character in a trinary word. + """ + return trin(ord(carattere), True) + +def trinchr(trinary): + """ + Returns the ASCII character given a trinary word. + """ + return chr(trinary.decimal % 256) + +def trinlist(trilist=[], convert=False): + """ + Returns a trilist accessible by trinary indices given a list word. + Provide convert=False as a parameter only if the elements of trilist + are trinary. Do not use lists with mixed basis. + """ + return Trilist(trilist, convert)