aboutsummaryrefslogtreecommitdiff
path: root/core/errors.nom
blob: 6779922d87e54551357aa9671f43ae8c38dd42b1 (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
#!/usr/bin/env nomsu -V6.13.12.8
#
    This file contains basic error reporting code
    
use "core/metaprogramming.nom"

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

(barf $msg) compiles to
    "error(\(=lua "\$msg and \($msg as lua expr) or '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
        ")

(assume $condition or barf $message) compiles to ("
    if not \($condition as lua expr) then
        error(\($message as lua expr), 0)
    end
")

test:
    try (barf) and if it succeeds:
        barf "try failed."
    $worked = (no)
    try (barf) and if it barfs:
        $worked = (yes)
    assume $worked or barf "try/catch failed"
    $x = 1
    try:
        $x = 2
        do (barf) then always: $x = 3
    ..and if it barfs:
        do nothing
    assume ($x == 3) or barf "do/then always failed"

# Try/except
[
    try $action and if it succeeds $success or if it barfs $msg $fallback
    try $action and if it barfs $msg $fallback or if it succeeds $success
] all compile to ("
    do
        local fell_through = false
        local err, erred = nil, false
        local ok, ret = xpcall(function()
            \($action as lua)
            fell_through = true
        end, function(\(=lua "\$fallback and \($msg as lua expr) or ''"))
            local ok, ret = pcall(function()
                \((=lua "\$fallback or \$msg") as lua)
            end)
            if not ok then err, erred = ret, true end
        end)
        if ok then
            \($success as lua)
            if not fell_through then
                return ret
            end
        elseif erred then
            error(err, 0)
        end
    end
")

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

(try $action) parses as
    try $action and if it succeeds (do nothing) or if it barfs (do nothing)

(try $action and if it barfs $msg $fallback) parses as
    try $action and if it succeeds (do nothing) or if it barfs $msg $fallback

(try $action and if it succeeds $success) parses as
    try $action and if it succeeds $success or if it barfs (do nothing)