| 1 | // Copyright 2013 The Go 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 | // Except for this comment, this file is a verbatim copy of the file |
| 6 | // with the same name in $GOROOT/src/go/internal/gccgoimporter, with |
| 7 | // a small modification in parseInterface to support older Go versions. |
| 8 | |
| 9 | package gccgoimporter |
| 10 | |
| 11 | import ( |
| 12 | "bytes" |
| 13 | "errors" |
| 14 | "fmt" |
| 15 | "go/constant" |
| 16 | "go/token" |
| 17 | "go/types" |
| 18 | "io" |
| 19 | "strconv" |
| 20 | "strings" |
| 21 | "text/scanner" |
| 22 | "unicode/utf8" |
| 23 | ) |
| 24 | |
| 25 | type parser struct { |
| 26 | scanner *scanner.Scanner |
| 27 | version string // format version |
| 28 | tok rune // current token |
| 29 | lit string // literal string; only valid for Ident, Int, String tokens |
| 30 | pkgpath string // package path of imported package |
| 31 | pkgname string // name of imported package |
| 32 | pkg *types.Package // reference to imported package |
| 33 | imports map[string]*types.Package // package path -> package object |
| 34 | typeList []types.Type // type number -> type |
| 35 | typeData []string // unparsed type data (v3 and later) |
| 36 | fixups []fixupRecord // fixups to apply at end of parsing |
| 37 | initdata InitData // package init priority data |
| 38 | aliases map[int]string // maps saved type number to alias name |
| 39 | } |
| 40 | |
| 41 | // When reading export data it's possible to encounter a defined type |
| 42 | // N1 with an underlying defined type N2 while we are still reading in |
| 43 | // that defined type N2; see issues #29006 and #29198 for instances |
| 44 | // of this. Example: |
| 45 | // |
| 46 | // type N1 N2 |
| 47 | // type N2 struct { |
| 48 | // ... |
| 49 | // p *N1 |
| 50 | // } |
| 51 | // |
| 52 | // To handle such cases, the parser generates a fixup record (below) and |
| 53 | // delays setting of N1's underlying type until parsing is complete, at |
| 54 | // which point fixups are applied. |
| 55 | |
| 56 | type fixupRecord struct { |
| 57 | toUpdate *types.Named // type to modify when fixup is processed |
| 58 | target types.Type // type that was incomplete when fixup was created |
| 59 | } |
| 60 | |
| 61 | func (p *parser) init(filename string, src io.Reader, imports map[string]*types.Package) { |
| 62 | p.scanner = new(scanner.Scanner) |
| 63 | p.initScanner(filename, src) |
| 64 | p.imports = imports |
| 65 | p.aliases = make(map[int]string) |
| 66 | p.typeList = make([]types.Type, 1 /* type numbers start at 1 */, 16) |
| 67 | } |
| 68 | |
| 69 | func (p *parser) initScanner(filename string, src io.Reader) { |
| 70 | p.scanner.Init(src) |
| 71 | p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) } |
| 72 | p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings |
| 73 | p.scanner.Whitespace = 1<<'\t' | 1<<' ' |
| 74 | p.scanner.Filename = filename // for good error messages |
| 75 | p.next() |
| 76 | } |
| 77 | |
| 78 | type importError struct { |
| 79 | pos scanner.Position |
| 80 | err error |
| 81 | } |
| 82 | |
| 83 | func (e importError) Error() string { |
| 84 | return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err) |
| 85 | } |
| 86 | |
| 87 | func (p *parser) error(err interface{}) { |
| 88 | if s, ok := err.(string); ok { |
| 89 | err = errors.New(s) |
| 90 | } |
| 91 | // panic with a runtime.Error if err is not an error |
| 92 | panic(importError{p.scanner.Pos(), err.(error)}) |
| 93 | } |
| 94 | |
| 95 | func (p *parser) errorf(format string, args ...interface{}) { |
| 96 | p.error(fmt.Errorf(format, args...)) |
| 97 | } |
| 98 | |
| 99 | func (p *parser) expect(tok rune) string { |
| 100 | lit := p.lit |
| 101 | if p.tok != tok { |
| 102 | p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit) |
| 103 | } |
| 104 | p.next() |
| 105 | return lit |
| 106 | } |
| 107 | |
| 108 | func (p *parser) expectEOL() { |
| 109 | if p.version == "v1" || p.version == "v2" { |
| 110 | p.expect(';') |
| 111 | } |
| 112 | p.expect('\n') |
| 113 | } |
| 114 | |
| 115 | func (p *parser) expectKeyword(keyword string) { |
| 116 | lit := p.expect(scanner.Ident) |
| 117 | if lit != keyword { |
| 118 | p.errorf("expected keyword %s, got %q", keyword, lit) |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | func (p *parser) parseString() string { |
| 123 | str, err := strconv.Unquote(p.expect(scanner.String)) |
| 124 | if err != nil { |
| 125 | p.error(err) |
| 126 | } |
| 127 | return str |
| 128 | } |
| 129 | |
| 130 | // parseUnquotedString parses an UnquotedString: |
| 131 | // |
| 132 | // unquotedString = { unquotedStringChar } . |
| 133 | // unquotedStringChar = <neither a whitespace nor a ';' char> . |
| 134 | func (p *parser) parseUnquotedString() string { |
| 135 | if p.tok == scanner.EOF { |
| 136 | p.error("unexpected EOF") |
| 137 | } |
| 138 | var buf bytes.Buffer |
| 139 | buf.WriteString(p.scanner.TokenText()) |
| 140 | // This loop needs to examine each character before deciding whether to consume it. If we see a semicolon, |
| 141 | // we need to let it be consumed by p.next(). |
| 142 | for ch := p.scanner.Peek(); ch != '\n' && ch != ';' && ch != scanner.EOF && p.scanner.Whitespace&(1<<uint(ch)) == 0; ch = p.scanner.Peek() { |
| 143 | buf.WriteRune(ch) |
| 144 | p.scanner.Next() |
| 145 | } |
| 146 | p.next() |
| 147 | return buf.String() |
| 148 | } |
| 149 | |
| 150 | func (p *parser) next() { |
| 151 | p.tok = p.scanner.Scan() |
| 152 | switch p.tok { |
| 153 | case scanner.Ident, scanner.Int, scanner.Float, scanner.String, 'ยท': |
| 154 | p.lit = p.scanner.TokenText() |
| 155 | default: |
| 156 | p.lit = "" |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | func (p *parser) parseQualifiedName() (path, name string) { |
| 161 | return p.parseQualifiedNameStr(p.parseString()) |
| 162 | } |
| 163 | |
| 164 | func (p *parser) parseUnquotedQualifiedName() (path, name string) { |
| 165 | return p.parseQualifiedNameStr(p.parseUnquotedString()) |
| 166 | } |
| 167 | |
| 168 | // parseQualifiedNameStr is given the leading name (unquoted by the caller if necessary) |
| 169 | // and then parses the remainder of a qualified name: |
| 170 | // |
| 171 | // qualifiedName = [ ["."] unquotedString "." ] unquotedString . |
| 172 | // |
| 173 | // The above production uses greedy matching. |
| 174 | func (p *parser) parseQualifiedNameStr(unquotedName string) (pkgpath, name string) { |
| 175 | parts := strings.Split(unquotedName, ".") |
| 176 | if parts[0] == "" { |
| 177 | parts = parts[1:] |
| 178 | } |
| 179 | |
| 180 | switch len(parts) { |
| 181 | case 0: |
| 182 | p.errorf("malformed qualified name: %q", unquotedName) |
| 183 | case 1: |
| 184 | // unqualified name |
| 185 | pkgpath = p.pkgpath |
| 186 | name = parts[0] |
| 187 | default: |
| 188 | // qualified name, which may contain periods |
| 189 | pkgpath = strings.Join(parts[0:len(parts)-1], ".") |
| 190 | name = parts[len(parts)-1] |
| 191 | } |
| 192 | |
| 193 | return |
| 194 | } |
| 195 | |
| 196 | // getPkg returns the package for a given path. If the package is |
| 197 | // not found but we have a package name, create the package and |
| 198 | // add it to the p.imports map. |
| 199 | func (p *parser) getPkg(pkgpath, name string) *types.Package { |
| 200 | // package unsafe is not in the imports map - handle explicitly |
| 201 | if pkgpath == "unsafe" { |
| 202 | return types.Unsafe |
| 203 | } |
| 204 | pkg := p.imports[pkgpath] |
| 205 | if pkg == nil && name != "" { |
| 206 | pkg = types.NewPackage(pkgpath, name) |
| 207 | p.imports[pkgpath] = pkg |
| 208 | } |
| 209 | return pkg |
| 210 | } |
| 211 | |
| 212 | // parseExportedName is like parseQualifiedName, but |
| 213 | // the package path is resolved to an imported *types.Package. |
| 214 | // |
| 215 | // ExportedName = string [string] . |
| 216 | func (p *parser) parseExportedName() (pkg *types.Package, name string) { |
| 217 | path, name := p.parseQualifiedName() |
| 218 | var pkgname string |
| 219 | if p.tok == scanner.String { |
| 220 | pkgname = p.parseString() |
| 221 | } |
| 222 | pkg = p.getPkg(path, pkgname) |
| 223 | if pkg == nil { |
| 224 | p.errorf("package %s (path = %q) not found", name, path) |
| 225 | } |
| 226 | return |
| 227 | } |
| 228 | |
| 229 | // parseName parses a Name: |
| 230 | // |
| 231 | // Name = QualifiedName | "?" . |
| 232 | func (p *parser) parseName() string { |
| 233 | if p.tok == '?' { |
| 234 | // Anonymous. |
| 235 | p.next() |
| 236 | return "" |
| 237 | } |
| 238 | // The package path is redundant for us. Don't try to parse it. |
| 239 | _, name := p.parseUnquotedQualifiedName() |
| 240 | return name |
| 241 | } |
| 242 | |
| 243 | func deref(typ types.Type) types.Type { |
| 244 | if p, _ := typ.(*types.Pointer); p != nil { |
| 245 | typ = p.Elem() |
| 246 | } |
| 247 | return typ |
| 248 | } |
| 249 | |
| 250 | // parseField parses a Field: |
| 251 | // |
| 252 | // Field = Name Type [string] . |
| 253 | func (p *parser) parseField(pkg *types.Package) (field *types.Var, tag string) { |
| 254 | name := p.parseName() |
| 255 | typ, n := p.parseTypeExtended(pkg) |
| 256 | anon := false |
| 257 | if name == "" { |
| 258 | anon = true |
| 259 | // Alias? |
| 260 | if aname, ok := p.aliases[n]; ok { |
| 261 | name = aname |
| 262 | } else { |
| 263 | switch typ := deref(typ).(type) { |
| 264 | case *types.Basic: |
| 265 | name = typ.Name() |
| 266 | case *types.Named: |
| 267 | name = typ.Obj().Name() |
| 268 | default: |
| 269 | p.error("embedded field expected") |
| 270 | } |
| 271 | } |
| 272 | } |
| 273 | field = types.NewField(token.NoPos, pkg, name, typ, anon) |
| 274 | if p.tok == scanner.String { |
| 275 | tag = p.parseString() |
| 276 | } |
| 277 | return |
| 278 | } |
| 279 | |
| 280 | // parseParam parses a Param: |
| 281 | // |
| 282 | // Param = Name ["..."] Type . |
| 283 | func (p *parser) parseParam(pkg *types.Package) (param *types.Var, isVariadic bool) { |
| 284 | name := p.parseName() |
| 285 | // Ignore names invented for inlinable functions. |
| 286 | if strings.HasPrefix(name, "p.") || strings.HasPrefix(name, "r.") || strings.HasPrefix(name, "$ret") { |
| 287 | name = "" |
| 288 | } |
| 289 | if p.tok == '<' && p.scanner.Peek() == 'e' { |
| 290 | // EscInfo = "<esc:" int ">" . (optional and ignored) |
| 291 | p.next() |
| 292 | p.expectKeyword("esc") |
| 293 | p.expect(':') |
| 294 | p.expect(scanner.Int) |
| 295 | p.expect('>') |
| 296 | } |
| 297 | if p.tok == '.' { |
| 298 | p.next() |
| 299 | p.expect('.') |
| 300 | p.expect('.') |
| 301 | isVariadic = true |
| 302 | } |
| 303 | typ := p.parseType(pkg) |
| 304 | if isVariadic { |
| 305 | typ = types.NewSlice(typ) |
| 306 | } |
| 307 | param = types.NewParam(token.NoPos, pkg, name, typ) |
| 308 | return |
| 309 | } |
| 310 | |
| 311 | // parseVar parses a Var: |
| 312 | // |
| 313 | // Var = Name Type . |
| 314 | func (p *parser) parseVar(pkg *types.Package) *types.Var { |
| 315 | name := p.parseName() |
| 316 | v := types.NewVar(token.NoPos, pkg, name, p.parseType(pkg)) |
| 317 | if name[0] == '.' || name[0] == '<' { |
| 318 | // This is an unexported variable, |
| 319 | // or a variable defined in a different package. |
| 320 | // We only want to record exported variables. |
| 321 | return nil |
| 322 | } |
| 323 | return v |
| 324 | } |
| 325 | |
| 326 | // parseConversion parses a Conversion: |
| 327 | // |
| 328 | // Conversion = "convert" "(" Type "," ConstValue ")" . |
| 329 | func (p *parser) parseConversion(pkg *types.Package) (val constant.Value, typ types.Type) { |
| 330 | p.expectKeyword("convert") |
| 331 | p.expect('(') |
| 332 | typ = p.parseType(pkg) |
| 333 | p.expect(',') |
| 334 | val, _ = p.parseConstValue(pkg) |
| 335 | p.expect(')') |
| 336 | return |
| 337 | } |
| 338 | |
| 339 | // parseConstValue parses a ConstValue: |
| 340 | // |
| 341 | // ConstValue = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) | Conversion . |
| 342 | // FloatOrComplex = float ["i" | ("+"|"-") float "i"] . |
| 343 | func (p *parser) parseConstValue(pkg *types.Package) (val constant.Value, typ types.Type) { |
| 344 | // v3 changed to $false, $true, $convert, to avoid confusion |
| 345 | // with variable names in inline function bodies. |
| 346 | if p.tok == '$' { |
| 347 | p.next() |
| 348 | if p.tok != scanner.Ident { |
| 349 | p.errorf("expected identifier after '$', got %s (%q)", scanner.TokenString(p.tok), p.lit) |
| 350 | } |
| 351 | } |
| 352 | |
| 353 | switch p.tok { |
| 354 | case scanner.String: |
| 355 | str := p.parseString() |
| 356 | val = constant.MakeString(str) |
| 357 | typ = types.Typ[types.UntypedString] |
| 358 | return |
| 359 | |
| 360 | case scanner.Ident: |
| 361 | b := false |
| 362 | switch p.lit { |
| 363 | case "false": |
| 364 | case "true": |
| 365 | b = true |
| 366 | |
| 367 | case "convert": |
| 368 | return p.parseConversion(pkg) |
| 369 | |
| 370 | default: |
| 371 | p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit) |
| 372 | } |
| 373 | |
| 374 | p.next() |
| 375 | val = constant.MakeBool(b) |
| 376 | typ = types.Typ[types.UntypedBool] |
| 377 | return |
| 378 | } |
| 379 | |
| 380 | sign := "" |
| 381 | if p.tok == '-' { |
| 382 | p.next() |
| 383 | sign = "-" |
| 384 | } |
| 385 | |
| 386 | switch p.tok { |
| 387 | case scanner.Int: |
| 388 | val = constant.MakeFromLiteral(sign+p.lit, token.INT, 0) |
| 389 | if val == nil { |
| 390 | p.error("could not parse integer literal") |
| 391 | } |
| 392 | |
| 393 | p.next() |
| 394 | if p.tok == '\'' { |
| 395 | p.next() |
| 396 | typ = types.Typ[types.UntypedRune] |
| 397 | } else { |
| 398 | typ = types.Typ[types.UntypedInt] |
| 399 | } |
| 400 | |
| 401 | case scanner.Float: |
| 402 | re := sign + p.lit |
| 403 | p.next() |
| 404 | |
| 405 | var im string |
| 406 | switch p.tok { |
| 407 | case '+': |
| 408 | p.next() |
| 409 | im = p.expect(scanner.Float) |
| 410 | |
| 411 | case '-': |
| 412 | p.next() |
| 413 | im = "-" + p.expect(scanner.Float) |
| 414 | |
| 415 | case scanner.Ident: |
| 416 | // re is in fact the imaginary component. Expect "i" below. |
| 417 | im = re |
| 418 | re = "0" |
| 419 | |
| 420 | default: |
| 421 | val = constant.MakeFromLiteral(re, token.FLOAT, 0) |
| 422 | if val == nil { |
| 423 | p.error("could not parse float literal") |
| 424 | } |
| 425 | typ = types.Typ[types.UntypedFloat] |
| 426 | return |
| 427 | } |
| 428 | |
| 429 | p.expectKeyword("i") |
| 430 | reval := constant.MakeFromLiteral(re, token.FLOAT, 0) |
| 431 | if reval == nil { |
| 432 | p.error("could not parse real component of complex literal") |
| 433 | } |
| 434 | imval := constant.MakeFromLiteral(im+"i", token.IMAG, 0) |
| 435 | if imval == nil { |
| 436 | p.error("could not parse imag component of complex literal") |
| 437 | } |
| 438 | val = constant.BinaryOp(reval, token.ADD, imval) |
| 439 | typ = types.Typ[types.UntypedComplex] |
| 440 | |
| 441 | default: |
| 442 | p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit) |
| 443 | } |
| 444 | |
| 445 | return |
| 446 | } |
| 447 | |
| 448 | // parseConst parses a Const: |
| 449 | // |
| 450 | // Const = Name [Type] "=" ConstValue . |
| 451 | func (p *parser) parseConst(pkg *types.Package) *types.Const { |
| 452 | name := p.parseName() |
| 453 | var typ types.Type |
| 454 | if p.tok == '<' { |
| 455 | typ = p.parseType(pkg) |
| 456 | } |
| 457 | p.expect('=') |
| 458 | val, vtyp := p.parseConstValue(pkg) |
| 459 | if typ == nil { |
| 460 | typ = vtyp |
| 461 | } |
| 462 | return types.NewConst(token.NoPos, pkg, name, typ, val) |
| 463 | } |
| 464 | |
| 465 | // reserved is a singleton type used to fill type map slots that have |
| 466 | // been reserved (i.e., for which a type number has been parsed) but |
| 467 | // which don't have their actual type yet. When the type map is updated, |
| 468 | // the actual type must replace a reserved entry (or we have an internal |
| 469 | // error). Used for self-verification only - not required for correctness. |
| 470 | var reserved = new(struct{ types.Type }) |
| 471 | |
| 472 | // reserve reserves the type map entry n for future use. |
| 473 | func (p *parser) reserve(n int) { |
| 474 | // Notes: |
| 475 | // - for pre-V3 export data, the type numbers we see are |
| 476 | // guaranteed to be in increasing order, so we append a |
| 477 | // reserved entry onto the list. |
| 478 | // - for V3+ export data, type numbers can appear in |
| 479 | // any order, however the 'types' section tells us the |
| 480 | // total number of types, hence typeList is pre-allocated. |
| 481 | if len(p.typeData) == 0 { |
| 482 | if n != len(p.typeList) { |
| 483 | p.errorf("invalid type number %d (out of sync)", n) |
| 484 | } |
| 485 | p.typeList = append(p.typeList, reserved) |
| 486 | } else { |
| 487 | if p.typeList[n] != nil { |
| 488 | p.errorf("previously visited type number %d", n) |
| 489 | } |
| 490 | p.typeList[n] = reserved |
| 491 | } |
| 492 | } |
| 493 | |
| 494 | // update sets the type map entries for the entries in nlist to t. |
| 495 | // An entry in nlist can be a type number in p.typeList, |
| 496 | // used to resolve named types, or it can be a *types.Pointer, |
| 497 | // used to resolve pointers to named types in case they are referenced |
| 498 | // by embedded fields. |
| 499 | func (p *parser) update(t types.Type, nlist []interface{}) { |
| 500 | if t == reserved { |
| 501 | p.errorf("internal error: update(%v) invoked on reserved", nlist) |
| 502 | } |
| 503 | if t == nil { |
| 504 | p.errorf("internal error: update(%v) invoked on nil", nlist) |
| 505 | } |
| 506 | for _, n := range nlist { |
| 507 | switch n := n.(type) { |
| 508 | case int: |
| 509 | if p.typeList[n] == t { |
| 510 | continue |
| 511 | } |
| 512 | if p.typeList[n] != reserved { |
| 513 | p.errorf("internal error: update(%v): %d not reserved", nlist, n) |
| 514 | } |
| 515 | p.typeList[n] = t |
| 516 | case *types.Pointer: |
| 517 | if *n != (types.Pointer{}) { |
| 518 | elem := n.Elem() |
| 519 | if elem == t { |
| 520 | continue |
| 521 | } |
| 522 | p.errorf("internal error: update: pointer already set to %v, expected %v", elem, t) |
| 523 | } |
| 524 | *n = *types.NewPointer(t) |
| 525 | default: |
| 526 | p.errorf("internal error: %T on nlist", n) |
| 527 | } |
| 528 | } |
| 529 | } |
| 530 | |
| 531 | // parseNamedType parses a NamedType: |
| 532 | // |
| 533 | // NamedType = TypeName [ "=" ] Type { Method } . |
| 534 | // TypeName = ExportedName . |
| 535 | // Method = "func" "(" Param ")" Name ParamList ResultList [InlineBody] ";" . |
| 536 | func (p *parser) parseNamedType(nlist []interface{}) types.Type { |
| 537 | pkg, name := p.parseExportedName() |
| 538 | scope := pkg.Scope() |
| 539 | obj := scope.Lookup(name) |
| 540 | if obj != nil && obj.Type() == nil { |
| 541 | p.errorf("%v has nil type", obj) |
| 542 | } |
| 543 | |
| 544 | if p.tok == scanner.Ident && p.lit == "notinheap" { |
| 545 | p.next() |
| 546 | // The go/types package has no way of recording that |
| 547 | // this type is marked notinheap. Presumably no user |
| 548 | // of this package actually cares. |
| 549 | } |
| 550 | |
| 551 | // type alias |
| 552 | if p.tok == '=' { |
| 553 | p.next() |
| 554 | p.aliases[nlist[len(nlist)-1].(int)] = name |
| 555 | if obj != nil { |
| 556 | // use the previously imported (canonical) type |
| 557 | t := obj.Type() |
| 558 | p.update(t, nlist) |
| 559 | p.parseType(pkg) // discard |
| 560 | return t |
| 561 | } |
| 562 | t := p.parseType(pkg, nlist...) |
| 563 | obj = types.NewTypeName(token.NoPos, pkg, name, t) |
| 564 | scope.Insert(obj) |
| 565 | return t |
| 566 | } |
| 567 | |
| 568 | // defined type |
| 569 | if obj == nil { |
| 570 | // A named type may be referred to before the underlying type |
| 571 | // is known - set it up. |
| 572 | tname := types.NewTypeName(token.NoPos, pkg, name, nil) |
| 573 | types.NewNamed(tname, nil, nil) |
| 574 | scope.Insert(tname) |
| 575 | obj = tname |
| 576 | } |
| 577 | |
| 578 | // use the previously imported (canonical), or newly created type |
| 579 | t := obj.Type() |
| 580 | p.update(t, nlist) |
| 581 | |
| 582 | nt, ok := t.(*types.Named) |
| 583 | if !ok { |
| 584 | // This can happen for unsafe.Pointer, which is a TypeName holding a Basic type. |
| 585 | pt := p.parseType(pkg) |
| 586 | if pt != t { |
| 587 | p.error("unexpected underlying type for non-named TypeName") |
| 588 | } |
| 589 | return t |
| 590 | } |
| 591 | |
| 592 | underlying := p.parseType(pkg) |
| 593 | if nt.Underlying() == nil { |
| 594 | if underlying.Underlying() == nil { |
| 595 | fix := fixupRecord{toUpdate: nt, target: underlying} |
| 596 | p.fixups = append(p.fixups, fix) |
| 597 | } else { |
| 598 | nt.SetUnderlying(underlying.Underlying()) |
| 599 | } |
| 600 | } |
| 601 | |
| 602 | if p.tok == '\n' { |
| 603 | p.next() |
| 604 | // collect associated methods |
| 605 | for p.tok == scanner.Ident { |
| 606 | p.expectKeyword("func") |
| 607 | if p.tok == '/' { |
| 608 | // Skip a /*nointerface*/ or /*asm ID */ comment. |
| 609 | p.expect('/') |
| 610 | p.expect('*') |
| 611 | if p.expect(scanner.Ident) == "asm" { |
| 612 | p.parseUnquotedString() |
| 613 | } |
| 614 | p.expect('*') |
| 615 | p.expect('/') |
| 616 | } |
| 617 | p.expect('(') |
| 618 | receiver, _ := p.parseParam(pkg) |
| 619 | p.expect(')') |
| 620 | name := p.parseName() |
| 621 | params, isVariadic := p.parseParamList(pkg) |
| 622 | results := p.parseResultList(pkg) |
| 623 | p.skipInlineBody() |
| 624 | p.expectEOL() |
| 625 | |
| 626 | sig := types.NewSignature(receiver, params, results, isVariadic) |
| 627 | nt.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig)) |
| 628 | } |
| 629 | } |
| 630 | |
| 631 | return nt |
| 632 | } |
| 633 | |
| 634 | func (p *parser) parseInt64() int64 { |
| 635 | lit := p.expect(scanner.Int) |
| 636 | n, err := strconv.ParseInt(lit, 10, 64) |
| 637 | if err != nil { |
| 638 | p.error(err) |
| 639 | } |
| 640 | return n |
| 641 | } |
| 642 | |
| 643 | func (p *parser) parseInt() int { |
| 644 | lit := p.expect(scanner.Int) |
| 645 | n, err := strconv.ParseInt(lit, 10, 0 /* int */) |
| 646 | if err != nil { |
| 647 | p.error(err) |
| 648 | } |
| 649 | return int(n) |
| 650 | } |
| 651 | |
| 652 | // parseArrayOrSliceType parses an ArrayOrSliceType: |
| 653 | // |
| 654 | // ArrayOrSliceType = "[" [ int ] "]" Type . |
| 655 | func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []interface{}) types.Type { |
| 656 | p.expect('[') |
| 657 | if p.tok == ']' { |
| 658 | p.next() |
| 659 | |
| 660 | t := new(types.Slice) |
| 661 | p.update(t, nlist) |
| 662 | |
| 663 | *t = *types.NewSlice(p.parseType(pkg)) |
| 664 | return t |
| 665 | } |
| 666 | |
| 667 | t := new(types.Array) |
| 668 | p.update(t, nlist) |
| 669 | |
| 670 | len := p.parseInt64() |
| 671 | p.expect(']') |
| 672 | |
| 673 | *t = *types.NewArray(p.parseType(pkg), len) |
| 674 | return t |
| 675 | } |
| 676 | |
| 677 | // parseMapType parses a MapType: |
| 678 | // |
| 679 | // MapType = "map" "[" Type "]" Type . |
| 680 | func (p *parser) parseMapType(pkg *types.Package, nlist []interface{}) types.Type { |
| 681 | p.expectKeyword("map") |
| 682 | |
| 683 | t := new(types.Map) |
| 684 | p.update(t, nlist) |
| 685 | |
| 686 | p.expect('[') |
| 687 | key := p.parseType(pkg) |
| 688 | p.expect(']') |
| 689 | elem := p.parseType(pkg) |
| 690 | |
| 691 | *t = *types.NewMap(key, elem) |
| 692 | return t |
| 693 | } |
| 694 | |
| 695 | // parseChanType parses a ChanType: |
| 696 | // |
| 697 | // ChanType = "chan" ["<-" | "-<"] Type . |
| 698 | func (p *parser) parseChanType(pkg *types.Package, nlist []interface{}) types.Type { |
| 699 | p.expectKeyword("chan") |
| 700 | |
| 701 | t := new(types.Chan) |
| 702 | p.update(t, nlist) |
| 703 | |
| 704 | dir := types.SendRecv |
| 705 | switch p.tok { |
| 706 | case '-': |
| 707 | p.next() |
| 708 | p.expect('<') |
| 709 | dir = types.SendOnly |
| 710 | |
| 711 | case '<': |
| 712 | // don't consume '<' if it belongs to Type |
| 713 | if p.scanner.Peek() == '-' { |
| 714 | p.next() |
| 715 | p.expect('-') |
| 716 | dir = types.RecvOnly |
| 717 | } |
| 718 | } |
| 719 | |
| 720 | *t = *types.NewChan(dir, p.parseType(pkg)) |
| 721 | return t |
| 722 | } |
| 723 | |
| 724 | // parseStructType parses a StructType: |
| 725 | // |
| 726 | // StructType = "struct" "{" { Field } "}" . |
| 727 | func (p *parser) parseStructType(pkg *types.Package, nlist []interface{}) types.Type { |
| 728 | p.expectKeyword("struct") |
| 729 | |
| 730 | t := new(types.Struct) |
| 731 | p.update(t, nlist) |
| 732 | |
| 733 | var fields []*types.Var |
| 734 | var tags []string |
| 735 | |
| 736 | p.expect('{') |
| 737 | for p.tok != '}' && p.tok != scanner.EOF { |
| 738 | field, tag := p.parseField(pkg) |
| 739 | p.expect(';') |
| 740 | fields = append(fields, field) |
| 741 | tags = append(tags, tag) |
| 742 | } |
| 743 | p.expect('}') |
| 744 | |
| 745 | *t = *types.NewStruct(fields, tags) |
| 746 | return t |
| 747 | } |
| 748 | |
| 749 | // parseParamList parses a ParamList: |
| 750 | // |
| 751 | // ParamList = "(" [ { Parameter "," } Parameter ] ")" . |
| 752 | func (p *parser) parseParamList(pkg *types.Package) (*types.Tuple, bool) { |
| 753 | var list []*types.Var |
| 754 | isVariadic := false |
| 755 | |
| 756 | p.expect('(') |
| 757 | for p.tok != ')' && p.tok != scanner.EOF { |
| 758 | if len(list) > 0 { |
| 759 | p.expect(',') |
| 760 | } |
| 761 | par, variadic := p.parseParam(pkg) |
| 762 | list = append(list, par) |
| 763 | if variadic { |
| 764 | if isVariadic { |
| 765 | p.error("... not on final argument") |
| 766 | } |
| 767 | isVariadic = true |
| 768 | } |
| 769 | } |
| 770 | p.expect(')') |
| 771 | |
| 772 | return types.NewTuple(list...), isVariadic |
| 773 | } |
| 774 | |
| 775 | // parseResultList parses a ResultList: |
| 776 | // |
| 777 | // ResultList = Type | ParamList . |
| 778 | func (p *parser) parseResultList(pkg *types.Package) *types.Tuple { |
| 779 | switch p.tok { |
| 780 | case '<': |
| 781 | p.next() |
| 782 | if p.tok == scanner.Ident && p.lit == "inl" { |
| 783 | return nil |
| 784 | } |
| 785 | taa, _ := p.parseTypeAfterAngle(pkg) |
| 786 | return types.NewTuple(types.NewParam(token.NoPos, pkg, "", taa)) |
| 787 | |
| 788 | case '(': |
| 789 | params, _ := p.parseParamList(pkg) |
| 790 | return params |
| 791 | |
| 792 | default: |
| 793 | return nil |
| 794 | } |
| 795 | } |
| 796 | |
| 797 | // parseFunctionType parses a FunctionType: |
| 798 | // |
| 799 | // FunctionType = ParamList ResultList . |
| 800 | func (p *parser) parseFunctionType(pkg *types.Package, nlist []interface{}) *types.Signature { |
| 801 | t := new(types.Signature) |
| 802 | p.update(t, nlist) |
| 803 | |
| 804 | params, isVariadic := p.parseParamList(pkg) |
| 805 | results := p.parseResultList(pkg) |
| 806 | |
| 807 | *t = *types.NewSignature(nil, params, results, isVariadic) |
| 808 | return t |
| 809 | } |
| 810 | |
| 811 | // parseFunc parses a Func: |
| 812 | // |
| 813 | // Func = Name FunctionType [InlineBody] . |
| 814 | func (p *parser) parseFunc(pkg *types.Package) *types.Func { |
| 815 | if p.tok == '/' { |
| 816 | // Skip an /*asm ID */ comment. |
| 817 | p.expect('/') |
| 818 | p.expect('*') |
| 819 | if p.expect(scanner.Ident) == "asm" { |
| 820 | p.parseUnquotedString() |
| 821 | } |
| 822 | p.expect('*') |
| 823 | p.expect('/') |
| 824 | } |
| 825 | |
| 826 | name := p.parseName() |
| 827 | f := types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg, nil)) |
| 828 | p.skipInlineBody() |
| 829 | |
| 830 | if name[0] == '.' || name[0] == '<' || strings.ContainsRune(name, '$') { |
| 831 | // This is an unexported function, |
| 832 | // or a function defined in a different package, |
| 833 | // or a type$equal or type$hash function. |
| 834 | // We only want to record exported functions. |
| 835 | return nil |
| 836 | } |
| 837 | |
| 838 | return f |
| 839 | } |
| 840 | |
| 841 | // parseInterfaceType parses an InterfaceType: |
| 842 | // |
| 843 | // InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" . |
| 844 | func (p *parser) parseInterfaceType(pkg *types.Package, nlist []interface{}) types.Type { |
| 845 | p.expectKeyword("interface") |
| 846 | |
| 847 | t := new(types.Interface) |
| 848 | p.update(t, nlist) |
| 849 | |
| 850 | var methods []*types.Func |
| 851 | var embeddeds []types.Type |
| 852 | |
| 853 | p.expect('{') |
| 854 | for p.tok != '}' && p.tok != scanner.EOF { |
| 855 | if p.tok == '?' { |
| 856 | p.next() |
| 857 | embeddeds = append(embeddeds, p.parseType(pkg)) |
| 858 | } else { |
| 859 | method := p.parseFunc(pkg) |
| 860 | if method != nil { |
| 861 | methods = append(methods, method) |
| 862 | } |
| 863 | } |
| 864 | p.expect(';') |
| 865 | } |
| 866 | p.expect('}') |
| 867 | |
| 868 | *t = *newInterface(methods, embeddeds) |
| 869 | return t |
| 870 | } |
| 871 | |
| 872 | // parsePointerType parses a PointerType: |
| 873 | // |
| 874 | // PointerType = "*" ("any" | Type) . |
| 875 | func (p *parser) parsePointerType(pkg *types.Package, nlist []interface{}) types.Type { |
| 876 | p.expect('*') |
| 877 | if p.tok == scanner.Ident { |
| 878 | p.expectKeyword("any") |
| 879 | t := types.Typ[types.UnsafePointer] |
| 880 | p.update(t, nlist) |
| 881 | return t |
| 882 | } |
| 883 | |
| 884 | t := new(types.Pointer) |
| 885 | p.update(t, nlist) |
| 886 | |
| 887 | *t = *types.NewPointer(p.parseType(pkg, t)) |
| 888 | |
| 889 | return t |
| 890 | } |
| 891 | |
| 892 | // parseTypeSpec parses a TypeSpec: |
| 893 | // |
| 894 | // TypeSpec = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType . |
| 895 | func (p *parser) parseTypeSpec(pkg *types.Package, nlist []interface{}) types.Type { |
| 896 | switch p.tok { |
| 897 | case scanner.String: |
| 898 | return p.parseNamedType(nlist) |
| 899 | |
| 900 | case scanner.Ident: |
| 901 | switch p.lit { |
| 902 | case "map": |
| 903 | return p.parseMapType(pkg, nlist) |
| 904 | |
| 905 | case "chan": |
| 906 | return p.parseChanType(pkg, nlist) |
| 907 | |
| 908 | case "struct": |
| 909 | return p.parseStructType(pkg, nlist) |
| 910 | |
| 911 | case "interface": |
| 912 | return p.parseInterfaceType(pkg, nlist) |
| 913 | } |
| 914 | |
| 915 | case '*': |
| 916 | return p.parsePointerType(pkg, nlist) |
| 917 | |
| 918 | case '[': |
| 919 | return p.parseArrayOrSliceType(pkg, nlist) |
| 920 | |
| 921 | case '(': |
| 922 | return p.parseFunctionType(pkg, nlist) |
| 923 | } |
| 924 | |
| 925 | p.errorf("expected type name or literal, got %s", scanner.TokenString(p.tok)) |
| 926 | return nil |
| 927 | } |
| 928 | |
| 929 | const ( |
| 930 | // From gofrontend/go/export.h |
| 931 | // Note that these values are negative in the gofrontend and have been made positive |
| 932 | // in the gccgoimporter. |
| 933 | gccgoBuiltinINT8 = 1 |
| 934 | gccgoBuiltinINT16 = 2 |
| 935 | gccgoBuiltinINT32 = 3 |
| 936 | gccgoBuiltinINT64 = 4 |
| 937 | gccgoBuiltinUINT8 = 5 |
| 938 | gccgoBuiltinUINT16 = 6 |
| 939 | gccgoBuiltinUINT32 = 7 |
| 940 | gccgoBuiltinUINT64 = 8 |
| 941 | gccgoBuiltinFLOAT32 = 9 |
| 942 | gccgoBuiltinFLOAT64 = 10 |
| 943 | gccgoBuiltinINT = 11 |
| 944 | gccgoBuiltinUINT = 12 |
| 945 | gccgoBuiltinUINTPTR = 13 |
| 946 | gccgoBuiltinBOOL = 15 |
| 947 | gccgoBuiltinSTRING = 16 |
| 948 | gccgoBuiltinCOMPLEX64 = 17 |
| 949 | gccgoBuiltinCOMPLEX128 = 18 |
| 950 | gccgoBuiltinERROR = 19 |
| 951 | gccgoBuiltinBYTE = 20 |
| 952 | gccgoBuiltinRUNE = 21 |
| 953 | ) |
| 954 | |
| 955 | func lookupBuiltinType(typ int) types.Type { |
| 956 | return [...]types.Type{ |
| 957 | gccgoBuiltinINT8: types.Typ[types.Int8], |
| 958 | gccgoBuiltinINT16: types.Typ[types.Int16], |
| 959 | gccgoBuiltinINT32: types.Typ[types.Int32], |
| 960 | gccgoBuiltinINT64: types.Typ[types.Int64], |
| 961 | gccgoBuiltinUINT8: types.Typ[types.Uint8], |
| 962 | gccgoBuiltinUINT16: types.Typ[types.Uint16], |
| 963 | gccgoBuiltinUINT32: types.Typ[types.Uint32], |
| 964 | gccgoBuiltinUINT64: types.Typ[types.Uint64], |
| 965 | gccgoBuiltinFLOAT32: types.Typ[types.Float32], |
| 966 | gccgoBuiltinFLOAT64: types.Typ[types.Float64], |
| 967 | gccgoBuiltinINT: types.Typ[types.Int], |
| 968 | gccgoBuiltinUINT: types.Typ[types.Uint], |
| 969 | gccgoBuiltinUINTPTR: types.Typ[types.Uintptr], |
| 970 | gccgoBuiltinBOOL: types.Typ[types.Bool], |
| 971 | gccgoBuiltinSTRING: types.Typ[types.String], |
| 972 | gccgoBuiltinCOMPLEX64: types.Typ[types.Complex64], |
| 973 | gccgoBuiltinCOMPLEX128: types.Typ[types.Complex128], |
| 974 | gccgoBuiltinERROR: types.Universe.Lookup("error").Type(), |
| 975 | gccgoBuiltinBYTE: types.Universe.Lookup("byte").Type(), |
| 976 | gccgoBuiltinRUNE: types.Universe.Lookup("rune").Type(), |
| 977 | }[typ] |
| 978 | } |
| 979 | |
| 980 | // parseType parses a Type: |
| 981 | // |
| 982 | // Type = "<" "type" ( "-" int | int [ TypeSpec ] ) ">" . |
| 983 | // |
| 984 | // parseType updates the type map to t for all type numbers n. |
| 985 | func (p *parser) parseType(pkg *types.Package, n ...interface{}) types.Type { |
| 986 | p.expect('<') |
| 987 | t, _ := p.parseTypeAfterAngle(pkg, n...) |
| 988 | return t |
| 989 | } |
| 990 | |
| 991 | // (*parser).Type after reading the "<". |
| 992 | func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...interface{}) (t types.Type, n1 int) { |
| 993 | p.expectKeyword("type") |
| 994 | |
| 995 | n1 = 0 |
| 996 | switch p.tok { |
| 997 | case scanner.Int: |
| 998 | n1 = p.parseInt() |
| 999 | if p.tok == '>' { |
| 1000 | if len(p.typeData) > 0 && p.typeList[n1] == nil { |
| 1001 | p.parseSavedType(pkg, n1, n) |
| 1002 | } |
| 1003 | t = p.typeList[n1] |
| 1004 | if len(p.typeData) == 0 && t == reserved { |
| 1005 | p.errorf("invalid type cycle, type %d not yet defined (nlist=%v)", n1, n) |
| 1006 | } |
| 1007 | p.update(t, n) |
| 1008 | } else { |
| 1009 | p.reserve(n1) |
| 1010 | t = p.parseTypeSpec(pkg, append(n, n1)) |
| 1011 | } |
| 1012 | |
| 1013 | case '-': |
| 1014 | p.next() |
| 1015 | n1 := p.parseInt() |
| 1016 | t = lookupBuiltinType(n1) |
| 1017 | p.update(t, n) |
| 1018 | |
| 1019 | default: |
| 1020 | p.errorf("expected type number, got %s (%q)", scanner.TokenString(p.tok), p.lit) |
| 1021 | return nil, 0 |
| 1022 | } |
| 1023 | |
| 1024 | if t == nil || t == reserved { |
| 1025 | p.errorf("internal error: bad return from parseType(%v)", n) |
| 1026 | } |
| 1027 | |
| 1028 | p.expect('>') |
| 1029 | return |
| 1030 | } |
| 1031 | |
| 1032 | // parseTypeExtended is identical to parseType, but if the type in |
| 1033 | // question is a saved type, returns the index as well as the type |
| 1034 | // pointer (index returned is zero if we parsed a builtin). |
| 1035 | func (p *parser) parseTypeExtended(pkg *types.Package, n ...interface{}) (t types.Type, n1 int) { |
| 1036 | p.expect('<') |
| 1037 | t, n1 = p.parseTypeAfterAngle(pkg, n...) |
| 1038 | return |
| 1039 | } |
| 1040 | |
| 1041 | // InlineBody = "<inl:NN>" .{NN} |
| 1042 | // Reports whether a body was skipped. |
| 1043 | func (p *parser) skipInlineBody() { |
| 1044 | // We may or may not have seen the '<' already, depending on |
| 1045 | // whether the function had a result type or not. |
| 1046 | if p.tok == '<' { |
| 1047 | p.next() |
| 1048 | p.expectKeyword("inl") |
| 1049 | } else if p.tok != scanner.Ident || p.lit != "inl" { |
| 1050 | return |
| 1051 | } else { |
| 1052 | p.next() |
| 1053 | } |
| 1054 | |
| 1055 | p.expect(':') |
| 1056 | want := p.parseInt() |
| 1057 | p.expect('>') |
| 1058 | |
| 1059 | defer func(w uint64) { |
| 1060 | p.scanner.Whitespace = w |
| 1061 | }(p.scanner.Whitespace) |
| 1062 | p.scanner.Whitespace = 0 |
| 1063 | |
| 1064 | got := 0 |
| 1065 | for got < want { |
| 1066 | r := p.scanner.Next() |
| 1067 | if r == scanner.EOF { |
| 1068 | p.error("unexpected EOF") |
| 1069 | } |
| 1070 | got += utf8.RuneLen(r) |
| 1071 | } |
| 1072 | } |
| 1073 | |
| 1074 | // parseTypes parses a Types: |
| 1075 | // |
| 1076 | // Types = "types" maxp1 exportedp1 (offset length)* . |
| 1077 | func (p *parser) parseTypes(pkg *types.Package) { |
| 1078 | maxp1 := p.parseInt() |
| 1079 | exportedp1 := p.parseInt() |
| 1080 | p.typeList = make([]types.Type, maxp1) |
| 1081 | |
| 1082 | type typeOffset struct { |
| 1083 | offset int |
| 1084 | length int |
| 1085 | } |
| 1086 | var typeOffsets []typeOffset |
| 1087 | |
| 1088 | total := 0 |
| 1089 | for i := 1; i < maxp1; i++ { |
| 1090 | len := p.parseInt() |
| 1091 | typeOffsets = append(typeOffsets, typeOffset{total, len}) |
| 1092 | total += len |
| 1093 | } |
| 1094 | |
| 1095 | defer func(w uint64) { |
| 1096 | p.scanner.Whitespace = w |
| 1097 | }(p.scanner.Whitespace) |
| 1098 | p.scanner.Whitespace = 0 |
| 1099 | |
| 1100 | // We should now have p.tok pointing to the final newline. |
| 1101 | // The next runes from the scanner should be the type data. |
| 1102 | |
| 1103 | var sb strings.Builder |
| 1104 | for sb.Len() < total { |
| 1105 | r := p.scanner.Next() |
| 1106 | if r == scanner.EOF { |
| 1107 | p.error("unexpected EOF") |
| 1108 | } |
| 1109 | sb.WriteRune(r) |
| 1110 | } |
| 1111 | allTypeData := sb.String() |
| 1112 | |
| 1113 | p.typeData = []string{""} // type 0, unused |
| 1114 | for _, to := range typeOffsets { |
| 1115 | p.typeData = append(p.typeData, allTypeData[to.offset:to.offset+to.length]) |
| 1116 | } |
| 1117 | |
| 1118 | for i := 1; i < int(exportedp1); i++ { |
| 1119 | p.parseSavedType(pkg, i, nil) |
| 1120 | } |
| 1121 | } |
| 1122 | |
| 1123 | // parseSavedType parses one saved type definition. |
| 1124 | func (p *parser) parseSavedType(pkg *types.Package, i int, nlist []interface{}) { |
| 1125 | defer func(s *scanner.Scanner, tok rune, lit string) { |
| 1126 | p.scanner = s |
| 1127 | p.tok = tok |
| 1128 | p.lit = lit |
| 1129 | }(p.scanner, p.tok, p.lit) |
| 1130 | |
| 1131 | p.scanner = new(scanner.Scanner) |
| 1132 | p.initScanner(p.scanner.Filename, strings.NewReader(p.typeData[i])) |
| 1133 | p.expectKeyword("type") |
| 1134 | id := p.parseInt() |
| 1135 | if id != i { |
| 1136 | p.errorf("type ID mismatch: got %d, want %d", id, i) |
| 1137 | } |
| 1138 | if p.typeList[i] == reserved { |
| 1139 | p.errorf("internal error: %d already reserved in parseSavedType", i) |
| 1140 | } |
| 1141 | if p.typeList[i] == nil { |
| 1142 | p.reserve(i) |
| 1143 | p.parseTypeSpec(pkg, append(nlist, i)) |
| 1144 | } |
| 1145 | if p.typeList[i] == nil || p.typeList[i] == reserved { |
| 1146 | p.errorf("internal error: parseSavedType(%d,%v) reserved/nil", i, nlist) |
| 1147 | } |
| 1148 | } |
| 1149 | |
| 1150 | // parsePackageInit parses a PackageInit: |
| 1151 | // |
| 1152 | // PackageInit = unquotedString unquotedString int . |
| 1153 | func (p *parser) parsePackageInit() PackageInit { |
| 1154 | name := p.parseUnquotedString() |
| 1155 | initfunc := p.parseUnquotedString() |
| 1156 | priority := -1 |
| 1157 | if p.version == "v1" { |
| 1158 | priority = p.parseInt() |
| 1159 | } |
| 1160 | return PackageInit{Name: name, InitFunc: initfunc, Priority: priority} |
| 1161 | } |
| 1162 | |
| 1163 | // Create the package if we have parsed both the package path and package name. |
| 1164 | func (p *parser) maybeCreatePackage() { |
| 1165 | if p.pkgname != "" && p.pkgpath != "" { |
| 1166 | p.pkg = p.getPkg(p.pkgpath, p.pkgname) |
| 1167 | } |
| 1168 | } |
| 1169 | |
| 1170 | // parseInitDateDirective parses an InitDataDirective: |
| 1171 | // |
| 1172 | // InitDataDirective = ( "v1" | "v2" | "v3" ) ";" | |
| 1173 | // "priority" int ";" | |
| 1174 | // "init" { PackageInit } ";" | |
| 1175 | // "checksum" unquotedString ";" . |
| 1176 | func (p *parser) parseInitDataDirective() { |
| 1177 | if p.tok != scanner.Ident { |
| 1178 | // unexpected token kind; panic |
| 1179 | p.expect(scanner.Ident) |
| 1180 | } |
| 1181 | |
| 1182 | switch p.lit { |
| 1183 | case "v1", "v2", "v3": |
| 1184 | p.version = p.lit |
| 1185 | p.next() |
| 1186 | p.expect(';') |
| 1187 | p.expect('\n') |
| 1188 | |
| 1189 | case "priority": |
| 1190 | p.next() |
| 1191 | p.initdata.Priority = p.parseInt() |
| 1192 | p.expectEOL() |
| 1193 | |
| 1194 | case "init": |
| 1195 | p.next() |
| 1196 | for p.tok != '\n' && p.tok != ';' && p.tok != scanner.EOF { |
| 1197 | p.initdata.Inits = append(p.initdata.Inits, p.parsePackageInit()) |
| 1198 | } |
| 1199 | p.expectEOL() |
| 1200 | |
| 1201 | case "init_graph": |
| 1202 | p.next() |
| 1203 | // The graph data is thrown away for now. |
| 1204 | for p.tok != '\n' && p.tok != ';' && p.tok != scanner.EOF { |
| 1205 | p.parseInt64() |
| 1206 | p.parseInt64() |
| 1207 | } |
| 1208 | p.expectEOL() |
| 1209 | |
| 1210 | case "checksum": |
| 1211 | // Don't let the scanner try to parse the checksum as a number. |
| 1212 | defer func(mode uint) { |
| 1213 | p.scanner.Mode = mode |
| 1214 | }(p.scanner.Mode) |
| 1215 | p.scanner.Mode &^= scanner.ScanInts | scanner.ScanFloats |
| 1216 | p.next() |
| 1217 | p.parseUnquotedString() |
| 1218 | p.expectEOL() |
| 1219 | |
| 1220 | default: |
| 1221 | p.errorf("unexpected identifier: %q", p.lit) |
| 1222 | } |
| 1223 | } |
| 1224 | |
| 1225 | // parseDirective parses a Directive: |
| 1226 | // |
| 1227 | // Directive = InitDataDirective | |
| 1228 | // "package" unquotedString [ unquotedString ] [ unquotedString ] ";" | |
| 1229 | // "pkgpath" unquotedString ";" | |
| 1230 | // "prefix" unquotedString ";" | |
| 1231 | // "import" unquotedString unquotedString string ";" | |
| 1232 | // "indirectimport" unquotedString unquotedstring ";" | |
| 1233 | // "func" Func ";" | |
| 1234 | // "type" Type ";" | |
| 1235 | // "var" Var ";" | |
| 1236 | // "const" Const ";" . |
| 1237 | func (p *parser) parseDirective() { |
| 1238 | if p.tok != scanner.Ident { |
| 1239 | // unexpected token kind; panic |
| 1240 | p.expect(scanner.Ident) |
| 1241 | } |
| 1242 | |
| 1243 | switch p.lit { |
| 1244 | case "v1", "v2", "v3", "priority", "init", "init_graph", "checksum": |
| 1245 | p.parseInitDataDirective() |
| 1246 | |
| 1247 | case "package": |
| 1248 | p.next() |
| 1249 | p.pkgname = p.parseUnquotedString() |
| 1250 | p.maybeCreatePackage() |
| 1251 | if p.version != "v1" && p.tok != '\n' && p.tok != ';' { |
| 1252 | p.parseUnquotedString() |
| 1253 | p.parseUnquotedString() |
| 1254 | } |
| 1255 | p.expectEOL() |
| 1256 | |
| 1257 | case "pkgpath": |
| 1258 | p.next() |
| 1259 | p.pkgpath = p.parseUnquotedString() |
| 1260 | p.maybeCreatePackage() |
| 1261 | p.expectEOL() |
| 1262 | |
| 1263 | case "prefix": |
| 1264 | p.next() |
| 1265 | p.pkgpath = p.parseUnquotedString() |
| 1266 | p.expectEOL() |
| 1267 | |
| 1268 | case "import": |
| 1269 | p.next() |
| 1270 | pkgname := p.parseUnquotedString() |
| 1271 | pkgpath := p.parseUnquotedString() |
| 1272 | p.getPkg(pkgpath, pkgname) |
| 1273 | p.parseString() |
| 1274 | p.expectEOL() |
| 1275 | |
| 1276 | case "indirectimport": |
| 1277 | p.next() |
| 1278 | pkgname := p.parseUnquotedString() |
| 1279 | pkgpath := p.parseUnquotedString() |
| 1280 | p.getPkg(pkgpath, pkgname) |
| 1281 | p.expectEOL() |
| 1282 | |
| 1283 | case "types": |
| 1284 | p.next() |
| 1285 | p.parseTypes(p.pkg) |
| 1286 | p.expectEOL() |
| 1287 | |
| 1288 | case "func": |
| 1289 | p.next() |
| 1290 | fun := p.parseFunc(p.pkg) |
| 1291 | if fun != nil { |
| 1292 | p.pkg.Scope().Insert(fun) |
| 1293 | } |
| 1294 | p.expectEOL() |
| 1295 | |
| 1296 | case "type": |
| 1297 | p.next() |
| 1298 | p.parseType(p.pkg) |
| 1299 | p.expectEOL() |
| 1300 | |
| 1301 | case "var": |
| 1302 | p.next() |
| 1303 | v := p.parseVar(p.pkg) |
| 1304 | if v != nil { |
| 1305 | p.pkg.Scope().Insert(v) |
| 1306 | } |
| 1307 | p.expectEOL() |
| 1308 | |
| 1309 | case "const": |
| 1310 | p.next() |
| 1311 | c := p.parseConst(p.pkg) |
| 1312 | p.pkg.Scope().Insert(c) |
| 1313 | p.expectEOL() |
| 1314 | |
| 1315 | default: |
| 1316 | p.errorf("unexpected identifier: %q", p.lit) |
| 1317 | } |
| 1318 | } |
| 1319 | |
| 1320 | // parsePackage parses a Package: |
| 1321 | // |
| 1322 | // Package = { Directive } . |
| 1323 | func (p *parser) parsePackage() *types.Package { |
| 1324 | for p.tok != scanner.EOF { |
| 1325 | p.parseDirective() |
| 1326 | } |
| 1327 | for _, f := range p.fixups { |
| 1328 | if f.target.Underlying() == nil { |
| 1329 | p.errorf("internal error: fixup can't be applied, loop required") |
| 1330 | } |
| 1331 | f.toUpdate.SetUnderlying(f.target.Underlying()) |
| 1332 | } |
| 1333 | p.fixups = nil |
| 1334 | for _, typ := range p.typeList { |
| 1335 | if it, ok := typ.(*types.Interface); ok { |
| 1336 | it.Complete() |
| 1337 | } |
| 1338 | } |
| 1339 | p.pkg.MarkComplete() |
| 1340 | return p.pkg |
| 1341 | } |
| 1342 |
Members