this repo has no description www.jonmsterling.com/01HC/
dependent-types proof-assistant swift
at pattern-unification 480 lines 11 kB view raw
1// SPDX-FileCopyrightText: 2025 The Project Pterodactyl Developers 2// SPDX-FileCopyrightText: 2026 The Project Pterodactyl Developers 3// 4// SPDX-License-Identifier: MPL-2.0 5 6import OrderedCollections 7 8extension Parser { 9 10 struct DelimiterInfo { 11 let left: TokenKind 12 let sep: TokenKind 13 let right: TokenKind 14 15 static var block: DelimiterInfo { 16 DelimiterInfo(left: .blockBegin, sep: .blockSep, right: .blockEnd) 17 } 18 19 static var curly: DelimiterInfo { 20 DelimiterInfo(left: .punctuation(.lbrace), sep: .punctuation(.semicolon), right: .punctuation(.rbrace)) 21 } 22 } 23 24 mutating func open(_ delim: DelimiterInfo) -> Bool { 25 guard isAt(kind: delim.left) else { return false } 26 expect(kind: delim.left) 27 _ = eatSeparators(delim) 28 return true 29 } 30 31 /// A liberal parser that allows unlimited dead delimiters separating only trivia. 32 mutating func eatSeparators(_ delim: DelimiterInfo) -> Bool { 33 eatTrivia() 34 var status = false 35 while eat(kind: delim.sep) { 36 status = true 37 eatTrivia() 38 } 39 return status 40 } 41 42 mutating func close(_ delim: DelimiterInfo) { 43 eatTrivia() 44 expect(kind: delim.right) 45 } 46 47 mutating func declLhs() { 48 var handle = structure(kind: .declLhs) 49 defer { handle.close() } 50 51 problemPattern() 52 } 53 54 mutating func problemPattern() { 55 var appHandle = structure(kind: .spine) 56 defer { appHandle.close() } 57 58 do { 59 var handle = structure(kind: .identifier) 60 defer { handle.close() } 61 expect(kind: .identifier, metadata: TokenMetadata(semanticTokenType: .function)) 62 } 63 64 eatTrivia() 65 66 var isNonempty = false 67 while trySpineFrame() { 68 eatTrivia() 69 isNonempty = true 70 } 71 72 if !isNonempty { appHandle.cancel() } 73 } 74 75 struct Scanner { 76 let tokens: [Token] 77 var position: Int 78 79 var currentToken: Token { tokens[position] } 80 81 mutating func eat(kindSatisfying predicate: (TokenKind) -> Bool) -> Bool { 82 guard position < tokens.count, predicate(currentToken.kind) else { return false } 83 position += 1 84 return true 85 } 86 87 mutating func eat(kind: TokenKind) -> Bool { 88 eat(kindSatisfying: { $0 == kind }) 89 } 90 91 mutating func eatTrivia() { 92 while position < tokens.count, currentToken.kind.isTrivia { position += 1 } 93 } 94 } 95 96 97 var isAtTypedBinder: Bool { 98 var scanner = Scanner(tokens: tokens, position: self.position) 99 guard scanner.eat(kind: .punctuation(.lparen)) else { return false } 100 scanner.eatTrivia() 101 guard scanner.eat(kind: .identifier) else { return false } 102 scanner.eatTrivia() 103 guard scanner.eat(kind: .punctuation(.colon)) else { return false } 104 return true 105 } 106 107 mutating func typedBinder() { 108 var handle = structure(kind: .typedBinder) 109 defer { handle.close() } 110 111 expect(kind: .punctuation(.lparen)) 112 eatTrivia() 113 expect(kind: .identifier) 114 eatTrivia() 115 expect(kind: .punctuation(.colon)) 116 eatTrivia() 117 expression() 118 eatTrivia() 119 expect(kind: .punctuation(.rparen)) 120 } 121 122 mutating func tryDepFunType() -> Bool { 123 guard isAtTypedBinder else { return false } 124 125 var handle = structure(kind: .depFunType) 126 defer { handle.close() } 127 128 while isAtTypedBinder { 129 typedBinder() 130 eatTrivia() 131 } 132 133 expect(kind: .punctuation(.rightArrow), metadata: TokenMetadata(semanticTokenType: .keyword)) 134 eatTrivia() 135 expression() 136 137 return true 138 } 139 140 mutating func tryRecordItem() -> Bool { 141 guard isAt(kind: .identifier) else { return false } 142 var handle = structure() 143 defer { handle.close() } 144 145 expect(kind: .identifier) 146 eatTrivia() 147 148 let choices: OrderedDictionary<TokenKind, (TokenMetadata?, RecordItemKind)> = [ 149 .punctuation(.colon): (TokenMetadata(semanticTokenType: .keyword), .spec), 150 .punctuation(.doubleRightArrow): (TokenMetadata(semanticTokenType: .keyword), .impl) 151 ] 152 153 if let kind = expect(choices: choices) { 154 handle.kind = .recordItem(kind: kind) 155 eatTrivia() 156 expression() 157 } else { 158 handle.cancel() 159 } 160 161 return true 162 } 163 164 mutating func tryRecord() -> Bool { 165 var handle = structure(kind: .record) 166 defer { handle.close() } 167 168 let delim = DelimiterInfo.curly 169 guard open(delim) else { 170 handle.cancel() 171 return false 172 } 173 defer { close(delim) } 174 175 while true { 176 _ = tryRecordItem() 177 guard eatSeparators(delim) else { break } 178 } 179 return true 180 } 181 182 mutating func tryReflExpression() -> Bool { 183 guard isAt(kind: .keyword(.refl)) else { return false } 184 185 var handle = structure(kind: .refl) 186 defer { handle.close() } 187 188 expect(kind: .keyword(.refl), metadata: TokenMetadata(semanticTokenType: .keyword)) 189 return true 190 } 191 192 mutating func universeCodesExpression() -> Bool { 193 let kind = TokenKind.keyword(.type) 194 guard isAt(kind: kind) else { return false } 195 196 var handle = structure(kind: .universeCodes) 197 defer { handle.close() } 198 199 expect(kind: kind, metadata: TokenMetadata(semanticTokenType: .type)) // TODO: is this the right semantic token type? 200 201 return true 202 } 203 204 mutating func holeExpression() -> Bool { 205 let kind = TokenKind.punctuation(.questionMark) 206 guard isAt(kind: kind) else { return false } 207 208 var handle = structure(kind: .hole) 209 defer { handle.close() } 210 211 expect(kind: kind, metadata: TokenMetadata(semanticTokenType: .comment, semanticTokenModifiers: [.abstract])) 212 213 return true 214 } 215 216 mutating func identifierExpression() -> Bool { 217 guard isAt(kind: .identifier) else { return false } 218 var handle = structure(kind: .identifier) 219 defer { handle.close() } 220 expect(kind: .identifier) 221 return true 222 } 223 224 mutating func parenthesisedExpression() -> Bool { 225 guard isAt(kind: .punctuation(.lparen)) else { return false } 226 expect(kind: .punctuation(.lparen)) 227 eatTrivia() 228 expression() 229 eatTrivia() 230 expect(kind: .punctuation(.rparen)) 231 return true 232 } 233 234 mutating func tryAppFrame() -> Bool { 235 var handle = structure(kind: .appFrame) 236 defer { handle.close() } 237 238 guard tryAtomicExpression() else { 239 handle.cancel() 240 return false 241 } 242 243 return true 244 } 245 246 mutating func tryProjFrame() -> Bool { 247 guard isAt(kind: .punctuation(.dot)) else { return false } 248 249 var handle = structure(kind: .projFrame) 250 defer { handle.close() } 251 252 expect(kind: .punctuation(.dot)) 253 expect(kind: .identifier) 254 255 return true 256 } 257 258 mutating func trySpineFrame() -> Bool { 259 tryAppFrame() || tryProjFrame() 260 } 261 262 mutating func trySpineOrIdExpression() -> Bool { 263 var handle = structure() 264 defer { handle.close() } 265 266 guard tryAtomicExpression() else { 267 handle.cancel() 268 return false 269 } 270 271 eatTrivia() 272 273 if isAt(kind: .punctuation(.equal)) { 274 handle.kind = .idType 275 expect(kind: .punctuation(.equal), metadata: TokenMetadata(semanticTokenType: .operator)) 276 eatTrivia() 277 atomicExpression() 278 return true 279 } else { 280 handle.kind = .spine 281 282 var isNonempty = false 283 while trySpineFrame() { 284 eatTrivia() 285 isNonempty = true 286 } 287 288 if !isNonempty { handle.cancel() } 289 290 return true 291 } 292 } 293 294 mutating func tryAtomicExpression() -> Bool { 295 return holeExpression() 296 || universeCodesExpression() 297 || identifierExpression() 298 || parenthesisedExpression() 299 || tryRecord() 300 || tryReflExpression() 301 } 302 303 mutating func atomicExpression() { 304 guard tryAtomicExpression() else { 305 return advance(error: "Expected atomic expression") 306 } 307 } 308 309 mutating func tryExpression() -> Bool { 310 if tryDepFunType() { return true } 311 312 var handle = structure() 313 defer { handle.close() } 314 315 guard trySpineOrIdExpression() else { 316 handle.cancel() 317 return false 318 } 319 320 var scanner = Scanner(tokens: tokens, position: position) 321 scanner.eatTrivia() 322 if scanner.eat(kind: .punctuation(.rightArrow)) { 323 handle.kind = .funType 324 eatTrivia() 325 expect(kind: .punctuation(.rightArrow), metadata: TokenMetadata(semanticTokenType: .keyword)) 326 eatTrivia() 327 expression() 328 } else { 329 handle.cancel() 330 } 331 332 return true 333 } 334 335 mutating func expression() { 336 guard tryExpression() else { 337 return advance(error: "Expected expression") 338 } 339 } 340 341 mutating func declRhs(declKind: SyntaxTreeKind) { 342 var handle = structure(kind: .declRhs) 343 defer { handle.close() } 344 345 switch declKind { 346 case .claimDecl, .defineDecl: 347 _ = tryExpression() 348 case .refineDecl: 349 _ = eat(kind: .identifier, metadata: TokenMetadata(semanticTokenType: .keyword)) // TODO 350 default: 351 return 352 } 353 } 354 355 mutating func tryLeafDecl() -> Bool { 356 guard isAt(kind: .identifier) else { return false } 357 358 var handle = structure() 359 defer { handle.close() } 360 361 declLhs() 362 eatTrivia() 363 364 switch currentToken.kind { 365 case .punctuation(.doubleLeftArrow): 366 advance(metadata: TokenMetadata(semanticTokenType: .keyword)) 367 handle.kind = .refineDecl 368 case .punctuation(.doubleRightArrow): 369 advance(metadata: TokenMetadata(semanticTokenType: .keyword)) 370 handle.kind = .defineDecl 371 case .punctuation(.colon): 372 advance(metadata: TokenMetadata(semanticTokenType: .keyword)) 373 handle.kind = .claimDecl 374 default: 375 handle.kind = .probeDecl 376 } 377 378 eatTrivia() 379 declRhs(declKind: handle.kind) 380 381 return true 382 } 383 384 mutating func tryDecl() -> Bool { 385 return tryTheory() || tryLeafDecl() 386 } 387 388 mutating func keyword(_ keyword: Keyword) { 389 expect(kind: .keyword(keyword), metadata: TokenMetadata(semanticTokenType: .keyword)) 390 } 391 392 mutating func theoryName() { 393 var handle = structure(kind: .theoryName) 394 defer { handle.close() } 395 expect(kind: .identifier, metadata: TokenMetadata(semanticTokenType: .interface)) 396 } 397 398 mutating func theoryBlock() { 399 var handle = recoveryStack.push([.blockSep, .blockEnd]) 400 defer { handle.close() } 401 402 let delim = DelimiterInfo.block 403 404 guard open(delim) else { return } 405 defer { close(delim) } 406 407 while true { 408 _ = tryDecl() 409 guard eatSeparators(delim) else { break } 410 } 411 } 412 413 mutating func tryTheory() -> Bool { 414 guard isAt(kind: .keyword(.theory)) else { return false } 415 416 var handle = structure(kind: .theory, metadata: SyntaxTreeMetadata(delimitedFoldingRangeKind: .region)) 417 defer { handle.close() } 418 419 eatTrivia() 420 keyword(.theory) 421 eatTrivia() 422 theoryName() 423 eatTrivia() 424 keyword(.where) 425 eatTrivia() 426 theoryBlock() 427 428 return true 429 } 430 431 mutating func importName() { 432 var handle = structure(kind: .importName) 433 defer { handle.close() } 434 expect(kind: .identifier) 435 } 436 437 mutating func importDecl() -> Bool { 438 guard isAt(kind: .keyword(.import)) else { return false } 439 440 var handle = structure(kind: .import) 441 defer { handle.close() } 442 443 keyword(.import) 444 eatTrivia() 445 importName() 446 447 return true 448 } 449 450 mutating func tryDocumentItem() -> Bool { 451 if importDecl() { return true } 452 return tryDecl() 453 } 454 455 mutating func documentBlock() { 456 var handle = recoveryStack.push([.blockSep, .blockEnd]) 457 defer { handle.close() } 458 459 let delim = DelimiterInfo.block 460 461 guard open(delim) else { return } 462 defer { close(delim) } 463 464 while true { 465 _ = tryDocumentItem() 466 guard eatSeparators(delim) else { break } 467 } 468 } 469 470 public mutating func document() { 471 var handle = structure(kind: .document) 472 defer { handle.close() } 473 474 eatTrivia() 475 documentBlock() 476 eatTrivia() 477 478 expect(kind: .eof) 479 } 480}