# Path: Popen_noblock.py
# ON_POSIX = 'posix' in sys.builtin_module_names
# def enqueue_output(out, queue):
#     def __init__(self, *args, **kwargs):
# class Popen_async(object):
# 
# Path: memoize.py
# def memoize(f):
#     """ Memoization decorator for a function taking one or more arguments. """
#     class memodict(dict):
#         def __getitem__(self, *key, **kwkey):
#             return dict.__getitem__(self, (tuple(key), tuple((k, kwkey[k]) for k in sorted(kwkey.keys()))))
# 
#         def __missing__(self, key):
#             args, kwargs = key
#             self[key] = ret = f(*args, **dict(kwargs))
#             return ret
# 
#     return memodict().__getitem__
# 
# Path: file_util.py
# def clean_v_file(file_name):
#     clean_extra_coq_files(file_name, extra_exts=('.v',))
# 
# Path: util.py
# def re_escape(*args, **kwargs):
#     ret = re.escape(*args, **kwargs)
#     for ch in ':"':
#         ret = ret.replace('\\' + ch, ch)
#     return ret
# 
# Path: custom_arguments.py
# LOG_ALWAYS=None
# 
# Path: coq_version.py
# def group_coq_args(args, coqc_help, topname=None, is_coq_makefile=False):
#     bindings, unrecognized_bindings = group_coq_args_split_recognized(args, coqc_help, topname=topname, is_coq_makefile=is_coq_makefile)
#     return bindings + [tuple([v]) for v in unrecognized_bindings]
# 
# def get_coqc_help(coqc_prog, **kwargs):
#     kwargs['log']('Running command: "%s"' % '" "'.join([coqc_prog, "-q", "--help"]), level=2)
#     return get_coqc_help_helper(coqc_prog)


import os, sys, tempfile, subprocess, re, time, math, glob, threading, shutil, traceback
import util
from Popen_noblock import Popen_async, Empty
from memoize import memoize
from file_util import clean_v_file
from util import re_escape
from custom_arguments import LOG_ALWAYS
from coq_version import group_coq_args, get_coqc_help
    Precondition: has_error(output, reg_string)
    """
    errors = get_error_match(output, reg_string=reg_string, pre_reg_string=pre_reg_string)
    return (int(errors.groups()[1]), int(errors.groups()[2]))

@memoize
def get_error_string(output, reg_string=DEFAULT_ERROR_REG_STRING, pre_reg_string=DEFAULT_PRE_ERROR_REG_STRING):
    """Returns the error string of the error matching reg_string.

    Precondition: has_error(output, reg_string)
    """
    errors = get_error_match(output, reg_string=reg_string, pre_reg_string=pre_reg_string)
    return errors.groups()[1]

@memoize
def make_reg_string(output, strict_whitespace=False):
    """Returns a regular expression for matching the particular error
    in output.

    Precondition: has_error(output)
    """
    unstrictify_whitespace = (lambda s: s)
    if not strict_whitespace:
        unstrictify_whitespace = (lambda s: re.sub(r'(?:\\s\\+)+', r'\\s+', re.sub(r'(?:\\ )+', r'\\s+', re.sub(r'(\\n|\n)(?:\\ )+', r'\\s+', s.replace('\\\n', '\n')))).replace('\n', '\s').replace(r'\s+\s', r'\s+').replace(r'\s++', r'\s+'))

    error_string = get_error_string(output).strip()
    if not util.PY3: error_string = error_string.decode('utf-8')
    if 'Anomaly' in error_string and re.search(r'Constant [^\s]+\s+does not appear in the environment', error_string):
        re_string = re.sub(r'(Constant\\ )[^\s]+(\\ )',
                           r'\1[^\\s]+\2',

# Path: Popen_noblock.py
# ON_POSIX = 'posix' in sys.builtin_module_names
# def enqueue_output(out, queue):
#     def __init__(self, *args, **kwargs):
# class Popen_async(object):
# 
# Path: memoize.py
# def memoize(f):
#     """ Memoization decorator for a function taking one or more arguments. """
#     class memodict(dict):
#         def __getitem__(self, *key, **kwkey):
#             return dict.__getitem__(self, (tuple(key), tuple((k, kwkey[k]) for k in sorted(kwkey.keys()))))
# 
#         def __missing__(self, key):
#             args, kwargs = key
#             self[key] = ret = f(*args, **dict(kwargs))
#             return ret
# 
#     return memodict().__getitem__
# 
# Path: file_util.py
# def clean_v_file(file_name):
#     clean_extra_coq_files(file_name, extra_exts=('.v',))
# 
# Path: util.py
# def re_escape(*args, **kwargs):
#     ret = re.escape(*args, **kwargs)
#     for ch in ':"':
#         ret = ret.replace('\\' + ch, ch)
#     return ret
# 
# Path: custom_arguments.py
# LOG_ALWAYS=None
# 
# Path: coq_version.py
# def group_coq_args(args, coqc_help, topname=None, is_coq_makefile=False):
#     bindings, unrecognized_bindings = group_coq_args_split_recognized(args, coqc_help, topname=topname, is_coq_makefile=is_coq_makefile)
#     return bindings + [tuple([v]) for v in unrecognized_bindings]
# 
# def get_coqc_help(coqc_prog, **kwargs):
#     kwargs['log']('Running command: "%s"' % '" "'.join([coqc_prog, "-q", "--help"]), level=2)
#     return get_coqc_help_helper(coqc_prog)


# Path: diagnose_error.py
import os, sys, tempfile, subprocess, re, time, math, glob, threading, shutil, traceback
import util
from Popen_noblock import Popen_async, Empty
from memoize import memoize
from file_util import clean_v_file
from util import re_escape
from custom_arguments import LOG_ALWAYS
from coq_version import group_coq_args, get_coqc_help

    Precondition: has_error(output, reg_string)
    """
    errors = get_error_match(output, reg_string=reg_string, pre_reg_string=pre_reg_string)
    return (int(errors.groups()[1]), int(errors.groups()[2]))

@memoize
def get_error_string(output, reg_string=DEFAULT_ERROR_REG_STRING, pre_reg_string=DEFAULT_PRE_ERROR_REG_STRING):
    """Returns the error string of the error matching reg_string.

    Precondition: has_error(output, reg_string)
    """
    errors = get_error_match(output, reg_string=reg_string, pre_reg_string=pre_reg_string)
    return errors.groups()[1]

@memoize
def make_reg_string(output, strict_whitespace=False):
    """Returns a regular expression for matching the particular error
    in output.

    Precondition: has_error(output)
    """
    unstrictify_whitespace = (lambda s: s)
    if not strict_whitespace:
        unstrictify_whitespace = (lambda s: re.sub(r'(?:\\s\\+)+', r'\\s+', re.sub(r'(?:\\ )+', r'\\s+', re.sub(r'(\\n|\n)(?:\\ )+', r'\\s+', s.replace('\\\n', '\n')))).replace('\n', '\s').replace(r'\s+\s', r'\s+').replace(r'\s++', r'\s+'))

    error_string = get_error_string(output).strip()
    if not util.PY3: error_string = error_string.decode('utf-8')
    if 'Anomaly' in error_string and re.search(r'Constant [^\s]+\s+does not appear in the environment', error_string):
        re_string = re.sub(r'(Constant\\ )[^\s]+(\\ )',
                           r'\1[^\\s]+\2',

                           re_escape(error_string))