aboutsummaryrefslogtreecommitdiff
path: root/lib/core/errors.nom
blob: 9a2cc9b997d1487124597b01b39172a3f2b68684 (plain)
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
#!/usr/bin/env nomsu -V6.15.13.8
#
    This file contains basic error reporting code
    
use "core/metaprogramming"
use "core/operators"
use "core/control_flow"

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

(fail $msg) compiles to "error(\(($msg as lua expr) if $msg else "nil"), 0);"
(assume $condition) compiles to:
    lua> ("
        local \$assumption = 'Assumption failed: '..tostring((\$condition):get_source_code())
    ")
    
    return
        Lua ("
            if not \($condition as lua expr) then
                error(\(quote "\$assumption"), 0)
            end
        ")

(assume $a == $b) compiles to:
    lua> "local \$assumption = 'Assumption failed: '..tostring(\(\($a == $b) as nomsu))"
    define mangler
    return
        Lua ("
            do
                local \(mangle "a"), \(mangle "b") = \($a as lua expr), \($b as lua expr)
                if \(mangle "a") ~= \(mangle "b") then
                    error(\(quote "\$assumption").."\\n"..tostring(\(mangle "a")).." != "..tostring(\
            ..\(mangle "b")), 0)
                end
            end
        ")

test:
    try: fail
    $worked = (no)
    try:
        fail "xx"
    ..if it fails with $failure:
        $worked = (yes)
    ..if it succeeds:
        fail "'try' incorrectly ran success case."
    assume $failure == "xx"
    unless $worked:
        fail "'try' failed to recover from failure"

# Try/except
[
    try $action if it succeeds $success if it fails with $msg $fallback
    try $action if it fails with $msg $fallback if it succeeds $success
] all compile to:
    $success_lua = ($success as lua)
    if ((#"\$success_lua") > 0):
        $success_lua, add "\n"
    $success_lua, prepend "-- Success:\n"
    $success_lua, 
        add "if not _fell_through then return table.unpack(_result, 2) end"
    $fallback_lua = ($fallback as lua)
    if ((#"\$fallback_lua") > 0):
        $msg_lua = ($msg as lua expr)
        if ((#"\$msg_lua") > 0):
            $fallback_lua, prepend "\n\$msg_lua = _result[2]\n"
            if ($msg_lua, text, is lua id):
                $fallback_lua, add free vars [($msg_lua, text)]
    $fallback_lua, prepend "-- Failure:\n"
    return
        Lua ("
            do
                local _fell_through = false
                local _result = {pcall(function()
                    \($action as lua)
                    _fell_through = true
                end)}
                if _result[1] then
                    \$success_lua
                else
                    \$fallback_lua
                end
            end
        ")

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

(try $action) parses as
    try $action if it succeeds (do nothing) if it fails (do nothing)

(try $action if it fails $fallback) parses as
    try $action if it succeeds (do nothing) if it fails $fallback

(try $action if it fails with $msg $fallback) parses as
    try $action if it succeeds (do nothing) if it fails with $msg $fallback

(try $action if it succeeds $success) parses as
    try $action if it succeeds $success if it fails (do nothing)

(try $action if it fails $fallback if it succeeds $success) parses as
    try $action if it fails with (=lua "") $fallback if it succeeds $success

(try $action if it succeeds $success if it fails $fallback) parses as
    try $action if it succeeds $success if it fails with (=lua "") $fallback

test:
    $success = (no)
    try:
        do: fail
        ..then always:
            $success = (yes)
    ..if it succeeds:
        fail "'try ... then always ...' didn't propagate failure"
    
    unless $success:
        fail "'try ... then always ...' didn't execute the 'always' code"

(do $action then always $final_action) compiles to ("
    do -- do/then always
        local _fell_through = false
        local _results = {pcall(function()
            \($action as lua)
            _fell_through = true
        end)}
        \($final_action as lua)
        if not _results[1] then error(_results[2], 0) end
        if not _fell_through then return table.unpack(_results, 2) end
    end
")