Appearance
| 1 | namespace IR.Values is | |
| 2 | use Semantic.Types.Type; | |
| 3 | ||
| 4 | // The result of `a ?? b` for a reference-typed `a: T?`. `T?` is a | |
| 5 | // reference that may be null at IL, so a single dup-and-branch is | |
| 6 | // enough — `b` is evaluated only when `a` is null. | |
| 7 | // | |
| 8 | // <left IL> // [..., a] | |
| 9 | // dup // [..., a, a] | |
| 10 | // brtrue.s <end> // pops the top a; non-null leaves the | |
| 11 | // // other a on the stack at end | |
| 12 | // pop // [...] | |
| 13 | // <right IL> // [..., b] | |
| 14 | // <end>: | |
| 15 | // | |
| 16 | // Built by COMPILE_OPERATORS.visit_binary when the operator is `??`. | |
| 17 | // The two operands are evaluated by their own Values; this Value | |
| 18 | // composes the surrounding short-circuit shell. | |
| 19 | class NULL_COALESCE: Value is | |
| 20 | left: Value; | |
| 21 | right: Value; | |
| 22 | _result_type: Type; | |
| 23 | ||
| 24 | type: Type => _result_type; | |
| 25 | is_lightweight_pure: bool => false; | |
| 26 | ||
| 27 | init(left: Value, right: Value, result_type: Type) is | |
| 28 | super.init(); | |
| 29 | ||
| 30 | self.left = left; | |
| 31 | self.right = right; | |
| 32 | self._result_type = result_type; | |
| 33 | si | |
| 34 | ||
| 35 | gen(context: IR.CONTEXT) is | |
| 36 | let end_label = IR.LABEL(); | |
| 37 | ||
| 38 | gen(left, context); | |
| 39 | context.write_line("dup"); | |
| 40 | context.write_line("brtrue.s {end_label}"); | |
| 41 | context.write_line("pop"); | |
| 42 | gen(right, context); | |
| 43 | context.write_line("{end_label}:"); | |
| 44 | si | |
| 45 | ||
| 46 | to_string() -> string => | |
| 47 | "null-coalesce:[{type}]({left},{right})"; | |
| 48 | si | |
| 49 | si |