<commit_before>
// sdk
import threading/Thread
import structs/[Stack, LinkedList]
import lang/Backtrace

include setjmp, assert, errno

version(windows) {
    include windows

    DebugBreak: extern func
    RaiseException: extern func (ULong, ULong, ULong, Pointer)
    IsDebuggerPresent: extern func -> Pointer
}

JmpBuf: cover from jmp_buf {
    setJmp: extern(setjmp) func -> Int
    longJmp: extern(longjmp) func (value: Int)
}

_StackFrame: cover {
    buf: JmpBuf
}

StackFrame: cover from _StackFrame* {
    new: static func -> This {
        gc_malloc(_StackFrame size)
    }
}

exceptionStack := ThreadLocal<Stack<StackFrame>> new()

_exception := ThreadLocal<Exception> new()
_EXCEPTION: Int = 1

_pushStackFrame: inline func -> StackFrame {
    stack: Stack<StackFrame>
    if(!exceptionStack hasValue?()) {
        stack = Stack<StackFrame> new()
        exceptionStack set(stack)
    } else {
        stack = exceptionStack get()
    }
    buf := StackFrame new()
    stack push(buf)
    buf
}

_setException: inline func (e: Exception) {
    _exception set(e)
}

_getException: inline func -> Exception {
    _exception get()
}

_popStackFrame: inline func -> StackFrame {
    exceptionStack get() as Stack<StackFrame> pop() as StackFrame
}

_hasStackFrame: inline func -> Bool {
    exceptionStack hasValue?() && exceptionStack get() as Stack<StackFrame> size > 0
}

assert: extern func(Bool)

version(windows) {
    import native/win32/[types, errors]

    getOSErrorCode: func -> Int {
        GetLastError()
    }

    getOSError: func -> String {
        GetWindowsErrorMessage(GetLastError())
        
    }
} else {
    errno: extern Int
    strerror: extern func (Int) -> CString

    getOSErrorCode: func -> Int {
        errno
    }

    getOSError: func -> String {
        x := strerror(errno)
        return (x != null) ? x toString() : ""
    }
}

raise: func(msg: String) {
    Exception new(msg) throw()
}

raise: func ~withClass(clazz: Class, msg: String) {
    Exception new(clazz, msg) throw()
}

/**
 * Base class for all exceptions that can be thrown
 */
