#!/usr/bin/env python
#     Copyright 2013, Kay Hayen, mailto:kay.hayen@gmail.com
#
#     Part of "Nuitka", an optimizing Python compiler that is compatible and
#     integrates with CPython, but also works on its own.
#
#     Licensed under the Apache License, Version 2.0 (the "License");
#     you may not use this file except in compliance with the License.
#     You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#     Unless required by applicable law or agreed to in writing, software
#     distributed under the License is distributed on an "AS IS" BASIS,
#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#     See the License for the specific language governing permissions and
#     limitations under the License.
#

"""

This is the main program of Nuitka, it checks the options and then translates one or more
modules to a C++ source code using Python C/API in a build directory compiles it to either
an executable or an extension module.

"""

import sys, os

# LIBDIR trick start (marker for removal on platforms that don't need it)
libdir = '@LIBDIR@'

# Two cases:
if libdir != '@' 'LIBDIR' '@':
    # Changed by our distutils hook, then use the given path.

    if not os.path.isabs( libdir ):
        libdir = os.path.join( os.path.dirname( os.path.realpath( __file__ ) ), libdir )
        libdir = os.path.abspath( libdir )

    sys.path.insert( 0, libdir )
else:
    # Unchanged, running from checkout, use the parent directory, the nuitka package ought be there.
    sys.path.insert( 0, os.path.join( os.path.dirname( __file__ ), ".." ) )
# LIBDIR trick end (marker for removal on platforms that don't need it)

import logging
logging.basicConfig( format = 'Nuitka:%(levelname)s:%(message)s' )

# We don't care, and these are triggered by run time calculations of "range" and
# others, while on python2.7 they are disabled by default.
import warnings
warnings.simplefilter( "ignore", DeprecationWarning )

from nuitka import Options

intended_version = Options.getIntendedPythonVersion()

# Make sure on the promise to execute with a specific version. When compiled, this may
# not be supported.
if intended_version is not None:
    current_version = "%d.%d" % ( sys.version_info[0], sys.version_info[1] )

    if current_version != intended_version:
        assert intended_version in ( "2.6", "2.7", "3.2", "3.3" )

        if os.name == "nt":
            python_binary = r"C:\Python%s\python.exe" % intended_version.replace( ".", "" )
        else:
            python_binary = "/usr/bin/python" + intended_version

        args = [ python_binary, "python" ] + sys.argv

        # That's the API of execl, pylint: disable=W0142
        os.execl( *args )


from nuitka import MainControl, SyntaxErrors

positional_args = Options.getPositionalArgs()
assert len( positional_args ) > 0

filename = Options.getPositionalArgs()[0]

# Turn that source code into a node tree structure.
try:
    tree = MainControl.createNodeTree(
        filename = filename
    )
except (SyntaxError, IndentationError) as e:
    sys.exit( SyntaxErrors.formatOutput( e ) )

if Options.shallDumpBuiltTree():
    MainControl.dumpTree( tree )
elif Options.shallDumpBuiltTreeXML():
    MainControl.dumpTreeXML( tree )
elif Options.shallDisplayBuiltTree():
    MainControl.displayTree( tree )
else:
    import shutil

    result, options = MainControl.compileTree( tree )

    # Exit if compilation failed.
    if not result:
        sys.exit( 1 )

    # Remove the source directory (now build directory too) if asked to.
    if Options.isRemoveBuildDir():
        shutil.rmtree( MainControl.getSourceDirectoryPath( tree ) )

    # Execute the module immediately if option was given.
    if Options.shallExecuteImmediately():
        if Options.shallMakeModule():
            MainControl.executeModule(
                tree       = tree,
                clean_path = Options.shallClearPythonPathEnvironment()
            )
        else:
            MainControl.executeMain(
                binary_filename = options[ "result_file" ] + ".exe",
                tree            = tree,
                clean_path      = Options.shallClearPythonPathEnvironment()
            )
