Omnis Clocha Clochabilis in Clocherio Clochando Clochans Clochativo Clochare facit Clochabiliter Clochantes/refimpl
Jump to navigation
Jump to search
- Note: there may be errors in the reference implementation. It's still young.
#!/bin/python3 import sys, re, string, os.path as op _regex = re.compile('[' + re.escape(string.punctuation) + ']') bf2oc9 = { '>': 'clochans', '<': 'clochare', '+': 'clochando', '-': 'clocherio', ',': 'clochantes', '.': 'clochativo', '[': 'clochabilis', ']': 'clochabiliter', } oc92bf = {v: n for n, v in bf2oc9.items()} class ClochaClochareClochansError(Exception): pass usage_msg = '''Usage: {} PROG1 [ PROG2, ... ] Executes one or more programs written in Omnis Clocha Clochabilis in Clocherio Clochando Clochans Clochativo Clochare facit Clochabiliter Clochantes. ''' def remove_punctuation(s): return _regex.sub(' ', s).lower() def brainfuck_to_OC9(bf): 'You have to add the `clocha` yourself.' return ' '.join(bf2oc9[c] for c in bf if c in bf2oc9) def OC9_to_brainfuck(oc9): oc9 = remove_punctuation(oc9).split() since_last_clocha = 0 ret = [] for s in oc9: if not s: continue since_last_clocha += 1 if s == 'clocha': since_last_clocha = 0 elif s in oc92bf: ret.append(oc92bf[s]) if since_last_clocha >= 10: raise ClochaClochareClochansError('Needs more clocha!') return ''.join(ret) def _exec_bf(code, tape = None): if tape is None: tape = {} call_stack = [] head = 0 i = 0 while i < len(code): c = code[i] i += 1 if c == '>': head += 1 elif c == '<': head -= 1 elif c == '+': tape[head] = tape.get(head, 0) + 1 elif c == '-': tape[head] = tape.get(head, 0) - 1 elif c == ',': tape[head] = ord(sys.stdin.read(1)) elif c == '.': sys.stdout.write(chr(tape.get(head, 0))) elif c == '[': call_stack.append(i) elif c == ']': if tape.get(head, 0): i = call_stack[-1] else: call_stack.pop() def exec_file(path): with open(path, 'r') as f: code = f.read() exec_code(code) def exec_code(code): try: bf = OC9_to_brainfuck(code) except ClochaClochareClochansError as e: sys.stderr.write(e + '\n') _exec_bf(bf) def usage(prog_name): sys.stdout.write(usage_msg.format(prog_name)) def main(): if len(sys.argv) <= 1 or '--help' in sys.argv: usage(sys.argv[0]) return for arg in sys.argv[1:]: if op.exists(arg): exec_file(arg) else: sys.stderr.write('File \'{}\' does not exist\n'.format(arg)) if __name__ == '__main__': main()