' Gambas module file

Export
Class __Jit

Property Read Time As Float
Property Debug As Boolean

Public _Time As Float

Private $bDebug As Integer
Private $sDir As String
Private $bWarning As Boolean

Public Sub _exit()

  Dim sFile As String
  
  If IsDir($sDir) Then
    For Each sFile In Dir($sDir)
      Try Kill $sDir &/ sFile
    Next
    Try Rmdir $sDir
  Endif
  Try Rmdir File.Dir($sDir)
  $sDir = ""
  
End

Private Sub GetArchiveName(sArch As String) As String
  
  If Not sArch Then Return "gb"
  Return Replace(sArch, "/", ".")
  
End

Public Sub _Search() As Boolean
  
  Try CCompilation.Init()
  If Error Then Return True
  
End

Public Sub _Compile(sArch As String) As Boolean

  Dim sFile As String
  Dim sName As String
  Dim sPath As String
  Dim hFile As File
  Dim fTime As Float
  Dim hComp As CCompilation
  Dim sDir As String
  Dim sPathPtr As String
  Dim hFilePtr As File
  Dim bTrace As Boolean
  Dim bCache As Boolean = True
  
  fTime = Timer
  
  Try $bDebug = CInt(Env["GB_JIT_DEBUG"])
  Try bTrace = CInt(Env["GB_JIT_TRACE"])
  Try bCache = CInt(Env["GB_JIT_CACHE"])
  
  If $bDebug Then Error "gb.jit: translating "; If(sArch, "'" & sArch & "'", "project"); "..."
  
  sName = GetArchiveName(sArch)
  
  $sDir = Env["XDG_RUNTIME_DIR"]
  If Not $sDir Then
    $sDir = Application.TempDir
    If $bDebug And If Not $bWarning Then
      $bWarning = True
      Error "gb.jit: warning: XDG_RUNTIME_DIR is not set, use '"; $sDir; "' instead."
    Endif
  Else
    $sDir &/= "gambas"
    Try Mkdir $sDir
    $sDir &/= Application.Id
    Try Mkdir $sDir
  Endif
  
  $sDir &/= "jit"
  Try Mkdir $sDir
  
  ' sPath = $sDir &/ "jit.h"
  ' 
  ' If Not Exist(sPath) Then
  '   
  '   If $bDebug Then Error "gb.jit: generating header"
  '   
  '   hFile = Open sPath For Output Create
  '   
  '   Print #hFile, "#define NO_CONFIG_H"
  '   
  '   Print #hFile, File.Load("gambas.h")
  '   Print #hFile, File.Load("gb_overflow.h")
  '   Print #hFile, File.Load("jit.h")
  '   Print #hFile, File.Load("gb.jit.h")
  '   
  '   Print #hFile, "GB_INTERFACE * GB_PTR;"
  '   Print #hFile, "#define GB (*GB_PTR)"
  '   Print #hFile, "JIT_INTERFACE * JIT_PTR;"
  '   Print #hFile, "#define JIT (*JIT_PTR)"
  ' 
  '   Print #hFile, File.Load("gb_error_common.h")
  '   
  '   Print #hFile, File.Load("jit_after.h")
  '   
  '   Close #hFile
  '   
  '   If $bDebug Then
  '     Try Kill "/tmp/jit.h"
  '     Copy $sDir &/ "jit.h" To "/tmp/jit.h"
  '   Endif
  '   
  '   ' 'Shell $sCompiler & " -fPIC " & Shell(sPath) To sResult
  '   ' sResult = RunCompiler(sPath,, "-fPIC")
  '   ' If Not Exist(sPath & ".gch") Then
  '   '   Error "gb.jit: error: unable to generate precompiled header"
  '   '   Error sResult
  '   '   Return
  '   ' Endif
  '   ' 
  '   ' If $bDebug Then 
  '   '   Try Kill "/tmp/" & File.Name(sPath)
  '   '   Copy sPath To "/tmp/" & File.Name(sPath)
  '   '   Try Kill "/tmp/" & File.Name(sPath & ".gch")
  '   '   Copy sPath & ".gch" To "/tmp/" & File.Name(sPath & ".gch")
  '   ' Endif
  '   
  ' Endif
  
  sPath = $sDir &/ sName & ".c"
  If bCache Then sPathPtr = $sDir &/ sName & "_ptr.c"

  If $bDebug Then Error "gb.jit: generating "; sPath; " and "; sPathPtr

  hFile = Open sPath For Output Create
  If bCache Then 
    hFilePtr = Open sPathPtr For Output Create
  Else 
    hFilePtr = hFile
  Endif

  Print #hFile, "// "; CCompilation.GetFlags()
  'Print #hFile, "#include \"jit.h\""
  
  Print #hFile, "#define NO_CONFIG_H"
  
  Print #hFile, File.Load("gambas.h")
  Print #hFile, File.Load("gb_overflow.h")
  Print #hFile, File.Load("jit.h")
  Print #hFile, File.Load("gb.jit.h")
  
  Print #hFile, "GB_INTERFACE * GB_PTR;"
  Print #hFile, "#define GB (*GB_PTR)"
  Print #hFile, "JIT_INTERFACE * JIT_PTR;"
  Print #hFile, "#define JIT (*JIT_PTR)"

  Print #hFile, File.Load("gb_error_common.h")
  
  Print #hFile, File.Load("jit_after.h")
  
  
  If bTrace Then Print #hFile, "#include <stdio.h>"
  Print #hFile

  ' Print #hFilePtr, "// "; CCompilation.GetFlags()
  ' Print #hFilePtr, "#include \"jit.h\""
  ' Print #hFilePtr

  If sArch Then
    sDir = "." &/ sName
  Else
    sDir = "..."
  Endif
  
  For Each sFile In Dir(sDir &/ ".gambas")
    _ClassStat.Stat(sDir, sFile)
    If Not _ClassStat.HasFast Then Continue 

    sFile = _ClassStat.Name
    If $bDebug Then Error "gb.jit: translating class "; sFile
    
    __Jit.Translate(sFile, sArch, bTrace, bCache)
    
    If Not bCache Then Print #hFilePtr, "static ";
    Print #hFilePtr, __Jit.Pointers
    Print #hFilePtr
    
    'If $bDebug Then
    '  Print #hFile, Replace(__Jit.Translation, ";", ";\n")
    'Else 
      Print #hFile, __Jit.Translation
    'Endif
  Next
  
  Close #hFile
  If bCache Then Close #hFilePtr
  
  If $bDebug Then 
    Try Kill "/tmp/" & File.Name(sPath)
    Copy sPath To "/tmp/" & File.Name(sPath)
    If bCache Then
      Try Kill "/tmp/" & File.Name(sPathPtr)
      Copy sPathPtr To "/tmp/" & File.Name(sPathPtr)
    Endif
  Endif
  
  'If $bDebug Then Error "gb.jit: compiling to "; File.SetExt(sPath, "o")
  
  hComp = New CCompilation(sName, sPath, sPathPtr, fTime)
  
  hComp.Run()

  ' If $bDebug Then Error "gb.jit: linking to "; sPathSO
  ' 
  ' 'gcc -shared -o libfoo.so foo.o
  ' 'Exec [$sCompiler, "-shared", "-o", File.SetExt(sPath, "so"), File.SetExt(sPath, "o")] To sResult
  ' 'Shell $sCompiler & " -shared " & sFlag & " -lm -o " & Shell(sPathSO) & " " & Shell(sPathO) & " 2>&1" To sResult
  ' RunCompiler(sPathO, sPathSO, "-shared -lm")
  ' If Not Exist(sPathSO) Then 
  '   Error "gb.jit: warning: unable to link JIT code:"
  '   Error sResult
  '   Return
  ' Endif
  
End

Public Sub _Wait(sArch As String) As String

  Dim hComp As CCompilation
  
  hComp = CCompilation.All[GetArchiveName(sArch)]
  If hComp Then Return hComp.Wait()
  
End

Public Sub _Abort()

  Dim hComp As CCompilation
  
  If CCompilation.All.Count = 0 Then Return
  
  For Each hComp In CCompilation.All
    hComp.Kill
  Next
  
  CCompilation.All.Clear
  
  _exit
  
End

Private Function Time_Read() As Float

  Return _Time

End

Private Function Debug_Read() As Boolean

  Return $bDebug

End

Private Sub Debug_Write(Value As Boolean)

  $bDebug = Value

End
