Genişlik
Tercüman halen devam etmekte olan bir çalışma (hala kullanılmayan birkaç komut alanım var). Daha fazla dokümantasyon içeren repo burada bulunabilir . .
Dennis bir dakikadan daha kısa bir süre önce TIO'ya Genişlik ekledi: Çevrimiçi Deneyin!
Genişlik, bu soruya ilk olarak attığım fikirlere dayanarak son zamanlarda geliştirdiğim ezoterik bir yığına dayalı dildir . Tamamen, bir mektubun "normal" bir yazı tipinde ne kadar geniş, az ya da çok olmasına dayanır. Her şeyi yapan tek karakterler harfler, büyük ve küçük harflerdir. Diğer tüm karakterler göz ardı edilir. Harfleri Genişlikte mümkün olan 10 farklı eylemi oluşturan 10 farklı genişlik kategorisine ayırırım:
0: i j l # do while counter > 0
1: f r t I # end
2: c k s v x y z J # 0 in commands
3: a b d e g h n o p q u L # separator (no-op)
4: F T Z # push base 10 number, using left side row titles (width numbers); terminated with original char
5: A B E K P S V X Y # 1 in commands
6: w C D H N R U # 2 in commands
7: G O Q # push string literal; sets of 2 width numbers equate to index in printable ASCII; terminated with original char
8: m M # if top of stack
9: W # else
2
, 5
ve 6
çoğu yığınla etkileşime giren komutlara erişim sağlar. Daha fazla bilgi bulabilirsinizinfo.txt
Github deposundaki sayfada bulabilirsiniz.
Bu, tercümanın Python kodudur. Hala ekleyecek birkaç komutum var ve hata işlemeyle nasıl çalışılacağını düşünüyorum, ancak aksi halde tamamlanması gerekiyor. (Aynı zamanda daha soyut bir sözdizimi ile test edilmesine izin vermek için bir noktaya bir bayrak ekleyeceğim, çünkü aksi halde bu dil çalışmak çok büyük bir acıdır)
import sys
import math
import numbers
import functools
try:
file = sys.argv[1]
except IndexError:
file = "source.wide"
with open(file) as f:
source = f.read()
translation = ("ijl", "frtI", "cksvxyzJ", "abdeghnopquL", "FTZ", "ABEKPSVXY", "wCDHNRU", "GOQ", "mM", "W")
chars = "".join(sorted("".join(translation)))
strings = """ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\n\t"""
def trans(letter):
for each in translation:
if letter in each:
return translation.index(each)
COMMAND = "COMMAND"
COMMANDS = (2, 5, 6)
NUMBER = "NUMBER"
STRING = "STRING"
DO = "DO"
IF = "IF"
ELSE = "ELSE"
END = "END"
SEPARATOR = "SEPARATOR"
class Token:
def __init__(self, val, type_):
self.val = val
self.type = type_
class Lexer:
def __init__(self, src):
self.src = src
self.pos = 0
self.char = self.src[self.pos]
def read(self):
if self.char is None:
return None
command = trans(self.char)
if command == 0:
self.advance()
return Token(0, DO)
elif command == 1:
self.advance()
return Token(1, END)
elif command == 3:
self.advance()
return Token(3, SEPARATOR)
elif command == 4:
return self.read_num()
elif command == 7:
return self.read_str()
elif command == 8:
self.advance()
return Token(8, IF)
elif command == 9:
self.advance()
return Token(9, ELSE)
else:
return self.read_cmd()
def advance(self):
self.pos += 1
try:
self.char = self.src[self.pos]
except IndexError:
self.char = None
def read_num(self):
delim = self.char
self.advance()
res = ""
while self.char is not None and self.char != delim:
res += str(trans(self.char))
self.advance()
self.advance()
return Token(int(res), NUMBER)
def read_str(self):
def read_char():
res_ = str(trans(self.char))
self.advance()
res_ += str(trans(self.char))
self.advance()
try:
return strings[int(res_)]
except IndexError:
return " "
delim = self.char
self.advance()
res = ""
while self.char is not None and self.char != delim:
res += read_char()
self.advance()
return Token(res, STRING)
def read_cmd(self):
command = ""
while self.char is not None and trans(self.char) in COMMANDS and len(command) <= 4:
command += str(COMMANDS.index(trans(self.char)))
self.advance()
return Token(command, COMMAND)
source = "".join(filter(lambda c: c in chars, source))
stack = []
backburner = []
counter = 0
def set_counter(val):
global counter
counter = int(val)
if counter < 0:
counter = 0
def set_stack(val):
global stack
stack = val
def num_input():
inp = input()
try:
stack.append(int(inp))
except ValueError:
try:
stack.append(float(inp))
except ValueError:
pass
def flip_ends():
if len(stack) > 1:
stack[0], stack[-1] = stack[-1], stack[0]
def clear_stack():
global stack
stack = []
def reload_stack(is_top):
global backburner, stack
if is_top:
stack.extend(backburner)
else:
stack = backburner + stack
backburner = []
# https://stackoverflow.com/a/15285588/7605753
def is_prime(n):
if n == 2 or n == 3:
return True
if n < 2 or n % 2 == 0:
return False
if n < 9:
return True
if n % 3 == 0:
return False
r = int(math.sqrt(n))
_f = 5
while _f <= r:
if n % _f == 0:
return False
if n % (_f + 2) == 0:
return False
_f += 6
return True
def error():
raise Exception
commands = {
"0": lambda: stack.append(stack[-1]),
"1": lambda: stack.append(stack.pop(-2)),
"2": lambda: stack.pop(),
"00": lambda: set_counter(stack[-1]),
"01": lambda: stack.append(len(stack)),
"02": lambda: stack.append(input()),
"10": num_input,
"11": lambda: stack.append(str(stack.pop())),
"12": lambda: stack.append(int(stack.pop())),
"20": lambda: set_counter(counter + 1),
"21": lambda: set_counter(counter - 1),
"22": lambda: print(stack.pop()),
"000": lambda: stack.append(float(stack.pop())),
"001": lambda: stack.append(-stack.pop()),
"002": lambda: stack.append(not stack.pop()),
"010": lambda: stack.append(stack.pop(-2) + stack.pop()),
"011": lambda: stack.append(stack.pop(-2) - stack.pop()),
"012": lambda: stack.append(stack.pop(-2) / stack.pop()),
"020": lambda: stack.append(stack.pop(-2) // stack.pop()),
"021": lambda: stack.append(stack.pop(-2) * stack.pop()),
"022": lambda: stack.append(stack.pop(-2) % stack.pop()),
"100": lambda: stack.append(math.factorial(stack.pop())),
"101": lambda: stack.append(str(stack.pop(-2)) + str(stack.pop())),
"102": lambda: stack.append(math.pow(stack.pop(-2), stack.pop())),
"110": lambda: stack.append(math.sqrt(stack.pop())),
"111": lambda: stack.append(math.log(stack.pop(-2), stack.pop())),
"112": lambda: stack.append(~stack.pop()),
"120": lambda: stack.append(stack.pop(-2) | stack.pop()),
"121": lambda: stack.append(stack.pop(-2) & stack.pop()),
"122": lambda: stack.append(stack.pop(-2) << stack.pop()),
"200": lambda: stack.append(stack.pop(-2) >> stack.pop()),
"201": lambda: stack.append(stack.pop(-2)[stack.pop()]),
"202": lambda: stack.append(str(stack.pop(-2)) * stack.pop()),
"210": lambda: stack.append(counter),
"211": lambda: set_counter(stack.pop()),
"212": lambda: stack.extend(list(str(stack.pop()))),
"220": flip_ends,
"221": lambda: stack.append(len(stack[-1])),
"222": lambda: print(stack[-1]),
"0000": lambda: stack.reverse(),
"0001": lambda: stack.sort(),
"0002": lambda: stack.append(stack[counter]),
"0010": lambda: stack.append(stack[stack.pop()]),
"0011": 0,
"0012": 0,
"0020": lambda: stack.append(sum(n for n in stack if isinstance(n, numbers.Number))),
"0021": lambda: stack.append(functools.reduce(lambda x, y: x*y, [n for n in stack if isinstance(n, numbers.Number)], 1)),
"0022": 0,
"0100": lambda: (backburner.extend(stack), clear_stack()),
"0101": lambda: reload_stack(True),
"0102": lambda: reload_stack(False),
"0110": lambda: backburner.append(stack.pop()),
"0111": lambda: backburner.append(list(stack.pop())),
"0112": lambda: stack.pop().split(stack.pop()),
"0120": lambda: stack.append(backburner[-1]),
"0121": lambda: (lambda depth=stack.pop(): (set_stack(stack[-depth:]), backburner.append(stack[:depth])))(),
"0122": lambda: (lambda depth=stack.pop(): (set_stack(stack[:-depth]), backburner.append(stack[depth:])))(),
"0200": lambda: set_stack([stack.pop().join(stack)]),
"0201": lambda: set_stack(["".join(stack)]),
"0202": lambda: (lambda depth=stack.pop(-2): set_stack(stack[-depth:] + [stack.pop().join(stack[:depth])]))(),
"0210": lambda: (lambda depth=stack.pop(): set_stack(stack[-depth:] + ["".join(stack[:depth])]))(),
"0211": 0,
"0212": 0,
"0220": lambda: stack.append(stack.pop().split(stack.pop())),
"0221": lambda: stack.append(stack.pop().split(", ")),
"0222": 0,
"1000": lambda: stack.append(is_prime(stack[-1])),
"1001": lambda: stack.append((lambda s=stack.pop(): s == s[::-1])()),
"1002": lambda: stack.append(1 / stack.pop()),
"1010": lambda: stack.append(stack.pop() - 1),
"1011": lambda: stack.append(stack.pop() + 1),
"1012": lambda: stack.append(stack.pop() * 2),
"1020": lambda: stack.append(stack.pop() / 2),
"1021": lambda: stack.append(stack.pop() ** 2),
"1022": lambda: float("." + str(stack.pop())),
"1100": lambda: stack.append(stack.pop() == stack.pop()),
"1101": lambda: stack.append(stack.pop() != stack.pop()),
"1102": lambda: stack.append(stack.pop() > stack.pop()),
"1110": lambda: stack.append(stack.pop() < stack.pop()),
"1111": lambda: stack.append(stack.pop() >= stack.pop()),
"1112": lambda: stack.append(stack.pop() <= stack.pop()),
"1120": lambda: stack.append(stack.pop() in stack),
"1121": lambda: stack.append(stack.pop() in backburner),
"1122": lambda: stack.append(stack.pop() == counter),
"1200": lambda: stack.append(stack.pop() in stack.pop()),
"1201": lambda: stack.append(stack.pop(-2).find(stack.pop())),
"1202": 0,
"1210": 0,
"1211": 0,
"1212": lambda: stack.append(stack.pop().lower()),
"1220": lambda: stack.append(stack.pop().upper()),
"1221": lambda: stack.append(ord(stack.pop())),
"1222": lambda: stack.append(chr(stack.pop())),
"2000": lambda: stack.append(math.floor(stack.pop())),
"2001": lambda: stack.append(math.ceil(stack.pop())),
"2002": lambda: stack.append(round(stack.pop())),
"2010": lambda: stack.append(abs(stack.pop())),
"2011": 0,
"2012": 0,
"2020": lambda: stack.append(len(stack.pop())),
"2021": 0,
"2022": 0,
"2100": lambda: stack.append(min(stack)),
"2101": lambda: stack.append(max(stack)),
"2102": lambda: stack.append(stack.count(stack.pop())),
"2110": lambda: stack.append(sum(stack) / len(stack)),
"2111": 0,
"2112": 0,
"2120": 0,
"2121": 0,
"2122": 0,
"2200": lambda: stack.append(stack.pop(-3).replace(stack.pop(-2), stack.pop())),
"2201": lambda: stack.append(stack.pop(-3).replace(stack.pop(-2), stack.pop(), 1)),
"2202": lambda: stack.append(stack.pop(-2).replace(stack.pop(), "")),
"2210": lambda: stack.append(stack.pop(-2).replace(stack.pop(), "", 1)),
"2211": 0,
"2212": lambda: stack.append(eval(stack.pop())),
"2220": lambda: stack.append(eval(input())),
"2221": lambda: print(stack[-1]),
"2222": lambda: error()
}
def run_cmd(name):
global stack, counter, backburner
state = {
"stack": list(stack),
"counter": counter,
"backburner": list(backburner)
}
# TODO: unknown command
try:
commands[name]()
except IndexError:
stack = state["stack"]
counter = state["counter"]
backburner = state["backburner"]
class AST:
pass
class Main(AST):
def __init__(self):
self.nodes = []
class Do(AST):
def __init__(self, node):
self.node = node
class If(AST):
def __init__(self, first, second):
self.first = first
self.second = second
class Literal(AST):
def __init__(self, val):
self.val = val
class Command(AST):
def __init__(self, val):
self.val = val
class Parser:
def __init__(self, lexer):
self.lexer = lexer
self.token = None
def parse(self):
pgm = Main()
self.token = self.lexer.read()
while self.token is not None and self.token.type != END and self.token.type != ELSE:
if self.token.type == DO:
pgm.nodes.append(Do(self.parse()))
elif self.token.type == NUMBER or self.token.type == STRING:
pgm.nodes.append(Literal(self.token.val))
elif self.token.type == IF:
first = self.parse()
if self.token.type == ELSE:
second = self.parse()
else:
second = None
pgm.nodes.append(If(first, second))
elif self.token.type == COMMAND:
pgm.nodes.append(Command(self.token.val))
self.token = self.lexer.read()
return pgm
class Interpreter:
def __init__(self, tree):
self.tree = tree
def visit(self, node):
method_name = "visit_" + type(node).__name__
visitor = getattr(self, method_name.lower())
return visitor(node)
def interpret(self):
self.visit(self.tree)
def visit_main(self, node):
for each in node.nodes:
self.visit(each)
def visit_do(self, node):
while counter:
self.visit(node)
def visit_if(self, node):
if stack[-1]:
self.visit(node.first)
elif node.second:
self.visit(node.second)
def visit_literal(self, node):
stack.append(node.val)
def visit_command(self, node):
run_cmd(node.val)
if source == "":
with open("info.txt") as f:
info = f.read()
print(info)
else:
main = Parser(Lexer(source)).parse()
interpreter = Interpreter(main)
interpreter.interpret()
try:
sys.exit(stack[-1])
except IndexError:
pass