@@ -1037,5 +1037,242 @@ final class RegisterMacroTests: XCTestCase {
1037
1037
macros: Self . macros,
1038
1038
indentationWidth: Self . indentationWidth)
1039
1039
}
1040
+
1041
+ func test_bitRange_overlap( ) {
1042
+ XCTAssertTrue ( ![ BitRange] ( ) . isOverlapped)
1043
+ let bitRange1 = BitRange ( " [1, 1] " )
1044
+ let bitRange2 = BitRange ( " [1, 1] " )
1045
+ XCTAssertTrue ( [ bitRange1, bitRange2] . isOverlapped)
1046
+ let bitRange3 = BitRange ( " (-∞, 1] " )
1047
+ let bitRange4 = BitRange ( " (-∞, 1] " )
1048
+ XCTAssertTrue ( [ bitRange3, bitRange4] . isOverlapped)
1049
+ let bitRange5 = BitRange ( " (1, +∞) " )
1050
+ let bitRange6 = BitRange ( " (1, +∞) " )
1051
+ XCTAssertTrue ( [ bitRange5, bitRange6] . isOverlapped)
1052
+ let bitRange7 = BitRange ( " (1, 2] " )
1053
+ let bitRange8 = BitRange ( " [2, +∞) " )
1054
+ XCTAssertTrue ( [ bitRange7, bitRange8] . isOverlapped)
1055
+ XCTAssertTrue ( [ bitRange8, bitRange7] . isOverlapped)
1056
+ let bitRange9 = BitRange ( " [1, 2) " )
1057
+ let bitRange10 = BitRange ( " (1, +∞) " )
1058
+ XCTAssertTrue ( ![ bitRange9, bitRange10] . isOverlapped)
1059
+ XCTAssertTrue ( ![ bitRange10, bitRange9] . isOverlapped)
1060
+ }
1061
+
1062
+ func test_overlapped_bitRanges_detection_multipleFields( ) {
1063
+ let bitRanges : [ BitRange ] = [
1064
+ . init( " [0, 2) " ) !,
1065
+ . init( " [1, 2) " ) !,
1066
+ ]
1067
+ assertMacroExpansion (
1068
+ """
1069
+ @Register(bitWidth: 0x8)
1070
+ public struct S {
1071
+ @ReadOnly(bits: 0..<2, as: Bool.self)
1072
+ var v1: V1
1073
+ @WriteOnly(bits: 1..<2, as: Bool.self)
1074
+ var v2: V2
1075
+ }
1076
+ """ ,
1077
+ expandedSource: """
1078
+ public struct S {
1079
+ @available(*, unavailable)
1080
+ var v1: V1 {
1081
+ get {
1082
+ fatalError()
1083
+ }
1084
+ }
1085
+ @available(*, unavailable)
1086
+ var v2: V2 {
1087
+ get {
1088
+ fatalError()
1089
+ }
1090
+ }
1091
+
1092
+ private init() {
1093
+ fatalError()
1094
+ }
1095
+
1096
+ private var _never: Never
1097
+
1098
+ public enum V1: ContiguousBitField {
1099
+ public typealias Storage = UInt8
1100
+ public typealias Projection = Bool
1101
+ public static let bitRange = 0 ..< 2
1102
+ }
1103
+
1104
+ public enum V2: ContiguousBitField {
1105
+ public typealias Storage = UInt8
1106
+ public typealias Projection = Bool
1107
+ public static let bitRange = 1 ..< 2
1108
+ }
1109
+
1110
+ public struct Raw: RegisterValueRaw {
1111
+ public typealias Value = S
1112
+ public typealias Storage = UInt8
1113
+ public var storage: Storage
1114
+ public init(_ storage: Storage) {
1115
+ self.storage = storage
1116
+ }
1117
+ public init(_ value: Value.Read) {
1118
+ self.storage = value.storage
1119
+ }
1120
+ public init(_ value: Value.Write) {
1121
+ self.storage = value.storage
1122
+ }
1123
+ public var v1: UInt8 {
1124
+ @inlinable @inline(__always) get {
1125
+ V1.extractBits(from: self.storage)
1126
+ }
1127
+ @inlinable @inline(__always) set {
1128
+ V1.insertBits(newValue, into: &self.storage)
1129
+ }
1130
+ }
1131
+ public var v2: UInt8 {
1132
+ @inlinable @inline(__always) get {
1133
+ V2.extractBits(from: self.storage)
1134
+ }
1135
+ @inlinable @inline(__always) set {
1136
+ V2.insertBits(newValue, into: &self.storage)
1137
+ }
1138
+ }
1139
+ }
1140
+
1141
+ public struct Read: RegisterValueRead {
1142
+ public typealias Value = S
1143
+ var storage: UInt8
1144
+ public init(_ value: Raw) {
1145
+ self.storage = value.storage
1146
+ }
1147
+ public var v1: Bool {
1148
+ @inlinable @inline(__always) get {
1149
+ V1.extract(from: self.storage)
1150
+ }
1151
+ }
1152
+ }
1153
+
1154
+ public struct Write: RegisterValueWrite {
1155
+ public typealias Value = S
1156
+ var storage: UInt8
1157
+ public init(_ value: Raw) {
1158
+ self.storage = value.storage
1159
+ }
1160
+ public init(_ value: Read) {
1161
+ // FIXME: mask off bits
1162
+ self.storage = value.storage
1163
+ }
1164
+ public var v2: Bool {
1165
+ @available(*, deprecated, message: " API misuse; read from write view returns the value to be written, not the value initially read. " )
1166
+ @inlinable @inline(__always) get {
1167
+ V2.extract(from: self.storage)
1168
+ }
1169
+ @inlinable @inline(__always) set {
1170
+ V2.insert(newValue, into: &self.storage)
1171
+ }
1172
+ }
1173
+ }
1174
+ }
1175
+
1176
+ """ ,
1177
+ diagnostics: [
1178
+ . init(
1179
+ message: ErrorDiagnostic . cannotHaveOverlappedBitRanges ( bitRanges) . message,
1180
+ line: 1 ,
1181
+ column: 1 ,
1182
+ highlights: [ " @Register(bitWidth: 0x8) " ] ) ,
1183
+ ] ,
1184
+ macros: Self . macros,
1185
+ indentationWidth: Self . indentationWidth)
1186
+ }
1187
+
1188
+ func test_overlapped_bitRanges_detection_multipleBitRangesInOneFields( ) {
1189
+ let bitRanges : [ BitRange ] = [
1190
+ . init( " [0, 4) " ) !,
1191
+ . init( " [3, 4) " ) !,
1192
+ ]
1193
+ assertMacroExpansion (
1194
+ """
1195
+ @Register(bitWidth: 0x8)
1196
+ struct S {
1197
+ @ReadWrite(bits: 0..<4, 3..<4, as: UInt16.self)
1198
+ var v1: V1
1199
+ }
1200
+ """ ,
1201
+ expandedSource: """
1202
+ struct S {
1203
+ @available(*, unavailable)
1204
+ var v1: V1 {
1205
+ get {
1206
+ fatalError()
1207
+ }
1208
+ }
1209
+
1210
+ private init() {
1211
+ fatalError()
1212
+ }
1213
+
1214
+ private var _never: Never
1215
+
1216
+ enum V1: DiscontiguousBitField {
1217
+ typealias Storage = UInt8
1218
+ typealias Projection = UInt16
1219
+ static let bitRanges = [0 ..< 4, 3 ..< 4]
1220
+ }
1221
+
1222
+ struct Raw: RegisterValueRaw {
1223
+ typealias Value = S
1224
+ typealias Storage = UInt8
1225
+ var storage: Storage
1226
+ init(_ storage: Storage) {
1227
+ self.storage = storage
1228
+ }
1229
+ init(_ value: Value.ReadWrite) {
1230
+ self.storage = value.storage
1231
+ }
1232
+ var v1: UInt8 {
1233
+ @inlinable @inline(__always) get {
1234
+ V1.extractBits(from: self.storage)
1235
+ }
1236
+ @inlinable @inline(__always) set {
1237
+ V1.insertBits(newValue, into: &self.storage)
1238
+ }
1239
+ }
1240
+ }
1241
+
1242
+ typealias Read = ReadWrite
1243
+
1244
+ typealias Write = ReadWrite
1245
+
1246
+ struct ReadWrite: RegisterValueRead, RegisterValueWrite {
1247
+ typealias Value = S
1248
+ var storage: UInt8
1249
+ init(_ value: ReadWrite) {
1250
+ self.storage = value.storage
1251
+ }
1252
+ init(_ value: Raw) {
1253
+ self.storage = value.storage
1254
+ }
1255
+ var v1: UInt16 {
1256
+ @inlinable @inline(__always) get {
1257
+ V1.extract(from: self.storage)
1258
+ }
1259
+ @inlinable @inline(__always) set {
1260
+ V1.insert(newValue, into: &self.storage)
1261
+ }
1262
+ }
1263
+ }
1264
+ }
1265
+
1266
+ """ ,
1267
+ diagnostics: [
1268
+ . init(
1269
+ message: ErrorDiagnostic . cannotHaveOverlappedBitRanges ( bitRanges) . message,
1270
+ line: 1 ,
1271
+ column: 1 ,
1272
+ highlights: [ " @Register(bitWidth: 0x8) " ] ) ,
1273
+ ] ,
1274
+ macros: Self . macros,
1275
+ indentationWidth: Self . indentationWidth)
1276
+ }
1040
1277
}
1041
1278
#endif
0 commit comments