-
-
Save harrynull/24a7ab92ae48b318c158539daac5e148 to your computer and use it in GitHub Desktop.
compiler written for hackergame 2021
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
i = 0 | |
j = 0 | |
ret = "" | |
ops = { | |
'read': '~', | |
'output': '.', | |
'pop': '$', | |
'nop': '?', | |
'dup': ':', | |
'not': '!', | |
'mod': '%', | |
} | |
defined = {} | |
markers = {} | |
def cur_cmd(): | |
return defined.get((i, j)) | |
def add_command(cmd, nl): | |
global ret, defined | |
ret += f"({i}, {j}, 0) -> {ord(cmd)} " | |
if (i, j) in defined and defined[(i, j)] != cmd: | |
print(i, j, "redefined!", defined[(i, j)], '->', cmd, "@", nl + 1, file=sys.stderr) | |
defined[(i, j)] = cmd | |
TEST = 1 | |
USE_TEST_PROG = 0 | |
TEST_PROG = """ | |
v* | |
#1 | |
nop* | |
#2 | |
nop* | |
#3 | |
nop | |
@test | |
> | |
nop | |
nop | |
goto 4 test | |
nop | |
nop | |
nop | |
goto 6 test | |
goto 1 test | |
nop | |
@test2 | |
> | |
nop | |
""" | |
with open('prog.txt') as prog: | |
prog_to_parse = prog.readlines() if not USE_TEST_PROG else TEST_PROG.splitlines() | |
for nl, line in enumerate(prog_to_parse): | |
line = line.strip() | |
if len(line) == 0: continue | |
in_place = False | |
if line[-1] == '*' and len(line) > 1: | |
in_place = True | |
line = line[:-1] | |
if line[0] == '!': | |
if line[1] == 'w': j -= 1 | |
if line[1] == 's': j += 1 | |
if line[1] == 'a': i -= 1 | |
if line[1] == 'd': i += 1 | |
continue | |
if line[0] == '#': | |
if line[1:].isdigit(): | |
j = int(line[1:]) | |
continue | |
if line[0] == '@': | |
markers[line[1:]] = (i, j) | |
continue | |
if line[0] == '$': | |
i, j = markers[line[1:]] | |
continue | |
if line == "debug": | |
print(i, j, file=sys.stderr) | |
continue | |
if line == 'wrap up': | |
j -= 1 | |
add_command('>', nl) | |
i += 1 | |
add_command('v', nl) | |
j += 1 | |
add_command('>', nl) | |
i += 1 | |
continue | |
if line == 'wrap down': | |
j += 1 | |
add_command('>', nl) | |
i += 1 | |
add_command('^', nl) | |
j -= 1 | |
add_command('>', nl) | |
i += 1 | |
continue | |
if line.split()[0] == 'nop' and len(line) > 4: | |
for cmd in range(int(line.split()[1])): | |
add_command('?', nl) | |
i += 1 | |
continue | |
if line.split()[0] == 'fetch': | |
tar = line.split()[1] | |
for cmd in ['1', tar, '\\', ':', '2', str(int(tar) + 1), '\\']: | |
add_command(cmd, nl) | |
i += 1 | |
continue | |
if line.split()[0] == 'goto': | |
_, channel, marker_id = line.split() | |
oldi, oldj = i, j | |
channel = int(channel) | |
went_down = j < channel | |
if j != channel: | |
add_command('^' if j > channel else 'v', nl) | |
j += 1 if j < channel else -1 | |
while j != channel: | |
add_command('?', nl) | |
j += 1 if j < channel else -1 | |
add_command('<', nl) | |
i -= 1 | |
while i > markers[marker_id][0]: | |
if (i, j) not in defined: | |
add_command('?', nl) | |
elif defined[(i, j)] != '?' and defined[(i, j)] != '<': | |
print(i, j, "redefined!", defined[(i, j)], '-x> nop', "@", nl + 1, file=sys.stderr) | |
i -= 1 | |
target_j = markers[marker_id][1] | |
add_command('^' if j > target_j else 'v', nl) | |
if j != target_j: | |
j += 1 if j < target_j else -1 | |
while j != target_j: | |
if cur_cmd() != '?' and cur_cmd() != '^' if j > target_j else 'v': | |
add_command('?', nl) | |
j += 1 if j < target_j else -1 | |
i, j = oldi, oldj | |
i += 1 | |
continue | |
if line in ops: | |
line = ops[line] | |
add_command(line, nl) | |
if not in_place: | |
i += 1 | |
ret += " END" | |
print(ret) | |
if TEST: | |
board = [[' ' for _ in range(512)] for _ in range(11)] | |
for c, d in defined.items(): | |
board[c[1]][c[0]] = d | |
for i, line in enumerate(board): | |
print(str(i).zfill(2), ''.join(line), file=sys.stderr) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment