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))
Alexis Sellier committed ago 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