Evaluate a CBM_TYPE_CONDITIONAL `T extends U ? X : Y`. With distribution: when T is a UNION, evaluate per member and union the results. Uses the partial relater for the extends check.
| 1171 | // a UNION, evaluate per member and union the results. Uses the partial relater for |
| 1172 | // the extends check. |
| 1173 | static const CBMType *eval_conditional(TSLSPContext *ctx, const CBMType *t, int depth) { |
| 1174 | if (!t || t->kind != CBM_TYPE_CONDITIONAL || depth > 16) |
| 1175 | return t; |
| 1176 | const CBMType *check = t->data.conditional.check; |
| 1177 | const CBMType *extends = t->data.conditional.extends; |
| 1178 | const CBMType *tb = t->data.conditional.true_branch; |
| 1179 | const CBMType *fb = t->data.conditional.false_branch; |
| 1180 | if (!check || !extends) |
| 1181 | return t; |
| 1182 | |
| 1183 | // Distribution: when check is a UNION, evaluate per member and union results. |
| 1184 | if (check->kind == CBM_TYPE_UNION && check->data.union_type.members && |
| 1185 | check->data.union_type.count > 0) { |
| 1186 | const CBMType **results = (const CBMType **)cbm_arena_alloc( |
| 1187 | ctx->arena, (size_t)(check->data.union_type.count + 1) * sizeof(const CBMType *)); |
| 1188 | if (!results) |
| 1189 | return t; |
| 1190 | int n = 0; |
| 1191 | for (int i = 0; i < check->data.union_type.count; i++) { |
| 1192 | const CBMType *member = check->data.union_type.members[i]; |
| 1193 | const CBMType *sub = cbm_type_conditional(ctx->arena, member, extends, tb, fb); |
| 1194 | results[n++] = eval_conditional(ctx, sub, depth + 1); |
| 1195 | } |
| 1196 | results[n] = NULL; |
| 1197 | if (n == 1) |
| 1198 | return results[0]; |
| 1199 | return cbm_type_union(ctx->arena, results, n); |
| 1200 | } |
| 1201 | |
| 1202 | // `infer X` in extends pattern: pattern-match check against extends, capturing |
| 1203 | // bindings, then substitute them in the true_branch. |
| 1204 | if (contains_infer(extends, 0)) { |
| 1205 | TSInferBinding binds[TS_INFER_MAX] = {{0}}; |
| 1206 | int bind_count = 0; |
| 1207 | if (match_with_infer(ctx, check, extends, binds, &bind_count, 0)) { |
| 1208 | return subst_infer_bindings(ctx, tb, binds, bind_count, 0); |
| 1209 | } |
| 1210 | return fb; |
| 1211 | } |
| 1212 | |
| 1213 | // Non-distributive: single resolution. |
| 1214 | bool yes = ts_is_assignable(ctx, check, extends); |
| 1215 | return yes ? tb : fb; |
| 1216 | } |
| 1217 | |
| 1218 | // Resolve a CBMType against the registry's alias chain when it's a NAMED type that's a |
| 1219 | // pure alias (`type Foo = Bar`). Also evaluates inline conditional types. |
no test coverage detected