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