1
2
3
4
5 package specdoc
6
7 import (
8 "fmt"
9 "go/ast"
10 "go/token"
11 "strconv"
12
13 "simd/archsimd/_gen/specgen"
14 "simd/archsimd/_gen/specgen/specexpr"
15 )
16
17
18 func fieldListArgs(fl *ast.FieldList) ([]specgen.Arg, error) {
19 if fl == nil {
20 return nil, nil
21 }
22 var args []specgen.Arg
23 for _, f := range fl.List {
24 typ, err := parseTypeExpr(f.Type)
25 if err != nil {
26 return nil, err
27 }
28 if len(f.Names) == 0 {
29 args = append(args, specgen.Arg{Name: "", Type: typ})
30 continue
31 }
32 for _, n := range f.Names {
33 args = append(args, specgen.Arg{Name: n.Name, Type: typ})
34 }
35 }
36 return args, nil
37 }
38
39
40 func parseTypeExpr(expr ast.Expr) (specexpr.Type, error) {
41 switch t := expr.(type) {
42 case *ast.Ident:
43 return specexpr.ParseTypeName(t.Name)
44
45 case *ast.StarExpr:
46 elem, err := parseTypeExpr(t.X)
47 if err != nil {
48 return nil, err
49 }
50 return specexpr.Pointer{Elem: elem}, nil
51
52 case *ast.ArrayType:
53 elem, err := parseTypeExpr(t.Elt)
54 if err != nil {
55 return nil, err
56 }
57 if t.Len == nil {
58 return specexpr.Slice{Elem: elem}, nil
59 }
60 lit, ok := t.Len.(*ast.BasicLit)
61 if !ok || lit.Kind != token.INT {
62 return nil, fmt.Errorf("array bound is not an integer literal: %T", t.Len)
63 }
64 n, err := strconv.Atoi(lit.Value)
65 if err != nil || n < 0 {
66 return nil, fmt.Errorf("invalid array bound %q: %w", lit.Value, err)
67 }
68 return specexpr.Array{Elem: elem, Len: specexpr.Int(n)}, nil
69
70 case *ast.ParenExpr:
71 return parseTypeExpr(t.X)
72
73 default:
74 return nil, fmt.Errorf("unexpected type expression: %T", expr)
75 }
76 }
77
View as plain text