#!/usr/bin/python3.8
import sys
import struct
import traceback
from typing import Any, Dict, List, Iterator, Sequence
import os
import code
import re

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

    def write(self, data: str) -> None:
        self.cache.append(data)

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

    def guru_meditate(self, traceback: str) -> str:
        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) -> Iterator[str]:
        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: str) -> Iterator[str]:
        if not "self" in self.locals.keys():
            self.locals["self"] = self
        self.cache = []
        sys.stdout = sys.stderr = self  # type: ignore
        for line in code.splitlines():
            self.push(line)
        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()
