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 &parameters{
  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, &parameter{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 &not{
  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 = &parameterSpecification{
  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  }