Appearance
| 1 | namespace Syntax.Trees.Expressions is | |
| 2 | use Source; | |
| 3 | ||
| 4 | // `val ... lav` — a value-producing block. | |
| 5 | // | |
| 6 | // The block's value is the LUB of every contributing source: the | |
| 7 | // tail expression of `body` (if the tail provides a value) and | |
| 8 | // every `return E` whose target is this block. `return E` inside | |
| 9 | // a `val ... lav` exits this block (innermost wins on nesting), | |
| 10 | // not the enclosing function. | |
| 11 | class VAL_BLOCK: Expression is | |
| 12 | body: Statements.LIST public; | |
| 13 | ||
| 14 | // Set by the wrapping context (compile-expressions). False | |
| 15 | // when the block is in expression-statement position or in a | |
| 16 | // void-returning `=>` body — fall-through is allowed to be | |
| 17 | // void there. True everywhere else. | |
| 18 | want_value: bool public; | |
| 19 | ||
| 20 | // Pushed expected_type from outer context, threaded onto the | |
| 21 | // tail expression and every return that targets us so they | |
| 22 | // participate in inference / overload resolution against the | |
| 23 | // expected type. | |
| 24 | expected_type: Semantic.Types.Type? public; | |
| 25 | expected_type_error_message: string? public; | |
| 26 | ||
| 27 | // Collected at compile-expressions time: the value type of | |
| 28 | // every return targeting this block. visit() LUBs these with | |
| 29 | // the tail's value type to settle the block's value type. | |
| 30 | return_types: Collections.MutableList[Semantic.Types.Type] public; | |
| 31 | ||
| 32 | // True when any RETURN statement inside the body targets | |
| 33 | // this block (with or without an expression). `return_types` | |
| 34 | // alone misses bare `return;`; this flag is set by | |
| 35 | // compile_bindings.pre_return whenever a return's target is | |
| 36 | // resolved to this block. | |
| 37 | has_targeted_return: bool public; | |
| 38 | ||
| 39 | // Label placed at end of block body in generate-il; returns | |
| 40 | // with this block as target push their value and `br` here. | |
| 41 | // All paths (every targeted return + the natural fall- | |
| 42 | // through) converge with the value on the evaluation stack — | |
| 43 | // the same shape `if`/`case`-in-expression IL uses, so async | |
| 44 | // and generator state machines work without value-across- | |
| 45 | // suspend special handling. | |
| 46 | end_label: IR.LABEL? public; | |
| 47 | ||
| 48 | init(location: LOCATION, body: Statements.LIST) is | |
| 49 | super.init(location); | |
| 50 | ||
| 51 | ||
| 52 | self.body = body; | |
| 53 | self.want_value = true; | |
| 54 | self.return_types = Collections.LIST[Semantic.Types.Type](); | |
| 55 | si | |
| 56 | ||
| 57 | clear() is | |
| 58 | super.clear(); | |
| 59 | ||
| 60 | want_value = true; | |
| 61 | expected_type = null; | |
| 62 | expected_type_error_message = null; | |
| 63 | return_types = Collections.LIST[Semantic.Types.Type](); | |
| 64 | has_targeted_return = false; | |
| 65 | end_label = null; | |
| 66 | si | |
| 67 | ||
| 68 | set_expected_type(expected_type: Semantic.Types.Type?, error_message: string?) is | |
| 69 | self.expected_type = expected_type; | |
| 70 | self.expected_type_error_message = error_message; | |
| 71 | ||
| 72 | // Push the constraint onto the tail expression so it | |
| 73 | // participates in inference / overload resolution against | |
| 74 | // the expected type — same shape as `if`/`case` | |
| 75 | // expression-position branches. Returns targeting this | |
| 76 | // block pick the constraint up from `expected_type` via | |
| 77 | // compile_bindings.pre_return. | |
| 78 | body.set_expected_type(expected_type, error_message); | |
| 79 | si | |
| 80 | ||
| 81 | clear_expected_type() is | |
| 82 | expected_type = null; | |
| 83 | expected_type_error_message = null; | |
| 84 | body.clear_expected_type(); | |
| 85 | si | |
| 86 | ||
| 87 | accept(visitor: Visitor) is | |
| 88 | visitor.visit(self); | |
| 89 | si | |
| 90 | ||
| 91 | walk(visitor: Visitor) is | |
| 92 | if !visitor.pre(self) then | |
| 93 | body.walk(visitor); | |
| 94 | fi | |
| 95 | ||
| 96 | accept(visitor); | |
| 97 | si | |
| 98 | si | |
| 99 | si |