package eta.runtime;

import eta.runtime.Runtime;
import eta.runtime.stg.Capability;
import eta.runtime.stg.Closure;
import eta.runtime.stg.TSO;
import eta.runtime.exception.RuntimeInternalError;

public class RuntimeLogging {
    public static void barf(String msg, Object... args) {
        throw new RuntimeInternalError(String.format(msg, args));
    }

    public static void errorBelch(String msg, Object... args) {
        System.err.print("***Exception***: ");
        System.err.format(msg, args);
        System.err.print("\n");
        TSO tso = Capability.getLocal().context.currentTSO;
        if (tso.hasStackTrace()) {
            StackTraceElement[] stackTrace = tso.getStackTrace();
            for (StackTraceElement element : stackTrace) {
                String className = element.getClassName();
                if (!className.startsWith("eta.runtime") && !className.startsWith("java")) {
                    System.err.println("    in " + element.getClassName());
                }
            }
            tso.setStackTrace(null);
        }
    }

    public static void debugBelch(String msg, Object... args) {
        System.out.format(msg, args);
        System.out.print("\n");
    }

    public static void debugScheduler(String msg, Object... args) {
        debugGeneric(Runtime.debugScheduler(), "Scheduler", msg, args);
    }

    public static void debugSTM(String msg, Object... args) {
        debugGeneric(Runtime.debugSTM(), "STM", msg, args);
    }

    public static void debugMemoryManager(String msg, Object... args) {
        debugGeneric(Runtime.debugMemoryManager(), "MemoryManager", msg, args);
    }

    public static void debugGeneric(boolean shouldDebug, String type, String msg, Object... args) {
        if (shouldDebug) {
            Capability cap = Capability.getLocal();
            String worker = cap.worker? "[Worker]" : "";
            debugBelch("[Eta-RTS](Capability" + worker + " %d){" + type + "}: " + msg,
                       cap.id, args);
        }
    }

    public static void printClosure(Closure closure) {
        // TODO: Override toString and make the closure more readable
        System.out.println("Closure: " + closure);
    }
}

@@ -194,37 +194,160 @@
 r;%0A%0A
-public class RuntimeLogging %7B
+import java.util.concurrent.atomic.AtomicBoolean;%0A%0Apublic class RuntimeLogging %7B%0A    public static final AtomicBoolean errorLock = new AtomicBoolean();%0A
 %0A   
@@ -551,28 +551,192 @@
    S
-ystem.err.print(%22***
+tringBuilder sw = new StringBuilder();%0A        sw.append(%22Exception in thread %5C%22%22%0A                  + Thread.currentThread().getName()%0A                  + %22%5C%22 eta.runtime.exception.Eta
 Exce
@@ -744,11 +744,8 @@
 tion
-***
 : %22)
@@ -754,26 +754,32 @@
         
-System.err
+sw.append(String
 .format(
@@ -780,32 +780,33 @@
 ormat(msg, args)
+)
 ;%0A        System
@@ -799,32 +799,25 @@
         
-System.err.print
+sw.append
 (%22%5Cn%22);%0A
@@ -1115,131 +1115,295 @@
     
-if (!className.startsWith(%22eta.runtime%22) && !className.startsWith(%22java%22)) %7B%0A                    System.err.println
+String sourceFile = element.getFileName();%0A                if (sourceFile != null) %7B%0A                    sourceFile = %22(%22 + sourceFile + %22:%22 + element.getLineNumber() + %22)%22;%0A                %7D else %7B%0A                    sourceFile = %22%22;%0A                %7D%0A                sw.append
 (%22    
-in
+at
  %22 +
@@ -1429,79 +1429,427 @@
 me()
-);%0A                %7D%0A            %7D%0A            tso.setStackTrace(null);
+ + %22.%22%0A                                    + element.getMethodName()%0A                                    + sourceFile%0A                                    + %22%5Cn%22);%0A            %7D%0A            tso.setStackTrace(null);%0A            try %7B%0A                while (!errorLock.compareAndSet(false, true));%0A                System.err.print(sw.toString());%0A            %7D finally %7B%0A                errorLock.set(false);%0A            %7D
 %0A   

Improve debugging for the concurrent runtime