adapter.go raw
1 package syntax
2
3 import (
4 "bytes"
5 "go/ast"
6 "go/token"
7 )
8
9 type commentEntry struct {
10 pos Pos
11 text string
12 }
13
14 type pragmaData struct {
15 comments []commentEntry
16 }
17
18 func pragmaHandler(pos Pos, blank bool, text string, current Pragma) Pragma {
19 p, _ := current.(*pragmaData)
20 if p == nil {
21 p = &pragmaData{}
22 }
23 prefix := "//"
24 p.comments = append(p.comments, commentEntry{pos: pos, text: prefix + text})
25 return p
26 }
27
28 func (a *Adapter) pragmaToDoc(p Pragma) *ast.CommentGroup {
29 pd, _ := p.(*pragmaData)
30 if pd == nil || len(pd.comments) == 0 {
31 return nil
32 }
33 cg := &ast.CommentGroup{}
34 for _, c := range pd.comments {
35 cg.List = append(cg.List, &ast.Comment{
36 Slash: a.pos(c.pos),
37 Text: c.text,
38 })
39 }
40 return cg
41 }
42
43 type Adapter struct {
44 fset *token.FileSet
45 file *token.File
46 }
47
48 // Convert parses src using the bootstrap parser and returns a go/ast.File
49 // registered in fset. filename is used for position info.
50 func Convert(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
51 af, _, err := ConvertAndKeep(fset, filename, src)
52 return af, err
53 }
54
55 // ConvertAndKeep is like Convert but also returns the parsed *syntax.File.
56 // The syntax.File is used by the native type checker (B1) to annotate
57 // expressions with type info without going through go/ast.
58 func ConvertAndKeep(fset *token.FileSet, filename string, src []byte) (*ast.File, *File, error) {
59 base := NewFileBase(filename)
60 sf, err := Parse(base, bytes.NewReader(src), nil, pragmaHandler, 0)
61 if err != nil {
62 return nil, nil, err
63 }
64
65 a := &Adapter{fset: fset}
66 a.file = fset.AddFile(filename, -1, len(src))
67
68 var lines []int
69 lines = append(lines, 0)
70 for i, b := range src {
71 if b == '\n' && i+1 < len(src) {
72 lines = append(lines, i+1)
73 }
74 }
75 a.file.SetLines(lines)
76
77 af := a.convertFile(sf)
78 return af, sf, nil
79 }
80
81 func (a *Adapter) pos(p Pos) token.Pos {
82 // syntax Pos stores 0-based line/col from scanner snapshot
83 line := int(p.Line()) + 1
84 col := int(p.Col()) + 1
85 if line < 1 {
86 line = 1
87 }
88 if col < 1 {
89 col = 1
90 }
91 if line > a.file.LineCount() {
92 line = a.file.LineCount()
93 }
94 result := a.file.LineStart(line) + token.Pos(col-1)
95 return result
96 }
97
98 func (a *Adapter) ident(n *Name) *ast.Ident {
99 if n == nil {
100 return nil
101 }
102 return &ast.Ident{NamePos: a.pos(n.Pos()), Name: n.Value}
103 }
104
105 func (a *Adapter) convertFile(f *File) *ast.File {
106 af := &ast.File{
107 Package: a.pos(f.Pos()),
108 Name: a.ident(f.PkgName),
109 FileStart: token.Pos(a.file.Base()),
110 FileEnd: token.Pos(a.file.Base() + a.file.Size()),
111 }
112
113 var imports []*ast.ImportSpec
114 groupMap := map[*Group]*ast.GenDecl{}
115
116 for _, d := range f.DeclList {
117 g := declGroup(d)
118 if g != nil {
119 if gd, ok := groupMap[g]; ok {
120 // Add spec to existing group
121 gd.Specs = append(gd.Specs, a.spec(d))
122 continue
123 }
124 // Start new group
125 gd := &ast.GenDecl{
126 TokPos: a.pos(d.Pos()),
127 Tok: declToken(d),
128 Lparen: a.pos(d.Pos()),
129 Specs: []ast.Spec{a.spec(d)},
130 }
131 groupMap[g] = gd
132 af.Decls = append(af.Decls, gd)
133 continue
134 }
135
136 ad := a.decl(d)
137 if ad != nil {
138 af.Decls = append(af.Decls, ad)
139 }
140 }
141
142 for _, d := range af.Decls {
143 switch d := d.(type) {
144 case *ast.GenDecl:
145 if d.Doc != nil {
146 af.Comments = append(af.Comments, d.Doc)
147 }
148 if d.Tok == token.IMPORT {
149 for _, s := range d.Specs {
150 if is, ok := s.(*ast.ImportSpec); ok {
151 imports = append(imports, is)
152 }
153 }
154 }
155 case *ast.FuncDecl:
156 if d.Doc != nil {
157 af.Comments = append(af.Comments, d.Doc)
158 }
159 }
160 }
161 af.Imports = imports
162 return af
163 }
164
165 func declGroup(d Decl) *Group {
166 switch d := d.(type) {
167 case *ImportDecl:
168 return d.Group
169 case *ConstDecl:
170 return d.Group
171 case *TypeDecl:
172 return d.Group
173 case *VarDecl:
174 return d.Group
175 }
176 return nil
177 }
178
179 func declToken(d Decl) token.Token {
180 switch d.(type) {
181 case *ImportDecl:
182 return token.IMPORT
183 case *ConstDecl:
184 return token.CONST
185 case *TypeDecl:
186 return token.TYPE
187 case *VarDecl:
188 return token.VAR
189 }
190 return token.ILLEGAL
191 }
192
193 func (a *Adapter) spec(d Decl) ast.Spec {
194 switch d := d.(type) {
195 case *ImportDecl:
196 spec := &ast.ImportSpec{Path: a.basicLit(d.Path)}
197 if d.LocalPkgName != nil {
198 spec.Name = a.ident(d.LocalPkgName)
199 }
200 return spec
201 case *ConstDecl:
202 return &ast.ValueSpec{
203 Names: a.nameList(d.NameList),
204 Type: a.expr(d.Type),
205 Values: a.exprList(d.Values),
206 }
207 case *TypeDecl:
208 ts := &ast.TypeSpec{
209 Name: a.ident(d.Name),
210 Type: a.expr(d.Type),
211 }
212 if d.Alias {
213 ts.Assign = a.pos(d.Pos())
214 }
215 if len(d.TParamList) > 0 {
216 ts.TypeParams = a.fieldList(d.TParamList)
217 }
218 return ts
219 case *VarDecl:
220 return &ast.ValueSpec{
221 Names: a.nameList(d.NameList),
222 Type: a.expr(d.Type),
223 Values: a.exprList(d.Values),
224 }
225 }
226 return nil
227 }
228
229 func (a *Adapter) decl(d Decl) ast.Decl {
230 switch d := d.(type) {
231 case *ImportDecl:
232 spec := &ast.ImportSpec{
233 Path: a.basicLit(d.Path),
234 }
235 if d.LocalPkgName != nil {
236 spec.Name = a.ident(d.LocalPkgName)
237 }
238 return &ast.GenDecl{
239 Doc: a.pragmaToDoc(d.Pragma),
240 TokPos: a.pos(d.Pos()),
241 Tok: token.IMPORT,
242 Specs: []ast.Spec{spec},
243 }
244 case *ConstDecl:
245 vs := &ast.ValueSpec{
246 Names: a.nameList(d.NameList),
247 Type: a.expr(d.Type),
248 Values: a.exprList(d.Values),
249 }
250 return &ast.GenDecl{
251 Doc: a.pragmaToDoc(d.Pragma),
252 TokPos: a.pos(d.Pos()),
253 Tok: token.CONST,
254 Specs: []ast.Spec{vs},
255 }
256 case *TypeDecl:
257 ts := &ast.TypeSpec{
258 Name: a.ident(d.Name),
259 Assign: 0,
260 Type: a.expr(d.Type),
261 }
262 if d.Alias {
263 ts.Assign = a.pos(d.Pos())
264 }
265 if len(d.TParamList) > 0 {
266 ts.TypeParams = a.fieldList(d.TParamList)
267 }
268 return &ast.GenDecl{
269 Doc: a.pragmaToDoc(d.Pragma),
270 TokPos: a.pos(d.Pos()),
271 Tok: token.TYPE,
272 Specs: []ast.Spec{ts},
273 }
274 case *VarDecl:
275 vs := &ast.ValueSpec{
276 Names: a.nameList(d.NameList),
277 Type: a.expr(d.Type),
278 Values: a.exprList(d.Values),
279 }
280 return &ast.GenDecl{
281 Doc: a.pragmaToDoc(d.Pragma),
282 TokPos: a.pos(d.Pos()),
283 Tok: token.VAR,
284 Specs: []ast.Spec{vs},
285 }
286 case *FuncDecl:
287 fd := &ast.FuncDecl{
288 Doc: a.pragmaToDoc(d.Pragma),
289 Name: a.ident(d.Name),
290 Type: a.funcType(d.Type),
291 Body: a.blockStmt(d.Body),
292 }
293 if d.Recv != nil {
294 fd.Recv = &ast.FieldList{
295 List: []*ast.Field{a.field(d.Recv)},
296 }
297 }
298 if len(d.TParamList) > 0 {
299 fd.Type.TypeParams = a.fieldList(d.TParamList)
300 }
301 return fd
302 }
303 return nil
304 }
305
306 func (a *Adapter) nameList(names []*Name) []*ast.Ident {
307 var out []*ast.Ident
308 for _, n := range names {
309 out = append(out, a.ident(n))
310 }
311 return out
312 }
313
314 func (a *Adapter) exprList(e Expr) []ast.Expr {
315 if e == nil {
316 return nil
317 }
318 if l, ok := e.(*ListExpr); ok {
319 var out []ast.Expr
320 for _, el := range l.ElemList {
321 out = append(out, a.expr(el))
322 }
323 return out
324 }
325 return []ast.Expr{a.expr(e)}
326 }
327
328 func (a *Adapter) expr(e Expr) ast.Expr {
329 if e == nil {
330 return nil
331 }
332 switch e := e.(type) {
333 case *Name:
334 return a.ident(e)
335 case *BasicLit:
336 return a.basicLit(e)
337 case *CompositeLit:
338 cl := &ast.CompositeLit{
339 Type: a.expr(e.Type),
340 Rbrace: a.pos(e.Rbrace),
341 }
342 for _, el := range e.ElemList {
343 cl.Elts = append(cl.Elts, a.expr(el))
344 }
345 return cl
346 case *KeyValueExpr:
347 return &ast.KeyValueExpr{
348 Key: a.expr(e.Key),
349 Colon: a.pos(e.Pos()),
350 Value: a.expr(e.Value),
351 }
352 case *FuncLit:
353 return &ast.FuncLit{
354 Type: a.funcType(e.Type),
355 Body: a.blockStmt(e.Body),
356 }
357 case *ParenExpr:
358 return &ast.ParenExpr{
359 Lparen: a.pos(e.Pos()),
360 X: a.expr(e.X),
361 }
362 case *SelectorExpr:
363 return &ast.SelectorExpr{
364 X: a.expr(e.X),
365 Sel: a.ident(e.Sel),
366 }
367 case *IndexExpr:
368 if le, ok := e.Index.(*ListExpr); ok && len(le.ElemList) > 1 {
369 var indices []ast.Expr
370 for _, el := range le.ElemList {
371 indices = append(indices, a.expr(el))
372 }
373 return &ast.IndexListExpr{
374 X: a.expr(e.X),
375 Indices: indices,
376 }
377 }
378 return &ast.IndexExpr{
379 X: a.expr(e.X),
380 Index: a.expr(e.Index),
381 }
382 case *SliceExpr:
383 se := &ast.SliceExpr{
384 X: a.expr(e.X),
385 Low: a.expr(e.Index[0]),
386 High: a.expr(e.Index[1]),
387 Max: a.expr(e.Index[2]),
388 Slice3: e.Full,
389 }
390 return se
391 case *AssertExpr:
392 return &ast.TypeAssertExpr{
393 X: a.expr(e.X),
394 Type: a.expr(e.Type),
395 }
396 case *TypeSwitchGuard:
397 return &ast.TypeAssertExpr{
398 X: a.expr(e.X),
399 }
400 case *Operation:
401 return a.operation(e)
402 case *CallExpr:
403 ce := &ast.CallExpr{
404 Fun: a.expr(e.Fun),
405 }
406 for _, arg := range e.ArgList {
407 ce.Args = append(ce.Args, a.expr(arg))
408 }
409 if e.HasDots {
410 ce.Ellipsis = a.pos(e.Pos())
411 }
412 return ce
413 case *ListExpr:
414 if len(e.ElemList) == 1 {
415 return a.expr(e.ElemList[0])
416 }
417 // multi-element list: shouldn't appear as a standalone expression
418 return a.expr(e.ElemList[0])
419 case *ArrayType:
420 if e.Len == nil {
421 return &ast.ArrayType{
422 Lbrack: a.pos(e.Pos()),
423 Len: &ast.Ellipsis{Ellipsis: a.pos(e.Pos())},
424 Elt: a.expr(e.Elem),
425 }
426 }
427 return &ast.ArrayType{
428 Lbrack: a.pos(e.Pos()),
429 Len: a.expr(e.Len),
430 Elt: a.expr(e.Elem),
431 }
432 case *SliceType:
433 return &ast.ArrayType{
434 Lbrack: a.pos(e.Pos()),
435 Elt: a.expr(e.Elem),
436 }
437 case *DotsType:
438 return &ast.Ellipsis{
439 Ellipsis: a.pos(e.Pos()),
440 Elt: a.expr(e.Elem),
441 }
442 case *StructType:
443 return &ast.StructType{
444 Struct: a.pos(e.Pos()),
445 Fields: a.structFieldList(e),
446 }
447 case *InterfaceType:
448 methods := a.fieldListFromFields(e.MethodList)
449 if methods == nil {
450 methods = &ast.FieldList{}
451 }
452 return &ast.InterfaceType{
453 Interface: a.pos(e.Pos()),
454 Methods: methods,
455 }
456 case *FuncType:
457 return a.funcType(e)
458 case *MapType:
459 return &ast.MapType{
460 Map: a.pos(e.Pos()),
461 Key: a.expr(e.Key),
462 Value: a.expr(e.Value),
463 }
464 case *ChanType:
465 ct := &ast.ChanType{
466 Begin: a.pos(e.Pos()),
467 Value: a.expr(e.Elem),
468 }
469 switch e.Dir {
470 case SendOnly:
471 ct.Dir = ast.SEND
472 case RecvOnly:
473 ct.Dir = ast.RECV
474 default:
475 ct.Dir = ast.SEND | ast.RECV
476 }
477 return ct
478 case *BadExpr:
479 return &ast.BadExpr{From: a.pos(e.Pos())}
480 }
481 return &ast.BadExpr{}
482 }
483
484 func (a *Adapter) operation(e *Operation) ast.Expr {
485 if e.Y == nil {
486 if e.Op == Mul {
487 return &ast.StarExpr{
488 Star: a.pos(e.Pos()),
489 X: a.expr(e.X),
490 }
491 }
492 if e.Op == And {
493 return &ast.UnaryExpr{
494 OpPos: a.pos(e.Pos()),
495 Op: token.AND,
496 X: a.expr(e.X),
497 }
498 }
499 return &ast.UnaryExpr{
500 OpPos: a.pos(e.Pos()),
501 Op: operatorToToken(e.Op),
502 X: a.expr(e.X),
503 }
504 }
505 return &ast.BinaryExpr{
506 X: a.expr(e.X),
507 OpPos: a.pos(e.Pos()),
508 Op: operatorToToken(e.Op),
509 Y: a.expr(e.Y),
510 }
511 }
512
513 func operatorToToken(op Operator) token.Token {
514 switch op {
515 case Add:
516 return token.ADD
517 case Sub:
518 return token.SUB
519 case Mul:
520 return token.MUL
521 case Div:
522 return token.QUO
523 case Rem:
524 return token.REM
525 case And:
526 return token.AND
527 case Or:
528 return token.OR
529 case Xor:
530 return token.XOR
531 case Shl:
532 return token.SHL
533 case Shr:
534 return token.SHR
535 case AndNot:
536 return token.AND_NOT
537 case OrOr:
538 return token.LOR
539 case AndAnd:
540 return token.LAND
541 case Eql:
542 return token.EQL
543 case Neq:
544 return token.NEQ
545 case Lss:
546 return token.LSS
547 case Leq:
548 return token.LEQ
549 case Gtr:
550 return token.GTR
551 case Geq:
552 return token.GEQ
553 case Not:
554 return token.NOT
555 case Recv:
556 return token.ARROW
557 case Tilde:
558 return token.TILDE
559 }
560 return token.ILLEGAL
561 }
562
563 func (a *Adapter) basicLit(lit *BasicLit) *ast.BasicLit {
564 if lit == nil {
565 return nil
566 }
567 var kind token.Token
568 switch lit.Kind {
569 case IntLit:
570 kind = token.INT
571 case FloatLit:
572 kind = token.FLOAT
573 case ImagLit:
574 kind = token.IMAG
575 case RuneLit:
576 kind = token.CHAR
577 case StringLit:
578 kind = token.STRING
579 }
580 return &ast.BasicLit{
581 ValuePos: a.pos(lit.Pos()),
582 Kind: kind,
583 Value: lit.Value,
584 }
585 }
586
587 func (a *Adapter) funcType(ft *FuncType) *ast.FuncType {
588 if ft == nil {
589 return &ast.FuncType{Params: &ast.FieldList{}}
590 }
591 params := a.fieldListFromFields(ft.ParamList)
592 if params == nil {
593 params = &ast.FieldList{}
594 }
595 return &ast.FuncType{
596 Func: a.pos(ft.Pos()),
597 Params: params,
598 Results: a.fieldListFromFields(ft.ResultList),
599 }
600 }
601
602 func (a *Adapter) fieldListFromFields(fields []*Field) *ast.FieldList {
603 if len(fields) == 0 {
604 return nil
605 }
606 fl := &ast.FieldList{}
607 for _, f := range fields {
608 fl.List = append(fl.List, a.field(f))
609 }
610 return fl
611 }
612
613 func (a *Adapter) fieldList(fields []*Field) *ast.FieldList {
614 return a.fieldListFromFields(fields)
615 }
616
617 func (a *Adapter) field(f *Field) *ast.Field {
618 af := &ast.Field{
619 Type: a.expr(f.Type),
620 }
621 if f.Name != nil {
622 af.Names = []*ast.Ident{a.ident(f.Name)}
623 }
624 return af
625 }
626
627 func (a *Adapter) structFieldList(st *StructType) *ast.FieldList {
628 fl := &ast.FieldList{}
629 for i, f := range st.FieldList {
630 af := a.field(f)
631 if i < len(st.TagList) && st.TagList[i] != nil {
632 af.Tag = a.basicLit(st.TagList[i])
633 }
634 fl.List = append(fl.List, af)
635 }
636 return fl
637 }
638
639 func (a *Adapter) blockStmt(b *BlockStmt) *ast.BlockStmt {
640 if b == nil {
641 return nil
642 }
643 bs := &ast.BlockStmt{
644 Lbrace: a.pos(b.Pos()),
645 Rbrace: a.pos(b.Rbrace),
646 }
647 for _, s := range b.List {
648 as := a.stmt(s)
649 if as != nil {
650 bs.List = append(bs.List, as)
651 }
652 }
653 return bs
654 }
655
656 func (a *Adapter) stmt(s Stmt) ast.Stmt {
657 if s == nil {
658 return nil
659 }
660 switch s := s.(type) {
661 case *EmptyStmt:
662 return &ast.EmptyStmt{Semicolon: a.pos(s.Pos())}
663 case *LabeledStmt:
664 return &ast.LabeledStmt{
665 Label: a.ident(s.Label),
666 Colon: a.pos(s.Pos()),
667 Stmt: a.stmt(s.Stmt),
668 }
669 case *BlockStmt:
670 return a.blockStmt(s)
671 case *ExprStmt:
672 return &ast.ExprStmt{X: a.expr(s.X)}
673 case *SendStmt:
674 return &ast.SendStmt{
675 Chan: a.expr(s.Chan),
676 Arrow: a.pos(s.Pos()),
677 Value: a.expr(s.Value),
678 }
679 case *DeclStmt:
680 gd := &ast.GenDecl{TokPos: a.pos(s.Pos()), Tok: token.VAR}
681 for _, d := range s.DeclList {
682 ad := a.decl(d)
683 if gd2, ok := ad.(*ast.GenDecl); ok {
684 gd.Tok = gd2.Tok
685 gd.Specs = append(gd.Specs, gd2.Specs...)
686 }
687 }
688 return &ast.DeclStmt{Decl: gd}
689 case *AssignStmt:
690 if s.Rhs == nil {
691 // increment/decrement
692 tok := token.INC
693 if s.Op == Sub {
694 tok = token.DEC
695 }
696 return &ast.IncDecStmt{
697 X: a.expr(s.Lhs),
698 TokPos: a.pos(s.Pos()),
699 Tok: tok,
700 }
701 }
702 tok := token.ASSIGN
703 if s.Op == Def {
704 tok = token.DEFINE
705 } else if s.Op != 0 {
706 tok = assignOpToToken(s.Op)
707 }
708 return &ast.AssignStmt{
709 Lhs: a.exprList(s.Lhs),
710 Tok: tok,
711 Rhs: a.exprList(s.Rhs),
712 }
713 case *BranchStmt:
714 tok := token.BREAK
715 switch s.Tok {
716 case Continue:
717 tok = token.CONTINUE
718 case Fallthrough:
719 tok = token.FALLTHROUGH
720 case Goto:
721 tok = token.GOTO
722 }
723 return &ast.BranchStmt{
724 TokPos: a.pos(s.Pos()),
725 Tok: tok,
726 Label: a.ident(s.Label),
727 }
728 case *CallStmt:
729 ce := a.expr(s.Call).(*ast.CallExpr)
730 if s.Tok == Defer {
731 return &ast.DeferStmt{
732 Defer: a.pos(s.Pos()),
733 Call: ce,
734 }
735 }
736 return &ast.GoStmt{
737 Go: a.pos(s.Pos()),
738 Call: ce,
739 }
740 case *ReturnStmt:
741 return &ast.ReturnStmt{
742 Return: a.pos(s.Pos()),
743 Results: a.exprList(s.Results),
744 }
745 case *IfStmt:
746 is := &ast.IfStmt{
747 If: a.pos(s.Pos()),
748 Init: a.stmt(s.Init),
749 Cond: a.expr(s.Cond),
750 Body: a.blockStmt(s.Then),
751 Else: a.stmt(s.Else),
752 }
753 return is
754 case *ForStmt:
755 if rc, ok := s.Init.(*RangeClause); ok {
756 rs := &ast.RangeStmt{
757 For: a.pos(s.Pos()),
758 X: a.expr(rc.X),
759 Body: a.blockStmt(s.Body),
760 }
761 if rc.Lhs != nil {
762 lhs := a.exprList(rc.Lhs)
763 if len(lhs) > 0 {
764 rs.Key = lhs[0]
765 }
766 if len(lhs) > 1 {
767 rs.Value = lhs[1]
768 }
769 if rc.Def {
770 rs.Tok = token.DEFINE
771 } else {
772 rs.Tok = token.ASSIGN
773 }
774 }
775 return rs
776 }
777 return &ast.ForStmt{
778 For: a.pos(s.Pos()),
779 Init: a.stmt(s.Init),
780 Cond: a.expr(s.Cond),
781 Post: a.stmt(s.Post),
782 Body: a.blockStmt(s.Body),
783 }
784 case *SwitchStmt:
785 if s.Tag != nil {
786 if _, ok := s.Tag.(*TypeSwitchGuard); ok {
787 return a.typeSwitchStmt(s)
788 }
789 }
790 ss := &ast.SwitchStmt{
791 Switch: a.pos(s.Pos()),
792 Init: a.stmt(s.Init),
793 Tag: a.expr(s.Tag),
794 Body: a.switchBody(s.Body, s.Rbrace),
795 }
796 return ss
797 case *SelectStmt:
798 return &ast.SelectStmt{
799 Select: a.pos(s.Pos()),
800 Body: a.selectBody(s.Body, s.Rbrace),
801 }
802 }
803 return &ast.EmptyStmt{Semicolon: a.pos(s.Pos())}
804 }
805
806 func (a *Adapter) typeSwitchStmt(s *SwitchStmt) *ast.TypeSwitchStmt {
807 tsg := s.Tag.(*TypeSwitchGuard)
808 var assign ast.Stmt
809 ta := &ast.TypeAssertExpr{X: a.expr(tsg.X)}
810 if tsg.Lhs != nil {
811 assign = &ast.AssignStmt{
812 Lhs: []ast.Expr{a.ident(tsg.Lhs)},
813 Tok: token.DEFINE,
814 Rhs: []ast.Expr{ta},
815 }
816 } else {
817 assign = &ast.ExprStmt{X: ta}
818 }
819 return &ast.TypeSwitchStmt{
820 Switch: a.pos(s.Pos()),
821 Init: a.stmt(s.Init),
822 Assign: assign,
823 Body: a.switchBody(s.Body, s.Rbrace),
824 }
825 }
826
827 func (a *Adapter) switchBody(clauses []*CaseClause, rbrace Pos) *ast.BlockStmt {
828 bs := &ast.BlockStmt{Rbrace: a.pos(rbrace)}
829 for _, c := range clauses {
830 cc := &ast.CaseClause{
831 Case: a.pos(c.Pos()),
832 List: a.exprList(c.Cases),
833 Colon: a.pos(c.Colon),
834 }
835 for _, s := range c.Body {
836 as := a.stmt(s)
837 if as != nil {
838 cc.Body = append(cc.Body, as)
839 }
840 }
841 bs.List = append(bs.List, cc)
842 }
843 return bs
844 }
845
846 func (a *Adapter) selectBody(clauses []*CommClause, rbrace Pos) *ast.BlockStmt {
847 bs := &ast.BlockStmt{Rbrace: a.pos(rbrace)}
848 for _, c := range clauses {
849 cc := &ast.CommClause{
850 Case: a.pos(c.Pos()),
851 Comm: a.stmt(c.Comm),
852 Colon: a.pos(c.Colon),
853 }
854 for _, s := range c.Body {
855 as := a.stmt(s)
856 if as != nil {
857 cc.Body = append(cc.Body, as)
858 }
859 }
860 bs.List = append(bs.List, cc)
861 }
862 return bs
863 }
864
865 func assignOpToToken(op Operator) token.Token {
866 switch op {
867 case Add:
868 return token.ADD_ASSIGN
869 case Sub:
870 return token.SUB_ASSIGN
871 case Mul:
872 return token.MUL_ASSIGN
873 case Div:
874 return token.QUO_ASSIGN
875 case Rem:
876 return token.REM_ASSIGN
877 case And:
878 return token.AND_ASSIGN
879 case Or:
880 return token.OR_ASSIGN
881 case Xor:
882 return token.XOR_ASSIGN
883 case Shl:
884 return token.SHL_ASSIGN
885 case Shr:
886 return token.SHR_ASSIGN
887 case AndNot:
888 return token.AND_NOT_ASSIGN
889 }
890 return token.ASSIGN
891 }
892