Skip to content
This repository
tree: 3d7999ae0b
Fetching contributors…

Cannot retrieve contributors at this time

file 188 lines (169 sloc) 5.674 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
$include_const "iglobals.pasm";

/* Utilities for Parrot-Specific things
*/
namespace Rosella.Parrot
{
    inline __get_config_hash() return var
    {
        return getinterp()[IGLOBALS_CONFIG_HASH];
    }

    // Get the Config hash
    function get_config_hash()
    {
        return __get_config_hash();
    }

    // Return true if this is a Linux machine
    function is_linux()
    {
        return __get_config_hash()["osname"] == "linux";
    }

    // Return true if this is a Windows machine
    function is_windows()
    {
        return __get_config_hash()["osname"] == "windows";
    }

    // TODO: is_darwin()

    // Get an array of strings representing a backtrace from the caller
    function get_backtrace_strings()
    {
        var cur_ctx = get_context();
        var last_ctx = cur_ctx.caller_ctx;
        return format_backtrace(last_ctx.backtrace());
    }

    // Get an array of strings representing a backtrace from the exception
    function get_backtrace_ex_strings(var ex)
    {
        var bt = ex.backtrace();
        return format_backtrace(bt);
    }

    // Execute a function. Catch any exceptions and print the message and
    // backtrace out to a specified handle. Swap out the standard handles,
    // if alternatives are provided. Return whatever values the function
    // returns
    function try_report(var sub, var handles = null)
    {
        var out = null;
        if (handles != null && exists handles["stderr"])
            out = handles["stderr"];
        else
            out = getstdout();
        if (handles != null)
            handles = Rosella.IO.swap_handles(handles);

        var p;
        var n;
        try {
            /*:(p [slurpy], n [slurpy,named]) = */sub();
        } catch (e) {
            var fmt = Rosella.Parrot.exception_formatter();
            out.print(fmt.format_default(e));
        }

        if (handles != null)
            Rosella.IO.swap_handles(handles);

        /*return p:[flat], n:[flat,named];*/
    }

    // private routine. Format backtrace information into an array of
    // human-readable strings
    function format_backtrace(var bt)
    {
        var bts = [];
        var fmt = Rosella.Parrot.exception_formatter();
        for (int i = 0; i < elements(bt); i++) {
            var sub; string text;
            :(sub, text) = fmt.format_frame_default(bt[i]);
            bts[i] = text;
            if (sub == null)
                break;
        }
        return bts;
    }

    // Get the default exception formatter object
    function exception_formatter()
    {
        return Rosella.StringFormatter.autoget_type_formatter("Exception",
            function() { return new Rosella.Parrot.ExceptionFormatter(); }
        );
    }
}

class Rosella.Parrot.ExceptionFormatter : Rosella.StringFormatter
{
    function ExceptionFormatter() { }

    // Create a string from an object and a format string
    function format(var obj, string fmt)
    {
        var sb = new 'StringBuilder';
        push(sb, obj.message);
        push(sb, "\n");
        var bt = obj.backtrace();
        for (int i = 0; i < elements(bt); i++) {
            :(var sub, string text) = self.format_frame(bt[i], fmt);
            push(sb, text);
            if (sub == null)
                break;
        }
        return sb;
    }

    // Create a string from the object using a default formatting rule
    function format_default(var obj)
    {
        var sb = new 'StringBuilder';
        push(sb, obj.message);
        push(sb, " at \n");
        var bt = obj.backtrace();
        for (int i = 0; i < elements(bt); i++) {
            :(var sub, string text) = self.format_frame_default(bt[i]);
            push(sb, text);
            push(sb, "\n");
            if (sub == null)
                break;
        }
        return sb;
    }

    // Format a frame
    function format_frame(var frame, var f)
    {
        var sub = frame["sub"];
        string subname = (sub == null) ? "(entry)" : string(sub);
        var annotations = frame["annotations"];
        string filename = annotations["file"];
        if (filename == null || filename == "")
            filename = "<Unknown File>";
        int lineno = annotations["line"];
        string ns;
        string hll_ns;
        if (sub == null) {
            ns = "";
            hll_ns = "";
        } else {
            var ns_parts = sub.get_namespace().get_name();
            hll_ns = ns_parts.shift();
            ns = join(".", ns_parts);
        }

        if (contains_substr(f, "NS")) f = f.replace("NS", ns);
        if (contains_substr(f, "HLL")) f = f.replace("HLL", hll_ns);
        if (contains_substr(f, "SUB")) f = f.replace("SUB", subname);
        if (contains_substr(f, "FILE")) f = f.replace("FILE", filename);
        if (contains_substr(f, "LINE")) f = f.replace("LINE", string(lineno));
        return sub, f;
    }

    // Format a frame using the default formatting
    function format_frame_default(var frame)
    {
        var sub = frame["sub"];
        string subname = (sub == null) ? "(entry)" : string(sub);
        var annotations = frame["annotations"];
        string filename = annotations["file"];
        if (filename == null || filename == "")
            filename = "<Unknown File>";
        int lineno = annotations["line"];
        string ns;
        if (sub == null) {
            ns = "";
        } else {
            var ns_parts = sub.get_namespace().get_name();
            ns_parts.shift();
            ns = join(".", ns_parts);
        }
        string text = Winxed_Builtins.sprintf("\t[%s] '%s'\t(%s %d)", [ns, subname, filename, lineno]);
        return sub, text;
    }
}
Something went wrong with that request. Please try again.