modernc.org/knuth@v0.0.4/web/pascal.go (about) 1 // Copyright 2023 The Knuth Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package web // modernc.org/knuth/web 6 7 import ( 8 "fmt" 9 "go/token" 10 "math" 11 "path/filepath" 12 "strconv" 13 "strings" 14 15 "modernc.org/mathutil" 16 mtoken "modernc.org/token" 17 ) 18 19 var ( 20 _ node = (*pasToken)(nil) 21 22 pasKeywords = map[string]token.Token{ 23 "and": tokAnd, 24 "array": tokArray, 25 "begin": tokBegin, 26 "case": tokCase, 27 "const": tokConst, 28 "div": tokDiv, 29 "do": tokDo, 30 "downto": tokDownto, 31 "else": tokElse, 32 "end": tokEnd, 33 "file": tokFile, 34 "for": tokFor, 35 "function": tokFunction, 36 "goto": tokGoto, 37 "if": tokIf, 38 "in": tokIn, 39 "label": tokLabel, 40 "mod": tokMod, 41 "nil": tokNil, 42 "not": tokNot, 43 "of": tokOf, 44 "or": tokOr, 45 "packed": tokPacked, 46 "procedure": tokProcedure, 47 "program": tokProgram, 48 "record": tokRecord, 49 "repeat": tokRepeat, 50 "set": tokSet, 51 "then": tokThen, 52 "to": tokTo, 53 "type": tokType, 54 "until": tokUntil, 55 "var": tokVar, 56 "while": tokWhile, 57 "with": tokWith, 58 } 59 ) 60 61 const ( 62 tokEOF = -iota - 1 63 64 tokAssign 65 tokEllipsis 66 tokFloat 67 tokGeq 68 tokIdent 69 tokInt 70 tokInvalid 71 tokLeq 72 tokNeq 73 tokString 74 tokZero 75 76 tokAnd 77 tokArray 78 tokBegin 79 tokCase 80 tokConst 81 tokDiv 82 tokDo 83 tokDownto 84 tokElse 85 tokEnd 86 tokFile 87 tokFor 88 tokFunction 89 tokGoto 90 tokIf 91 tokIn 92 tokLabel 93 tokMod 94 tokNil 95 tokNot 96 tokOf 97 tokOr 98 tokPacked 99 tokProcedure 100 tokProgram 101 tokRecord 102 tokRepeat 103 tokSet 104 tokThen 105 tokTo 106 tokType 107 tokUntil 108 tokVar 109 tokWhile 110 tokWith 111 ) 112 113 const ( 114 charAlign = 1 115 charSize = 1 116 integerAlign = 4 117 integerSize = 4 118 real32Align = 4 119 real32Size = 4 120 realAlign = 8 121 realSize = 8 122 ) 123 124 // node is an item of the CST tree. 125 type node interface { 126 Position() token.Position 127 } 128 129 // pasToken represents a lexeme, its position and its semantic value. 130 type pasToken struct { // 16 bytes on 64 bit arch 131 source *pasSource 132 133 ch int32 134 index int32 135 } 136 137 func (t pasToken) String() string { return fmt.Sprintf("%v: %q %#U", t.Position(), t.Src(), t.ch) } 138 139 // isValid reports t is a valid token. Zero value reports false. 140 func (t pasToken) isValid() bool { return t.source != nil } 141 142 // Next returns the token following t or a zero value if no such token exists. 143 func (t pasToken) Next() (r pasToken) { 144 if t.source == nil { 145 return r 146 } 147 148 if index := t.index + 1; index < int32(len(t.source.toks)) { 149 s := t.source 150 return pasToken{source: s, ch: s.toks[index].ch, index: index} 151 } 152 153 return r 154 } 155 156 // Sep returns any separators, combined, preceding t. 157 func (t pasToken) Sep() string { 158 if t.source == nil { 159 return "" 160 } 161 162 s := t.source 163 if p, ok := s.sepPatches[t.index]; ok { 164 return p 165 } 166 167 return string(s.buf[s.toks[t.index].sep:s.toks[t.index].src]) 168 } 169 170 // Src returns t's source form. 171 func (t pasToken) Src() string { 172 if t.source == nil { 173 return "" 174 } 175 176 s := t.source 177 if p, ok := s.srcPatches[t.index]; ok { 178 return p 179 } 180 181 if t.ch != int32(tokEOF) { 182 next := t.source.off 183 if t.index < int32(len(s.toks))-1 { 184 next = s.toks[t.index+1].sep 185 } 186 return string(s.buf[s.toks[t.index].src:next]) 187 } 188 189 return "" 190 } 191 192 // Positions implements Node. 193 func (t pasToken) Position() (r token.Position) { 194 if t.source == nil { 195 return r 196 } 197 198 s := t.source 199 off := mathutil.MinInt32(int32(len(s.buf)), s.toks[t.index].src) 200 return token.Position(s.file.PositionFor(mtoken.Pos(s.base+off), true)) 201 } 202 203 type tok struct { // 12 bytes 204 ch int32 205 sep int32 206 src int32 207 } 208 209 // pasSource represents a single Go pasSource file, editor text buffer etc. 210 type pasSource struct { 211 buf []byte 212 file *mtoken.File 213 name string 214 sepPatches map[int32]string 215 srcPatches map[int32]string 216 toks []tok 217 218 base int32 219 off int32 220 } 221 222 // 'buf' becomes owned by the result and must not be modified afterwards. 223 func newPasSource(name string, buf []byte) *pasSource { 224 file := mtoken.NewFile(name, len(buf)) 225 return &pasSource{ 226 buf: buf, 227 file: file, 228 name: name, 229 base: int32(file.Base()), 230 } 231 } 232 233 type errWithPosition struct { 234 pos token.Position 235 err error 236 } 237 238 func (e errWithPosition) String() string { 239 switch { 240 case e.pos.IsValid(): 241 return fmt.Sprintf("%v: %v", e.pos, e.err) 242 default: 243 return fmt.Sprintf("%v", e.err) 244 } 245 } 246 247 type errList []errWithPosition 248 249 func (e errList) Err() (r error) { 250 if len(e) == 0 { 251 return nil 252 } 253 254 return e 255 } 256 257 func (e errList) Error() string { 258 w := 0 259 prev := errWithPosition{pos: token.Position{Offset: -1}} 260 for _, v := range e { 261 if v.pos.Line == 0 || v.pos.Offset != prev.pos.Offset || v.err.Error() != prev.err.Error() { 262 e[w] = v 263 w++ 264 prev = v 265 } 266 } 267 268 var a []string 269 for _, v := range e { 270 a = append(a, fmt.Sprint(v)) 271 } 272 return strings.Join(a, "\n") 273 } 274 275 func (e *errList) err(pos token.Position, msg string, args ...interface{}) { 276 switch { 277 case len(args) == 0: 278 *e = append(*e, errWithPosition{pos, fmt.Errorf("%s", msg)}) 279 default: 280 *e = append(*e, errWithPosition{pos, fmt.Errorf(msg, args...)}) 281 } 282 } 283 284 type pasScanner struct { 285 *pasSource 286 dir string 287 errs errList 288 tok tok 289 290 last int32 291 292 errBudget int 293 294 c byte // Look ahead byte. 295 296 eof bool 297 isClosed bool 298 } 299 300 func newPasScanner(name string, buf []byte) *pasScanner { 301 dir, _ := filepath.Split(name) 302 r := &pasScanner{pasSource: newPasSource(name, buf), errBudget: 10, dir: dir} 303 switch { 304 case len(buf) == 0: 305 r.eof = true 306 default: 307 r.c = buf[0] 308 if r.c == '\n' { 309 r.file.AddLine(int(r.base + r.off)) 310 } 311 } 312 return r 313 } 314 315 func (s *pasScanner) isDigit(c byte) bool { return c >= '0' && c <= '9' } 316 func (s *pasScanner) isIDNext(c byte) bool { return s.isIDFirst(c) || s.isDigit(c) } 317 func (s *pasScanner) isOctalDigit(c byte) bool { return c >= '0' && c <= '7' } 318 319 func (s *pasScanner) isHexDigit(c byte) bool { 320 return s.isDigit(c) || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F' 321 } 322 323 func (s *pasScanner) isIDFirst(c byte) bool { 324 return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_' 325 } 326 327 func (s *pasScanner) position() token.Position { 328 return token.Position(s.pasSource.file.PositionFor(mtoken.Pos(s.base+s.off), true)) 329 } 330 331 func (s *pasScanner) pos(off int32) token.Position { 332 return token.Position(s.file.PositionFor(mtoken.Pos(s.base+off), true)) 333 } 334 335 func (s *pasScanner) close() { 336 if s.isClosed { 337 return 338 } 339 340 s.tok.ch = int32(tokInvalid) 341 s.eof = true 342 s.isClosed = true 343 } 344 345 func (s *pasScanner) token() pasToken { 346 return pasToken{source: s.pasSource, ch: s.tok.ch, index: int32(len(s.toks) - 1)} 347 } 348 349 func (s *pasScanner) peek(off int) rune { 350 if n := s.off + int32(off); n < int32(len(s.buf)) { 351 return rune(s.buf[n]) 352 } 353 354 return -1 355 } 356 357 func (s *pasScanner) next() { 358 if s.eof { 359 return 360 } 361 362 s.off++ 363 if int(s.off) == len(s.buf) { 364 s.c = 0 365 s.eof = true 366 return 367 } 368 369 s.c = s.buf[s.off] 370 if s.c == '\n' { 371 s.file.AddLine(int(s.base + s.off)) 372 } 373 } 374 375 func (s *pasScanner) err(off int32, msg string, args ...interface{}) { 376 if s.errBudget <= 0 { 377 s.close() 378 return 379 } 380 381 s.errBudget-- 382 if n := int32(len(s.buf)); off >= n { 383 off = n 384 } 385 s.errs.err(s.pos(off), msg, args...) 386 } 387 388 func (s *pasScanner) scan() (r bool) { 389 if s.isClosed { 390 return false 391 } 392 393 s.last = s.tok.ch 394 s.tok.sep = s.off 395 s.tok.ch = tokZero 396 for { 397 if r = s.scan0(); !r || s.tok.ch != tokZero { 398 s.toks = append(s.toks, s.tok) 399 return r 400 } 401 } 402 } 403 404 func (s *pasScanner) scan0() (r bool) { 405 s.tok.src = mathutil.MinInt32(s.off, int32(len(s.buf))) 406 switch s.c { 407 case '{': 408 off := s.off 409 s.next() 410 s.generalComment(off) 411 case ' ', '\t', '\r', '\n': 412 s.next() 413 case '(', ',', ')', ';', '=', '[', ']', '+', '-', '*', '/', '^': 414 s.tok.ch = rune(s.c) 415 s.next() 416 case '.': 417 s.next() 418 if s.c != '.' { 419 s.tok.ch = '.' 420 return true 421 } 422 423 s.next() 424 s.tok.ch = int32(tokEllipsis) 425 case ':': 426 s.tok.ch = ':' 427 s.next() 428 if s.c == '=' { 429 s.next() 430 s.tok.ch = int32(tokAssign) 431 } 432 case '\'', '"': 433 s.stringLiteral() 434 case '>': 435 s.next() 436 switch s.c { 437 case '=': 438 s.next() 439 s.tok.ch = int32(tokGeq) 440 default: 441 s.tok.ch = '>' 442 } 443 case '<': 444 s.next() 445 switch s.c { 446 case '>': 447 s.next() 448 s.tok.ch = int32(tokNeq) 449 case '=': 450 s.next() 451 s.tok.ch = int32(tokLeq) 452 default: 453 s.tok.ch = '<' 454 } 455 default: 456 switch { 457 case s.isIDFirst(s.c): 458 s.next() 459 s.identifierOrKeyword() 460 case s.isDigit(s.c): 461 s.numericLiteral() 462 case s.eof: 463 s.close() 464 s.tok.ch = int32(tokEOF) 465 s.tok.sep = mathutil.MinInt32(s.tok.sep, s.tok.src) 466 return false 467 default: 468 panic(todo("%v: %#U", s.position(), s.c)) 469 } 470 } 471 return true 472 } 473 474 func (s *pasScanner) stringLiteral() { 475 // Leadind " or ' not consumed. 476 off := s.off 477 ch := s.c 478 s.next() 479 s.tok.ch = int32(tokString) 480 for { 481 switch { 482 case s.c == ch: 483 s.next() 484 if s.c != ch { 485 return 486 } 487 case s.c == '\n': 488 fallthrough 489 case s.eof: 490 s.err(off, "string literal not terminated") 491 return 492 } 493 s.next() 494 } 495 } 496 497 func (s *pasScanner) numericLiteral() { 498 // Leading decimal digit not consumed. 499 more: 500 switch s.c { 501 case '0': 502 s.next() 503 switch s.c { 504 case 'x', 'X': 505 s.tok.ch = int32(tokInt) 506 s.next() 507 if s.hexadecimals() == 0 { 508 s.err(s.base+s.off, "hexadecimal literal has no digits") 509 return 510 } 511 case '.': 512 s.tok.ch = int32(tokInt) 513 if s.isDigit(byte(s.peek(1))) { 514 s.next() 515 s.decimals() 516 s.tok.ch = int32(tokFloat) 517 } 518 return 519 default: 520 invalidOff := int32(-1) 521 var invalidDigit byte 522 for { 523 if s.isOctalDigit(s.c) { 524 s.next() 525 continue 526 } 527 528 if s.isDigit(s.c) { 529 if invalidOff < 0 { 530 invalidOff = s.off 531 invalidDigit = s.c 532 } 533 s.next() 534 continue 535 } 536 537 break 538 } 539 switch s.c { 540 case '.', 'e', 'E', 'i': 541 break more 542 } 543 if s.isDigit(s.c) { 544 break more 545 } 546 if invalidOff > 0 { 547 s.err(invalidOff, "invalid digit '%c' in octal literal", invalidDigit) 548 } 549 s.tok.ch = int32(tokInt) 550 return 551 } 552 default: 553 s.decimals() 554 if s.c == '.' && s.isDigit(byte(s.peek(1))) { 555 s.next() 556 s.decimals() 557 s.tok.ch = int32(tokFloat) 558 return 559 } 560 } 561 s.tok.ch = int32(tokInt) 562 563 } 564 565 func (s *pasScanner) hexadecimals() (r int) { 566 for { 567 switch { 568 case s.isHexDigit(s.c): 569 s.next() 570 r++ 571 case s.c == '_': 572 for n := 0; s.c == '_'; n++ { 573 if n == 1 { 574 s.err(s.off, "'_' must separate successive digits") 575 } 576 s.next() 577 } 578 if !s.isHexDigit(s.c) { 579 s.err(s.off-1, "'_' must separate successive digits") 580 } 581 default: 582 return r 583 } 584 } 585 } 586 587 func (s *pasScanner) decimals() (r int) { 588 for { 589 switch { 590 case s.isDigit(s.c): 591 s.next() 592 r++ 593 default: 594 return r 595 } 596 } 597 } 598 599 func (s *pasScanner) generalComment(off int32) { 600 // Leading "{" consumed 601 for { 602 switch { 603 case s.c == '}': 604 s.next() 605 return 606 case s.eof: 607 s.tok.ch = 0 608 s.err(off, "comment not terminated") 609 return 610 default: 611 s.next() 612 } 613 } 614 } 615 616 func (s *pasScanner) identifierOrKeyword() { 617 for { 618 switch { 619 case s.isIDNext(s.c): 620 s.next() 621 default: 622 if s.tok.ch = int32(pasKeywords[strings.ToLower(string(s.buf[s.tok.src:s.off]))]); s.tok.ch == 0 { 623 s.tok.ch = int32(tokIdent) 624 } 625 return 626 } 627 } 628 } 629 630 func pasParse(s *pasScanner) (r *ast, err error) { 631 p := newPasParser(s) 632 p.scan() 633 program := p.program() 634 if p.c() != eof { 635 panic(todo("", p.token())) 636 } 637 638 if err = p.errs.Err(); err != nil { 639 return nil, err 640 } 641 642 return &ast{ 643 program: program, 644 eof: p.token(), 645 }, nil 646 } 647 648 type pasParser struct { 649 *pasScanner 650 scope *scope 651 } 652 653 func newPasParser(s *pasScanner) (r *pasParser) { 654 return &pasParser{ 655 pasScanner: s, 656 scope: newScope(nil), 657 } 658 } 659 660 func (p *pasParser) c() rune { return p.tok.ch } 661 func (p *pasParser) mustIdent(ch rune) (r *identifier) { return &identifier{ident: p.must(ch)} } 662 func (p *pasParser) shift() pasToken { r := p.token(); p.scan(); return r } 663 664 func (p *pasParser) must(ch rune) (r pasToken) { 665 if p.c() == ch { 666 r = p.token() 667 } else { 668 panic(todo("", p.token())) 669 } 670 671 p.shift() 672 return r 673 } 674 675 func (p *pasParser) opt(ch rune) (r pasToken) { 676 if p.c() == ch { 677 r = p.shift() 678 } 679 return r 680 } 681 682 type program struct { 683 programHeading *programHeading 684 semi pasToken 685 block *block 686 dot pasToken 687 } 688 689 // Program = ProgramHeading ";" Block "." . 690 func (p *pasParser) program() (r *program) { 691 switch p.c() { 692 case tokProgram: 693 return &program{ 694 p.programHeading(), 695 p.must(';'), 696 p.block(), 697 p.must('.'), 698 } 699 default: 700 panic(todo("", p.token())) 701 } 702 } 703 704 type identifier struct { 705 ident pasToken 706 scope *scope 707 708 resolvedTo node 709 typ interface{} 710 } 711 712 func (n identifier) Position() token.Position { return n.ident.Position() } 713 func (n identifier) Sep() string { return n.ident.Sep() } 714 func (n identifier) Src() string { return n.ident.Src() } 715 716 type programHeading struct { 717 program pasToken 718 ident *identifier 719 programParameterList *programParameterList 720 } 721 722 // ProgramHeading = "program" Identifier [ ProgramParameterList ] . 723 func (p *pasParser) programHeading() (r *programHeading) { 724 return &programHeading{ 725 p.must(tokProgram), 726 p.mustIdent(tokIdent), 727 p.programParameterList(), 728 } 729 } 730 731 type programParameterList struct { 732 lparen pasToken 733 identifierList []*identifierList 734 rparen pasToken 735 736 idents []*identifier 737 } 738 739 // ProgramParameterList = "(" IdentifierList ")" . 740 func (p *pasParser) programParameterList() (r *programParameterList) { 741 if p.c() != '(' { 742 return nil 743 } 744 745 return &programParameterList{ 746 lparen: p.must('('), 747 identifierList: p.identifierList(), 748 rparen: p.must(')'), 749 } 750 } 751 752 type identifierList struct { 753 comma pasToken 754 ident *identifier 755 } 756 757 // IdentifierList = Identifier { "," Identifier } . 758 func (p *pasParser) identifierList() (r []*identifierList) { 759 r = []*identifierList{{ident: p.mustIdent(tokIdent)}} 760 for p.c() == ',' { 761 r = append(r, &identifierList{p.shift(), p.mustIdent(tokIdent)}) 762 } 763 return r 764 } 765 766 type block struct { 767 labelDeclarationPart *labelDeclarationPart 768 constantDefinitionPart *constantDefinitionPart 769 typeDefinitionPart *typeDefinitionPart 770 variableDeclarationPart *variableDeclarationPart 771 procedureAndFunctionDeclarationPart []*procedureAndFunctionDeclarationPart 772 statementPart *compoundStatement 773 } 774 775 func (n *block) Position() (r token.Position) { 776 if n == nil { 777 return r 778 } 779 780 if x := n.labelDeclarationPart; x != nil { 781 return x.Position() 782 } 783 784 if x := n.constantDefinitionPart; x != nil { 785 return x.Position() 786 } 787 788 if x := n.typeDefinitionPart; x != nil { 789 return x.Position() 790 } 791 792 if x := n.variableDeclarationPart; x != nil { 793 return x.Position() 794 } 795 796 if len(n.procedureAndFunctionDeclarationPart) != 0 { 797 return n.procedureAndFunctionDeclarationPart[0].Position() 798 } 799 800 return n.statementPart.Position() 801 } 802 803 // Block = LabelDeclarationPart 804 // 805 // ConstantDefinitionPart 806 // TypeDefinitionPart 807 // VariableDeclarationPart 808 // ProcedureAndFunctionDeclarationPart 809 // StatementPart . 810 func (p *pasParser) block() (r *block) { 811 return &block{ 812 p.labelDeclarationPart(), 813 p.constantDefinitionPart(), 814 p.typeDefinitionPart(), 815 p.variableDeclarationPart(), 816 p.procedureAndFunctionDeclarationPart(), 817 p.compoundStatement(), 818 } 819 } 820 821 type typeDefinitionPart struct { 822 type1 pasToken 823 typeDefinitionList []*typeDefinitionList 824 } 825 826 func (n *typeDefinitionPart) Position() (r token.Position) { 827 if n == nil { 828 return r 829 } 830 831 return n.type1.Position() 832 } 833 834 type typeDefinitionList struct { 835 typeDefinition *typeDefinition 836 semi pasToken 837 } 838 839 // TypeDefinitionPart = [ "type" TypeDefinition ";" { TypeDefinition ";" } ] . 840 func (p *pasParser) typeDefinitionPart() (r *typeDefinitionPart) { 841 if p.c() != tokType { 842 return nil 843 } 844 845 r = &typeDefinitionPart{ 846 p.shift(), 847 []*typeDefinitionList{{p.typeDefinition(), p.must(';')}}, 848 } 849 for { 850 switch p.c() { 851 case tokVar, tokBegin: 852 return r 853 case tokIdent: 854 r.typeDefinitionList = append(r.typeDefinitionList, &typeDefinitionList{p.typeDefinition(), p.must(';')}) 855 default: 856 panic(todo("", p.token())) 857 } 858 } 859 } 860 861 type typeDefinition struct { 862 ident *identifier 863 eq pasToken 864 type1 node 865 866 typ interface{} 867 } 868 869 func (n *typeDefinition) Position() (r token.Position) { 870 if n == nil { 871 return r 872 } 873 874 return n.ident.Position() 875 } 876 877 // TypeDefinition = Identifier "=" Type . 878 func (p *pasParser) typeDefinition() (r *typeDefinition) { 879 r = &typeDefinition{ 880 ident: p.mustIdent(tokIdent), 881 eq: p.must('='), 882 type1: p.type1(), 883 } 884 p.scope.add(r.ident.Src(), r) 885 return r 886 } 887 888 // Type = SimpleType | StructuredType | PointerType . 889 func (p *pasParser) type1() (r node) { 890 switch p.c() { 891 case tokInt, tokIdent, '-', tokString: 892 return p.simpleType() 893 case tokPacked, tokArray, tokRecord, tokFile: 894 return p.structuredType() 895 case '^': 896 return &pointerType{p.shift(), p.type1()} 897 default: 898 panic(todo("", p.token())) 899 } 900 } 901 902 type pointerType struct { 903 carret pasToken 904 type1 node 905 } 906 907 func (n *pointerType) Position() (r token.Position) { 908 if n == nil { 909 return r 910 } 911 912 return n.carret.Position() 913 } 914 915 // PointerType = "^" DomainType | PointerTypeldentifier . 916 917 // StructuredType = [ "packed" ] UnpackedStructuredType | StructuredTypeIdentifier . 918 func (p *pasParser) structuredType() (r node) { 919 packed := p.opt(tokPacked) 920 switch p.c() { 921 case tokArray, tokRecord, tokFile: 922 return p.unpackedStructuredType(packed) 923 default: 924 panic(todo("", p.token())) 925 } 926 } 927 928 // UnpackedStructuredType = ArrayType | RecordType | SetType | FileType . 929 func (p *pasParser) unpackedStructuredType(packed pasToken) (r node) { 930 switch p.c() { 931 case tokFile: 932 return p.fileType(packed) 933 case tokArray: 934 return p.arrayType(packed) 935 case tokRecord: 936 return p.recordType(packed) 937 default: 938 panic(todo("", p.token())) 939 } 940 } 941 942 type field struct { 943 off int64 944 typ interface{} 945 946 inVariantPart bool 947 } 948 949 type recordType struct { 950 packedTok pasToken 951 record pasToken 952 fieldList *fieldList 953 end pasToken 954 955 align int64 956 size int64 957 958 fields map[string]*field 959 960 checked bool 961 hasVariants bool 962 packed bool 963 } 964 965 func (n *recordType) isPacked() bool { return n.packed } 966 967 func (n *recordType) Position() (r token.Position) { 968 if n == nil { 969 return r 970 } 971 972 return n.record.Position() 973 } 974 975 func (n *recordType) String() string { 976 return fmt.Sprintf("record %s end", n.fieldList) 977 } 978 979 func (n *recordType) canAssignFrom(c *ctx, m *recordType) (r bool) { 980 if n == nil || m == nil { 981 return false 982 } 983 984 return n.fieldList.canAssignFrom(c, m.fieldList) 985 } 986 987 func (n *recordType) field(nm pasToken) *field { 988 r := n.fields[nm.Src()] 989 if r == nil { 990 panic(todo("", nm)) 991 } 992 993 return r 994 } 995 996 func (n *recordType) check(c *ctx) interface{} { 997 if n == nil || n.checked { 998 return nil 999 } 1000 1001 n.checked = true 1002 n.fields = map[string]*field{} 1003 n.size = n.fieldList.check(c, n, false, 0) 1004 if !n.packed { 1005 n.size = roundup(n.size, n.align) 1006 } 1007 return n 1008 } 1009 1010 // RecordType = "record" FieldList "end" . 1011 func (p *pasParser) recordType(packed pasToken) (r *recordType) { 1012 return &recordType{ 1013 packedTok: packed, 1014 record: p.must(tokRecord), 1015 fieldList: p.fieldList(), 1016 end: p.must(tokEnd), 1017 size: -1, 1018 } 1019 } 1020 1021 type fieldList struct { 1022 fixedPart []*fixedPart 1023 semi pasToken 1024 variantPart *variantPart 1025 semi2 pasToken 1026 } 1027 1028 func (n *fieldList) Position() (r token.Position) { 1029 if n == nil { 1030 return r 1031 } 1032 1033 if len(n.fixedPart) != 0 { 1034 return n.fixedPart[0].Position() 1035 } 1036 1037 return n.variantPart.Position() 1038 } 1039 1040 func (n *fieldList) String() string { 1041 var a []string 1042 for _, v := range n.fixedPart { 1043 a = append(a, v.String()) 1044 } 1045 return strings.Join(a, "; ") 1046 } 1047 1048 func (n *fieldList) check(c *ctx, r *recordType, inVariantPart bool, off int64) int64 { 1049 if n == nil { 1050 return off 1051 } 1052 1053 for _, v := range n.fixedPart { 1054 off = v.check(c, r, inVariantPart, off) 1055 } 1056 return n.variantPart.check(c, r, off) 1057 } 1058 1059 func (n *fieldList) canAssignFrom(c *ctx, m *fieldList) (r bool) { 1060 if n == nil || m == nil || len(n.fixedPart) != len(m.fixedPart) { 1061 return false 1062 } 1063 1064 for i, v := range n.fixedPart { 1065 if !v.canAssignFrom(c, m.fixedPart[i]) { 1066 return false 1067 } 1068 } 1069 1070 return n.variantPart == nil && m.variantPart == nil || n.variantPart.canAssignFrom(c, m.variantPart) 1071 } 1072 1073 // FieldList = [ ( FixedPart [ ";" VariantPart ] | VariantPart ) [ ";" ] ] . 1074 func (p *pasParser) fieldList() (r *fieldList) { 1075 switch p.c() { 1076 case tokIdent: 1077 fp, semi := p.fixedPart() 1078 r = &fieldList{ 1079 fixedPart: fp, 1080 semi: semi, 1081 } 1082 switch p.c() { 1083 case tokEnd, ')': 1084 return r 1085 case tokCase: 1086 r.variantPart, r.semi2 = p.variantPart() 1087 return r 1088 default: 1089 panic(todo("", p.token())) 1090 } 1091 case tokCase: 1092 r = &fieldList{} 1093 r.variantPart, r.semi2 = p.variantPart() 1094 return r 1095 default: 1096 panic(todo("", p.token())) 1097 } 1098 } 1099 1100 type recordSection struct { 1101 identifierList []*identifierList 1102 colon pasToken 1103 type1 node 1104 1105 typ interface{} 1106 } 1107 1108 func (n *recordSection) Position() (r token.Position) { 1109 if n == nil { 1110 return r 1111 } 1112 1113 return n.identifierList[0].ident.Position() 1114 } 1115 1116 func (n *recordSection) String() string { 1117 var a []string 1118 for _, v := range n.identifierList { 1119 a = append(a, strings.ToLower(v.ident.Src())) 1120 } 1121 return strings.Join(a, ", ") + ": " + typeStr(n.typ) 1122 } 1123 1124 func (n *recordSection) canAssignFrom(c *ctx, m *recordSection) (r bool) { 1125 if n == nil || m == nil || len(n.identifierList) != len(m.identifierList) { 1126 return false 1127 } 1128 1129 for i, v := range n.identifierList { 1130 if strings.ToLower(v.ident.Src()) != strings.ToLower(m.identifierList[i].ident.Src()) { 1131 return false 1132 } 1133 } 1134 1135 return c.checkAssign(n, -1, n.typ, m.typ, nil) 1136 } 1137 1138 func (n *recordSection) check(c *ctx, r *recordType, inVariantPart bool, off int64) int64 { 1139 if n == nil { 1140 return off 1141 } 1142 1143 n.typ = c.checkType(n.type1) 1144 if inVariantPart { 1145 switch underlyingType(n.typ).(type) { 1146 case *pascalReal: 1147 n.typ = &pascalReal32{} 1148 } 1149 } 1150 for _, v := range n.identifierList { 1151 nm := v.ident.Src() 1152 if _, ok := r.fields[nm]; ok { 1153 panic(todo("", v.ident)) 1154 } 1155 1156 align, sz := c.sizeof(n.typ) 1157 r.align = mathutil.MaxInt64(r.align, align) 1158 if !r.packed { 1159 off = roundup(off, align) 1160 } 1161 r.fields[nm] = &field{typ: n.typ, inVariantPart: inVariantPart, off: off} 1162 off += sz 1163 } 1164 return off 1165 } 1166 1167 func underlyingType(t interface{}) interface{} { 1168 switch x := t.(type) { 1169 case *typeDefinition: 1170 return x.typ 1171 default: 1172 return t 1173 } 1174 } 1175 1176 func (c *ctx) sizeof(t interface{}) (align, size int64) { 1177 switch x := underlyingType(t).(type) { 1178 case *subrangeType: 1179 switch { 1180 case x.lo >= 0 && x.hi <= math.MaxUint8: 1181 return 1, 1 1182 case x.lo >= 0 && x.hi <= math.MaxUint16: 1183 return 2, 2 1184 case x.lo >= 0 && x.hi <= math.MaxUint32: 1185 return 4, 4 1186 case x.lo >= math.MinInt8 && x.hi <= math.MaxInt8: 1187 return 1, 1 1188 case x.lo >= math.MinInt16 && x.hi <= math.MaxInt16: 1189 return 2, 2 1190 default: 1191 panic(todo("", x.lo, x.hi)) 1192 } 1193 case *pascalInteger: 1194 return integerAlign, integerSize 1195 case *recordType: 1196 if !x.checked || x.size <= 0 || x.align <= 0 { 1197 panic(todo("", x, x.checked, x.size)) 1198 } 1199 1200 return x.align, x.size 1201 case *pascalReal: 1202 return realAlign, realSize 1203 case *pascalReal32: 1204 return real32Align, real32Size 1205 case *pascalChar: 1206 return charAlign, charSize 1207 default: 1208 panic(todo("%T", x)) 1209 } 1210 } 1211 1212 // RecordSection = IdentifierList ":" Type. 1213 func (p *pasParser) recordSection() (r *recordSection) { 1214 return &recordSection{ 1215 identifierList: p.identifierList(), 1216 colon: p.must(':'), 1217 type1: p.type1(), 1218 } 1219 } 1220 1221 type variantPart struct { 1222 case1 pasToken 1223 variantSelector *variantSelector 1224 of pasToken 1225 variants []*variant 1226 } 1227 1228 func (n *variantPart) Position() (r token.Position) { 1229 if n == nil { 1230 return r 1231 } 1232 1233 return n.case1.Position() 1234 } 1235 1236 func (n *variantPart) check(c *ctx, r *recordType, off int64) int64 { 1237 if n == nil { 1238 return off 1239 } 1240 1241 r.hasVariants = true 1242 n.variantSelector.check(c) 1243 switch x := underlyingType(n.variantSelector.typ).(type) { 1244 case *subrangeType, *pascalBoolean: 1245 // ok 1246 default: 1247 panic(todo("%v: %T", n.variantSelector.Position(), x)) 1248 } 1249 off0 := off 1250 for _, v := range n.variants { 1251 off = mathutil.MaxInt64(off, v.check(c, n.variantSelector, r, off0)) 1252 } 1253 return off 1254 } 1255 1256 func (n *variantPart) canAssignFrom(c *ctx, m *variantPart) (r bool) { 1257 if n == nil || m == nil || len(n.variants) != len(m.variants) { 1258 return false 1259 } 1260 1261 if !c.checkAssign(n, -1, n.variantSelector.typ, m.variantSelector.typ, nil) { 1262 return false 1263 } 1264 1265 for i, v := range n.variants { 1266 if !v.canAssignFrom(c, m.variants[i]) { 1267 return false 1268 } 1269 } 1270 1271 return true 1272 } 1273 1274 // VariantPart = "case" VariantSelector "of" Variant { ";" Variant } . 1275 func (p *pasParser) variantPart() (r *variantPart, semi pasToken) { 1276 r = &variantPart{ 1277 case1: p.must(tokCase), 1278 variantSelector: p.variantSelector(), 1279 of: p.must(tokOf), 1280 } 1281 r.variants, semi = p.variants() 1282 return r, semi 1283 } 1284 1285 type variant struct { 1286 semi pasToken 1287 constList []*constList 1288 comma pasToken 1289 lparen pasToken 1290 fieldList *fieldList 1291 rparen pasToken 1292 } 1293 1294 func (n *variant) canAssignFrom(c *ctx, m *variant) (r bool) { 1295 if n == nil || m == nil || len(n.constList) != len(m.constList) { 1296 return false 1297 } 1298 1299 return n.fieldList.canAssignFrom(c, m.fieldList) 1300 } 1301 1302 func (n *variant) check(c *ctx, selector *variantSelector, r *recordType, off int64) int64 { 1303 if n == nil { 1304 return off 1305 } 1306 1307 for _, v := range n.constList { 1308 v.check(c) 1309 c.checkAssign(v, -1, selector.typ, v.typ, v.val) 1310 } 1311 return n.fieldList.check(c, r, true, off) 1312 } 1313 1314 // Variant = Constant { "," Constant } ":" "(" FieIdList ")" . 1315 func (p *pasParser) variants() (r []*variant, semi pasToken) { 1316 r = []*variant{{ 1317 pasToken{}, 1318 p.constList(), 1319 p.must(':'), 1320 p.must('('), 1321 p.fieldList(), 1322 p.must(')'), 1323 }} 1324 for p.c() == ';' { 1325 semi2 := p.shift() 1326 switch p.c() { 1327 case tokInt, tokIdent: 1328 r = append(r, &variant{ 1329 semi2, 1330 p.constList(), 1331 p.must(':'), 1332 p.must('('), 1333 p.fieldList(), 1334 p.must(')'), 1335 }) 1336 case tokEnd: 1337 return r, semi2 1338 default: 1339 panic(todo("", p.token())) 1340 } 1341 } 1342 return r, semi 1343 } 1344 1345 type variantSelector struct { 1346 tagField pasToken 1347 comma pasToken 1348 tagType node 1349 1350 typ interface{} 1351 } 1352 1353 func (n *variantSelector) Position() (r token.Position) { 1354 if n == nil { 1355 return r 1356 } 1357 1358 if n.tagField.isValid() { 1359 return n.tagField.Position() 1360 } 1361 1362 return n.tagType.Position() 1363 } 1364 1365 func (n *variantSelector) check(c *ctx) { 1366 n.typ = c.checkType(n.tagType) 1367 } 1368 1369 // VariantSelector = [ TagField ":"] TagType . 1370 func (p *pasParser) variantSelector() (r *variantSelector) { 1371 switch p.c() { 1372 case tokIdent: 1373 id := &identifier{ident: p.shift()} 1374 switch p.c() { 1375 case tokOf: 1376 return &variantSelector{tagType: id} 1377 default: 1378 panic(todo("", p.token())) 1379 } 1380 default: 1381 panic(todo("", p.token())) 1382 } 1383 } 1384 1385 type fixedPart struct { 1386 semi pasToken 1387 recordSection *recordSection 1388 } 1389 1390 func (n *fixedPart) Position() (r token.Position) { 1391 if n == nil { 1392 return r 1393 } 1394 1395 return n.recordSection.Position() 1396 } 1397 1398 func (n *fixedPart) String() string { 1399 return n.recordSection.String() 1400 } 1401 1402 func (n *fixedPart) check(c *ctx, r *recordType, inVariantPart bool, off int64) int64 { 1403 if n == nil { 1404 return off 1405 } 1406 1407 return n.recordSection.check(c, r, inVariantPart, off) 1408 } 1409 1410 func (n *fixedPart) canAssignFrom(c *ctx, m *fixedPart) (r bool) { 1411 if n == nil || m == nil { 1412 return false 1413 } 1414 1415 return n.recordSection.canAssignFrom(c, m.recordSection) 1416 } 1417 1418 // FixedPart = RecordSection { ";" RecordSection } . 1419 func (p *pasParser) fixedPart() (r []*fixedPart, semi pasToken) { 1420 r = []*fixedPart{{recordSection: p.recordSection()}} 1421 for p.c() == ';' { 1422 semi := p.shift() 1423 switch p.c() { 1424 case tokIdent: 1425 r = append(r, &fixedPart{semi, p.recordSection()}) 1426 case tokEnd, tokCase: 1427 return r, semi 1428 default: 1429 panic(todo("", p.token())) 1430 } 1431 } 1432 return r, semi 1433 } 1434 1435 type arrayType struct { 1436 packedTok pasToken 1437 array pasToken 1438 lbracket pasToken 1439 typeList []*typeList 1440 rbracket pasToken 1441 of pasToken 1442 elemType node 1443 1444 indexTyp []interface{} 1445 elemTyp interface{} 1446 1447 packed bool 1448 } 1449 1450 func (n *arrayType) isPacked() bool { return n.packed } 1451 1452 func (n *arrayType) Position() (r token.Position) { 1453 if n == nil { 1454 return r 1455 } 1456 1457 return n.array.Position() 1458 } 1459 1460 func (n *arrayType) canAssignFrom(c *ctx, m *arrayType) bool { 1461 if n == nil || m == nil || len(n.indexTyp) != len(m.indexTyp) || !c.checkAssign(n, -1, n.elemTyp, m.elemTyp, nil) { 1462 return false 1463 } 1464 1465 for i, v := range n.indexTyp { 1466 if !c.checkAssign(n, -1, v, m.indexTyp[i], nil) { 1467 return false 1468 } 1469 } 1470 1471 return true 1472 } 1473 1474 // ArrayType = "array" "[" IndexType { "," IndexType } "]" "of" ComponentType . 1475 func (p *pasParser) arrayType(packed pasToken) (r *arrayType) { 1476 return &arrayType{ 1477 packedTok: packed, 1478 array: p.must(tokArray), 1479 lbracket: p.must('['), 1480 typeList: p.typeList(), 1481 rbracket: p.must(']'), 1482 of: p.must(tokOf), 1483 elemType: p.type1(), 1484 } 1485 } 1486 1487 type typeList struct { 1488 comma pasToken 1489 type1 node 1490 } 1491 1492 func (p *pasParser) typeList() (r []*typeList) { 1493 r = []*typeList{{type1: p.type1()}} 1494 for p.c() == ',' { 1495 r = append(r, &typeList{p.shift(), p.type1()}) 1496 } 1497 return r 1498 } 1499 1500 type fileType struct { 1501 packedTok pasToken 1502 file pasToken 1503 of pasToken 1504 type1 node 1505 1506 elemType interface{} 1507 1508 packed bool 1509 } 1510 1511 func (n *fileType) isPacked() bool { return n.packed } 1512 1513 func (n *fileType) Position() (r token.Position) { 1514 if n == nil { 1515 return r 1516 } 1517 1518 return n.file.Position() 1519 } 1520 1521 // FileType = "file" "of" Type . 1522 func (p *pasParser) fileType(packed pasToken) (r *fileType) { 1523 return &fileType{ 1524 packedTok: packed, 1525 file: p.must(tokFile), 1526 of: p.must(tokOf), 1527 type1: p.type1(), 1528 } 1529 } 1530 1531 // SimpleType = OrdinalType | RealTypeldentifier. 1532 func (p *pasParser) simpleType() (r node) { 1533 switch p.c() { 1534 case tokInt, '-', tokString: 1535 return p.ordinalType() 1536 case tokIdent: 1537 id := &identifier{ident: p.shift()} 1538 switch p.c() { 1539 case tokEllipsis: 1540 return &subrangeType{ 1541 constant: id, 1542 ellipsis: p.shift(), 1543 constant2: p.expression(), 1544 } 1545 default: 1546 return id 1547 } 1548 default: 1549 panic(todo("", p.token())) 1550 } 1551 } 1552 1553 // OrdinalType = EnumeratedType | SubrangeType | OrdinalTypeldentifier . 1554 func (p *pasParser) ordinalType() (r node) { 1555 switch p.c() { 1556 case tokInt, '-', tokString: 1557 return p.subrangeType() 1558 default: 1559 panic(todo("", p.token())) 1560 } 1561 } 1562 1563 type subrangeType struct { 1564 constant node 1565 ellipsis pasToken 1566 constant2 node 1567 1568 lo, hi int64 1569 } 1570 1571 func (n *subrangeType) Position() (r token.Position) { 1572 if n == nil { 1573 return r 1574 } 1575 1576 return n.constant.Position() 1577 } 1578 1579 // SubrangeType = Constant ".." Constant . 1580 func (p *pasParser) subrangeType() (r *subrangeType) { 1581 return &subrangeType{ 1582 constant: p.expression(), 1583 ellipsis: p.must(tokEllipsis), 1584 constant2: p.expression(), 1585 } 1586 } 1587 1588 type compoundStatement struct { 1589 begin pasToken 1590 statementSequence []*statementSequence 1591 end pasToken 1592 } 1593 1594 func (n *compoundStatement) Position() (r token.Position) { 1595 if n == nil { 1596 return r 1597 } 1598 1599 return n.begin.Position() 1600 } 1601 1602 // StatementPart = CompoundStatement . 1603 // CompoundStatement = "begin" StatementSequence "end" . 1604 func (p *pasParser) compoundStatement() (r *compoundStatement) { 1605 return &compoundStatement{ 1606 p.must(tokBegin), 1607 p.statementSequence(), 1608 p.must(tokEnd), 1609 } 1610 } 1611 1612 type statementSequence struct { 1613 semi pasToken 1614 statement node 1615 } 1616 1617 // StatementSequence = Statement { ";" Statement} . 1618 func (p *pasParser) statementSequence() (r []*statementSequence) { 1619 switch p.c() { 1620 case 1621 tokIdent, tokIf, tokRepeat, tokWhile, tokBegin, tokCase, tokFor, tokGoto, 1622 tokInt, ';', tokEnd: 1623 1624 r = []*statementSequence{{statement: p.statement(true)}} 1625 default: 1626 panic(todo("", p.token())) 1627 } 1628 for p.c() == ';' { 1629 r = append(r, &statementSequence{p.shift(), p.statement(true)}) 1630 } 1631 return r 1632 } 1633 1634 // Statement = [ Label ":" ] ( SimpleStatement | StructuredStatement ) . 1635 func (p *pasParser) statement(acceptLabel bool) (r node) { 1636 switch p.c() { 1637 case tokIdent, tokEnd, tokGoto: 1638 return p.simpleStatement() 1639 case tokFor, tokBegin, tokIf, tokWhile, tokRepeat, tokCase: 1640 return p.structuredStatement() 1641 case tokUntil, ';': 1642 return &emptyStatement{p.token()} 1643 case tokInt: 1644 if !acceptLabel { 1645 panic(todo("", p.token())) 1646 } 1647 1648 return &labeled{ 1649 label: p.expression(), 1650 colon: p.must(':'), 1651 stmt: p.statement(false), 1652 } 1653 default: 1654 panic(todo("", p.token())) 1655 } 1656 } 1657 1658 type labeled struct { 1659 label node 1660 plus pasToken 1661 off node 1662 colon pasToken 1663 stmt node 1664 } 1665 1666 func (n *labeled) Position() (r token.Position) { 1667 if n == nil { 1668 return r 1669 } 1670 1671 return n.label.Position() 1672 } 1673 1674 func (n *labeled) check(c *ctx) { 1675 if n == nil { 1676 return 1677 } 1678 1679 if n.off != nil { 1680 c.checkExpr(n.off) 1681 } 1682 c.checkStatement(n.stmt) 1683 } 1684 1685 // StructuredStatement = CompoundStatement | ConditionalStatement 1686 // 1687 // | RepetitiveStatement | WithStatement . 1688 func (p *pasParser) structuredStatement() (r node) { 1689 switch p.c() { 1690 case tokFor, tokWhile, tokRepeat: 1691 return p.repetitiveStatement() 1692 case tokBegin: 1693 return p.compoundStatement() 1694 case tokIf: 1695 return p.ifStatement() 1696 case tokCase: 1697 return p.caseStatement() 1698 default: 1699 panic(todo("", p.token())) 1700 } 1701 } 1702 1703 type caseStatement struct { 1704 case1 pasToken 1705 expr node 1706 of pasToken 1707 cases []*caseList 1708 semi pasToken 1709 else1 pasToken 1710 elseStmt node 1711 end pasToken 1712 } 1713 1714 func (n *caseStatement) Position() (r token.Position) { 1715 if n == nil { 1716 return r 1717 } 1718 1719 return n.case1.Position() 1720 } 1721 1722 func (n *caseStatement) check(c *ctx) { 1723 if n == nil { 1724 return 1725 } 1726 1727 t, _ := c.checkExpr(n.expr) 1728 switch x := underlyingType(t).(type) { 1729 case *pascalInteger, *subrangeType: 1730 // ok 1731 default: 1732 panic(todo("%v: %T", n.expr.Position(), x)) 1733 } 1734 for _, v := range n.cases { 1735 v.case1.check(c) 1736 } 1737 c.checkStatement(n.elseStmt) 1738 } 1739 1740 // CaseStatement = "case" Expression "of" Case { ";" Case } [ ";" ] "end" . 1741 func (p *pasParser) caseStatement() (r *caseStatement) { 1742 r = &caseStatement{ 1743 case1: p.must(tokCase), 1744 expr: p.expression(), 1745 of: p.must(tokOf), 1746 } 1747 var semi pasToken 1748 r.cases, semi = p.caseList() 1749 if p.c() == tokElse { 1750 semi = pasToken{} 1751 r.else1 = p.shift() 1752 r.elseStmt = p.statement(true) 1753 } 1754 if semi.isValid() { 1755 r.semi = semi 1756 } else { 1757 r.semi = p.opt(';') 1758 } 1759 r.end = p.must(tokEnd) 1760 return r 1761 } 1762 1763 type caseList struct { 1764 semi pasToken 1765 case1 *case1 1766 } 1767 1768 func (p *pasParser) caseList() (r []*caseList, semi pasToken) { 1769 r = []*caseList{{case1: p.case1()}} 1770 for p.c() == ';' { 1771 semi2 := p.shift() 1772 switch p.c() { 1773 case tokEnd, tokElse: 1774 return r, semi2 1775 default: 1776 r = append(r, &caseList{semi2, p.case1()}) 1777 } 1778 } 1779 return r, semi 1780 } 1781 1782 type case1 struct { 1783 constList []*constList 1784 comma pasToken 1785 stmt node 1786 } 1787 1788 // Case = Constant { "," Constant } ":" Statement . 1789 func (p *pasParser) case1() (r *case1) { 1790 return &case1{ 1791 p.constList(), 1792 p.must(':'), 1793 p.statement(true), 1794 } 1795 } 1796 1797 func (n *case1) check(c *ctx) { 1798 if n == nil { 1799 return 1800 } 1801 1802 for _, v := range n.constList { 1803 t, val := c.checkExpr(v.const1) 1804 switch x := t.(type) { 1805 case *pascalInteger, *subrangeType: 1806 // ok 1807 default: 1808 panic(todo("%v: %T", v.const1.Position(), x)) 1809 } 1810 switch x := val.(type) { 1811 case int64: 1812 // ok 1813 default: 1814 panic(todo("%v: %T", v.const1.Position(), x)) 1815 } 1816 } 1817 c.checkStatement(n.stmt) 1818 } 1819 1820 type constList struct { 1821 comma pasToken 1822 const1 node 1823 1824 typ, val interface{} 1825 } 1826 1827 func (n *constList) Position() (r token.Position) { 1828 if n == nil { 1829 return r 1830 } 1831 1832 if n.comma.isValid() { 1833 return n.comma.Position() 1834 } 1835 1836 return n.const1.Position() 1837 } 1838 1839 func (n *constList) check(c *ctx) { 1840 n.typ, n.val = c.checkExpr(n.const1) 1841 } 1842 1843 func (p *pasParser) constList() (r []*constList) { 1844 r = []*constList{{const1: p.expression()}} 1845 for p.c() == ',' { 1846 r = append(r, &constList{comma: p.shift(), const1: p.expression()}) 1847 } 1848 return r 1849 } 1850 1851 type ifStatement struct { 1852 if1 pasToken 1853 expr node 1854 then pasToken 1855 ifStmt node 1856 } 1857 1858 func (n *ifStatement) Position() (r token.Position) { 1859 if n == nil { 1860 return r 1861 } 1862 1863 return n.if1.Position() 1864 } 1865 1866 func (n *ifStatement) check(c *ctx) { 1867 if n == nil { 1868 return 1869 } 1870 1871 t, _ := c.checkExpr2(n.expr) 1872 switch x := t.(type) { 1873 case *pascalBoolean: 1874 // ok 1875 default: 1876 panic(todo("%v: %T", n.expr.Position(), x)) 1877 } 1878 c.checkStatement(n.ifStmt) 1879 } 1880 1881 type ifElseStatement struct { 1882 if1 pasToken 1883 expr node 1884 then pasToken 1885 ifStmt node 1886 else1 pasToken 1887 elseStmt node 1888 } 1889 1890 func (n *ifElseStatement) Position() (r token.Position) { 1891 if n == nil { 1892 return r 1893 } 1894 1895 return n.if1.Position() 1896 } 1897 1898 func (n *ifElseStatement) check(c *ctx) { 1899 if n == nil { 1900 return 1901 } 1902 1903 t, _ := c.checkExpr2(n.expr) 1904 switch x := t.(type) { 1905 case *pascalBoolean: 1906 // ok 1907 default: 1908 panic(todo("%v: %T", n.expr.Position(), x)) 1909 } 1910 c.checkStatement(n.ifStmt) 1911 c.checkStatement(n.elseStmt) 1912 } 1913 1914 // IfStatement = "if" BooleanExpression "then" Statement 1915 // 1916 // [ "else" Statement ] . 1917 func (p *pasParser) ifStatement() (r node) { 1918 x := &ifStatement{ 1919 p.must(tokIf), 1920 p.expression(), 1921 p.must(tokThen), 1922 p.statement(true), 1923 } 1924 if p.c() != tokElse { 1925 return x 1926 } 1927 1928 return &ifElseStatement{ 1929 x.if1, 1930 x.expr, 1931 x.then, 1932 x.ifStmt, 1933 p.shift(), 1934 p.statement(true), 1935 } 1936 } 1937 1938 // RepetitiveStatement = WhileStatement | RepeatStatement | ForStatement . 1939 func (p *pasParser) repetitiveStatement() (r node) { 1940 switch p.c() { 1941 case tokFor: 1942 return p.forStatement() 1943 case tokWhile: 1944 return p.whileStatement() 1945 case tokRepeat: 1946 return p.repeatStatement() 1947 default: 1948 panic(todo("", p.token())) 1949 } 1950 } 1951 1952 type repeatStatement struct { 1953 repeat pasToken 1954 stmt []*statementSequence 1955 until pasToken 1956 expr node 1957 } 1958 1959 func (n *repeatStatement) Position() (r token.Position) { 1960 if n == nil { 1961 return r 1962 } 1963 1964 return n.repeat.Position() 1965 } 1966 1967 func (n *repeatStatement) check(c *ctx) { 1968 if n == nil { 1969 return 1970 } 1971 1972 for _, v := range n.stmt { 1973 c.checkStatement(v.statement) 1974 } 1975 1976 t, _ := c.checkExpr(n.expr) 1977 switch x := t.(type) { 1978 case *pascalBoolean: 1979 // ok 1980 default: 1981 panic(todo("%v: %T", n.until.Position(), x)) 1982 } 1983 } 1984 1985 // RepeatStatement = "repeat" StatementSequence "until" Expression . 1986 func (p *pasParser) repeatStatement() (r *repeatStatement) { 1987 return &repeatStatement{ 1988 p.must(tokRepeat), 1989 p.statementSequence(), 1990 p.must(tokUntil), 1991 p.expression(), 1992 } 1993 } 1994 1995 type whileStatement struct { 1996 while pasToken 1997 expr node 1998 do pasToken 1999 stmt node 2000 } 2001 2002 func (n *whileStatement) Position() (r token.Position) { 2003 if n == nil { 2004 return r 2005 } 2006 2007 return n.while.Position() 2008 } 2009 2010 func (n *whileStatement) check(c *ctx) { 2011 if n == nil { 2012 return 2013 } 2014 2015 t, _ := c.checkExpr(n.expr) 2016 switch x := t.(type) { 2017 case *pascalBoolean: 2018 // ok 2019 default: 2020 panic(todo("%v: %T", n.expr.Position(), x)) 2021 } 2022 c.checkStatement(n.stmt) 2023 } 2024 2025 // WhileStatement = "while" BooleanExpression "do" Statement . 2026 func (p *pasParser) whileStatement() (r *whileStatement) { 2027 return &whileStatement{ 2028 p.must(tokWhile), 2029 p.expression(), 2030 p.must(tokDo), 2031 p.statement(true), 2032 } 2033 } 2034 2035 type forStatement struct { 2036 for1 pasToken 2037 variable *identifier 2038 assing pasToken 2039 initialValue node 2040 direction pasToken 2041 finalValue node 2042 do pasToken 2043 statement node 2044 } 2045 2046 func (n *forStatement) Position() (r token.Position) { 2047 if n == nil { 2048 return r 2049 } 2050 2051 return n.for1.Position() 2052 } 2053 2054 func (n *forStatement) check(c *ctx) { 2055 if n == nil { 2056 return 2057 } 2058 2059 vt, _ := c.checkExpr(n.variable) 2060 switch x := underlyingType(vt).(type) { 2061 case *pascalInteger, *subrangeType: 2062 // ok 2063 default: 2064 panic(todo("%v: %T", n.variable.Position(), x)) 2065 } 2066 ivt, _ := c.checkExpr(n.initialValue) 2067 switch x := underlyingType(ivt).(type) { 2068 case *pascalInteger, *subrangeType: 2069 // ok 2070 default: 2071 panic(todo("%v: %T", n.variable.Position(), x)) 2072 } 2073 fvt, _ := c.checkExpr(n.finalValue) 2074 switch x := underlyingType(fvt).(type) { 2075 case *pascalInteger, *subrangeType: 2076 // ok 2077 default: 2078 panic(todo("%v: %T", n.variable.Position(), x)) 2079 } 2080 c.checkStatement(n.statement) 2081 } 2082 2083 // ForStatement = "for" ControlVariable ":=" InitialValue ( "to" | "downto" ) FinalValue "do" Statement . 2084 func (p *pasParser) forStatement() (r *forStatement) { 2085 return &forStatement{ 2086 p.must(tokFor), 2087 p.mustIdent(tokIdent), 2088 p.must(tokAssign), 2089 p.expression(), 2090 p.forDir(), 2091 p.expression(), 2092 p.must(tokDo), 2093 p.statement(true), 2094 } 2095 } 2096 2097 func (p *pasParser) forDir() (r pasToken) { 2098 switch p.c() { 2099 case tokTo, tokDownto: 2100 return p.shift() 2101 default: 2102 panic(todo("", p.token())) 2103 } 2104 } 2105 2106 type emptyStatement struct { 2107 t pasToken 2108 } 2109 2110 func (n *emptyStatement) Position() (r token.Position) { 2111 if n == nil { 2112 return r 2113 } 2114 2115 return n.t.Position() 2116 } 2117 2118 // SimpleStatement = EmptyStatement | AssignmentStatement | ProcedureStatement | GotoStatement . 2119 func (p *pasParser) simpleStatement() (r node) { 2120 switch p.c() { 2121 case tokIdent: 2122 id := &identifier{ident: p.shift()} 2123 switch p.c() { 2124 case '(': 2125 return p.procedureStatement(id) 2126 case ';', tokElse, tokUntil, tokEnd: 2127 switch p.scope.mustLookup(id).(type) { 2128 case *procedureDeclaration: 2129 return p.procedureStatement(id) 2130 default: 2131 return id 2132 } 2133 case tokAssign, '[', '.', '^': 2134 return p.assignmentStatement(id) 2135 case ':': 2136 return &labeled{ 2137 label: id, 2138 colon: p.shift(), 2139 stmt: p.statement(false), 2140 } 2141 case '+': 2142 plus := p.shift() 2143 expr := p.expression() 2144 return &labeled{ 2145 label: id, 2146 plus: plus, 2147 off: expr, 2148 colon: p.must(':'), 2149 stmt: p.statement(false), 2150 } 2151 default: 2152 panic(todo("", p.token())) 2153 } 2154 case tokEnd: 2155 return &emptyStatement{p.token()} 2156 case tokGoto: 2157 return p.gotoStatement() 2158 default: 2159 panic(todo("", p.token())) 2160 } 2161 } 2162 2163 type gotoStatement struct { 2164 goto1 pasToken 2165 label node 2166 } 2167 2168 func (n *gotoStatement) Position() (r token.Position) { 2169 if n == nil { 2170 return r 2171 } 2172 2173 return n.goto1.Position() 2174 } 2175 2176 func (n *gotoStatement) check(c *ctx) { 2177 if n == nil { 2178 return 2179 } 2180 2181 switch x := n.label.(type) { 2182 case pasToken, *binaryExpression, *identifier: 2183 // ok 2184 default: 2185 panic(todo("%v: %T", n.label.Position(), x)) 2186 } 2187 } 2188 2189 // GotoStatement = "goto" Label . 2190 func (p *pasParser) gotoStatement() (r *gotoStatement) { 2191 return &gotoStatement{ 2192 p.must(tokGoto), 2193 p.expression(), 2194 } 2195 } 2196 2197 type assignmentStatement struct { 2198 lhs node 2199 assign pasToken 2200 expr node 2201 } 2202 2203 func (n *assignmentStatement) Position() (r token.Position) { 2204 if n == nil { 2205 return r 2206 } 2207 2208 return n.lhs.Position() 2209 } 2210 2211 func (n *assignmentStatement) check(c *ctx) { 2212 if n == nil { 2213 return 2214 } 2215 2216 lt, _ := c.checkExpr(n.lhs) 2217 rt, v := c.checkExpr(n.expr) 2218 c.mustAssign(n.assign, -1, lt, rt, v) 2219 } 2220 2221 // AssignmentStatement = ( Variable | FunctionIdentifier ) ":=" Expression . 2222 func (p *pasParser) assignmentStatement(lhs node) (r *assignmentStatement) { 2223 switch x := lhs.(type) { 2224 case *identifier: 2225 lhs = p.variable(x) 2226 default: 2227 panic(todo("%T %v:", x, lhs.Position())) 2228 } 2229 2230 return &assignmentStatement{ 2231 lhs, 2232 p.must(tokAssign), 2233 p.expression(), 2234 } 2235 } 2236 2237 // Variable = EntireVariable | ComponentVariable | 2238 // 2239 // IdentifiedVariable | BufferVariable . 2240 func (p *pasParser) variable(n node) (r node) { 2241 for { 2242 switch p.c() { 2243 case 2244 tokAssign, ';', ')', ':', ']', tokNeq, tokGeq, tokMod, tokDiv, 2245 '*', tokDo, '>', tokLeq, '=', '<', tokOf, ',', tokThen, '+', 2246 '-', tokElse, tokTo, tokDownto, '/', tokAnd: 2247 2248 return n 2249 case '[', '.': 2250 n = p.componentVariable(n) 2251 case '^': 2252 n = &deref{n, p.shift()} 2253 default: 2254 panic(todo("", p.token())) 2255 } 2256 } 2257 } 2258 2259 type deref struct { 2260 n node 2261 carret pasToken 2262 } 2263 2264 func (n *deref) Position() (r token.Position) { 2265 if n == nil { 2266 return r 2267 } 2268 2269 return n.n.Position() 2270 } 2271 2272 // ComponentVariable = IndexedVariable | FieldDesignator . 2273 func (p *pasParser) componentVariable(n node) (r node) { 2274 switch p.c() { 2275 case '[': 2276 return p.indexedVariable(n) 2277 case '.': 2278 return &fieldDesignator{ 2279 variable: n, 2280 dot: p.shift(), 2281 ident: p.mustIdent(tokIdent), 2282 } 2283 default: 2284 panic(todo("", p.token())) 2285 } 2286 } 2287 2288 type fieldDesignator struct { 2289 variable node 2290 dot pasToken 2291 ident *identifier 2292 2293 typ interface{} 2294 } 2295 2296 func (n *fieldDesignator) Position() (r token.Position) { 2297 if n == nil { 2298 return r 2299 } 2300 2301 return n.dot.Position() 2302 } 2303 2304 type indexedVariable struct { 2305 variable node 2306 lbracket pasToken 2307 indexList []*indexList 2308 rbracket pasToken 2309 2310 typ, varTyp interface{} 2311 } 2312 2313 func (n *indexedVariable) Position() (r token.Position) { 2314 if n == nil { 2315 return r 2316 } 2317 2318 return n.variable.Position() 2319 } 2320 2321 // IndexedVariable = ArrayVariahle "[" Index { "," Index ] "]" . 2322 func (p *pasParser) indexedVariable(n node) (r node) { 2323 return &indexedVariable{ 2324 variable: n, 2325 lbracket: p.must('['), 2326 indexList: p.indexList(), 2327 rbracket: p.must(']'), 2328 } 2329 } 2330 2331 type indexList struct { 2332 comma pasToken 2333 index node 2334 } 2335 2336 func (p *pasParser) indexList() (r []*indexList) { 2337 r = []*indexList{{index: p.expression()}} 2338 for p.c() == ',' { 2339 r = append(r, &indexList{p.shift(), p.expression()}) 2340 } 2341 return r 2342 } 2343 2344 type procedureStatement struct { 2345 ident *identifier 2346 parameters *parameters 2347 2348 typ interface{} 2349 } 2350 2351 func (n *procedureStatement) Position() (r token.Position) { 2352 if n == nil { 2353 return r 2354 } 2355 2356 return n.ident.Position() 2357 } 2358 2359 func (n *procedureStatement) check(c *ctx) { 2360 if n == nil { 2361 return 2362 } 2363 2364 switch x := c.scope.mustLookup(n.ident).(type) { 2365 case 2366 *pascalWrite, *pascalWriteln, *pascalReset, *pascalRewrite, *pascalRead, *pascalReadln, *procedureDeclaration, 2367 *knuthBreak, *knuthClose, *pascalGet, *knuthBreakIn, *pascalPut, *knuthSetPos, *knuthPanic: 2368 2369 n.typ = x 2370 n.parameters.check(c, x) 2371 default: 2372 panic(todo("%v %T", n.ident, x)) 2373 } 2374 } 2375 2376 // ProcedureStatement = ProcedureIdentifier [ ActualParameterList | WriteParameterList ] . 2377 func (p *pasParser) procedureStatement(id *identifier) (r *procedureStatement) { 2378 return &procedureStatement{ 2379 ident: id, 2380 parameters: p.parameters(), 2381 } 2382 } 2383 2384 type parameters struct { 2385 lparen pasToken 2386 parameters []*parameter 2387 rparen pasToken 2388 } 2389 2390 func (n *parameters) Position() (r token.Position) { 2391 if n == nil { 2392 return r 2393 } 2394 2395 return n.lparen.Position() 2396 } 2397 2398 func (n *parameters) check(c *ctx, t interface{}) { 2399 if n == nil { 2400 return 2401 } 2402 2403 switch x := t.(type) { 2404 case *pascalAbs: 2405 if len(n.parameters) != 1 { 2406 panic(todo("%v:", n.lparen.Position())) 2407 } 2408 2409 p := n.parameters[0] 2410 p.typ, p.val = c.checkExpr(p.parameter) 2411 switch y := underlyingType(p.typ).(type) { 2412 case *pascalInteger, *subrangeType, *pascalReal: 2413 // ok 2414 default: 2415 panic(todo("%v: %T", n.parameters[0].parameter.Position(), y)) 2416 } 2417 case *pascalChr: 2418 if len(n.parameters) != 1 { 2419 panic(todo("%v:", n.lparen.Position())) 2420 } 2421 2422 p := n.parameters[0] 2423 p.typ, p.val = c.checkExpr2(p.parameter) 2424 p.typ = underlyingType(p.typ) 2425 switch y := p.typ.(type) { 2426 case *pascalInteger, *subrangeType, *pascalReal: 2427 // ok 2428 default: 2429 panic(todo("%v: %T", n.parameters[0].parameter.Position(), y)) 2430 } 2431 case *pascalRound, *pascalTrunc: 2432 if len(n.parameters) != 1 { 2433 panic(todo("%v:", n.lparen.Position())) 2434 } 2435 2436 p := n.parameters[0] 2437 p.typ, p.val = c.checkExpr(p.parameter) 2438 switch y := p.typ.(type) { 2439 case *pascalReal, *pascalReal32: 2440 // ok 2441 default: 2442 panic(todo("%v: %T", n.parameters[0].parameter.Position(), y)) 2443 } 2444 case *pascalWrite, *pascalWriteln, *pascalReset, *pascalRewrite, *pascalRead, *pascalReadln: 2445 for i, v := range n.parameters { 2446 v.check(c, i, t) 2447 } 2448 case *pascalEOF, *pascalEOLN, *pascalOdd, *knuthBreak, *knuthErstat, *knuthClose, *pascalGet, *pascalPut, *knuthCurPos, *pascalOrd: 2449 if len(n.parameters) != 1 { 2450 panic(todo("%v:", n.lparen.Position())) 2451 } 2452 2453 n.parameters[0].check(c, 0, t) 2454 case *knuthBreakIn, *knuthSetPos: 2455 if len(n.parameters) != 2 { 2456 panic(todo("%v:", n.lparen.Position())) 2457 } 2458 2459 for i, v := range n.parameters { 2460 v.check(c, i, t) 2461 } 2462 case *knuthPanic: 2463 if len(n.parameters) != 1 { 2464 panic(todo("%v:", n.lparen.Position())) 2465 } 2466 2467 for i, v := range n.parameters { 2468 v.check(c, i, t) 2469 } 2470 case *procedureDeclaration: 2471 fp := x.procedureHeading.fp 2472 for i, v := range n.parameters { 2473 if i >= len(fp) { 2474 panic(todo("")) 2475 } 2476 2477 v.check(c, i, fp[i]) 2478 } 2479 case *functionDeclaration: 2480 fp := x.functionHeading.fp 2481 for i, v := range n.parameters { 2482 if i >= len(fp) { 2483 panic(todo("")) 2484 } 2485 2486 v.check(c, i, fp[i]) 2487 } 2488 default: 2489 panic(todo("%v: %T", n.lparen.Position(), x)) 2490 } 2491 } 2492 2493 // ActualParameterList = "(" ActualParameter { "," ActualParameter } ")" . 2494 // ActualParameter = Expression | Variable | Procedureldentifier | FunctionIdentifier . 2495 // WriteParameterList = "(" ( FileVariable | WriteParameter) { "," WriteParameter } ")" . 2496 // WriteParameter = Expression [ ":" IntegerExpression [ ":" IntegerExpression ] ] . 2497 func (p *pasParser) parameters() (r *parameters) { 2498 if p.c() != '(' { 2499 return nil 2500 } 2501 2502 return ¶meters{ 2503 p.shift(), 2504 p.parameterList(), 2505 p.must(')'), 2506 } 2507 } 2508 2509 type parameter struct { 2510 comma pasToken 2511 parameter node 2512 2513 typ, val interface{} 2514 } 2515 2516 func (n *parameter) check(c *ctx, ix int, t interface{}) { 2517 if n == nil { 2518 return 2519 } 2520 2521 n.typ, n.val = c.checkExpr2(n.parameter) 2522 c.mustAssign(n.parameter, ix, t, n.typ, n.val) 2523 } 2524 2525 func (c *ctx) mustAssign(n node, ix int, dt, st, sv interface{}) { 2526 if !c.checkAssign(n, ix, dt, st, sv) { 2527 panic(todo("%v: %T <- %T", n.Position(), dt, st)) 2528 } 2529 } 2530 2531 func (c *ctx) checkAssign(n node, ix int, dt, st, sv interface{}) bool { 2532 dt = underlyingType(dt) 2533 st = underlyingType(st) 2534 if f, ok := st.(*functionDeclaration); ok { 2535 st = underlyingType(f.functionHeading.result) 2536 } 2537 switch x := dt.(type) { 2538 case *pascalInteger, *subrangeType: 2539 switch y := st.(type) { 2540 case *pascalInteger, *subrangeType: 2541 return true 2542 default: 2543 panic(todo("%v: %T", n.Position(), y)) 2544 } 2545 case *pascalReal: 2546 switch y := st.(type) { 2547 case *pascalReal, *pascalReal32, *pascalInteger, *subrangeType: 2548 return true 2549 default: 2550 panic(todo("%v: %T", n.Position(), y)) 2551 } 2552 case *pascalReal32: 2553 switch y := st.(type) { 2554 case *pascalReal32, *pascalReal: 2555 return true 2556 default: 2557 panic(todo("%v: %T", n.Position(), y)) 2558 } 2559 case *pascalWrite, *pascalWriteln: 2560 switch y := st.(type) { 2561 case *stringLiteral, *pascalInteger, *subrangeType, *pascalChar, *pascalReal, *recordType: 2562 return true 2563 case *pascalText, *fileType, *pascalOutput, *pascalStderr: 2564 return ix == 0 2565 case *arrayType: 2566 switch z := y.elemTyp.(type) { 2567 case *pascalChar: 2568 return true 2569 default: 2570 panic(todo("%v: %T", n.Position(), z)) 2571 } 2572 default: 2573 panic(todo("%v: %T", n.Position(), y)) 2574 } 2575 case *pascalReset, *pascalRewrite: 2576 switch y := st.(type) { 2577 case *fileType, *pascalText: 2578 return ix == 0 2579 case *arrayType: 2580 switch z := y.elemTyp.(type) { 2581 case *pascalChar: 2582 return ix == 1 2583 default: 2584 panic(todo("%v: %T", n.Position(), z)) 2585 } 2586 case *stringLiteral: 2587 return ix != 0 2588 default: 2589 panic(todo("%v: %T", n.Position(), y)) 2590 } 2591 case *knuthBreakIn: 2592 switch y := st.(type) { 2593 case *fileType: 2594 return ix == 0 2595 case *pascalBoolean: 2596 return ix == 1 2597 default: 2598 panic(todo("%v: %T", n.Position(), y)) 2599 } 2600 case *knuthPanic: 2601 switch y := st.(type) { 2602 case *pascalInteger: 2603 return ix == 0 2604 default: 2605 panic(todo("%v: %T", n.Position(), y)) 2606 } 2607 case *knuthSetPos: 2608 switch y := st.(type) { 2609 case *fileType: 2610 return ix == 0 2611 case *pascalInteger: 2612 return ix == 1 2613 default: 2614 panic(todo("%v: %T", n.Position(), y)) 2615 } 2616 case *pascalEOF, *pascalEOLN, *knuthBreak, *knuthErstat, *knuthClose, *pascalGet, *pascalPut, *knuthCurPos: 2617 switch y := st.(type) { 2618 case *fileType, *pascalText, *pascalOutput, *pascalInput, *pascalStderr: 2619 return ix == 0 2620 default: 2621 panic(todo("%v: %T", n.Position(), y)) 2622 } 2623 case *pascalOdd: 2624 switch y := st.(type) { 2625 case *pascalInteger, *subrangeType: 2626 return ix == 0 2627 default: 2628 panic(todo("%v: %T", n.Position(), y)) 2629 } 2630 case *pascalOrd: 2631 switch y := st.(type) { 2632 case *pascalChar, *subrangeType, *pascalInteger: 2633 return ix == 0 2634 default: 2635 panic(todo("%v: %T", n.Position(), y)) 2636 } 2637 case *arrayType: 2638 switch y := x.elemTyp.(type) { 2639 case *pascalChar: 2640 switch z := st.(type) { 2641 case *stringLiteral: 2642 if len(x.indexTyp) != 1 { 2643 panic(todo("", n.Position())) 2644 } 2645 2646 return true 2647 default: 2648 panic(todo("%v: %T", n.Position(), z)) 2649 } 2650 default: 2651 switch z := st.(type) { 2652 case *arrayType: 2653 return x.isPacked() == z.isPacked() && x.canAssignFrom(c, z) 2654 default: 2655 panic(todo("%v: %T", n.Position(), z)) 2656 } 2657 panic(todo("%v: %T", n.Position(), y)) 2658 } 2659 case *pascalChar: 2660 switch y := st.(type) { 2661 case *pascalChar: 2662 return true 2663 default: 2664 panic(todo("%v: %T", n.Position(), y)) 2665 } 2666 case *pascalBoolean: 2667 switch y := st.(type) { 2668 case *pascalBoolean: 2669 return true 2670 default: 2671 panic(todo("%v: %T", n.Position(), y)) 2672 } 2673 case *pascalRead, *pascalReadln: 2674 switch y := st.(type) { 2675 case *fileType, *pascalText, *pascalInput: 2676 return ix == 0 2677 case *pascalInteger, *subrangeType, *pascalChar, *recordType: 2678 return true 2679 default: 2680 panic(todo("%v: %d %T", n.Position(), ix, y)) 2681 } 2682 case *functionDeclaration: 2683 nm := x.functionHeading.ident.Src() 2684 if c.inFunc[nm] == 0 { 2685 panic(todo("%v: %T", n.Position(), x)) 2686 } 2687 2688 return c.checkAssign(n, -1, x.functionHeading.result, st, sv) 2689 case *recordType: 2690 switch y := st.(type) { 2691 case *recordType: 2692 return x.isPacked() == y.isPacked() && x.canAssignFrom(c, y) 2693 default: 2694 panic(todo("%v: %d %T", n.Position(), ix, y)) 2695 } 2696 case *fileType: 2697 switch y := st.(type) { 2698 case *fileType: 2699 return x.isPacked() == y.isPacked() 2700 default: 2701 panic(todo("%v: %d %T", n.Position(), ix, y)) 2702 } 2703 default: 2704 panic(todo("%v: %T", n.Position(), x)) 2705 } 2706 } 2707 2708 func (p *pasParser) parameterList() (r []*parameter) { 2709 if p.c() == ')' { 2710 return nil 2711 } 2712 2713 r = []*parameter{{parameter: p.parameter()}} 2714 for { 2715 switch p.c() { 2716 case ')': 2717 return r 2718 case ',': 2719 r = append(r, ¶meter{comma: p.shift(), parameter: p.parameter()}) 2720 default: 2721 panic(todo("", p.token())) 2722 } 2723 } 2724 } 2725 2726 func (p *pasParser) parameter() (r node) { 2727 r = p.expression() 2728 switch p.c() { 2729 case ')', ',': 2730 return r 2731 case ':': 2732 wp := &writeParameter{ 2733 param: r, 2734 comma1: p.shift(), 2735 expr1: p.expression(), 2736 } 2737 if p.c() == ':' { 2738 wp.comma2 = p.shift() 2739 wp.expr2 = p.expression() 2740 } 2741 return wp 2742 default: 2743 panic(todo("", p.token())) 2744 } 2745 } 2746 2747 type writeParameter struct { 2748 param node // param : expr1 [ : expr2 ] 2749 comma1 pasToken 2750 expr1 node 2751 comma2 pasToken 2752 expr2 node 2753 2754 wtyp, wval interface{} 2755 wtyp2, wval2 interface{} 2756 } 2757 2758 func (n *writeParameter) Position() (r token.Position) { 2759 if n == nil { 2760 return r 2761 } 2762 2763 return n.param.Position() 2764 } 2765 2766 type binaryExpression struct { 2767 lhs node 2768 op pasToken 2769 rhs node 2770 2771 typ, value interface{} 2772 cmpTyp interface{} 2773 } 2774 2775 func (n *binaryExpression) Position() (r token.Position) { 2776 if n == nil { 2777 return r 2778 } 2779 2780 return n.lhs.Position() 2781 } 2782 2783 // Expression = SimpleExression [ RelationalOperator SimpleExression ] . 2784 func (p *pasParser) expression() (r node) { 2785 r = p.simpleExpression(true) 2786 switch p.c() { 2787 case '=', tokNeq, '<', tokLeq, '>', tokGeq, tokIn: 2788 return &binaryExpression{ 2789 lhs: r, 2790 op: p.shift(), 2791 rhs: p.simpleExpression(true), 2792 } 2793 default: 2794 return r 2795 } 2796 } 2797 2798 // SimpleExpression = [ Sign ] Term { AddingOperator Term } . 2799 func (p *pasParser) simpleExpression(acceptSign bool) (r node) { 2800 switch p.c() { 2801 case '-', '+': 2802 if !acceptSign { 2803 panic(todo("", p.token())) 2804 } 2805 2806 r = &signed{ 2807 sign: p.shift(), 2808 node: p.term(), 2809 } 2810 default: 2811 r = p.term() 2812 } 2813 for { 2814 switch p.c() { 2815 case '+', '-', tokOr: 2816 r = &binaryExpression{ 2817 lhs: r, 2818 op: p.shift(), 2819 rhs: p.term(), 2820 } 2821 default: 2822 return r 2823 } 2824 } 2825 } 2826 2827 // Term = Factor { MultiplyingOperator Factor } . 2828 func (p *pasParser) term() (r node) { 2829 r = p.factor() 2830 for { 2831 switch p.c() { 2832 case '*', '/', tokDiv, tokMod, tokAnd: 2833 r = &binaryExpression{ 2834 lhs: r, 2835 op: p.shift(), 2836 rhs: p.factor(), 2837 } 2838 default: 2839 return r 2840 } 2841 } 2842 } 2843 2844 // Factor = UnsignedConstant | BoundIdentifier | Variable 2845 // 2846 // | SetConstructor | FunctionDesignator | 2847 // "not" factor | "(" Expression ")" . 2848 func (p *pasParser) factor() (r node) { 2849 switch p.c() { 2850 case '-': 2851 sgn := p.shift() 2852 switch p.c() { 2853 case tokInt, tokFloat, tokString: 2854 return &signed{ 2855 sign: sgn, 2856 node: p.shift(), 2857 } 2858 default: 2859 panic(todo("", p.token())) 2860 } 2861 case tokString, tokInt, tokFloat, tokNil: 2862 return p.shift() 2863 case tokIdent: 2864 id := &identifier{ident: p.shift()} 2865 switch p.c() { 2866 case '(': 2867 return p.functionCall(id) 2868 case '[', '.', '^': 2869 return p.variable(id) 2870 default: 2871 if _, ok := p.scope.lookup(id).(*functionDeclaration); ok { 2872 return &functionCall{ident: id} 2873 } 2874 2875 return id 2876 } 2877 case '(': 2878 return p.parenthesizedExpression() 2879 case tokNot: 2880 return ¬{ 2881 not: p.shift(), 2882 factor: p.factor(), 2883 } 2884 default: 2885 panic(todo("", p.token())) 2886 } 2887 } 2888 2889 type not struct { 2890 not pasToken 2891 factor node 2892 2893 typ, val interface{} 2894 } 2895 2896 func (n *not) Position() (r token.Position) { 2897 if n == nil { 2898 return r 2899 } 2900 2901 return n.not.Position() 2902 } 2903 2904 type parenthesizedExpression struct { 2905 lparen pasToken 2906 expr node 2907 rparen pasToken 2908 2909 typ, val interface{} 2910 } 2911 2912 func (n *parenthesizedExpression) Position() (r token.Position) { 2913 if n == nil { 2914 return r 2915 } 2916 2917 return n.lparen.Position() 2918 } 2919 2920 func (p *pasParser) parenthesizedExpression() (r *parenthesizedExpression) { 2921 return &parenthesizedExpression{ 2922 lparen: p.must('('), 2923 expr: p.expression(), 2924 rparen: p.must(')'), 2925 } 2926 } 2927 2928 type functionCall struct { 2929 ident *identifier 2930 parameters *parameters 2931 2932 typ, ft interface{} 2933 } 2934 2935 func (n *functionCall) Position() (r token.Position) { 2936 if n == nil { 2937 return r 2938 } 2939 2940 return n.ident.Position() 2941 } 2942 2943 func (p *pasParser) functionCall(id *identifier) (r *functionCall) { 2944 return &functionCall{ 2945 ident: id, 2946 parameters: p.parameters(), 2947 } 2948 } 2949 2950 type procedureAndFunctionDeclarationPart struct { 2951 declaration node 2952 semi pasToken 2953 } 2954 2955 func (n *procedureAndFunctionDeclarationPart) Position() (r token.Position) { 2956 if n == nil { 2957 return r 2958 } 2959 2960 return n.declaration.Position() 2961 } 2962 2963 // ProcedureAndFunctionDeclarationPart = { ( ProcedureDeclaration | FunctionDeclaration ) ";" } . 2964 func (p *pasParser) procedureAndFunctionDeclarationPart() (r []*procedureAndFunctionDeclarationPart) { 2965 for { 2966 switch p.c() { 2967 case tokProcedure: 2968 r = append(r, &procedureAndFunctionDeclarationPart{p.procedureDeclaration(), p.must(';')}) 2969 case tokBegin: 2970 return r 2971 case tokFunction: 2972 r = append(r, &procedureAndFunctionDeclarationPart{p.functionDeclaration(), p.must(';')}) 2973 default: 2974 panic(todo("", p.token())) 2975 } 2976 } 2977 } 2978 2979 // FunctionDeclaration = FunctionHeading ";" Block | 2980 // 2981 // FunctionHeading ";" Directive | 2982 // FunctionIdentification ";" Block . 2983 func (p *pasParser) functionDeclaration() (r *functionDeclaration) { 2984 p.scope = newScope(p.scope) 2985 2986 defer func() { p.scope = p.scope.parent }() 2987 2988 r = &functionDeclaration{} 2989 r.functionHeading = p.functionHeading(r) 2990 r.semi = p.must(';') 2991 r.block = p.blockOrForward() 2992 return r 2993 } 2994 2995 func (p *pasParser) blockOrForward() (r node) { 2996 if p.c() == tokIdent { 2997 id := p.shift() 2998 if strings.ToLower(id.Src()) == "forward" { 2999 return id 3000 } 3001 3002 panic(todo("", id)) 3003 } 3004 3005 return p.block() 3006 } 3007 3008 type functionHeading struct { 3009 function pasToken 3010 ident *identifier 3011 formalParameterList *formalParameterList 3012 comma pasToken 3013 type1 node 3014 3015 fp []interface{} 3016 result interface{} 3017 } 3018 3019 func (n *functionHeading) Position() (r token.Position) { 3020 if n == nil { 3021 return r 3022 } 3023 3024 return n.function.Position() 3025 } 3026 3027 func (n *functionHeading) check(c *ctx) { 3028 if n == nil { 3029 return 3030 } 3031 3032 n.fp = n.formalParameterList.check(c) 3033 n.result = c.checkType(n.type1) 3034 } 3035 3036 // FunctionHeading = "function" Identifier [ FormalParameterList ] ":" Type . 3037 func (p *pasParser) functionHeading(n *functionDeclaration) (r *functionHeading) { 3038 r = &functionHeading{ 3039 function: p.must(tokFunction), 3040 ident: p.mustIdent(tokIdent), 3041 } 3042 if nm := r.ident.Src(); p.scope.parent.nodes[nm] == nil { 3043 p.scope.parent.add(nm, n) 3044 } 3045 switch p.c() { 3046 case '(': 3047 r.formalParameterList = p.formalParameterList() 3048 r.comma = p.must(':') 3049 r.type1 = p.type1() 3050 return r 3051 case ';': 3052 return r 3053 case ':': 3054 r.comma = p.shift() 3055 r.type1 = p.type1() 3056 return r 3057 default: 3058 panic(todo("", p.token())) 3059 } 3060 } 3061 3062 type functionDeclaration struct { 3063 functionHeading *functionHeading 3064 semi pasToken 3065 block node 3066 3067 paramTypes []interface{} 3068 scope *scope 3069 } 3070 3071 func (n *functionDeclaration) Position() (r token.Position) { 3072 if n == nil { 3073 return r 3074 } 3075 3076 return n.functionHeading.Position() 3077 } 3078 3079 func (n *functionDeclaration) isFwd() bool { 3080 if n == nil { 3081 return false 3082 } 3083 3084 _, ok := n.block.(pasToken) 3085 return ok 3086 } 3087 3088 func (n *functionDeclaration) check(c *ctx) { 3089 if n == nil { 3090 return 3091 } 3092 3093 nm := n.functionHeading.ident.Src() 3094 switch x := n.block.(type) { 3095 case *block: 3096 if x, ok := c.scope.nodes[nm].(*functionDeclaration); ok && x.isFwd() { 3097 delete(c.scope.nodes, nm) 3098 n.functionHeading = x.functionHeading 3099 } 3100 c.scope.add(nm, n) 3101 3102 defer func() { c.scope = c.scope.parent }() 3103 3104 scope := n.scope 3105 if scope == nil { 3106 c.scope = newScope(c.scope) 3107 n.scope = c.scope 3108 n.functionHeading.check(c) 3109 } 3110 c.inFunc[nm]++ 3111 3112 defer func() { c.inFunc[nm]-- }() 3113 3114 x.check(c) 3115 case pasToken: // forward 3116 c.scope.add(nm, n) 3117 c.scope = newScope(c.scope) 3118 n.scope = c.scope 3119 3120 defer func() { c.scope = c.scope.parent }() 3121 3122 n.functionHeading.check(c) 3123 default: 3124 panic(todo("%v %T", n.semi, x)) 3125 } 3126 } 3127 3128 type procedureDeclaration struct { 3129 procedureHeading *procedureHeading 3130 semi pasToken 3131 block node 3132 3133 scope *scope 3134 } 3135 3136 func (n *procedureDeclaration) Position() (r token.Position) { 3137 if n == nil { 3138 return r 3139 } 3140 3141 return n.procedureHeading.Position() 3142 } 3143 3144 func (n *procedureDeclaration) check(c *ctx) { 3145 if n == nil { 3146 return 3147 } 3148 3149 nm := n.procedureHeading.ident.Src() 3150 switch x := n.block.(type) { 3151 case *block: 3152 if x, ok := c.scope.nodes[nm].(*procedureDeclaration); ok && x.isFwd() { 3153 delete(c.scope.nodes, nm) 3154 n.procedureHeading = x.procedureHeading 3155 } 3156 c.scope.add(nm, n) 3157 3158 defer func() { c.scope = c.scope.parent }() 3159 3160 scope := n.scope 3161 if scope == nil { 3162 c.scope = newScope(c.scope) 3163 n.scope = c.scope 3164 n.procedureHeading.check(c) 3165 } 3166 x.check(c) 3167 case pasToken: // forward 3168 c.scope.add(nm, n) 3169 c.scope = newScope(c.scope) 3170 n.scope = c.scope 3171 3172 defer func() { c.scope = c.scope.parent }() 3173 3174 n.procedureHeading.check(c) 3175 default: 3176 panic(todo("%v %T", n.semi, x)) 3177 } 3178 } 3179 3180 func (n *procedureDeclaration) isFwd() bool { 3181 if n == nil { 3182 return false 3183 } 3184 3185 _, ok := n.block.(pasToken) 3186 return ok 3187 } 3188 3189 // ProcedureDeclaration = ProcedureHeading ";" Block | 3190 // 3191 // ProcedureHeading ";" Directive | 3192 // ProcedureIdentification ";" Block. 3193 func (p *pasParser) procedureDeclaration() (r *procedureDeclaration) { 3194 p.scope = newScope(p.scope) 3195 3196 defer func() { p.scope = p.scope.parent }() 3197 3198 r = &procedureDeclaration{} 3199 r.procedureHeading = p.procedureHeading(r) 3200 r.semi = p.must(';') 3201 r.block = p.blockOrForward() 3202 return r 3203 } 3204 3205 type formalParameterList struct { 3206 lparen pasToken 3207 params []*formalParameterSection 3208 rparen pasToken 3209 } 3210 3211 func (n *formalParameterList) Position() (r token.Position) { 3212 if n == nil { 3213 return r 3214 } 3215 3216 return n.lparen.Position() 3217 } 3218 3219 func (n *formalParameterList) check(c *ctx) (r []interface{}) { 3220 if n == nil { 3221 return 3222 } 3223 3224 for _, v := range n.params { 3225 r = append(r, v.check(c)...) 3226 } 3227 return r 3228 } 3229 3230 // FormalParameterList = "(" FormalParameterSection { ";" FormalParameterSection } ")" . 3231 func (p *pasParser) formalParameterList() (r *formalParameterList) { 3232 if p.c() != '(' { 3233 return nil 3234 } 3235 3236 return &formalParameterList{ 3237 p.must('('), 3238 p.formalParameterSection(), 3239 p.must(')'), 3240 } 3241 } 3242 3243 type formalParameterSection struct { 3244 semi pasToken 3245 param node 3246 } 3247 3248 func (n *formalParameterSection) check(c *ctx) (r []interface{}) { 3249 if n == nil { 3250 return 3251 } 3252 3253 switch x := n.param.(type) { 3254 case *parameterSpecification: 3255 r = append(r, x.check(c)...) 3256 default: 3257 panic(todo("%v: %T", n.param.Position(), x)) 3258 } 3259 return r 3260 } 3261 3262 // FormalParameterSection = ValueParameterSpecification | 3263 // 3264 // VariableParamererSpecification | 3265 // ProceduralParameterSpecification | 3266 // FunctionalParameterSpecification . 3267 func (p *pasParser) formalParameterSection() (r []*formalParameterSection) { 3268 switch p.c() { 3269 case tokIdent: 3270 r = []*formalParameterSection{{param: p.parameterSpecification(pasToken{})}} 3271 case tokVar: 3272 r = []*formalParameterSection{{param: p.parameterSpecification(p.shift())}} 3273 default: 3274 panic(todo("", p.token())) 3275 } 3276 for p.c() == ';' { 3277 semi := p.shift() 3278 switch p.c() { 3279 case tokIdent: 3280 r = append(r, &formalParameterSection{semi, p.parameterSpecification(pasToken{})}) 3281 case tokVar: 3282 r = append(r, &formalParameterSection{semi, p.parameterSpecification(p.shift())}) 3283 default: 3284 panic(todo("", p.token())) 3285 } 3286 } 3287 return r 3288 } 3289 3290 type parameterSpecification struct { 3291 var1 pasToken 3292 identifierList []*identifierList 3293 comma pasToken 3294 type1 node 3295 3296 typ interface{} 3297 } 3298 3299 func (n *parameterSpecification) Position() (r token.Position) { 3300 if n == nil { 3301 return r 3302 } 3303 3304 return n.identifierList[0].ident.Position() 3305 } 3306 3307 func (n *parameterSpecification) check(c *ctx) (r []interface{}) { 3308 if n == nil { 3309 return 3310 } 3311 3312 n.typ = c.checkType(n.type1) 3313 for _, v := range n.identifierList { 3314 r = append(r, n.typ) 3315 p := &variable{ 3316 ident: v.ident, 3317 typ: n.typ, 3318 isParam: true, 3319 } 3320 c.scope.add(v.ident.Src(), p) 3321 } 3322 return r 3323 } 3324 3325 // ValueParameterSpecification = IdentifierList ":" Type . 3326 func (p *pasParser) parameterSpecification(var1 pasToken) (r *parameterSpecification) { 3327 r = ¶meterSpecification{ 3328 var1: var1, 3329 identifierList: p.identifierList(), 3330 comma: p.must(':'), 3331 type1: p.type1(), 3332 } 3333 for _, v := range r.identifierList { 3334 p.scope.add(v.ident.Src(), r) 3335 } 3336 return r 3337 } 3338 3339 type procedureHeading struct { 3340 procedure pasToken 3341 ident *identifier 3342 formalParameterList *formalParameterList 3343 3344 fp []interface{} 3345 } 3346 3347 func (n *procedureHeading) Position() (r token.Position) { 3348 if n == nil { 3349 return r 3350 } 3351 3352 return n.procedure.Position() 3353 } 3354 3355 func (n *procedureHeading) check(c *ctx) { 3356 if n == nil { 3357 return 3358 } 3359 3360 n.fp = n.formalParameterList.check(c) 3361 } 3362 3363 // ProcedureHeading = "procedure" Identifier [ FormalParameterList ] . 3364 func (p *pasParser) procedureHeading(n *procedureDeclaration) (r *procedureHeading) { 3365 r = &procedureHeading{ 3366 procedure: p.must(tokProcedure), 3367 ident: p.mustIdent(tokIdent), 3368 formalParameterList: p.formalParameterList(), 3369 } 3370 if nm := r.ident.Src(); p.scope.parent.nodes[nm] == nil { 3371 p.scope.parent.add(nm, n) 3372 } 3373 return r 3374 } 3375 3376 type variableDeclarationPart struct { 3377 var1 pasToken 3378 variableDeclarationList []*variableDeclarationList 3379 } 3380 3381 func (n *variableDeclarationPart) Position() (r token.Position) { 3382 if n == nil { 3383 return r 3384 } 3385 3386 return n.var1.Position() 3387 } 3388 3389 // VariableDeclarationPart = [ "var" VariableDeclaration ";" { VariableDeclaration ";" } ] . 3390 func (p *pasParser) variableDeclarationPart() (r *variableDeclarationPart) { 3391 if p.c() != tokVar { 3392 return nil 3393 } 3394 3395 r = &variableDeclarationPart{ 3396 p.shift(), 3397 []*variableDeclarationList{{p.variableDeclaration(), p.must(';')}}, 3398 } 3399 for { 3400 switch p.c() { 3401 case tokProcedure, tokFunction, tokBegin: 3402 return r 3403 case tokIdent: 3404 r.variableDeclarationList = append(r.variableDeclarationList, &variableDeclarationList{p.variableDeclaration(), p.must(';')}) 3405 default: 3406 panic(todo("", p.token())) 3407 } 3408 } 3409 } 3410 3411 type variableDeclaration struct { 3412 identifierList []*identifierList 3413 colon pasToken 3414 type1 node 3415 3416 typ interface{} 3417 } 3418 3419 func (n *variableDeclaration) Position() (r token.Position) { 3420 if n == nil { 3421 return r 3422 } 3423 3424 return n.identifierList[0].ident.Position() 3425 } 3426 3427 // VariableDeclaration = IdentifierList ":" Type . 3428 func (p *pasParser) variableDeclaration() (r *variableDeclaration) { 3429 r = &variableDeclaration{ 3430 identifierList: p.identifierList(), 3431 colon: p.must(':'), 3432 type1: p.type1(), 3433 } 3434 for _, v := range r.identifierList { 3435 p.scope.add(v.ident.Src(), r) 3436 } 3437 return r 3438 } 3439 3440 type variableDeclarationList struct { 3441 variableDeclaration *variableDeclaration 3442 semi pasToken 3443 } 3444 3445 type constantDefinitionPart struct { 3446 const1 pasToken 3447 constantDefinitionList []*constantDefinitionList 3448 } 3449 3450 func (n *constantDefinitionPart) Position() (r token.Position) { 3451 if n == nil { 3452 return r 3453 } 3454 3455 return n.const1.Position() 3456 } 3457 3458 type constantDefinitionList struct { 3459 constantDefinition *constantDefinition 3460 semi pasToken 3461 } 3462 3463 // ConstantDefinitionPart = [ "const" ConstantDefinition ";" { ConstantDefinition ";" } ] . 3464 func (p *pasParser) constantDefinitionPart() (r *constantDefinitionPart) { 3465 if p.c() != tokConst { 3466 return nil 3467 } 3468 3469 r = &constantDefinitionPart{ 3470 p.shift(), 3471 []*constantDefinitionList{{p.constantDefinition(), p.must(';')}}, 3472 } 3473 for { 3474 switch p.c() { 3475 case tokIdent: 3476 r.constantDefinitionList = append(r.constantDefinitionList, &constantDefinitionList{p.constantDefinition(), p.must(';')}) 3477 case tokType, tokVar: 3478 return r 3479 default: 3480 panic(todo("", p.token())) 3481 } 3482 } 3483 } 3484 3485 type constantDefinition struct { 3486 ident *identifier 3487 eq pasToken 3488 constant node 3489 3490 value, typ interface{} 3491 } 3492 3493 func (n *constantDefinition) Position() (r token.Position) { 3494 if n == nil { 3495 return r 3496 } 3497 3498 return n.ident.Position() 3499 } 3500 3501 // ConstantDefinition = Identifier "=" Constant . 3502 func (p *pasParser) constantDefinition() (r *constantDefinition) { 3503 r = &constantDefinition{ 3504 ident: p.mustIdent(tokIdent), 3505 eq: p.must('='), 3506 constant: p.expression(), 3507 } 3508 p.scope.add(r.ident.Src(), r) 3509 return r 3510 } 3511 3512 type numericConstant struct { 3513 sign pasToken 3514 value node 3515 } 3516 3517 func (n *numericConstant) Position() (r token.Position) { 3518 if n == nil { 3519 return r 3520 } 3521 3522 if n.sign.isValid() { 3523 return n.sign.Position() 3524 } 3525 3526 return n.value.Position() 3527 } 3528 3529 type signed struct { 3530 sign pasToken 3531 node node 3532 3533 typ interface{} 3534 } 3535 3536 func (n *signed) Position() (r token.Position) { 3537 if n == nil { 3538 return r 3539 } 3540 3541 return n.sign.Position() 3542 } 3543 3544 // Constant = [ Sign ] ( UnsignedNumher | ConstantIdentifier) | CharacterString . 3545 func (p *pasParser) constant(acceptSign bool) (r node) { 3546 switch p.c() { 3547 case tokInt: 3548 return &numericConstant{value: p.expression()} 3549 case tokIdent, tokString: 3550 return p.shift() 3551 case '-', '+': 3552 if !acceptSign { 3553 panic(todo("", p.token())) 3554 } 3555 3556 return &signed{ 3557 sign: p.shift(), 3558 node: p.constant(false), 3559 } 3560 default: 3561 panic(todo("", p.token())) 3562 } 3563 } 3564 3565 type labelDeclarationPart struct { 3566 label pasToken 3567 digitSequenceList []*digitSequenceList 3568 semi pasToken 3569 } 3570 3571 func (n *labelDeclarationPart) Position() (r token.Position) { 3572 if n == nil { 3573 return r 3574 } 3575 3576 return n.label.Position() 3577 } 3578 3579 type digitSequenceList struct { 3580 comma pasToken 3581 digitSequence node 3582 } 3583 3584 // LabelDeclarationPart = [ "label" DigitSequence { "," DigitSequence } ";" ] 3585 func (p *pasParser) labelDeclarationPart() (r *labelDeclarationPart) { 3586 if p.c() != tokLabel { 3587 return nil 3588 } 3589 3590 r = &labelDeclarationPart{ 3591 label: p.shift(), 3592 } 3593 r.digitSequenceList = []*digitSequenceList{{digitSequence: p.expression()}} 3594 for p.c() == ',' { 3595 r.digitSequenceList = append(r.digitSequenceList, &digitSequenceList{p.shift(), p.expression()}) 3596 } 3597 r.semi = p.must(';') 3598 return r 3599 } 3600 3601 type scope struct { 3602 nodes map[string]node 3603 parent *scope 3604 3605 setResolution bool 3606 } 3607 3608 func newScope(parent *scope) *scope { 3609 setResolution := false 3610 if parent != nil { 3611 setResolution = parent.setResolution 3612 } 3613 return &scope{parent: parent, setResolution: setResolution} 3614 } 3615 3616 func (s *scope) isTLD() bool { return s.parent != nil && s.parent.isUniverse() } 3617 func (s *scope) isUniverse() bool { return s.parent == nil } 3618 3619 func (s *scope) add(nm string, n node) { 3620 nm = strings.ToLower(nm) 3621 if ex, ok := s.nodes[nm]; ok { 3622 panic(todo("%v: %q redefined, previous at %v: %T", n.Position(), nm, ex.Position(), ex)) 3623 } 3624 3625 if s.nodes == nil { 3626 s.nodes = map[string]node{} 3627 } 3628 s.nodes[nm] = n 3629 } 3630 3631 func (s *scope) mustLookup(id *identifier) (r node) { 3632 if r := s.lookup(id); r != nil { 3633 return r 3634 } 3635 3636 // for s != nil { 3637 // trc("tried %p, universe %v, tld %v, setResolution %v", s, s.isUniverse(), s.isTLD(), s.setResolution) 3638 // s = s.parent 3639 // } 3640 panic(todo("%v: undefined %q", id.Position(), id.Src())) 3641 } 3642 3643 func (s *scope) lookup(id *identifier) node { 3644 nm := strings.ToLower(id.Src()) 3645 for s != nil { 3646 if r := s.nodes[nm]; r != nil { 3647 if s.setResolution { 3648 id.scope = s 3649 id.resolvedTo = r 3650 } 3651 return r 3652 } 3653 3654 s = s.parent 3655 } 3656 3657 return nil 3658 } 3659 3660 type ctx struct { 3661 errs errList 3662 scope *scope 3663 3664 inFunc map[string]int 3665 } 3666 3667 func newCtx() (r *ctx) { 3668 universe := newScope(nil) 3669 universe.setResolution = true 3670 universe.add("abs", &pascalAbs{}) 3671 universe.add("boolean", &pascalBoolean{}) 3672 universe.add("break", &knuthBreak{}) 3673 universe.add("break_in", &knuthBreakIn{}) 3674 universe.add("char", &pascalChar{}) 3675 universe.add("chr", &pascalChr{}) 3676 universe.add("close", &knuthClose{}) 3677 universe.add("cur_pos", &knuthCurPos{}) 3678 universe.add("eof", &pascalEOF{}) 3679 universe.add("eoln", &pascalEOLN{}) 3680 universe.add("erstat", &knuthErstat{}) 3681 universe.add("false", &pascalFalse{}) 3682 universe.add("get", &pascalGet{}) 3683 universe.add("input", &pascalInput{}) 3684 universe.add("integer", &pascalInteger{}) 3685 universe.add("max_int", &pascalMaxInt{}) 3686 universe.add("odd", &pascalOdd{}) 3687 universe.add("ord", &pascalOrd{}) 3688 universe.add("output", &pascalOutput{}) 3689 universe.add("panic", &knuthPanic{}) 3690 universe.add("put", &pascalPut{}) 3691 universe.add("read", &pascalRead{}) 3692 universe.add("readln", &pascalReadln{}) 3693 universe.add("real", &pascalReal{}) 3694 universe.add("reset", &pascalReset{}) 3695 universe.add("rewrite", &pascalRewrite{}) 3696 universe.add("round", &pascalRound{}) 3697 universe.add("set_pos", &knuthSetPos{}) 3698 universe.add("stderr", &pascalStderr{}) 3699 universe.add("text", &pascalText{}) 3700 universe.add("true", &pascalTrue{}) 3701 universe.add("trunc", &pascalTrunc{}) 3702 universe.add("write", &pascalWrite{}) 3703 universe.add("writeln", &pascalWriteln{}) 3704 return &ctx{ 3705 inFunc: map[string]int{}, 3706 scope: newScope(universe), 3707 } 3708 } 3709 3710 type ast struct { 3711 eof pasToken 3712 program *program 3713 tldScope *scope 3714 } 3715 3716 func (n *ast) check() error { 3717 c := newCtx() 3718 n.tldScope = c.scope 3719 n.program.check(c) 3720 return c.errs.Err() 3721 } 3722 3723 func (n *program) check(c *ctx) { 3724 if n == nil { 3725 return 3726 } 3727 3728 n.programHeading.check(c) 3729 n.block.check(c) 3730 var progParams []*identifier 3731 if n.programHeading.programParameterList != nil { 3732 progParams = n.programHeading.programParameterList.idents 3733 } 3734 for _, v := range progParams { 3735 if x := c.scope.mustLookup(v); x == nil { 3736 panic(todo("", v)) 3737 } 3738 } 3739 } 3740 3741 func (n *programHeading) check(c *ctx) { 3742 if n == nil { 3743 return 3744 } 3745 3746 n.programParameterList.check(c) 3747 } 3748 3749 func (n *programParameterList) check(c *ctx) { 3750 if n == nil { 3751 return 3752 } 3753 3754 for _, v := range n.identifierList { 3755 n.idents = append(n.idents, v.ident) 3756 } 3757 } 3758 3759 func (n *block) check(c *ctx) { 3760 if n == nil { 3761 return 3762 } 3763 3764 n.labelDeclarationPart.check(c) 3765 n.constantDefinitionPart.check(c) 3766 n.typeDefinitionPart.check(c) 3767 n.variableDeclarationPart.check(c) 3768 for _, v := range n.procedureAndFunctionDeclarationPart { 3769 switch x := v.declaration.(type) { 3770 case *procedureDeclaration: 3771 x.check(c) 3772 case *functionDeclaration: 3773 x.check(c) 3774 default: 3775 panic(todo("%v: %T", x.Position(), x)) 3776 } 3777 } 3778 n.statementPart.check(c) 3779 } 3780 3781 type label struct { 3782 node 3783 3784 nm string 3785 lhs, rhs interface{} 3786 } 3787 3788 func (n *labelDeclarationPart) check(c *ctx) { 3789 if n == nil { 3790 return 3791 } 3792 3793 for _, v := range n.digitSequenceList { 3794 switch x := v.digitSequence.(type) { 3795 case *identifier: 3796 y := &label{x, x.Src(), x.Src(), nil} 3797 c.scope.add(y.nm, y) 3798 case pasToken: 3799 y := &label{x, x.Src(), x.Src(), nil} 3800 c.scope.add(y.nm, y) 3801 case *binaryExpression: 3802 if x.op.ch != '+' { 3803 panic(todo("")) 3804 } 3805 3806 switch y := x.lhs.(type) { 3807 case *identifier: 3808 _, rhs := c.checkExpr(x.rhs) 3809 lbl := &label{x, fmt.Sprintf("%s+%v", y.Src(), rhs), y.Src(), rhs} 3810 c.scope.add(lbl.nm, lbl) 3811 default: 3812 panic(todo("%T", y)) 3813 } 3814 default: 3815 panic(todo("%v: %T", x.Position(), x)) 3816 } 3817 } 3818 } 3819 3820 func (n *constantDefinitionPart) check(c *ctx) { 3821 if n == nil { 3822 return 3823 } 3824 3825 for _, v := range n.constantDefinitionList { 3826 v.constantDefinition.check(c) 3827 } 3828 } 3829 3830 func (n *constantDefinition) check(c *ctx) { 3831 if n == nil { 3832 return 3833 } 3834 3835 n.typ, n.value = c.checkExpr(n.constant) 3836 if n.value == nil { 3837 panic(todo("%v: not a constant expression", n.constant.Position())) 3838 } 3839 3840 nm := strings.ToLower(n.ident.Src()) 3841 if _, ok := c.scope.nodes[nm].(*label); ok { 3842 return 3843 } 3844 3845 c.scope.add(nm, n) 3846 } 3847 3848 func (c *ctx) checkExpr2(n node) (typ interface{}, val interface{}) { 3849 typ, val = c.checkExpr(n) 3850 if x, ok := typ.(*functionDeclaration); ok { 3851 typ = x.functionHeading.result 3852 } 3853 return typ, val 3854 } 3855 3856 func (c *ctx) checkExpr(n node) (typ interface{}, val interface{}) { 3857 switch x := n.(type) { 3858 case *identifier: 3859 defer func() { x.typ = typ }() 3860 3861 switch y := c.scope.mustLookup(x).(type) { 3862 case *constantDefinition: 3863 return y.typ, y.value 3864 case *variable: 3865 return y.typ, nil 3866 case *pascalTrue: 3867 return &pascalBoolean{}, true 3868 case *pascalFalse: 3869 return &pascalBoolean{}, false 3870 case *pascalEOF, *pascalEOLN, *functionDeclaration, *label, *pascalOutput, *pascalInput, *pascalStderr: 3871 return y, nil 3872 case *pascalMaxInt: 3873 return &pascalInteger{}, int64(math.MaxInt32) 3874 default: 3875 panic(todo("%v: %T", x.Position(), y)) 3876 } 3877 case pasToken: 3878 switch x.ch { 3879 case tokInt: 3880 s := x.Src() 3881 n, err := strconv.ParseInt(s, 10, 64) 3882 if err != nil { 3883 panic(todo("%v: %v", x.Position(), err)) 3884 } 3885 3886 return &pascalInteger{}, n 3887 case tokFloat: 3888 s := x.Src() 3889 n, err := strconv.ParseFloat(s, 64) 3890 if err != nil { 3891 panic(todo("%v: %v", x.Position(), err)) 3892 } 3893 3894 return &pascalReal{}, n 3895 case tokString: 3896 s := x.Src() 3897 s = s[1 : len(s)-1] // remove quotes 3898 s = strings.ReplaceAll(s, "''", "'") // unquote 3899 switch a := []rune(s); len(a) { 3900 case 1: 3901 return &pascalChar{}, int64(a[0]) 3902 default: 3903 return &stringLiteral{}, s 3904 } 3905 default: 3906 panic(todo("", x)) 3907 } 3908 case *binaryExpression: 3909 t1, v1 := c.checkExpr2(x.lhs) 3910 t2, v2 := c.checkExpr2(x.rhs) 3911 switch x.op.ch { 3912 case '+': 3913 x.typ, x.value = c.add(x.op, t1, v1, t2, v2) 3914 return x.typ, x.value 3915 case '-': 3916 x.typ, x.value = c.sub(x.op, t1, v1, t2, v2) 3917 return x.typ, x.value 3918 case '*': 3919 x.typ, x.value = c.mul(x.op, t1, v1, t2, v2) 3920 return x.typ, x.value 3921 case '/': 3922 x.typ, x.value = c.div(x.op, t1, v1, t2, v2) 3923 return x.typ, x.value 3924 case tokDiv: 3925 x.typ, x.value = c.idiv(x.op, t1, v1, t2, v2) 3926 return x.typ, x.value 3927 case tokMod: 3928 x.typ, x.value = c.mod(x.op, t1, v1, t2, v2) 3929 return x.typ, x.value 3930 case '=': 3931 x.typ, x.value = c.eq(x.op, t1, v1, t2, v2) 3932 x.cmpTyp = c.binType(t1, t2) 3933 return x.typ, x.value 3934 case '>': 3935 x.typ, x.value = c.gt(x.op, t1, v1, t2, v2) 3936 x.cmpTyp = c.binType(t1, t2) 3937 return x.typ, x.value 3938 case '<': 3939 x.typ, x.value = c.lt(x.op, t1, v1, t2, v2) 3940 x.cmpTyp = c.binType(t1, t2) 3941 return x.typ, x.value 3942 case tokNeq: 3943 x.typ, x.value = c.neq(x.op, t1, v1, t2, v2) 3944 x.cmpTyp = c.binType(t1, t2) 3945 return x.typ, x.value 3946 case tokGeq: 3947 x.typ, x.value = c.geq(x.op, t1, v1, t2, v2) 3948 x.cmpTyp = c.binType(t1, t2) 3949 return x.typ, x.value 3950 case tokLeq: 3951 x.typ, x.value = c.leq(x.op, t1, v1, t2, v2) 3952 x.cmpTyp = c.binType(t1, t2) 3953 return x.typ, x.value 3954 case tokOr: 3955 x.typ, x.value = c.or(x.op, t1, v1, t2, v2) 3956 return x.typ, x.value 3957 case tokAnd: 3958 x.typ, x.value = c.and(x.op, t1, v1, t2, v2) 3959 return x.typ, x.value 3960 default: 3961 panic(todo("%v %T %v %T %v", x.op, t1, v1, t2, v2)) 3962 } 3963 case *not: 3964 t, v := c.checkExpr2(x.factor) 3965 switch y := t.(type) { 3966 case *pascalBoolean: 3967 if v != nil { 3968 v = !v.(bool) 3969 } 3970 x.typ = y 3971 x.val = v 3972 return x.typ, x.val 3973 default: 3974 panic(todo("%v: %T", n.Position(), y)) 3975 } 3976 case *signed: 3977 t, v := c.checkExpr2(x.node) 3978 switch y := underlyingType(t).(type) { 3979 case *pascalInteger, *subrangeType: 3980 if v != nil { 3981 v = -v.(int64) 3982 } 3983 x.typ = y 3984 return x.typ, v 3985 case *pascalReal: 3986 if v != nil { 3987 v = -v.(float64) 3988 } 3989 x.typ = y 3990 return x.typ, v 3991 default: 3992 panic(todo("%v: %T", n.Position(), y)) 3993 } 3994 case *indexedVariable: 3995 x.varTyp, _ = c.checkExpr(x.variable) 3996 switch y := underlyingType(x.varTyp).(type) { 3997 case *arrayType: 3998 switch xDims, yDims := len(x.indexList), len(y.typeList); { 3999 case xDims == yDims: 4000 for _, v := range x.indexList { 4001 c.checkExpr2(v.index) 4002 } 4003 x.typ = y.elemTyp 4004 return x.typ, nil 4005 default: 4006 panic(todo("%v: %v %v", n.Position(), xDims, yDims)) 4007 } 4008 default: 4009 panic(todo("%v: %T", x.lbracket.Position(), y)) 4010 } 4011 case *fieldDesignator: 4012 vt, _ := c.checkExpr(x.variable) 4013 switch y := underlyingType(vt).(type) { 4014 case *recordType: 4015 x.typ = y.field(x.ident.ident).typ 4016 return x.typ, nil 4017 default: 4018 panic(todo("%v: %T", x.dot.Position(), y)) 4019 } 4020 case *functionCall: 4021 switch y := c.scope.mustLookup(x.ident).(type) { 4022 case *pascalAbs: 4023 x.ft = y 4024 x.parameters.check(c, y) 4025 if len(x.parameters.parameters) == 1 { 4026 x.typ = x.parameters.parameters[0].typ 4027 } 4028 case *pascalChr: 4029 x.typ = &pascalChar{} 4030 x.ft = y 4031 x.parameters.check(c, y) 4032 case *pascalRound, *knuthCurPos, *pascalOrd, *pascalTrunc: 4033 x.typ = &pascalInteger{} 4034 x.ft = y 4035 x.parameters.check(c, y) 4036 case *pascalEOF, *pascalEOLN, *pascalOdd: 4037 x.typ = &pascalBoolean{} 4038 x.ft = y 4039 x.parameters.check(c, y) 4040 case *knuthErstat: 4041 x.typ = &pascalInteger{} 4042 x.ft = y 4043 x.parameters.check(c, y) 4044 case *functionDeclaration: 4045 x.typ = y.functionHeading.result 4046 x.ft = y 4047 x.parameters.check(c, y) 4048 default: 4049 panic(todo("%v: %T", x.ident.Position(), y)) 4050 } 4051 return x.typ, nil 4052 case *parenthesizedExpression: 4053 x.typ, x.val = c.checkExpr(x.expr) 4054 return x.typ, x.val 4055 case *writeParameter: 4056 x.wtyp, x.wval = c.checkExpr2(x.expr1) 4057 x.wval = x.wval.(int64) 4058 if x.expr2 != nil { 4059 x.wtyp2, x.wval2 = c.checkExpr2(x.expr2) 4060 x.wval2 = x.wval2.(int64) 4061 } 4062 return c.checkExpr2(x.param) 4063 case *deref: 4064 t, _ := c.checkExpr2(x.n) 4065 switch y := underlyingType(t).(type) { 4066 case *fileType: 4067 return y.elemType, nil 4068 case *pascalInput: 4069 return &pascalChar{}, nil 4070 default: 4071 panic(todo("%v: %T", x.n.Position(), y)) 4072 } 4073 default: 4074 panic(todo("%v: %T", x.Position(), x)) 4075 } 4076 } 4077 4078 func (c *ctx) div(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4079 t1 = underlyingType(t1) 4080 t2 = underlyingType(t2) 4081 switch x := t1.(type) { 4082 case *pascalInteger, *subrangeType: 4083 switch y := t2.(type) { 4084 case *pascalInteger, *subrangeType: 4085 if v2 == int64(0) { 4086 panic(todo("")) 4087 } 4088 4089 if v1 != nil && v2 != nil { 4090 value = float64(v1.(int64)) / float64(v2.(int64)) 4091 } 4092 return &pascalReal{}, value 4093 case *pascalReal: 4094 if v2 == float64(0) { 4095 panic(todo("")) 4096 } 4097 4098 if v1 != nil && v2 != nil { 4099 value = float64(v1.(int64)) / v2.(float64) 4100 } 4101 return &pascalReal{}, value 4102 default: 4103 panic(todo("%v: %T", n.Position(), y)) 4104 } 4105 case *pascalReal: 4106 switch y := t2.(type) { 4107 case *pascalReal: 4108 if v2 == float64(0) { 4109 panic(todo("")) 4110 } 4111 4112 if v1 != nil && v2 != nil { 4113 value = v1.(float64) / v2.(float64) 4114 } 4115 return &pascalReal{}, value 4116 case *pascalInteger, *subrangeType: 4117 if v2 == int64(0) { 4118 panic(todo("")) 4119 } 4120 4121 if v1 != nil && v2 != nil { 4122 value = v1.(float64) / float64(v2.(int64)) 4123 } 4124 return &pascalReal{}, value 4125 default: 4126 panic(todo("%v: %T", n.Position(), y)) 4127 } 4128 default: 4129 panic(todo("%v: %T", n.Position(), x)) 4130 } 4131 } 4132 4133 func (c *ctx) idiv(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4134 t1 = underlyingType(t1) 4135 t2 = underlyingType(t2) 4136 switch x := t1.(type) { 4137 case *pascalInteger, *subrangeType: 4138 switch y := t2.(type) { 4139 case *pascalInteger, *subrangeType: 4140 if v2 == int64(0) { 4141 panic(todo("")) 4142 } 4143 4144 if v1 != nil && v2 != nil { 4145 value = v1.(int64) / v2.(int64) 4146 } 4147 return c.binType(t1, t2), value 4148 default: 4149 panic(todo("%v: %T", n.Position(), y)) 4150 } 4151 default: 4152 panic(todo("%v: %T", n.Position(), x)) 4153 } 4154 } 4155 4156 func (c *ctx) mod(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4157 t1 = underlyingType(t1) 4158 t2 = underlyingType(t2) 4159 switch x := t1.(type) { 4160 case *pascalInteger, *subrangeType: 4161 switch y := t2.(type) { 4162 case *pascalInteger, *subrangeType: 4163 if v2 == int64(0) { 4164 panic(todo("")) 4165 } 4166 4167 if v1 != nil && v2 != nil { 4168 value = v1.(int64) % v2.(int64) 4169 } 4170 return c.binType(t1, t2), value 4171 default: 4172 panic(todo("%v: %T", n.Position(), y)) 4173 } 4174 default: 4175 panic(todo("%v: %T", n.Position(), x)) 4176 } 4177 } 4178 4179 func (c *ctx) mul(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4180 t1 = underlyingType(t1) 4181 t2 = underlyingType(t2) 4182 switch x := t1.(type) { 4183 case *pascalInteger, *subrangeType: 4184 switch y := t2.(type) { 4185 case *pascalInteger, *subrangeType: 4186 if v1 != nil && v2 != nil { 4187 value = v1.(int64) * v2.(int64) 4188 } 4189 return c.binType(t1, t2), value 4190 case *pascalReal: 4191 if v1 != nil && v2 != nil { 4192 value = float64(v1.(int64)) * v2.(float64) 4193 } 4194 return y, value 4195 default: 4196 panic(todo("%v: %T", n.Position(), y)) 4197 } 4198 case *pascalReal: 4199 switch y := t2.(type) { 4200 case *pascalReal: 4201 if v1 != nil && v2 != nil { 4202 value = v1.(float64) * v2.(float64) 4203 } 4204 return t1, value 4205 case *pascalInteger, *subrangeType: 4206 if v1 != nil && v2 != nil { 4207 value = v1.(float64) * float64(v2.(int64)) 4208 } 4209 return t1, value 4210 default: 4211 panic(todo("%v: %T", n.Position(), y)) 4212 } 4213 case *pascalReal32: 4214 switch y := t2.(type) { 4215 case *pascalReal: 4216 if v1 != nil && v2 != nil { 4217 value = v1.(float64) * v2.(float64) 4218 } 4219 return &pascalReal{}, value 4220 case *pascalInteger, *subrangeType: 4221 if v1 != nil && v2 != nil { 4222 value = v1.(float64) * float64(v2.(int64)) 4223 } 4224 return &pascalReal{}, value 4225 default: 4226 panic(todo("%v: %T", n.Position(), y)) 4227 } 4228 default: 4229 panic(todo("%v: %T", n.Position(), x)) 4230 } 4231 } 4232 4233 func (c *ctx) add(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4234 t1 = underlyingType(t1) 4235 t2 = underlyingType(t2) 4236 switch x := t1.(type) { 4237 case *pascalInteger, *subrangeType: 4238 switch y := t2.(type) { 4239 case *pascalInteger, *subrangeType: 4240 if v1 != nil && v2 != nil { 4241 value = v1.(int64) + v2.(int64) 4242 } 4243 return c.binType(t1, t2), value 4244 case *pascalReal: 4245 if v1 != nil && v2 != nil { 4246 value = float64(v1.(int64)) + v2.(float64) 4247 } 4248 return &pascalReal{}, value 4249 default: 4250 panic(todo("%v: %T", n.Position(), y)) 4251 } 4252 case *pascalReal: 4253 switch y := t2.(type) { 4254 case *pascalReal: 4255 if v1 != nil && v2 != nil { 4256 value = v1.(float64) + v2.(float64) 4257 } 4258 return t1, value 4259 case *pascalInteger, *subrangeType: 4260 if v1 != nil && v2 != nil { 4261 value = v1.(float64) + float64(v2.(int64)) 4262 } 4263 return t1, value 4264 default: 4265 panic(todo("%v: %T", n.Position(), y)) 4266 } 4267 case *label: 4268 switch y := t2.(type) { 4269 case *pascalInteger, *subrangeType: 4270 v1 = x.lhs 4271 if v1 != nil && v2 != nil { 4272 value = v1.(int64) + v2.(int64) 4273 } 4274 return t1, value 4275 default: 4276 panic(todo("%v: %T", n.Position(), y)) 4277 } 4278 default: 4279 panic(todo("%v: %T", n.Position(), x)) 4280 } 4281 } 4282 4283 func (c *ctx) sub(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4284 t1 = underlyingType(t1) 4285 t2 = underlyingType(t2) 4286 switch x := t1.(type) { 4287 case *pascalInteger, *subrangeType: 4288 switch y := t2.(type) { 4289 case *pascalInteger, *subrangeType: 4290 if v1 != nil && v2 != nil { 4291 value = v1.(int64) - v2.(int64) 4292 } 4293 return c.binType(t1, t2), value 4294 default: 4295 panic(todo("%v: %T", n.Position(), y)) 4296 } 4297 case *pascalReal: 4298 switch y := t2.(type) { 4299 case *pascalReal: 4300 if v1 != nil && v2 != nil { 4301 value = v1.(float64) - v2.(float64) 4302 } 4303 return t1, value 4304 case *pascalInteger, *subrangeType: 4305 if v1 != nil && v2 != nil { 4306 value = v1.(float64) - float64(v2.(int64)) 4307 } 4308 return t1, value 4309 default: 4310 panic(todo("%v: %T", n.Position(), y)) 4311 } 4312 default: 4313 panic(todo("%v: %T", n.Position(), x)) 4314 } 4315 } 4316 4317 func (c *ctx) binType(a, b interface{}) interface{} { 4318 a = underlyingType(a) 4319 b = underlyingType(b) 4320 switch x := a.(type) { 4321 case *pascalInteger, *subrangeType, *pascalChar: 4322 switch y := b.(type) { 4323 case *pascalInteger, *subrangeType, *pascalChar: 4324 return &pascalInteger{} 4325 case *pascalReal: 4326 return y 4327 default: 4328 panic(todo("%T", y)) 4329 } 4330 case *pascalReal, *pascalBoolean: 4331 return a 4332 case *pascalReal32: 4333 return &pascalReal{} 4334 default: 4335 panic(todo("%T", x)) 4336 } 4337 } 4338 4339 func (c *ctx) eq(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4340 t1 = underlyingType(t1) 4341 t2 = underlyingType(t2) 4342 switch x := t1.(type) { 4343 case *pascalInteger, *subrangeType: 4344 switch y := t2.(type) { 4345 case *pascalInteger, *subrangeType: 4346 if v1 != nil && v2 != nil { 4347 value = v1.(int64) == v2.(int64) 4348 } 4349 return &pascalBoolean{}, value 4350 default: 4351 panic(todo("%v: %T", n.Position(), y)) 4352 } 4353 case *pascalReal: 4354 switch y := t2.(type) { 4355 case *pascalInteger, *subrangeType: 4356 if v1 != nil && v2 != nil { 4357 value = v1.(float64) == float64(v2.(int64)) 4358 } 4359 return &pascalBoolean{}, value 4360 default: 4361 panic(todo("%v: %T", n.Position(), y)) 4362 } 4363 case *pascalChar: 4364 switch y := t2.(type) { 4365 case *pascalChar: 4366 if v1 != nil && v2 != nil { 4367 value = v1.(int64) == v2.(int64) 4368 } 4369 return &pascalBoolean{}, value 4370 default: 4371 panic(todo("%v: %T", n.Position(), y)) 4372 } 4373 case *pascalBoolean: 4374 switch y := t2.(type) { 4375 case *pascalBoolean: 4376 if v1 != nil && v2 != nil { 4377 value = v1.(bool) == v2.(bool) 4378 } 4379 return &pascalBoolean{}, value 4380 default: 4381 panic(todo("%v: %T", n.Position(), y)) 4382 } 4383 default: 4384 panic(todo("%v: %T", n.Position(), x)) 4385 } 4386 } 4387 4388 func (c *ctx) lt(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4389 t1 = underlyingType(t1) 4390 t2 = underlyingType(t2) 4391 switch x := t1.(type) { 4392 case *pascalInteger, *subrangeType: 4393 switch y := t2.(type) { 4394 case *pascalInteger, *subrangeType: 4395 if v1 != nil && v2 != nil { 4396 value = v1.(int64) < v2.(int64) 4397 } 4398 return &pascalBoolean{}, value 4399 case *pascalReal: 4400 if v1 != nil && v2 != nil { 4401 value = float64(v1.(int64)) < v2.(float64) 4402 } 4403 return &pascalBoolean{}, value 4404 default: 4405 panic(todo("%v: %T", n.Position(), y)) 4406 } 4407 case *pascalReal: 4408 switch y := t2.(type) { 4409 case *pascalReal: 4410 if v1 != nil && v2 != nil { 4411 value = v1.(float64) < v2.(float64) 4412 } 4413 return &pascalBoolean{}, value 4414 default: 4415 panic(todo("%v: %T", n.Position(), y)) 4416 } 4417 default: 4418 panic(todo("%v: %T", n.Position(), x)) 4419 } 4420 } 4421 4422 func (c *ctx) gt(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4423 t1 = underlyingType(t1) 4424 t2 = underlyingType(t2) 4425 switch x := t1.(type) { 4426 case *pascalInteger, *subrangeType: 4427 switch y := t2.(type) { 4428 case *pascalInteger, *subrangeType: 4429 if v1 != nil && v2 != nil { 4430 value = v1.(int64) > v2.(int64) 4431 } 4432 return &pascalBoolean{}, value 4433 default: 4434 panic(todo("%v: %T", n.Position(), y)) 4435 } 4436 case *pascalReal: 4437 switch y := t2.(type) { 4438 case *pascalReal: 4439 if v1 != nil && v2 != nil { 4440 value = v1.(float64) > v2.(float64) 4441 } 4442 return &pascalBoolean{}, value 4443 case *pascalInteger, *subrangeType: 4444 if v1 != nil && v2 != nil { 4445 value = v1.(float64) > float64(v2.(int64)) 4446 } 4447 return &pascalBoolean{}, value 4448 default: 4449 panic(todo("%v: %T", n.Position(), y)) 4450 } 4451 default: 4452 panic(todo("%v: %T", n.Position(), x)) 4453 } 4454 } 4455 4456 func (c *ctx) neq(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4457 t1 = underlyingType(t1) 4458 t2 = underlyingType(t2) 4459 switch x := t1.(type) { 4460 case *pascalInteger, *subrangeType: 4461 switch y := t2.(type) { 4462 case *pascalInteger, *subrangeType: 4463 if v1 != nil && v2 != nil { 4464 value = v1.(int64) != v2.(int64) 4465 } 4466 return &pascalBoolean{}, value 4467 default: 4468 panic(todo("%v: %T", n.Position(), y)) 4469 } 4470 case *pascalChar: 4471 switch y := t2.(type) { 4472 case *pascalChar: 4473 if v1 != nil && v2 != nil { 4474 value = v1.(int64) != v2.(int64) 4475 } 4476 return &pascalBoolean{}, value 4477 default: 4478 panic(todo("%v: %T", n.Position(), y)) 4479 } 4480 case *pascalBoolean: 4481 switch y := t2.(type) { 4482 case *pascalBoolean: 4483 if v1 != nil && v2 != nil { 4484 value = v1.(bool) != v2.(bool) 4485 } 4486 return &pascalBoolean{}, value 4487 default: 4488 panic(todo("%v: %T", n.Position(), y)) 4489 } 4490 case *pascalReal: 4491 switch y := t2.(type) { 4492 case *pascalReal: 4493 if v1 != nil && v2 != nil { 4494 value = v1.(float64) != v2.(float64) 4495 } 4496 return &pascalBoolean{}, value 4497 case *pascalInteger, *subrangeType: 4498 if v1 != nil && v2 != nil { 4499 value = v1.(float64) != float64(v2.(int64)) 4500 } 4501 return &pascalBoolean{}, value 4502 default: 4503 panic(todo("%v: %T", n.Position(), y)) 4504 } 4505 default: 4506 panic(todo("%v: %T", n.Position(), x)) 4507 } 4508 } 4509 4510 func (c *ctx) and(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4511 t1 = underlyingType(t1) 4512 t2 = underlyingType(t2) 4513 switch x := t1.(type) { 4514 case *pascalBoolean: 4515 switch y := t2.(type) { 4516 case *pascalBoolean: 4517 if v1 != nil && v2 != nil { 4518 value = v1.(bool) && v2.(bool) 4519 } 4520 return &pascalBoolean{}, value 4521 default: 4522 panic(todo("%v: %T", n.Position(), y)) 4523 } 4524 default: 4525 panic(todo("%v: %T", n.Position(), x)) 4526 } 4527 } 4528 4529 func (c *ctx) or(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4530 t1 = underlyingType(t1) 4531 t2 = underlyingType(t2) 4532 switch x := t1.(type) { 4533 case *pascalBoolean: 4534 switch y := t2.(type) { 4535 case *pascalBoolean: 4536 if v1 != nil && v2 != nil { 4537 value = v1.(bool) || v2.(bool) 4538 } 4539 return &pascalBoolean{}, value 4540 default: 4541 panic(todo("%v: %T", n.Position(), y)) 4542 } 4543 default: 4544 panic(todo("%v: %T", n.Position(), x)) 4545 } 4546 } 4547 4548 func (c *ctx) leq(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4549 t1 = underlyingType(t1) 4550 t2 = underlyingType(t2) 4551 switch x := t1.(type) { 4552 case *pascalInteger, *subrangeType: 4553 switch y := t2.(type) { 4554 case *pascalInteger, *subrangeType: 4555 if v1 != nil && v2 != nil { 4556 value = v1.(int64) <= v2.(int64) 4557 } 4558 return &pascalBoolean{}, value 4559 default: 4560 panic(todo("%v: %T", n.Position(), y)) 4561 } 4562 default: 4563 panic(todo("%v: %T", n.Position(), x)) 4564 } 4565 } 4566 4567 func (c *ctx) geq(n node, t1, v1, t2, v2 interface{}) (typ, value interface{}) { 4568 t1 = underlyingType(t1) 4569 t2 = underlyingType(t2) 4570 switch x := t1.(type) { 4571 case *pascalInteger, *subrangeType: 4572 switch y := t2.(type) { 4573 case *pascalInteger, *subrangeType: 4574 if v1 != nil && v2 != nil { 4575 value = v1.(int64) >= v2.(int64) 4576 } 4577 return &pascalBoolean{}, value 4578 default: 4579 panic(todo("%v: %T", n.Position(), y)) 4580 } 4581 case *pascalReal: 4582 switch y := t2.(type) { 4583 case *pascalReal: 4584 if v1 != nil && v2 != nil { 4585 value = v1.(float64) >= v2.(float64) 4586 } 4587 return &pascalBoolean{}, value 4588 case *pascalInteger, *subrangeType: 4589 if v1 != nil && v2 != nil { 4590 value = v1.(float64) >= float64(v2.(int64)) 4591 } 4592 return &pascalBoolean{}, value 4593 default: 4594 panic(todo("%v: %T", n.Position(), y)) 4595 } 4596 default: 4597 panic(todo("%v: %T", n.Position(), x)) 4598 } 4599 } 4600 4601 func (n *typeDefinitionPart) check(c *ctx) { 4602 if n == nil { 4603 return 4604 } 4605 4606 for _, v := range n.typeDefinitionList { 4607 v.check(c) 4608 } 4609 } 4610 4611 func (n *typeDefinitionList) check(c *ctx) { 4612 if n == nil { 4613 return 4614 } 4615 4616 n.typeDefinition.check(c) 4617 } 4618 4619 func (n *typeDefinition) check(c *ctx) { 4620 if n == nil { 4621 return 4622 } 4623 4624 n.typ = c.checkType(n.type1) 4625 c.scope.add(n.ident.Src(), n) 4626 } 4627 4628 func (c *ctx) checkType(t node) (r interface{}) { 4629 switch x := t.(type) { 4630 case nil: 4631 return nil 4632 case *subrangeType: 4633 if x.lo != 0 || x.hi != 0 { 4634 return x 4635 } 4636 4637 _, v := c.checkExpr(x.constant) 4638 switch y := v.(type) { 4639 case int64: 4640 x.lo = y 4641 default: 4642 panic(todo("%T", y)) 4643 } 4644 _, v = c.checkExpr(x.constant2) 4645 switch y := v.(type) { 4646 case int64: 4647 x.hi = y 4648 default: 4649 panic(todo("%T", y)) 4650 } 4651 return x 4652 case *fileType: 4653 if x.elemType == nil { 4654 x.elemType = c.checkType(x.type1) 4655 } 4656 return x 4657 case *identifier: 4658 defer func() { x.typ = r }() 4659 4660 switch y := c.scope.mustLookup(x).(type) { 4661 case *typeDefinition: 4662 return y 4663 case *pascalText: 4664 return y 4665 case *pascalInteger: 4666 return y 4667 case *pascalBoolean: 4668 return y 4669 case *pascalReal: 4670 return y 4671 case *pascalChar: 4672 return y 4673 default: 4674 panic(todo("%v: %v %T", x.Position(), x, y)) 4675 } 4676 case *arrayType: 4677 if x.elemTyp == nil { 4678 x.indexTyp = nil 4679 for _, v := range x.typeList { 4680 x.indexTyp = append(x.indexTyp, underlyingType(c.checkType(v.type1))) 4681 } 4682 x.elemTyp = c.checkType(x.elemType) 4683 } 4684 return x 4685 case *recordType: 4686 x.check(c) 4687 return x 4688 default: 4689 panic(todo("%v: %T", t.Position(), x)) 4690 } 4691 } 4692 4693 func (n *variableDeclarationPart) check(c *ctx) { 4694 if n == nil { 4695 return 4696 } 4697 4698 for _, v := range n.variableDeclarationList { 4699 v.check(c) 4700 } 4701 } 4702 4703 func (n *variableDeclarationList) check(c *ctx) { 4704 if n == nil { 4705 return 4706 } 4707 4708 n.variableDeclaration.check(c) 4709 } 4710 4711 type variable struct { 4712 ident *identifier 4713 typ interface{} 4714 4715 isParam bool 4716 } 4717 4718 func (n *variable) Position() (r token.Position) { 4719 if n == nil { 4720 return r 4721 } 4722 4723 return n.ident.Position() 4724 } 4725 4726 func (n *variableDeclaration) check(c *ctx) { 4727 if n == nil { 4728 return 4729 } 4730 4731 n.typ = c.checkType(n.type1) 4732 for _, v := range n.identifierList { 4733 c.scope.add(v.ident.Src(), &variable{ident: v.ident, typ: n.typ}) 4734 } 4735 } 4736 4737 func (n *compoundStatement) check(c *ctx) { 4738 if n == nil { 4739 return 4740 } 4741 4742 for _, v := range n.statementSequence { 4743 c.checkStatement(v.statement) 4744 } 4745 } 4746 4747 func (c *ctx) checkStatement(n node) { 4748 if n == nil { 4749 return 4750 } 4751 4752 switch x := n.(type) { 4753 case *procedureStatement: 4754 x.check(c) 4755 case *assignmentStatement: 4756 x.check(c) 4757 case *forStatement: 4758 x.check(c) 4759 case *compoundStatement: 4760 x.check(c) 4761 case *emptyStatement: 4762 // nop 4763 case *ifElseStatement: 4764 x.check(c) 4765 case *ifStatement: 4766 x.check(c) 4767 case *whileStatement: 4768 x.check(c) 4769 case *repeatStatement: 4770 x.check(c) 4771 case *identifier: 4772 switch y := c.scope.mustLookup(x).(type) { 4773 case *procedureDeclaration: 4774 x.typ = y 4775 if len(y.procedureHeading.fp) != 0 { 4776 panic(todo("")) 4777 } 4778 4779 // ok 4780 default: 4781 panic(todo("%v: %T", x.Position(), y)) 4782 } 4783 case *caseStatement: 4784 x.check(c) 4785 case *gotoStatement: 4786 x.check(c) 4787 case *labeled: 4788 x.check(c) 4789 default: 4790 panic(todo("%v: %T", n.Position(), x)) 4791 } 4792 } 4793 4794 // ============================================================================ 4795 4796 type nopos struct{} 4797 4798 func (nopos) Position() (r token.Position) { return r } 4799 4800 type ( 4801 knuthBreak struct{ nopos } 4802 knuthBreakIn struct{ nopos } 4803 knuthClose struct{ nopos } 4804 knuthCurPos struct{ nopos } 4805 knuthErstat struct{ nopos } 4806 knuthPanic struct{ nopos } 4807 knuthSetPos struct{ nopos } 4808 pascalAbs struct{ nopos } 4809 pascalBoolean struct{ nopos } 4810 pascalChar struct{ nopos } 4811 pascalChr struct{ nopos } 4812 pascalEOF struct{ nopos } 4813 pascalEOLN struct{ nopos } 4814 pascalFalse struct{ nopos } 4815 pascalGet struct{ nopos } 4816 pascalInput struct{ nopos } 4817 pascalInteger struct{ nopos } 4818 pascalMaxInt struct{ nopos } 4819 pascalOdd struct{ nopos } 4820 pascalOrd struct{ nopos } 4821 pascalOutput struct{ nopos } 4822 pascalPut struct{ nopos } 4823 pascalRead struct{ nopos } 4824 pascalReadln struct{ nopos } 4825 pascalReal struct{ nopos } 4826 pascalReal32 struct{ nopos } 4827 pascalReset struct{ nopos } 4828 pascalStderr struct{ nopos } 4829 pascalRewrite struct{ nopos } 4830 pascalRound struct{ nopos } 4831 pascalString struct{ nopos } 4832 pascalText struct{ nopos } 4833 pascalTrue struct{ nopos } 4834 pascalTrunc struct{ nopos } 4835 pascalWrite struct{ nopos } 4836 pascalWriteln struct{ nopos } 4837 stringLiteral struct{ nopos } 4838 ) 4839 4840 func typeStr(t interface{}) string { 4841 switch x := t.(type) { 4842 case *subrangeType: 4843 return fmt.Sprintf("%d..%d", x.lo, x.hi) 4844 default: 4845 panic(todo("%T", x)) 4846 } 4847 }