Appearance
| 1 | namespace Syntax.Process is | |
| 2 | ||
| 3 | // Scans a function body for `await` expressions, stopping at | |
| 4 | // nested function/lambda boundaries (their awaits belong to | |
| 5 | // their own state machines). Used by declare-symbols to | |
| 6 | // classify functions; `found_value_return` distinguishes | |
| 7 | // void-async (`Tasks.TASK`) from value-async (`Tasks.TASK[T]`). | |
| 8 | class AWAIT_SCANNER: Visitor is | |
| 9 | _found: bool; | |
| 10 | _found_value_return: bool; | |
| 11 | ||
| 12 | init() is | |
| 13 | super.init(); | |
| 14 | si | |
| 15 | ||
| 16 | body_has_await(body: Trees.Bodies.Body) -> bool is | |
| 17 | scan(body); | |
| 18 | return _found; | |
| 19 | si | |
| 20 | ||
| 21 | scan(body: Trees.Bodies.Body?) is | |
| 22 | _found = false; | |
| 23 | _found_value_return = false; | |
| 24 | ||
| 25 | if body? then | |
| 26 | body.walk(self); | |
| 27 | fi | |
| 28 | si | |
| 29 | ||
| 30 | found: bool => _found; | |
| 31 | found_value_return: bool => _found_value_return; | |
| 32 | ||
| 33 | pre(await_expr: Trees.Expressions.AWAIT) -> bool is | |
| 34 | _found = true; | |
| 35 | ||
| 36 | return true; | |
| 37 | si | |
| 38 | ||
| 39 | pre(r: Trees.Statements.RETURN) -> bool is | |
| 40 | if r.expression? then | |
| 41 | _found_value_return = true; | |
| 42 | fi | |
| 43 | ||
| 44 | return false; | |
| 45 | si | |
| 46 | ||
| 47 | pre(function: Trees.Definitions.FUNCTION) -> bool => true; | |
| 48 | pre(function: Trees.Expressions.FUNCTION) -> bool => true; | |
| 49 | si | |
| 50 | ||
| 51 | // `await` inside a `catch` or `finally` HANDLER needs an AST- | |
| 52 | // level rewrite (pend the exception, perform the await OUTSIDE | |
| 53 | // the handler, restore the exception). Roslyn does exactly that | |
| 54 | // when lowering async; ghūl doesn't yet, so emit a diagnostic | |
| 55 | // pointing at the workaround. | |
| 56 | // | |
| 57 | // NOTE: `await` inside a `try` BODY is fine — state-machine | |
| 58 | // codegen handles it via per-region cold-resume dispatch + the | |
| 59 | // V_state local + state-guarded finally. Only the catch/finally | |
| 60 | // HANDLER bodies remain unsupported. | |
| 61 | class AWAIT_IN_PROTECTED_SCANNER: HANDLER_DEPTH_SCANNER is | |
| 62 | init(logger: Logging.Logger) is | |
| 63 | super.init(logger); | |
| 64 | si | |
| 65 | ||
| 66 | pre(await_expr: Trees.Expressions.AWAIT) -> bool is | |
| 67 | if handler_depth > 0 then | |
| 68 | logger.error(await_expr.location, "await inside a catch or finally handler is not yet supported"); | |
| 69 | fi | |
| 70 | return true; | |
| 71 | si | |
| 72 | si | |
| 73 | si |