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