Exception: class {
    backtraces: LinkedList<Backtrace> = LinkedList<Backtrace> new()

    addBacktrace: func {
        bt := BacktraceHandler get() backtrace()
        if (bt) {
            backtraces add(bt)
        }
    }

    printBacktrace: func {
        h := BacktraceHandler get()
        for (backtrace in backtraces) {
            stderr write(h backtraceSymbols(backtrace))
        }
    }

    /** Class which threw the exception. May be null */
    origin: Class

    /** Message associated with this exception. Printed when the exception is thrown. */
    message : String

    /**
     * Create an exception
     *
     * @param origin The class throwing this exception
     * @param message A short text explaning why the exception was thrown
     */
    init: func  (=origin, =message) {
    }

    /**
     * Create an exception
     *
     * @param message A short text explaning why the exception was thrown
     */
    init: func ~noOrigin (=message) {
        init(null, message)
    }


    /**
     * @return the exception's message, nicely formatted
     */
    formatMessage: func -> String {
        if(origin)
            "[%s in %s]: %s\n" format(class name toCString(), origin name toCString(), message ? message toCString() : "<no message>" toCString())
        else
            "[%s]: %s\n" format(class name toCString(), message ? message toCString() : "<no message>" toCString())
    }

    /**
     * Print this exception, with its origin, if specified, and its message
     */
    print: func {
        printMessage()
        printBacktrace()
    }

    /**
     * Print just the message
     */
    printMessage: func {
        fprintf(stderr, "%s", formatMessage() toCString())
    }

    /**
     * Throw this exception
     */
    throw: func {
        _setException(this)
        addBacktrace()
        if(!_hasStackFrame()) {
            version (windows) {
                if (IsDebuggerPresent()) {
                    // trigger a break point here, debugger will like that!
                    printMessage()
                    DebugBreak()
                } else {
                    // print the backtrace ourselves<commit_msg>red exception message<commit_after>
// sdk
import threading/Thread
import structs/[Stack, LinkedList]
import lang/Backtrace

include setjmp, assert, errno

version(windows) {
    include windows

    DebugBreak: extern func
    RaiseException: extern func (ULong, ULong, ULong, Pointer)
    IsDebuggerPresent: extern func -> Pointer
}

JmpBuf: cover from jmp_buf {
    setJmp: extern(setjmp) func -> Int
    longJmp: extern(longjmp) func (value: Int)
}

_StackFrame: cover {
    buf: JmpBuf
}

StackFrame: cover from _StackFrame* {
    new: static func -> This {
        gc_malloc(_StackFrame size)
    }
}

exceptionStack := ThreadLocal<Stack<StackFrame>> new()

_exception := ThreadLocal<Exception> new()
_EXCEPTION: Int = 1

_pushStackFrame: inline func -> StackFrame {
    stack: Stack<StackFrame>
    if(!exceptionStack hasValue?()) {
        stack = Stack<StackFrame> new()
        exceptionStack set(stack)
    } else {
        stack = exceptionStack get()
    }
    buf := StackFrame new()
    stack push(buf)
    buf
}

_setException: inline func (e: Exception) {
    _exception set(e)
}

_getException: inline func -> Exception {
    _exception get()
}

_popStackFrame: inline func -> StackFrame {
    exceptionStack get() as Stack<StackFrame> pop() as StackFrame
}

_hasStackFrame: inline func -> Bool {
    exceptionStack hasValue?() && exceptionStack get() as Stack<StackFrame> size > 0
}

assert: extern func(Bool)

version(windows) {
    import native/win32/[types, errors]

    getOSErrorCode: func -> Int {
        GetLastError()
    }

    getOSError: func -> String {
        GetWindowsErrorMessage(GetLastError())
        
    }
} else {
    errno: extern Int
    strerror: extern func (Int) -> CString

    getOSErrorCode: func -> Int {
        errno
    }

    getOSError: func -> String {
        x := strerror(errno)
        return (x != null) ? x toString() : ""
    }
}

raise: func(msg: String) {
    Exception new(msg) throw()
}

raise: func ~withClass(clazz: Class, msg: String) {
    Exception new(clazz, msg) throw()
}

/**
 * Base class for all exceptions that can be thrown
 */
Exception: class {
    backtraces: LinkedList<Backtrace> = LinkedList<Backtrace> new()

    addBacktrace: func {
        bt := BacktraceHandler get() backtrace()
        if (bt) {
            backtraces add(bt)
        }
    }

    printBacktrace: func {
        h := BacktraceHandler get()
        for (backtrace in backtraces) {
            stderr write(h backtraceSymbols(backtrace))
        }
    }

    /** Class which threw the exception. May be null */
    origin: Class

    /** Message associated with this exception. Printed when the exception is thrown. */
    message : String

    /**
     * Create an exception
     *
     * @param origin The class throwing this exception
     * @param message A short text explaning why the exception was thrown
     */
    init: func  (=origin, =message) {
    }

    /**
     * Create an exception
     *
     * @param message A short text explaning why the exception was thrown
     */
    init: func ~noOrigin (=message) {
        init(null, message)
    }


    /**
     * @return the exception's message, nicely formatted
     */
    formatMessage: func -> String {
        if(origin)
            "\x1b[31;1m[%s in %s]: %s\x1b[0m\n" format(class name toCString(), origin name toCString(), message ? message toCString() : "<no message>" toCString())
        else
            "\x1b[31;1m[%s]: %s\x1b[0m\n" format(class name toCString(), message ? message toCString() : "<no message>" toCString())
    }

    /**
     * Print this exception, with its origin, if specified, and its message
     */
    print: func {
        printMessage()
        printBacktrace()
    }

    /**
     * Print just the message
     */
    printMessage: func {
        fprintf(stderr, "%s", formatMessage() toCString())
    }

    /**
     * Throw this exception
     */
    throw: func {
        _setException(this)
        addBacktrace()
        if(!_hasStackFrame()) {
            version (windows) {
                if (IsDebuggerPresent()) {
                    // trigger a break point here, debugger will like that!
                    printMessage()
                    DebugBreak()
                } else {
                    // print the backtrace ourselves
{'fraction_non_alphanumeric': 0.11072261072261072, 'fraction_numerical': 0.002331002331002331, 'mean_word_length': 2.335017489312087, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1422522', 'n_tokens_mistral': 2565, 'n_tokens_neox': 2480, 'n_words': 751}