Skip to content
← Back

src/syntax/process/handler_depth_scanner.ghul

1
namespace Syntax.Process is
2
3
// Base class for scanners that flag a particular suspending
4
// statement (`await`, `yield`, possibly others later) inside a
5
// `catch` or `finally` HANDLER body.
6
//
7
// The state-machine codegen handles suspensions inside a `try`
8
// BODY via per-region cold-resume dispatch + V_state local +
9
// state-guarded finally. Handlers (the body of a `catch` clause
10
// or a `finally` block) still need an AST-level rewrite — pend
11
// the in-flight exception, perform the suspension outside the
12
// handler, re-raise — which ghūl doesn't yet do. So subclasses
13
// walk a method body, track depth into handler bodies, and
14
// override the suspending-statement `pre` to emit a clean
15
// compile-time error when caught inside one.
16
//
17
// Stops at nested function / lambda boundaries: their bodies
18
// are their own state machines and their own scanner walks.
19
class HANDLER_DEPTH_SCANNER: Visitor is
20
_handler_depth: int;
21
_logger: Logging.Logger;
22
23
init(logger: Logging.Logger) is
24
super.init();
25
_logger = logger;
26
si
27
28
handler_depth: int => _handler_depth;
29
logger: Logging.Logger => _logger;
30
31
scan(body: Trees.Bodies.Body?) is
32
if !body? then
33
return;
34
fi
35
36
_handler_depth = 0;
37
38
body.walk(self);
39
si
40
41
// CATCH body is a handler — walk it with depth bumped.
42
pre(`catch: Trees.Statements.CATCH) -> bool is
43
_handler_depth = _handler_depth + 1;
44
return false;
45
si
46
47
visit(`catch: Trees.Statements.CATCH) is
48
_handler_depth = _handler_depth - 1;
49
si
50
51
// TRY's finally body is also a handler. Walk body / catches
52
// / finally explicitly so only the finally bumps depth (the
53
// try body itself is OK — state-machine codegen handles
54
// suspensions inside it).
55
pre(`try: Trees.Statements.TRY) -> bool is
56
`try.body.walk(self);
57
58
for c in `try.catches do
59
c.walk(self);
60
od
61
62
let `finally = `try.`finally;
63
64
if `finally? then
65
_handler_depth = _handler_depth + 1;
66
`finally.walk(self);
67
_handler_depth = _handler_depth - 1;
68
fi
69
70
return true;
71
si
72
73
// Stop at nested function / lambda boundaries — each has
74
// its own state machine and its own scanner pass.
75
pre(function: Trees.Definitions.FUNCTION) -> bool => true;
76
pre(function: Trees.Expressions.FUNCTION) -> bool => true;
77
si
78
si