Collapse more nested patterns with auto-deref
2e8fdf4a863e6d07a2d77be009e7185e01a3bd596a9508571270b3f52e83f9c6
Lowerer: - lowerConstCallInto: SymbolData::Type(NominalType::Record(recInfo)) - lowerConstRecordLitInto: match on ty with nested Nominal patterns - lowerAggregateEq: Nominal(NominalType::Record/Union) as flat arms - lowerRecordLit: match on typ with nested Nominal patterns Resolver: - getRecordField: Type::Nominal(NominalType::Record(recInfo)) - isConstExpr: SymbolData::Type(NominalType::Record(recInfo)) - resolveFieldAccess: Type::Nominal(NominalType::Record(recordType))
1 parent
9875993b
lib/std/lang/lower.rad
+12 -26
| 1310 | 1310 | let calleeSym = resolver::nodeData(self.resolver, call.callee).sym |
|
| 1311 | 1311 | else throw LowerError::MissingSymbol(call.callee); |
|
| 1312 | 1312 | match calleeSym.data { |
|
| 1313 | 1313 | case resolver::SymbolData::Variant { .. } => |
|
| 1314 | 1314 | try lowerConstUnionVariantInto(self, node, calleeSym, ty, call.args, dataPrefix, b), |
|
| 1315 | - | case resolver::SymbolData::Type(nominal) => { |
|
| 1316 | - | let case resolver::NominalType::Record(recInfo) = *nominal |
|
| 1317 | - | else throw LowerError::MissingConst(node); |
|
| 1315 | + | case resolver::SymbolData::Type(resolver::NominalType::Record(recInfo)) => { |
|
| 1318 | 1316 | try lowerConstRecordCtorInto(self, call.args, recInfo, dataPrefix, b); |
|
| 1319 | 1317 | } |
|
| 1320 | 1318 | else => throw LowerError::MissingConst(node), |
|
| 1321 | 1319 | } |
|
| 1322 | 1320 | } |
| 1419 | 1417 | recLit: ast::RecordLit, |
|
| 1420 | 1418 | ty: resolver::Type, |
|
| 1421 | 1419 | dataPrefix: *[u8], |
|
| 1422 | 1420 | b: *mut DataValueBuilder |
|
| 1423 | 1421 | ) throws (LowerError) { |
|
| 1424 | - | let case resolver::Type::Nominal(nomType) = ty else { |
|
| 1425 | - | throw LowerError::ExpectedRecord; |
|
| 1426 | - | }; |
|
| 1427 | - | match *nomType { |
|
| 1428 | - | case resolver::NominalType::Record(recInfo) => { |
|
| 1422 | + | match ty { |
|
| 1423 | + | case resolver::Type::Nominal(resolver::NominalType::Record(recInfo)) => { |
|
| 1429 | 1424 | try lowerConstRecordCtorInto(self, recLit.fields, recInfo, dataPrefix, b); |
|
| 1430 | 1425 | } |
|
| 1431 | - | case resolver::NominalType::Union(_) => { |
|
| 1426 | + | case resolver::Type::Nominal(resolver::NominalType::Union(_)) => { |
|
| 1432 | 1427 | let typeName = recLit.typeName else { |
|
| 1433 | 1428 | throw LowerError::ExpectedVariant; |
|
| 1434 | 1429 | }; |
|
| 1435 | 1430 | let sym = resolver::nodeData(self.resolver, typeName).sym else { |
|
| 1436 | 1431 | throw LowerError::MissingSymbol(typeName); |
| 4498 | 4493 | } |
|
| 4499 | 4494 | case resolver::Type::Slice { item, mutable } => |
|
| 4500 | 4495 | return try lowerSliceEq(self, item, mutable, a, b, offset), |
|
| 4501 | 4496 | case resolver::Type::Array(arr) => |
|
| 4502 | 4497 | return try lowerArrayEq(self, arr, a, b, offset), |
|
| 4503 | - | case resolver::Type::Nominal(nom) => { |
|
| 4504 | - | match *nom { |
|
| 4505 | - | case resolver::NominalType::Record(recInfo) => |
|
| 4506 | - | return try lowerRecordEq(self, recInfo, a, b, offset), |
|
| 4507 | - | case resolver::NominalType::Union(unionInfo) => |
|
| 4508 | - | return try lowerUnionEq(self, unionInfo, a, b, offset), |
|
| 4509 | - | else => |
|
| 4510 | - | throw LowerError::ExpectedRecord, |
|
| 4511 | - | } |
|
| 4512 | - | } |
|
| 4498 | + | case resolver::Type::Nominal(resolver::NominalType::Record(recInfo)) => |
|
| 4499 | + | return try lowerRecordEq(self, recInfo, a, b, offset), |
|
| 4500 | + | case resolver::Type::Nominal(resolver::NominalType::Union(unionInfo)) => |
|
| 4501 | + | return try lowerUnionEq(self, unionInfo, a, b, offset), |
|
| 4513 | 4502 | else => { |
|
| 4514 | 4503 | let recInfo = recordInfoFromType(typ) else { |
|
| 4515 | 4504 | throw LowerError::ExpectedRecord; |
|
| 4516 | 4505 | }; |
|
| 4517 | 4506 | return try lowerRecordEq(self, recInfo, a, b, offset); |
| 4523 | 4512 | /// record literals like `Union::Variant { field: value }`. |
|
| 4524 | 4513 | fn lowerRecordLit(self: *mut FnLowerer, node: *ast::Node, lit: ast::RecordLit) -> il::Val throws (LowerError) { |
|
| 4525 | 4514 | let typ = resolver::typeFor(self.low.resolver, node) else { |
|
| 4526 | 4515 | throw LowerError::MissingType(node); |
|
| 4527 | 4516 | }; |
|
| 4528 | - | let case resolver::Type::Nominal(nominal) = typ else { |
|
| 4529 | - | throw LowerError::UnexpectedType(&typ); |
|
| 4530 | - | }; |
|
| 4531 | - | match *nominal { |
|
| 4532 | - | case resolver::NominalType::Record(recInfo) => { |
|
| 4517 | + | match typ { |
|
| 4518 | + | case resolver::Type::Nominal(resolver::NominalType::Record(recInfo)) => { |
|
| 4533 | 4519 | let dst = try emitReserve(self, typ); |
|
| 4534 | 4520 | try lowerRecordFields(self, dst, &recInfo, lit.fields, 0); |
|
| 4535 | 4521 | ||
| 4536 | 4522 | return il::Val::Reg(dst); |
|
| 4537 | 4523 | } |
|
| 4538 | - | case resolver::NominalType::Union(_) => { |
|
| 4524 | + | case resolver::Type::Nominal(resolver::NominalType::Union(_)) => { |
|
| 4539 | 4525 | // TODO: This can be inlined once we have a real register allocator. |
|
| 4540 | 4526 | return try lowerUnionRecordLit(self, typ, lit); |
|
| 4541 | 4527 | } |
|
| 4542 | - | else => throw LowerError::ExpectedRecord, |
|
| 4528 | + | else => throw LowerError::UnexpectedType(&typ), |
|
| 4543 | 4529 | } |
|
| 4544 | 4530 | } |
|
| 4545 | 4531 | ||
| 4546 | 4532 | /// Lower a union variant record literal like `Union::Variant { field: value }`. |
|
| 4547 | 4533 | fn lowerUnionRecordLit(self: *mut FnLowerer, typ: resolver::Type, lit: ast::RecordLit) -> il::Val throws (LowerError) { |
lib/std/lang/resolver.rad
+11 -18
| 1882 | 1882 | } |
|
| 1883 | 1883 | ||
| 1884 | 1884 | /// Get field info for a record-like type (records, slices) by field index. |
|
| 1885 | 1885 | pub fn getRecordField(ty: Type, index: u32) -> ?RecordField { |
|
| 1886 | 1886 | match ty { |
|
| 1887 | - | case Type::Nominal(info) => { |
|
| 1888 | - | let case NominalType::Record(recInfo) = *info else return nil; |
|
| 1887 | + | case Type::Nominal(NominalType::Record(recInfo)) => { |
|
| 1889 | 1888 | if index >= recInfo.fields.len { |
|
| 1890 | 1889 | return nil; |
|
| 1891 | 1890 | } |
|
| 1892 | 1891 | return recInfo.fields[index]; |
|
| 1893 | 1892 | } |
| 2895 | 2894 | // Constructor calls (union variants, unlabeled records) are constant |
|
| 2896 | 2895 | // if all payload args are themselves constant. |
|
| 2897 | 2896 | if let sym = symbolFor(self, call.callee) { |
|
| 2898 | 2897 | match sym.data { |
|
| 2899 | 2898 | case SymbolData::Variant { .. } => {} |
|
| 2900 | - | case SymbolData::Type(ty) => { |
|
| 2901 | - | if let case NominalType::Record(recInfo) = *ty { |
|
| 2902 | - | if recInfo.labeled { |
|
| 2903 | - | return false; |
|
| 2904 | - | } |
|
| 2905 | - | } else { |
|
| 2899 | + | case SymbolData::Type(NominalType::Record(recInfo)) => { |
|
| 2900 | + | if recInfo.labeled { |
|
| 2906 | 2901 | return false; |
|
| 2907 | 2902 | } |
|
| 2908 | 2903 | }, |
|
| 2909 | 2904 | else => return false, |
|
| 2910 | 2905 | } |
| 5348 | 5343 | { |
|
| 5349 | 5344 | let parentTy = try infer(self, access.parent); |
|
| 5350 | 5345 | let subjectTy = autoDeref(parentTy); |
|
| 5351 | 5346 | ||
| 5352 | 5347 | match subjectTy { |
|
| 5353 | - | case Type::Nominal(nominalTy) => { |
|
| 5354 | - | if let case NominalType::Record(recordType) = *nominalTy { |
|
| 5355 | - | let fieldNode = access.child; |
|
| 5356 | - | let fieldName = try nodeName(self, fieldNode); |
|
| 5357 | - | let fieldIndex = findRecordField(&recordType, fieldName) |
|
| 5358 | - | else throw emitError(self, node, ErrorKind::RecordFieldUnknown(fieldName)); |
|
| 5359 | - | let fieldTy = recordType.fields[fieldIndex].fieldType; |
|
| 5348 | + | case Type::Nominal(NominalType::Record(recordType)) => { |
|
| 5349 | + | let fieldNode = access.child; |
|
| 5350 | + | let fieldName = try nodeName(self, fieldNode); |
|
| 5351 | + | let fieldIndex = findRecordField(&recordType, fieldName) |
|
| 5352 | + | else throw emitError(self, node, ErrorKind::RecordFieldUnknown(fieldName)); |
|
| 5353 | + | let fieldTy = recordType.fields[fieldIndex].fieldType; |
|
| 5360 | 5354 | ||
| 5361 | - | setRecordFieldIndex(self, fieldNode, fieldIndex); |
|
| 5355 | + | setRecordFieldIndex(self, fieldNode, fieldIndex); |
|
| 5362 | 5356 | ||
| 5363 | - | return setNodeType(self, node, fieldTy); |
|
| 5364 | - | } |
|
| 5357 | + | return setNodeType(self, node, fieldTy); |
|
| 5365 | 5358 | } |
|
| 5366 | 5359 | case Type::Array(arrayInfo) => { |
|
| 5367 | 5360 | let fieldNode = access.child; |
|
| 5368 | 5361 | let fieldName = try nodeName(self, fieldNode); |
|
| 5369 | 5362 |