(expr: Expression, target: Type, source: Type)
| 198 | * Conversions involving unions. |
| 199 | */ |
| 200 | export function castUnion(expr: Expression, target: Type, source: Type): Expression { |
| 201 | // From non-union to union. |
| 202 | if (source.category != 'union' && target.category == 'union') { |
| 203 | // Convert undefined to std::monostate. |
| 204 | if (source.category == 'undefined') |
| 205 | return new CustomExpression(target, (ctx) => 'std::monostate{}'); |
| 206 | // Find the target subtype and do an explicit conversion. |
| 207 | const subtype = target.types.find(t => t.equal(source)); |
| 208 | if (!subtype) |
| 209 | throw new Error(`The target union "${target.name}" does not contain the source type "${source.name}"`); |
| 210 | return castExpression(expr, subtype); |
| 211 | } |
| 212 | // From union to non-union. |
| 213 | if (source.category == 'union' && target.category != 'union') { |
| 214 | const subtype = source.types.find(t => t.equal(target)); |
| 215 | if (!subtype) { |
| 216 | // When casting to types like size_t, convert to double and try again. |
| 217 | if (target.isNonJsPrimitive()) |
| 218 | return castUnion(expr, Type.createNumberType(), source); |
| 219 | throw new Error(`The union "${source.name}" does not contain the target type "${target.name}"`); |
| 220 | } |
| 221 | return new CustomExpression(subtype, (ctx) => { |
| 222 | return `std::get<${subtype.print(ctx)}>(${expr.print(ctx)})`; |
| 223 | }); |
| 224 | } |
| 225 | return expr; |
| 226 | } |
| 227 | |
| 228 | /** |
| 229 | * Conversions between optionals. |
no test coverage detected