import re
import subprocess

# Testsuite configuration setup for GHC
#
# This file is Python source
#
config.compiler              = 'ghc'
config.compiler_always_flags = ghc_compiler_always_flags.split()

config.haddock               = 'haddock'
config.hp2ps                 = 'hp2ps'
config.hpc                   = 'hpc'
config.gs                    = 'gs'
config.confdir               = '.'

# By default, the 'normal' and 'hpc' ways are enabled. In addition, certain
# ways are enabled automatically if this GHC supports them. Ways that fall in
# this group are 'optasm', 'optllvm', 'profasm', 'threaded1', 'threaded2',
# 'profthreaded', 'ghci', and whichever of 'static/dyn' is not this GHC's
# default mode. Other ways should be set explicitly from .T files.
config.compile_ways       = ['normal', 'hpc']
config.run_ways           = ['normal', 'hpc']

# ways that are not enabled by default, but can always be invoked explicitly
config.other_ways         = ['prof', 'normal_h',
                             'prof_hc_hb','prof_hb',
                             'prof_hd','prof_hy','prof_hr',
                             'threaded1_ls', 'threaded2_hT',
                             'llvm', 'debugllvm',
                             'profllvm', 'profoptllvm', 'profthreadedllvm',
                             'debug',
                             'ghci-ext']

if (ghc_with_native_codegen == 1):
    config.compile_ways.append('optasm')
    config.run_ways.append('optasm')

config.compiler_debugged = ghc_debugged

if (ghc_with_vanilla == 1):
    config.have_vanilla = True

if (ghc_with_dynamic == 1):
    config.have_dynamic = True

if (ghc_with_profiling == 1):
    config.have_profiling = True
    config.compile_ways.append('profasm')
    config.run_ways.append('profasm')

if (ghc_with_interpreter == 1):
    config.have_interp = True
    config.run_ways.append('ghci')

config.unregisterised = (ghc_unregisterised == 1)

if (ghc_with_threaded_rts == 1):
    config.run_ways.append('threaded1')
    if (ghc_with_smp == 1):
        config.have_smp = True
        config.run_ways.append('threaded2')

if (ghc_with_dynamic_rts == 1):
    config.have_shared_libs = True

config.ghc_dynamic_by_default = ghc_dynamic_by_default
if ghc_dynamic_by_default and ghc_with_vanilla == 1:
    config.run_ways.append('static')
else:
    if (ghc_with_dynamic_rts == 1):
        config.run_ways.append('dyn')

config.ghc_dynamic = ghc_dynamic

if (ghc_with_profiling == 1 and ghc_with_threaded_rts == 1):
    config.run_ways.append('profthreaded')

if (ghc_with_llvm == 1):
    config.compile_ways.append('optllvm')
    config.run_ways.append('optllvm')

config.in_tree_compiler = in_tree_compiler
config.clean_only       = clean_only

config.way_flags = lambda name : {
    'normal'       : [],
    'normal_h'     : [],
    'g1'           : [],
    'optasm'       : ['-O', '-fasm'],
    'llvm'         : ['-fllvm'],
    'optllvm'      : ['-O', '-fllvm'],
    'debugllvm'    : ['-fllvm', '-keep-llvm-files'],
    'prof'         : ['-prof', '-static', '-auto-all', '-fasm'],
    'profasm'      : ['-O', '-prof', '-static', '-auto-all'],
    'profthreaded' : ['-O', '-prof', '-static', '-auto-all', '-threaded'],
    'ghci'         : ['--interactive', '-v0', '-ignore-dot-ghci', '+RTS', '-I0.1', '-RTS'],
    'threaded1'    : ['-threaded', '-debug'],
    'threaded1_ls' : ['-threaded', '-debug'],
    'threaded2'    : ['-O', '-threaded', '-eventlog'],
    'threaded2_hT' : ['-O', '-threaded'],
    'hpc'          : ['-O', '-fhpc', '-hpcdir', '.hpc.' + name ],
    'prof_hc_hb'   : ['-O', '-prof', '-static', '-auto-all'],
    'prof_hb'      : ['-O', '-prof', '-static', '-auto-all'],
    'prof_hd'      : ['-O', '-prof', '-static', '-auto-all'],
    'prof_hy'      : ['-O', '-prof', '-static', '-auto-all'],
    'prof_hr'      : ['-O', '-prof', '-static', '-auto-all'],
    'dyn'          : ['-O', '-dynamic'],
    'static'       : ['-O', '-static'],
    'debug'        : ['-O', '-g', '-dannot-lint'],
    # llvm variants...
    'profllvm'         : ['-prof', '-static', '-auto-all', '-fllvm'],
    'profoptllvm'      : ['-O', '-prof', '-static', '-auto-all', '-fllvm'],
    'profthreadedllvm' : ['-O', '-prof', '-static', '-auto-all', '-threaded', '-fllvm'],
    'ghci-ext'         : ['--interactive', '-v0', '-ignore-dot-ghci', '-fexternal-interpreter', '+RTS', '-I0.1', '-RTS'],
   }

