Skip to content
← Back

src/syntax/process/yield_scanner.ghul

1
namespace Syntax.Process is
2
3
class YIELD_SCANNER: Visitor is
4
_found: bool;
5
6
init() is
7
super.init();
8
si
9
10
body_has_yield(body: Trees.Bodies.Body?) -> bool is
11
if !body? then
12
return false;
13
fi
14
15
_found = false;
16
17
body.walk(self);
18
19
return _found;
20
si
21
22
pre(`yield: Trees.Statements.YIELD) -> bool is
23
_found = true;
24
25
return true;
26
si
27
28
pre(function: Trees.Definitions.FUNCTION) -> bool => true;
29
pre(function: Trees.Expressions.FUNCTION) -> bool => true;
30
si
31
32
// Scans a generator body for `for` loops. `let` bindings ARE
33
// supported now (locals are lifted onto state-machine frame
34
// fields via state_machine_field), but `for` lowers to a hidden
35
// iterator TEMP that doesn't yet route through frame fields, so
36
// the iterator gets re-created on every MoveNext re-entry. Until
37
// TEMPs gain state-machine awareness, ask users to write the
38
// expansion by hand:
39
//
40
// let it = xs.iterator;
41
// while it.move_next() do
42
// yield it.current;
43
// od
44
class GENERATOR_FOR_SCANNER: Visitor is
45
_logger: Logging.Logger;
46
47
init(logger: Logging.Logger) is
48
super.init();
49
50
_logger = logger;
51
si
52
53
scan(body: Trees.Bodies.Body?) is
54
if !body? then
55
return;
56
fi
57
58
body.walk(self);
59
si
60
61
pre(`for: Trees.Statements.FOR) -> bool is
62
_logger.error(
63
`for.location,
64
"for loop inside generator body is not yet supported"
65
);
66
67
return false;
68
si
69
70
pre(function: Trees.Definitions.FUNCTION) -> bool => true;
71
pre(function: Trees.Expressions.FUNCTION) -> bool => true;
72
si
73
74
// Scans a generator body for `yield` inside a `catch` or
75
// `finally` HANDLER body. Yield in a try BODY is fine —
76
// state-machine codegen handles it via per-region dispatch + the
77
// `'.gen_state'` local + state-guarded finally. Handlers
78
// (catch / finally) still need an AST-level rewrite (pend
79
// exception, yield outside the handler, restore), so flag those
80
// with a clean compile-time error.
81
class YIELD_IN_TRY_SCANNER: HANDLER_DEPTH_SCANNER is
82
init(logger: Logging.Logger) is
83
super.init(logger);
84
si
85
86
pre(`yield: Trees.Statements.YIELD) -> bool is
87
if handler_depth > 0 then
88
logger.error(`yield.location, "yield inside a catch or finally handler is not yet supported");
89
fi
90
return true;
91
si
92
si
93
si