@@ -10,6 +10,7 @@ import (
10
10
"go/ast"
11
11
"go/parser"
12
12
"go/token"
13
+ "math"
13
14
"strconv"
14
15
)
15
16
@@ -27,8 +28,20 @@ func marshalCorpusFile(vals ...any) []byte {
27
28
// instead of changing to byte and rune respectively.
28
29
for _ , val := range vals {
29
30
switch t := val .(type ) {
30
- case int , int8 , int16 , int64 , uint , uint16 , uint32 , uint64 , float32 , float64 , bool :
31
+ case int , int8 , int16 , int64 , uint , uint16 , uint32 , uint64 , bool :
31
32
fmt .Fprintf (b , "%T(%v)\n " , t , t )
33
+ case float32 :
34
+ if math .IsNaN (float64 (t )) && math .Float32bits (t ) != math .Float32bits (float32 (math .NaN ())) {
35
+ fmt .Fprintf (b , "math.Float32frombits(%v)\n " , math .Float32bits (t ))
36
+ } else {
37
+ fmt .Fprintf (b , "%T(%v)\n " , t , t )
38
+ }
39
+ case float64 :
40
+ if math .IsNaN (t ) && math .Float64bits (t ) != math .Float64bits (math .NaN ()) {
41
+ fmt .Fprintf (b , "math.Float64frombits(%v)\n " , math .Float64bits (t ))
42
+ } else {
43
+ fmt .Fprintf (b , "%T(%v)\n " , t , t )
44
+ }
32
45
case string :
33
46
fmt .Fprintf (b , "string(%q)\n " , t )
34
47
case rune : // int32
@@ -105,44 +118,78 @@ func parseCorpusValue(line []byte) (any, error) {
105
118
return []byte (s ), nil
106
119
}
107
120
108
- idType , ok := call .Fun .(* ast.Ident )
109
- if ! ok {
110
- return nil , fmt .Errorf ("expected []byte or primitive type" )
111
- }
112
- if idType .Name == "bool" {
113
- id , ok := arg .(* ast.Ident )
121
+ var idType * ast.Ident
122
+ if selector , ok := call .Fun .(* ast.SelectorExpr ); ok {
123
+ xIdent , ok := selector .X .(* ast.Ident )
124
+ if ! ok || xIdent .Name != "math" {
125
+ return nil , fmt .Errorf ("invalid selector type" )
126
+ }
127
+ switch selector .Sel .Name {
128
+ case "Float64frombits" :
129
+ idType = & ast.Ident {Name : "float64-bits" }
130
+ case "Float32frombits" :
131
+ idType = & ast.Ident {Name : "float32-bits" }
132
+ default :
133
+ return nil , fmt .Errorf ("invalid selector type" )
134
+ }
135
+ } else {
136
+ idType , ok = call .Fun .(* ast.Ident )
114
137
if ! ok {
115
- return nil , fmt .Errorf ("malformed bool " )
138
+ return nil , fmt .Errorf ("expected []byte or primitive type " )
116
139
}
117
- if id .Name == "true" {
118
- return true , nil
119
- } else if id .Name == "false" {
120
- return false , nil
121
- } else {
122
- return nil , fmt .Errorf ("true or false required for type bool" )
140
+ if idType .Name == "bool" {
141
+ id , ok := arg .(* ast.Ident )
142
+ if ! ok {
143
+ return nil , fmt .Errorf ("malformed bool" )
144
+ }
145
+ if id .Name == "true" {
146
+ return true , nil
147
+ } else if id .Name == "false" {
148
+ return false , nil
149
+ } else {
150
+ return nil , fmt .Errorf ("true or false required for type bool" )
151
+ }
123
152
}
124
153
}
154
+
125
155
var (
126
156
val string
127
157
kind token.Token
128
158
)
129
159
if op , ok := arg .(* ast.UnaryExpr ); ok {
130
- // Special case for negative numbers.
131
- lit , ok := op .X .(* ast.BasicLit )
132
- if ! ok || (lit .Kind != token .INT && lit .Kind != token .FLOAT ) {
160
+ switch lit := op .X .(type ) {
161
+ case * ast.BasicLit :
162
+ if op .Op != token .SUB {
163
+ return nil , fmt .Errorf ("unsupported operation on int/float: %v" , op .Op )
164
+ }
165
+ // Special case for negative numbers.
166
+ val = op .Op .String () + lit .Value // e.g. "-" + "124"
167
+ kind = lit .Kind
168
+ case * ast.Ident :
169
+ if lit .Name != "Inf" {
170
+ return nil , fmt .Errorf ("expected operation on int or float type" )
171
+ }
172
+ if op .Op == token .SUB {
173
+ val = "-Inf"
174
+ } else {
175
+ val = "+Inf"
176
+ }
177
+ kind = token .FLOAT
178
+ default :
133
179
return nil , fmt .Errorf ("expected operation on int or float type" )
134
180
}
135
- if op .Op != token .SUB {
136
- return nil , fmt .Errorf ("unsupported operation on int: %v" , op .Op )
137
- }
138
- val = op .Op .String () + lit .Value // e.g. "-" + "124"
139
- kind = lit .Kind
140
181
} else {
141
- lit , ok := arg .(* ast.BasicLit )
142
- if ! ok {
182
+ switch lit := arg .(type ) {
183
+ case * ast.BasicLit :
184
+ val , kind = lit .Value , lit .Kind
185
+ case * ast.Ident :
186
+ if lit .Name != "NaN" {
187
+ return nil , fmt .Errorf ("literal value required for primitive type" )
188
+ }
189
+ val , kind = "NaN" , token .FLOAT
190
+ default :
143
191
return nil , fmt .Errorf ("literal value required for primitive type" )
144
192
}
145
- val , kind = lit .Value , lit .Kind
146
193
}
147
194
148
195
switch typ := idType .Name ; typ {
@@ -191,6 +238,24 @@ func parseCorpusValue(line []byte) (any, error) {
191
238
return nil , fmt .Errorf ("float or integer literal required for float64 type" )
192
239
}
193
240
return strconv .ParseFloat (val , 64 )
241
+ case "float32-bits" :
242
+ if kind != token .INT {
243
+ return nil , fmt .Errorf ("integer literal required for math.Float32frombits type" )
244
+ }
245
+ bits , err := parseUint (val , "uint32" )
246
+ if err != nil {
247
+ return nil , err
248
+ }
249
+ return math .Float32frombits (bits .(uint32 )), nil
250
+ case "float64-bits" :
251
+ if kind != token .FLOAT && kind != token .INT {
252
+ return nil , fmt .Errorf ("integer literal required for math.Float64frombits type" )
253
+ }
254
+ bits , err := parseUint (val , "uint64" )
255
+ if err != nil {
256
+ return nil , err
257
+ }
258
+ return math .Float64frombits (bits .(uint64 )), nil
194
259
default :
195
260
return nil , fmt .Errorf ("expected []byte or primitive type" )
196
261
}
0 commit comments