parseBiggestFloat is now builtin
This commit is contained in:
parent
396b5619fc
commit
a7911addf7
10 changed files with 309 additions and 95 deletions
|
|
@ -553,7 +553,7 @@ type
|
||||||
mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq,
|
mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq,
|
||||||
mIsPartOf, mAstToStr, mParallel,
|
mIsPartOf, mAstToStr, mParallel,
|
||||||
mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast,
|
mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast,
|
||||||
mNewString, mNewStringOfCap,
|
mNewString, mNewStringOfCap, mParseBiggestFloat,
|
||||||
mReset,
|
mReset,
|
||||||
mArray, mOpenArray, mRange, mSet, mSeq, mVarargs,
|
mArray, mOpenArray, mRange, mSet, mSeq, mVarargs,
|
||||||
mOrdinal,
|
mOrdinal,
|
||||||
|
|
|
||||||
|
|
@ -1640,7 +1640,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
|
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
|
||||||
mInSet:
|
mInSet:
|
||||||
genSetOp(p, e, d, op)
|
genSetOp(p, e, d, op)
|
||||||
of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit:
|
of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit,
|
||||||
|
mParseBiggestFloat:
|
||||||
var opr = e.sons[0].sym
|
var opr = e.sons[0].sym
|
||||||
if lfNoDecl notin opr.loc.flags:
|
if lfNoDecl notin opr.loc.flags:
|
||||||
discard cgsym(p.module, opr.loc.r.ropeToStr)
|
discard cgsym(p.module, opr.loc.r.ropeToStr)
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ proc initDefines*() =
|
||||||
defineSymbol("nimunion")
|
defineSymbol("nimunion")
|
||||||
defineSymbol("nimnewshared")
|
defineSymbol("nimnewshared")
|
||||||
defineSymbol("nimrequiresnimframe")
|
defineSymbol("nimrequiresnimframe")
|
||||||
|
defineSymbol("nimparsebiggestfloatmagic")
|
||||||
|
|
||||||
# add platform specific symbols:
|
# add platform specific symbols:
|
||||||
case targetCPU
|
case targetCPU
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import ast except getstr
|
||||||
|
|
||||||
import
|
import
|
||||||
strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
|
strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
|
||||||
parser, vmdeps, idents, trees, renderer, options, transf
|
parser, vmdeps, idents, trees, renderer, options, transf, parseutils
|
||||||
|
|
||||||
from semfold import leValueConv, ordinalValToString
|
from semfold import leValueConv, ordinalValToString
|
||||||
from evaltempl import evalTemplate
|
from evaltempl import evalTemplate
|
||||||
|
|
@ -776,6 +776,18 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
createStr regs[ra]
|
createStr regs[ra]
|
||||||
regs[ra].node.strVal = substr(regs[rb].node.strVal,
|
regs[ra].node.strVal = substr(regs[rb].node.strVal,
|
||||||
regs[rc].intVal.int, regs[rd].intVal.int)
|
regs[rc].intVal.int, regs[rd].intVal.int)
|
||||||
|
of opcParseFloat:
|
||||||
|
decodeBC(rkInt)
|
||||||
|
inc pc
|
||||||
|
assert c.code[pc].opcode == opcParseFloat
|
||||||
|
let rd = c.code[pc].regA
|
||||||
|
var rcAddr = addr(regs[rc])
|
||||||
|
if rcAddr.kind == rkRegisterAddr: rcAddr = rcAddr.regAddr
|
||||||
|
elif regs[rc].kind != rkFloat:
|
||||||
|
myreset(regs[rc])
|
||||||
|
regs[rc].kind = rkFloat
|
||||||
|
regs[ra].intVal = parseBiggestFloat(regs[rb].node.strVal,
|
||||||
|
rcAddr.floatVal, regs[rd].intVal.int)
|
||||||
of opcRangeChck:
|
of opcRangeChck:
|
||||||
let rb = instr.regB
|
let rb = instr.regB
|
||||||
let rc = instr.regC
|
let rc = instr.regC
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ type
|
||||||
opcMulSet, opcPlusSet, opcMinusSet, opcSymdiffSet, opcConcatStr,
|
opcMulSet, opcPlusSet, opcMinusSet, opcSymdiffSet, opcConcatStr,
|
||||||
opcContainsSet, opcRepr, opcSetLenStr, opcSetLenSeq,
|
opcContainsSet, opcRepr, opcSetLenStr, opcSetLenSeq,
|
||||||
opcSwap, opcIsNil, opcOf, opcIs,
|
opcSwap, opcIsNil, opcOf, opcIs,
|
||||||
opcSubStr, opcConv, opcCast, opcQuit, opcReset,
|
opcSubStr, opcParseFloat, opcConv, opcCast, opcQuit, opcReset,
|
||||||
opcNarrowS, opcNarrowU,
|
opcNarrowS, opcNarrowU,
|
||||||
|
|
||||||
opcAddStrCh,
|
opcAddStrCh,
|
||||||
|
|
|
||||||
|
|
@ -852,6 +852,24 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
c.freeTemp(tmp1)
|
c.freeTemp(tmp1)
|
||||||
c.freeTemp(tmp2)
|
c.freeTemp(tmp2)
|
||||||
c.freeTemp(tmp3)
|
c.freeTemp(tmp3)
|
||||||
|
of mParseBiggestFloat:
|
||||||
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
|
var d2: TRegister
|
||||||
|
# skip 'nkHiddenAddr':
|
||||||
|
let d2AsNode = n.sons[2].sons[0]
|
||||||
|
if needsAsgnPatch(d2AsNode):
|
||||||
|
d2 = c.getTemp(getSysType(tyFloat))
|
||||||
|
else:
|
||||||
|
d2 = c.genx(d2AsNode)
|
||||||
|
var
|
||||||
|
tmp1 = c.genx(n.sons[1])
|
||||||
|
tmp3 = c.genx(n.sons[3])
|
||||||
|
c.gABC(n, opcParseFloat, dest, tmp1, d2)
|
||||||
|
c.gABC(n, opcParseFloat, tmp3)
|
||||||
|
c.freeTemp(tmp1)
|
||||||
|
c.freeTemp(tmp3)
|
||||||
|
c.genAsgnPatch(d2AsNode, d2)
|
||||||
|
c.freeTemp(d2)
|
||||||
of mReset:
|
of mReset:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
var d = c.genx(n.sons[1])
|
var d = c.genx(n.sons[1])
|
||||||
|
|
|
||||||
|
|
@ -231,94 +231,96 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
|
||||||
else:
|
else:
|
||||||
number = int(res)
|
number = int(res)
|
||||||
|
|
||||||
proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
|
when defined(nimParseBiggestFloatMagic):
|
||||||
rtl, extern: "npuParseBiggestFloat", noSideEffect.} =
|
proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
|
||||||
## parses a float starting at `start` and stores the value into `number`.
|
magic: "ParseBiggestFloat", importc: "nimParseBiggestFloat", noSideEffect.}
|
||||||
## Result is the number of processed chars or 0 if a parsing error
|
## parses a float starting at `start` and stores the value into `number`.
|
||||||
## occurred.
|
## Result is the number of processed chars or 0 if a parsing error
|
||||||
|
## occurred.
|
||||||
|
else:
|
||||||
|
proc tenToThePowerOf(b: int): BiggestFloat =
|
||||||
|
var b = b
|
||||||
|
var a = 10.0
|
||||||
|
result = 1.0
|
||||||
|
while true:
|
||||||
|
if (b and 1) == 1:
|
||||||
|
result *= a
|
||||||
|
b = b shr 1
|
||||||
|
if b == 0: break
|
||||||
|
a *= a
|
||||||
|
|
||||||
type struct_lconv {.importc: "struct lconv",header:"<locale.h>".} =
|
proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
|
||||||
object
|
rtl, extern: "npuParseBiggestFloat", noSideEffect.} =
|
||||||
# Unneeded fields have been omitted.
|
## parses a float starting at `start` and stores the value into `number`.
|
||||||
decimal_point: cstring
|
## Result is the number of processed chars or 0 if there occured a parsing
|
||||||
|
## error.
|
||||||
proc localeconv(): ptr struct_lconv {.importc, header: "<locale.h>",
|
var
|
||||||
noSideEffect.}
|
esign = 1.0
|
||||||
|
sign = 1.0
|
||||||
proc strtod(buf: cstring, endptr: ptr cstring): float64 {.importc,
|
i = start
|
||||||
header: "<stdlib.h>", noSideEffect.}
|
exponent: int
|
||||||
|
flags: int
|
||||||
# This routine leverages `strtod()` for the non-trivial task of
|
number = 0.0
|
||||||
# parsing floating point numbers correctly. Because `strtod()` is
|
if s[i] == '+': inc(i)
|
||||||
# locale-dependent with respect to the radix character, we create
|
elif s[i] == '-':
|
||||||
# a copy where the decimal point is replaced with the locale's
|
|
||||||
# radix character.
|
|
||||||
|
|
||||||
var
|
|
||||||
i = start
|
|
||||||
sign = 1.0
|
|
||||||
t = ""
|
|
||||||
hasdigits = false
|
|
||||||
|
|
||||||
# Sign?
|
|
||||||
if s[i] == '+' or s[i] == '-':
|
|
||||||
if s[i] == '-':
|
|
||||||
sign = -1.0
|
sign = -1.0
|
||||||
add(t, s[i])
|
|
||||||
inc(i)
|
|
||||||
|
|
||||||
# NaN?
|
|
||||||
if s[i] == 'N' or s[i] == 'n':
|
|
||||||
if s[i+1] == 'A' or s[i+1] == 'a':
|
|
||||||
if s[i+2] == 'N' or s[i+2] == 'n':
|
|
||||||
if s[i+3] notin IdentChars:
|
|
||||||
number = NaN
|
|
||||||
return i+3 - start
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# Inf?
|
|
||||||
if s[i] == 'I' or s[i] == 'i':
|
|
||||||
if s[i+1] == 'N' or s[i+1] == 'n':
|
|
||||||
if s[i+2] == 'F' or s[i+2] == 'f':
|
|
||||||
if s[i+3] notin IdentChars:
|
|
||||||
number = Inf*sign
|
|
||||||
return i+3 - start
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# Integer part?
|
|
||||||
while s[i] in {'0'..'9'}:
|
|
||||||
hasdigits = true
|
|
||||||
add(t, s[i])
|
|
||||||
inc(i)
|
|
||||||
while s[i] == '_': inc(i)
|
|
||||||
|
|
||||||
# Fractional part?
|
|
||||||
if s[i] == '.':
|
|
||||||
add(t, localeconv().decimal_point)
|
|
||||||
inc(i)
|
|
||||||
while s[i] in {'0'..'9'}:
|
|
||||||
hasdigits = true
|
|
||||||
add(t, s[i])
|
|
||||||
inc(i)
|
inc(i)
|
||||||
while s[i] == '_': inc(i)
|
if s[i] == 'N' or s[i] == 'n':
|
||||||
if not hasdigits:
|
if s[i+1] == 'A' or s[i+1] == 'a':
|
||||||
return 0
|
if s[i+2] == 'N' or s[i+2] == 'n':
|
||||||
|
if s[i+3] notin IdentChars:
|
||||||
# Exponent?
|
number = NaN
|
||||||
if s[i] in {'e', 'E'}:
|
return i+3 - start
|
||||||
add(t, s[i])
|
return 0
|
||||||
inc(i)
|
if s[i] == 'I' or s[i] == 'i':
|
||||||
if s[i] in {'+', '-'}:
|
if s[i+1] == 'N' or s[i+1] == 'n':
|
||||||
add(t, s[i])
|
if s[i+2] == 'F' or s[i+2] == 'f':
|
||||||
inc(i)
|
if s[i+3] notin IdentChars:
|
||||||
if s[i] notin {'0'..'9'}:
|
number = Inf*sign
|
||||||
|
return i+3 - start
|
||||||
return 0
|
return 0
|
||||||
while s[i] in {'0'..'9'}:
|
while s[i] in {'0'..'9'}:
|
||||||
add(t, s[i])
|
# Read integer part
|
||||||
|
flags = flags or 1
|
||||||
|
number = number * 10.0 + toFloat(ord(s[i]) - ord('0'))
|
||||||
inc(i)
|
inc(i)
|
||||||
while s[i] == '_': inc(i)
|
while s[i] == '_': inc(i)
|
||||||
number = strtod(t, nil)
|
# Decimal?
|
||||||
result = i - start
|
if s[i] == '.':
|
||||||
|
var hd = 1.0
|
||||||
|
inc(i)
|
||||||
|
while s[i] in {'0'..'9'}:
|
||||||
|
# Read fractional part
|
||||||
|
flags = flags or 2
|
||||||
|
number = number * 10.0 + toFloat(ord(s[i]) - ord('0'))
|
||||||
|
hd = hd * 10.0
|
||||||
|
inc(i)
|
||||||
|
while s[i] == '_': inc(i)
|
||||||
|
number = number / hd # this complicated way preserves precision
|
||||||
|
# Again, read integer and fractional part
|
||||||
|
if flags == 0: return 0
|
||||||
|
# Exponent?
|
||||||
|
if s[i] in {'e', 'E'}:
|
||||||
|
inc(i)
|
||||||
|
if s[i] == '+':
|
||||||
|
inc(i)
|
||||||
|
elif s[i] == '-':
|
||||||
|
esign = -1.0
|
||||||
|
inc(i)
|
||||||
|
if s[i] notin {'0'..'9'}:
|
||||||
|
return 0
|
||||||
|
while s[i] in {'0'..'9'}:
|
||||||
|
exponent = exponent * 10 + ord(s[i]) - ord('0')
|
||||||
|
inc(i)
|
||||||
|
while s[i] == '_': inc(i)
|
||||||
|
# Calculate Exponent
|
||||||
|
let hd = tenToThePowerOf(exponent)
|
||||||
|
if esign > 0.0: number = number * hd
|
||||||
|
else: number = number / hd
|
||||||
|
# evaluate sign
|
||||||
|
number = number * sign
|
||||||
|
result = i - start
|
||||||
|
|
||||||
|
|
||||||
proc parseFloat*(s: string, number: var float, start = 0): int {.
|
proc parseFloat*(s: string, number: var float, start = 0): int {.
|
||||||
rtl, extern: "npuParseFloat", noSideEffect.} =
|
rtl, extern: "npuParseFloat", noSideEffect.} =
|
||||||
|
|
|
||||||
|
|
@ -106,13 +106,10 @@ proc c_fopen(filename, mode: cstring): C_TextFileStar {.
|
||||||
importc: "fopen", header: "<stdio.h>".}
|
importc: "fopen", header: "<stdio.h>".}
|
||||||
proc c_fclose(f: C_TextFileStar) {.importc: "fclose", header: "<stdio.h>".}
|
proc c_fclose(f: C_TextFileStar) {.importc: "fclose", header: "<stdio.h>".}
|
||||||
|
|
||||||
proc c_sprintf(buf, frmt: cstring): int {.header: "<stdio.h>",
|
proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>",
|
||||||
importc: "sprintf", varargs, noSideEffect.}
|
importc: "sprintf", varargs, noSideEffect.}
|
||||||
# we use it only in a way that cannot lead to security issues
|
# we use it only in a way that cannot lead to security issues
|
||||||
|
|
||||||
proc c_localeconv():ptr cstring {.header: "<locale.h>",
|
|
||||||
importc: "localeconv", noSideEffect.}
|
|
||||||
|
|
||||||
proc c_fread(buf: pointer, size, n: int, f: C_BinaryFileStar): int {.
|
proc c_fread(buf: pointer, size, n: int, f: C_BinaryFileStar): int {.
|
||||||
importc: "fread", header: "<stdio.h>".}
|
importc: "fread", header: "<stdio.h>".}
|
||||||
proc c_fseek(f: C_BinaryFileStar, offset: clong, whence: int): int {.
|
proc c_fseek(f: C_BinaryFileStar, offset: clong, whence: int): int {.
|
||||||
|
|
|
||||||
|
|
@ -639,3 +639,87 @@ proc addChar(x: string, c: char) {.compilerproc, asmNoStackFrame.} =
|
||||||
"""
|
"""
|
||||||
|
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
|
proc tenToThePowerOf(b: int): BiggestFloat =
|
||||||
|
var b = b
|
||||||
|
var a = 10.0
|
||||||
|
result = 1.0
|
||||||
|
while true:
|
||||||
|
if (b and 1) == 1:
|
||||||
|
result *= a
|
||||||
|
b = b shr 1
|
||||||
|
if b == 0: break
|
||||||
|
a *= a
|
||||||
|
|
||||||
|
const
|
||||||
|
IdentChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'}
|
||||||
|
|
||||||
|
# XXX use JS's native way here
|
||||||
|
proc nimParseBiggestFloat(s: string, number: var BiggestFloat, start = 0): int {.
|
||||||
|
compilerProc.} =
|
||||||
|
var
|
||||||
|
esign = 1.0
|
||||||
|
sign = 1.0
|
||||||
|
i = start
|
||||||
|
exponent: int
|
||||||
|
flags: int
|
||||||
|
number = 0.0
|
||||||
|
if s[i] == '+': inc(i)
|
||||||
|
elif s[i] == '-':
|
||||||
|
sign = -1.0
|
||||||
|
inc(i)
|
||||||
|
if s[i] == 'N' or s[i] == 'n':
|
||||||
|
if s[i+1] == 'A' or s[i+1] == 'a':
|
||||||
|
if s[i+2] == 'N' or s[i+2] == 'n':
|
||||||
|
if s[i+3] notin IdentChars:
|
||||||
|
number = NaN
|
||||||
|
return i+3 - start
|
||||||
|
return 0
|
||||||
|
if s[i] == 'I' or s[i] == 'i':
|
||||||
|
if s[i+1] == 'N' or s[i+1] == 'n':
|
||||||
|
if s[i+2] == 'F' or s[i+2] == 'f':
|
||||||
|
if s[i+3] notin IdentChars:
|
||||||
|
number = Inf*sign
|
||||||
|
return i+3 - start
|
||||||
|
return 0
|
||||||
|
while s[i] in {'0'..'9'}:
|
||||||
|
# Read integer part
|
||||||
|
flags = flags or 1
|
||||||
|
number = number * 10.0 + toFloat(ord(s[i]) - ord('0'))
|
||||||
|
inc(i)
|
||||||
|
while s[i] == '_': inc(i)
|
||||||
|
# Decimal?
|
||||||
|
if s[i] == '.':
|
||||||
|
var hd = 1.0
|
||||||
|
inc(i)
|
||||||
|
while s[i] in {'0'..'9'}:
|
||||||
|
# Read fractional part
|
||||||
|
flags = flags or 2
|
||||||
|
number = number * 10.0 + toFloat(ord(s[i]) - ord('0'))
|
||||||
|
hd = hd * 10.0
|
||||||
|
inc(i)
|
||||||
|
while s[i] == '_': inc(i)
|
||||||
|
number = number / hd # this complicated way preserves precision
|
||||||
|
# Again, read integer and fractional part
|
||||||
|
if flags == 0: return 0
|
||||||
|
# Exponent?
|
||||||
|
if s[i] in {'e', 'E'}:
|
||||||
|
inc(i)
|
||||||
|
if s[i] == '+':
|
||||||
|
inc(i)
|
||||||
|
elif s[i] == '-':
|
||||||
|
esign = -1.0
|
||||||
|
inc(i)
|
||||||
|
if s[i] notin {'0'..'9'}:
|
||||||
|
return 0
|
||||||
|
while s[i] in {'0'..'9'}:
|
||||||
|
exponent = exponent * 10 + ord(s[i]) - ord('0')
|
||||||
|
inc(i)
|
||||||
|
while s[i] == '_': inc(i)
|
||||||
|
# Calculate Exponent
|
||||||
|
let hd = tenToThePowerOf(exponent)
|
||||||
|
if esign > 0.0: number = number * hd
|
||||||
|
else: number = number / hd
|
||||||
|
# evaluate sign
|
||||||
|
number = number * sign
|
||||||
|
result = i - start
|
||||||
|
|
|
||||||
|
|
@ -252,15 +252,114 @@ proc nimIntToStr(x: int): string {.compilerRtl.} =
|
||||||
|
|
||||||
proc nimFloatToStr(f: float): string {.compilerproc.} =
|
proc nimFloatToStr(f: float): string {.compilerproc.} =
|
||||||
var buf: array [0..64, char]
|
var buf: array [0..64, char]
|
||||||
var n:int = c_sprintf(buf, "%.16g", f)
|
var n: int = c_sprintf(buf, "%.16g", f)
|
||||||
|
var hasDot = false
|
||||||
for i in 0..n-1:
|
for i in 0..n-1:
|
||||||
if buf[i] notin {'0'..'9','-'}:
|
if buf[i] == ',':
|
||||||
return $buf
|
buf[i] = '.'
|
||||||
buf[n] = c_localeconv()[0]
|
hasDot = true
|
||||||
buf[n+1] = '0'
|
elif buf[i] in {'e', 'E', '.'}:
|
||||||
buf[n+2] = '\0'
|
hasDot = true
|
||||||
|
if not hasDot:
|
||||||
|
buf[n] = '.'
|
||||||
|
buf[n+1] = '0'
|
||||||
|
buf[n+2] = '\0'
|
||||||
result = $buf
|
result = $buf
|
||||||
|
|
||||||
|
proc strtod(buf: cstring, endptr: ptr cstring): float64 {.importc,
|
||||||
|
header: "<stdlib.h>", noSideEffect.}
|
||||||
|
|
||||||
|
var decimalPoint: char
|
||||||
|
|
||||||
|
proc getDecimalPoint(): char =
|
||||||
|
result = decimalPoint
|
||||||
|
if result == '\0':
|
||||||
|
if strtod("0,5", nil) == 0.5: result = ','
|
||||||
|
else: result = '.'
|
||||||
|
# yes this is threadsafe in practice, spare me:
|
||||||
|
decimalPoint = result
|
||||||
|
|
||||||
|
const
|
||||||
|
IdentChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'}
|
||||||
|
|
||||||
|
proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
|
||||||
|
start = 0): int {.compilerProc.} =
|
||||||
|
# This routine leverages `strtod()` for the non-trivial task of
|
||||||
|
# parsing floating point numbers correctly. Because `strtod()` is
|
||||||
|
# locale-dependent with respect to the radix character, we create
|
||||||
|
# a copy where the decimal point is replaced with the locale's
|
||||||
|
# radix character.
|
||||||
|
var
|
||||||
|
i = start
|
||||||
|
sign = 1.0
|
||||||
|
t: array[128, char]
|
||||||
|
ti = 0
|
||||||
|
hasdigits = false
|
||||||
|
|
||||||
|
template addToBuf(c) =
|
||||||
|
if ti < t.high:
|
||||||
|
t[ti] = c; inc(ti)
|
||||||
|
|
||||||
|
# Sign?
|
||||||
|
if s[i] == '+' or s[i] == '-':
|
||||||
|
if s[i] == '-':
|
||||||
|
sign = -1.0
|
||||||
|
t[ti] = s[i]
|
||||||
|
inc(i); inc(ti)
|
||||||
|
|
||||||
|
# NaN?
|
||||||
|
if s[i] == 'N' or s[i] == 'n':
|
||||||
|
if s[i+1] == 'A' or s[i+1] == 'a':
|
||||||
|
if s[i+2] == 'N' or s[i+2] == 'n':
|
||||||
|
if s[i+3] notin IdentChars:
|
||||||
|
number = NaN
|
||||||
|
return i+3 - start
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Inf?
|
||||||
|
if s[i] == 'I' or s[i] == 'i':
|
||||||
|
if s[i+1] == 'N' or s[i+1] == 'n':
|
||||||
|
if s[i+2] == 'F' or s[i+2] == 'f':
|
||||||
|
if s[i+3] notin IdentChars:
|
||||||
|
number = Inf*sign
|
||||||
|
return i+3 - start
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Integer part?
|
||||||
|
while s[i] in {'0'..'9'}:
|
||||||
|
hasdigits = true
|
||||||
|
addToBuf(s[i])
|
||||||
|
inc(i);
|
||||||
|
while s[i] == '_': inc(i)
|
||||||
|
|
||||||
|
# Fractional part?
|
||||||
|
if s[i] == '.':
|
||||||
|
addToBuf(getDecimalPoint())
|
||||||
|
inc(i)
|
||||||
|
while s[i] in {'0'..'9'}:
|
||||||
|
hasdigits = true
|
||||||
|
addToBuf(s[i])
|
||||||
|
inc(i)
|
||||||
|
while s[i] == '_': inc(i)
|
||||||
|
if not hasdigits:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Exponent?
|
||||||
|
if s[i] in {'e', 'E'}:
|
||||||
|
addToBuf(s[i])
|
||||||
|
inc(i)
|
||||||
|
if s[i] in {'+', '-'}:
|
||||||
|
addToBuf(s[i])
|
||||||
|
inc(i)
|
||||||
|
if s[i] notin {'0'..'9'}:
|
||||||
|
return 0
|
||||||
|
while s[i] in {'0'..'9'}:
|
||||||
|
addToBuf(s[i])
|
||||||
|
inc(i)
|
||||||
|
while s[i] == '_': inc(i)
|
||||||
|
number = strtod(t, nil)
|
||||||
|
result = i - start
|
||||||
|
|
||||||
proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
|
proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
|
||||||
result = newString(sizeof(x)*4)
|
result = newString(sizeof(x)*4)
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue