import shutil
from pyrite import fs
from pyrite.command_line import run_command
from pyrite.errors import UserError
from pyrite.globals import Globals
from os.path import join

class LLVMInterface:
    _clang_path: str

    def __init__(self):
        self._clang_path = self._get_clang_path()

    def _get_clang_path(self) -> str:
        clang_path = shutil.which(Globals.get_compiler_options().clang_command)

        if not clang_path:
            raise UserError(
                "Pyrite requires clang to be installed, but no such installation was found."
            )
        
        return clang_path
    
    def compile_ll(self, source: str, output_path: str) -> None:
        """
        Compile the contents of [source] as LLVM IR code, outputting a binary
        specified by [output_path]. If any errors arise in compilation,
        raise an error.
        """

        ir_path = join(self.get_build_directory(), "build.ll")

        fs.write_file(
            path=ir_path,
            data=source
        )

        result = run_command([self._clang_path, ir_path, "-o", output_path])
        
        if result.stderr:
            fs.write_file(
                path=join(self.get_build_directory(), "llvm_error.txt"),
                data=result.stderr
            )

            raise UserError(
                "An unexpected error occurred during the compilation process. A detailed report has been written to {}".format(
                    self.get_build_directory()
                )
            )


    def get_build_directory(self) -> str:
        """
        Pyrite uses a temporary working "build" directory to store files needed for LLVM/Clang
        """
        cwd = Globals.get_compiler_options().cwd

        return join(cwd, "_build")

[((33, 8, 36, 9), 'pyrite.fs.write_file', 'fs.write_file', (), '', False, 'from pyrite import fs\n'), ((38, 17, 38, 76), 'pyrite.command_line.run_command', 'run_command', ({(38, 29, 38, 75): "[self._clang_path, ir_path, '-o', output_path]"}, {}), "([self._clang_path, ir_path, '-o', output_path])", False, 'from pyrite.command_line import run_command\n'), ((59, 15, 59, 34), 'os.path.join', 'join', ({(59, 20, 59, 23): 'cwd', (59, 25, 59, 33): '"""_build"""'}, {}), "(cwd, '_build')", False, 'from os.path import join\n'), ((18, 18, 20, 13), 'pyrite.errors.UserError', 'UserError', ({(19, 16, 19, 92): '"""Pyrite requires clang to be installed, but no such installation was found."""'}, {}), "(\n    'Pyrite requires clang to be installed, but no such installation was found.'\n    )", False, 'from pyrite.errors import UserError\n'), ((57, 14, 57, 44), 'pyrite.globals.Globals.get_compiler_options', 'Globals.get_compiler_options', ({}, {}), '()', False, 'from pyrite.globals import Globals\n'), ((15, 34, 15, 64), 'pyrite.globals.Globals.get_compiler_options', 'Globals.get_compiler_options', ({}, {}), '()', False, 'from pyrite.globals import Globals\n')]