#!/usr/bin/python3
import sys
import struct
import traceback
import os
import code
import re

class Interpreter(code.InteractiveConsole):
    def __init__(self, localVars):
        self.cache = []
        self.TRACE_REGEX = re.compile(r"([A-Z][a-z]+Error|[A-Z][a-z]+Exception):?(?:\s+)?(.+)?")
        code.InteractiveConsole.__init__(self, localVars)

    def write(self, data):
        self.cache.append(data)

    def is_exception(self, data):
        return True if 'File "<console>", line ' in data else False

    def guru_meditate(self, traceback):
        match = self.TRACE_REGEX.search(traceback)
        if not match:
            return traceback
        exc_name, exc_args = match.groups()
        out = "%s: %s" % (exc_name, exc_args)
        return out


    def flushbuf(self):
        out = "".join(self.cache).strip()

        if self.is_exception(out):
            # most likely a traceback, only capture exception
            out = self.guru_meditate(out.rsplit("\n", 1)[1])
            raise RuntimeError(out)

        if len(out) > 0:
            for line in out.split('\n'):
                yield line

        self.cache = []

    def run(self, code):
        if not "self" in self.locals.keys():
            self.locals["self"] = self
        self.cache = []
        sys.stdout = sys.stderr = self
        self.push(code)
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__
        return self.flushbuf()

interp = Interpreter({})

while True:
    header = sys.stdin.buffer.read(10)
    assert header[:2] == b"ST"
    length = struct.unpack("L", header[2:])[0]
    data = sys.stdin.buffer.read(length).decode('utf-8')
    try:
        result = '\n'.join(interp.run(data)).encode('utf-8')
    except RuntimeError as e:
        result = str(e).encode('utf-8')
    length = len(result)
    sys.stdout.buffer.write(b"ST"+struct.pack("L", length))
    sys.stdout.buffer.write(result)
    sys.stdout.buffer.flush()
