226
226
227
227
rettype (:: Type{T} ) where {T} = T === Number ? Nothing : T
228
228
229
+ # when a function is passed to apply to the parsed value, we have to be really careful that the `x`
230
+ # returned from parsedigits is `Nothing`, otherwise we end up with an overall return type like
231
+ # `Tuple{Union{Nothing, T}, ReturnCode, Int}`, which can cause dynamic dispatches/inlining issues
232
+ # for callers. The rule to follow is that before any call to `@goto done`, we need to ensure `x`
233
+ # has been "handled" properly: either applied or in error cases, set to `nothing`
234
+ getx (x, f) = f === nothing ? x : nothing
235
+
229
236
# if we need to _widen the type due to `digits` overflow, we want a non-inlined version so base case compilation doesn't get out of control
230
237
@noinline _parsedigits (conf:: AbstractConf{T} , source, pos, len, b, code, options, digits:: IntType , neg:: Bool , startpos, overflow_invalid:: Bool , ndigits:: Int , f:: F ) where {T, IntType, F} =
231
238
parsedigits (conf, source, pos, len, b, code, options, digits, neg, startpos, overflow_invalid, ndigits, f):: Tuple{rettype(T), ReturnCode, Int}
@@ -250,7 +257,7 @@ rettype(::Type{T}) where {T} = T === Number ? Nothing : T
250
257
fastseek! (source, startpos - 1 )
251
258
pos = startpos
252
259
code |= INVALID
253
- x = f === nothing ? x : nothing
260
+ x = getx (x, f)
254
261
@goto done
255
262
end
256
263
digits = _muladd (ten (IntType), digits, b)
@@ -271,13 +278,13 @@ rettype(::Type{T}) where {T} = T === Number ? Nothing : T
271
278
@goto done
272
279
end
273
280
elseif has_groupmark && b == groupmark0
274
- prev_b0 == groupmark0 && (code |= INVALID; @goto done) # two groupmarks in a row
281
+ prev_b0 == groupmark0 && (code |= INVALID; x = getx (x, f); @goto done) # two groupmarks in a row
275
282
pos += 1
276
283
Parsers. incr! (source)
277
- Parsers. eof (source, pos, len) && (code |= INVALID | EOF; @goto done) # groupmark at end of input
284
+ Parsers. eof (source, pos, len) && (code |= INVALID | EOF; x = getx (x, f); @goto done) # groupmark at end of input
278
285
else
279
286
# if `b` isn't a digit or a groupmark, time to break out of digit parsing while loop
280
- ((has_groupmark && prev_b0 == groupmark0) || ! anydigits) && (code |= INVALID; @goto done) # ended with groupmark
287
+ ((has_groupmark && prev_b0 == groupmark0) || ! anydigits) && (code |= INVALID; x = getx (x, f); @goto done) # ended with groupmark
281
288
break
282
289
end
283
290
prev_b0 = b
@@ -306,7 +313,7 @@ rettype(::Type{T}) where {T} = T === Number ? Nothing : T
306
313
# otherwise ok, like "1.a" (only "1." is parsed)
307
314
if ! anydigits
308
315
code |= INVALID
309
- x = f === nothing ? x : nothing
316
+ x = getx (x, f)
310
317
@goto done
311
318
else
312
319
if T === Number
356
363
# input is simple non-scientific-notation floating number, like "1.1"
357
364
if overflow_invalid && - signed (frac) > 308
358
365
code |= INVALID
359
- x = f === nothing ? x : nothing
366
+ x = getx (x, f)
360
367
else
361
368
x, code = scale (conf, FT, digits, - signed (frac), neg, code, ndigits, f, options)
362
369
code |= OK | EOF
381
388
if eof (source, pos, len)
382
389
# it's an error to have a "dangling" 'e', so input was something like "1.1e"
383
390
code |= INVALID | EOF
384
- x = f === nothing ? x : nothing
391
+ x = getx (x, f)
385
392
@goto done
386
393
end
387
394
b = peekbyte (source, pos)
393
400
if eof (source, pos, len)
394
401
# it's an error to have a "dangling" '-' or '+', so input was something like "1.1e-"
395
402
code |= INVALID | EOF
396
- x = f === nothing ? x : nothing
403
+ x = getx (x, f)
397
404
@goto done
398
405
end
399
406
b = peekbyte (source, pos)
402
409
if b > 0x09
403
410
# invalid to have a "dangling" 'e'
404
411
code |= INVALID
405
- x = f === nothing ? x : nothing
412
+ x = getx (x, f)
406
413
@goto done
407
414
end
408
415
414
421
if parsedanyfrac
415
422
if overflow_invalid && - signed (frac) > 308
416
423
code |= INVALID
417
- x = f === nothing ? x : nothing
424
+ x = getx (x, f)
418
425
@goto done
419
426
else
420
427
x, code = scale (conf, FT, digits, - signed (frac), neg, code, ndigits, f, options)
446
453
ee = ifelse (negexp, - signed (exp), signed (exp)) - signed (frac)
447
454
if overflow_invalid && ee > 308
448
455
code |= INVALID
449
- x = f === nothing ? x : nothing
456
+ x = getx (x, f)
450
457
else
451
458
x, code = scale (conf, FT, digits, ee, neg, code, ndigits, f, options)
452
459
code |= OK | EOF
459
466
ee = ifelse (negexp, - signed (exp), signed (exp)) - signed (frac)
460
467
if overflow_invalid && ee > 308
461
468
code |= INVALID
462
- x = f === nothing ? x : nothing
469
+ x = getx (x, f)
463
470
else
464
471
x, code = scale (conf, FT, digits, ifelse (negexp, - signed (exp), signed (exp)) - signed (frac), neg, code, ndigits, f, options)
465
472
code |= OK
0 commit comments