@@ -15,6 +15,7 @@ import (
15
15
"strconv"
16
16
"strings"
17
17
"text/scanner"
18
+ "unicode/utf8"
18
19
)
19
20
20
21
type parser struct {
@@ -41,7 +42,7 @@ func (p *parser) init(filename string, src io.Reader, imports map[string]*types.
41
42
func (p * parser ) initScanner (filename string , src io.Reader ) {
42
43
p .scanner .Init (src )
43
44
p .scanner .Error = func (_ * scanner.Scanner , msg string ) { p .error (msg ) }
44
- p .scanner .Mode = scanner .ScanIdents | scanner .ScanInts | scanner .ScanFloats | scanner .ScanStrings | scanner . ScanComments | scanner . SkipComments
45
+ p .scanner .Mode = scanner .ScanIdents | scanner .ScanInts | scanner .ScanFloats | scanner .ScanStrings
45
46
p .scanner .Whitespace = 1 << '\t' | 1 << ' '
46
47
p .scanner .Filename = filename // for good error messages
47
48
p .next ()
@@ -281,6 +282,15 @@ func (p *parser) parseConversion(pkg *types.Package) (val constant.Value, typ ty
281
282
// ConstValue = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) | Conversion .
282
283
// FloatOrComplex = float ["i" | ("+"|"-") float "i"] .
283
284
func (p * parser ) parseConstValue (pkg * types.Package ) (val constant.Value , typ types.Type ) {
285
+ // v3 changed to $false, $true, $convert, to avoid confusion
286
+ // with variable names in inline function bodies.
287
+ if p .tok == '$' {
288
+ p .next ()
289
+ if p .tok != scanner .Ident {
290
+ p .errorf ("expected identifer after '$', got %s (%q)" , scanner .TokenString (p .tok ), p .lit )
291
+ }
292
+ }
293
+
284
294
switch p .tok {
285
295
case scanner .String :
286
296
str := p .parseString ()
@@ -443,7 +453,7 @@ func (p *parser) update(t types.Type, nlist []int) {
443
453
444
454
// NamedType = TypeName [ "=" ] Type { Method } .
445
455
// TypeName = ExportedName .
446
- // Method = "func" "(" Param ")" Name ParamList ResultList ";" .
456
+ // Method = "func" "(" Param ")" Name ParamList ResultList [InlineBody] ";" .
447
457
func (p * parser ) parseNamedType (nlist []int ) types.Type {
448
458
pkg , name := p .parseExportedName ()
449
459
scope := pkg .Scope ()
@@ -508,6 +518,7 @@ func (p *parser) parseNamedType(nlist []int) types.Type {
508
518
name := p .parseName ()
509
519
params , isVariadic := p .parseParamList (pkg )
510
520
results := p .parseResultList (pkg )
521
+ p .skipInlineBody ()
511
522
p .expectEOL ()
512
523
513
524
sig := types .NewSignature (receiver , params , results , isVariadic )
@@ -653,7 +664,11 @@ func (p *parser) parseParamList(pkg *types.Package) (*types.Tuple, bool) {
653
664
func (p * parser ) parseResultList (pkg * types.Package ) * types.Tuple {
654
665
switch p .tok {
655
666
case '<' :
656
- return types .NewTuple (types .NewParam (token .NoPos , pkg , "" , p .parseType (pkg )))
667
+ p .next ()
668
+ if p .tok == scanner .Ident && p .lit == "inl" {
669
+ return nil
670
+ }
671
+ return types .NewTuple (types .NewParam (token .NoPos , pkg , "" , p .parseTypeAfterAngle (pkg )))
657
672
658
673
case '(' :
659
674
params , _ := p .parseParamList (pkg )
@@ -676,7 +691,7 @@ func (p *parser) parseFunctionType(pkg *types.Package, nlist []int) *types.Signa
676
691
return t
677
692
}
678
693
679
- // Func = Name FunctionType .
694
+ // Func = Name FunctionType [InlineBody] .
680
695
func (p * parser ) parseFunc (pkg * types.Package ) * types.Func {
681
696
name := p .parseName ()
682
697
if strings .ContainsRune (name , '$' ) {
@@ -685,7 +700,9 @@ func (p *parser) parseFunc(pkg *types.Package) *types.Func {
685
700
p .discardDirectiveWhileParsingTypes (pkg )
686
701
return nil
687
702
}
688
- return types .NewFunc (token .NoPos , pkg , name , p .parseFunctionType (pkg , nil ))
703
+ f := types .NewFunc (token .NoPos , pkg , name , p .parseFunctionType (pkg , nil ))
704
+ p .skipInlineBody ()
705
+ return f
689
706
}
690
707
691
708
// InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" .
@@ -823,8 +840,13 @@ func lookupBuiltinType(typ int) types.Type {
823
840
//
824
841
// parseType updates the type map to t for all type numbers n.
825
842
//
826
- func (p * parser ) parseType (pkg * types.Package , n ... int ) ( t types.Type ) {
843
+ func (p * parser ) parseType (pkg * types.Package , n ... int ) types.Type {
827
844
p .expect ('<' )
845
+ return p .parseTypeAfterAngle (pkg , n ... )
846
+ }
847
+
848
+ // (*parser).Type after reading the "<".
849
+ func (p * parser ) parseTypeAfterAngle (pkg * types.Package , n ... int ) (t types.Type ) {
828
850
p .expectKeyword ("type" )
829
851
830
852
switch p .tok {
@@ -863,6 +885,39 @@ func (p *parser) parseType(pkg *types.Package, n ...int) (t types.Type) {
863
885
return
864
886
}
865
887
888
+ // InlineBody = "<inl:NN>" .{NN}
889
+ // Reports whether a body was skipped.
890
+ func (p * parser ) skipInlineBody () {
891
+ // We may or may not have seen the '<' already, depending on
892
+ // whether the function had a result type or not.
893
+ if p .tok == '<' {
894
+ p .next ()
895
+ p .expectKeyword ("inl" )
896
+ } else if p .tok != scanner .Ident || p .lit != "inl" {
897
+ return
898
+ } else {
899
+ p .next ()
900
+ }
901
+
902
+ p .expect (':' )
903
+ want := p .parseInt ()
904
+ p .expect ('>' )
905
+
906
+ defer func (w uint64 ) {
907
+ p .scanner .Whitespace = w
908
+ }(p .scanner .Whitespace )
909
+ p .scanner .Whitespace = 0
910
+
911
+ got := 0
912
+ for got < want {
913
+ r := p .scanner .Next ()
914
+ if r == scanner .EOF {
915
+ p .error ("unexpected EOF" )
916
+ }
917
+ got += utf8 .RuneLen (r )
918
+ }
919
+ }
920
+
866
921
// Types = "types" maxp1 exportedp1 (offset length)* .
867
922
func (p * parser ) parseTypes (pkg * types.Package ) {
868
923
maxp1 := p .parseInt ()
@@ -882,6 +937,11 @@ func (p *parser) parseTypes(pkg *types.Package) {
882
937
total += len
883
938
}
884
939
940
+ defer func (w uint64 ) {
941
+ p .scanner .Whitespace = w
942
+ }(p .scanner .Whitespace )
943
+ p .scanner .Whitespace = 0
944
+
885
945
// We should now have p.tok pointing to the final newline.
886
946
// The next runes from the scanner should be the type data.
887
947
0 commit comments