config.way_rts_flags = {
    'normal'       : [],
    'normal_h'     : ['-h'], # works without -prof
    'g1'           : ['-G1'],
    'optasm'       : [],
    'llvm'         : [],
    'optllvm'      : [],
    'debugllvm'    : [],
    'prof'         : ['-p'],
    'profasm'      : ['-hc', '-p'], # test heap profiling too
    'profthreaded' : ['-p'],
    'ghci'         : [],
    'threaded1'    : [],
    'threaded1_ls' : ['-ls'],
    'threaded2'    : ['-N2 -ls'],
    'threaded2_hT' : ['-N2', '-hT'],
    'hpc'          : [],
    'prof_hc_hb'   : ['-hc -hbvoid'],
    'prof_hb'      : ['-hb'],
    'prof_hd'      : ['-hd'],
    'prof_hy'      : ['-hy'],
    'prof_hr'      : ['-hr'],
    'dyn'          : [],
    'static'       : [],
    'debug'        : [],
    # llvm variants...
    'profllvm'         : ['-p'],
    'profoptllvm'      : ['-hc', '-p'],
    'profthreadedllvm' : ['-p'],
    'ghci-ext'         : [],
   }

# Useful classes of ways that can be used with only_ways() and
# expect_broken_for().

prof_ways     = [x[0] for x in config.way_flags('dummy_name').items()
                      if '-prof' in x[1]]

threaded_ways = [x[0] for x in config.way_flags('dummy_name').items()
                      if '-threaded' in x[1] or 'ghci' == x[0]]

opt_ways      = [x[0] for x in config.way_flags('dummy_name').items()
                      if '-O' in x[1]]

llvm_ways     = [x[0] for x in config.way_flags('dummy_name').items()
                      if '-fflvm' in x[1]]

def get_compiler_info():
    s = getStdout([config.compiler, '--info']).decode('utf8')
    s = re.sub('[\r\n]', '', s)
    compilerInfoDict = dict(eval(s))
    s = getStdout([config.compiler, '+RTS', '--info']).decode('utf8')
    s = re.sub('[\r\n]', '', s)
    rtsInfoDict = dict(eval(s))

    config.libdir = compilerInfoDict['LibDir']

    v = compilerInfoDict["Project version"].split('-')
    config.compiler_version = v[0]
    config.compiler_maj_version = re.sub('^([0-9]+\.[0-9]+).*',r'\1', v[0])
    config.compiler_tags = v[1:]

    # -fno-ghci-history was added in 7.3
    if version_ge(config.compiler_version, '7.3'):
       config.compiler_always_flags = \
          config.compiler_always_flags + ['-fno-ghci-history']

    if re.match(".*_p(_.*|$)", rtsInfoDict["RTS way"]):
        config.compiler_profiled = True
    else:
        config.compiler_profiled = False

    try:
        config.package_conf_cache_file = compilerInfoDict["Global Package DB"] + '/package.cache'
    except:
        config.package_conf_cache_file = ''

    try:
        if compilerInfoDict["GHC Dynamic"] == "YES":
            ghcDynamic = True
        elif compilerInfoDict["GHC Dynamic"] == "NO":
            ghcDynamic = False
        else:
            raise 'Bad value for "GHC Dynamic"'
    except KeyError:
        # GHC < 7.7 doesn't have a "GHC Dynamic" field
        ghcDynamic = False

    if ghcDynamic:
        config.ghc_th_way_flags = "-dynamic"
        config.ghci_way_flags   = "-dynamic"
        config.ghc_th_way       = "dyn"
        config.ghc_plugin_way   = "dyn"
    elif config.compiler_profiled:
        config.ghc_th_way_flags = "-prof"
        config.ghci_way_flags   = "-prof"
        config.ghc_th_way       = "prof"
        config.ghc_plugin_way   = "prof"
    else:
        config.ghc_th_way_flags = "-static"
        config.ghci_way_flags   = "-static"
        config.ghc_th_way       = "normal"
        config.ghc_plugin_way   = "normal"
