mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-13 07:03:45 +00:00
@@ -20,9 +20,6 @@ import strutils except addf
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
when not defined(nimHasCursor):
|
||||
{.pragma: cursor.}
|
||||
|
||||
proc hashNode*(p: RootRef): Hash
|
||||
proc treeToYaml*(conf: ConfigRef; n: PNode, indent: int = 0, maxRecDepth: int = - 1): Rope
|
||||
# Convert a tree into its YAML representation; this is used by the
|
||||
|
||||
@@ -1929,8 +1929,6 @@ template injectG() {.dirty.} =
|
||||
graph.backend = newModuleList(graph)
|
||||
let g = BModuleList(graph.backend)
|
||||
|
||||
when not defined(nimHasSinkInference):
|
||||
{.pragma: nosinks.}
|
||||
|
||||
proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} =
|
||||
injectG()
|
||||
|
||||
@@ -84,10 +84,24 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
defineSymbol("nimHasSignatureHashInMacro") # deadcode
|
||||
defineSymbol("nimHasDefault") # deadcode
|
||||
defineSymbol("nimMacrosSizealignof") # deadcode
|
||||
defineSymbol("nimNoZeroExtendMagic") # deadcode
|
||||
defineSymbol("nimMacrosGetNodeId") # deadcode
|
||||
defineSymbol("nimFixedForwardGeneric") # deadcode
|
||||
defineSymbol("nimToOpenArrayCString") # deadcode
|
||||
defineSymbol("nimHasUsed") # deadcode
|
||||
defineSymbol("nimnomagic64") # deadcode
|
||||
defineSymbol("nimNewShiftOps") # deadcode
|
||||
defineSymbol("nimHasCursor") # deadcode
|
||||
defineSymbol("nimAlignPragma") # deadcode
|
||||
defineSymbol("nimHasExceptionsQuery") # deadcode
|
||||
defineSymbol("nimHasIsNamedTuple") # deadcode
|
||||
defineSymbol("nimHashOrdinalFixed") # deadcode
|
||||
defineSymbol("nimHasSinkInference") # deadcode
|
||||
defineSymbol("nimNewIntegerOps") # deadcode
|
||||
defineSymbol("nimHasInvariant") # deadcode
|
||||
|
||||
|
||||
|
||||
# > 0.20.0
|
||||
defineSymbol("nimNoZeroExtendMagic")
|
||||
defineSymbol("nimMacrosGetNodeId")
|
||||
for f in Feature:
|
||||
defineSymbol("nimHas" & $f)
|
||||
|
||||
@@ -98,31 +112,18 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
|
||||
defineSymbol("nimFixedOwned")
|
||||
defineSymbol("nimHasStyleChecks")
|
||||
defineSymbol("nimToOpenArrayCString")
|
||||
defineSymbol("nimHasUsed")
|
||||
defineSymbol("nimFixedForwardGeneric")
|
||||
defineSymbol("nimnomagic64")
|
||||
defineSymbol("nimNewShiftOps")
|
||||
defineSymbol("nimHasCursor")
|
||||
defineSymbol("nimAlignPragma")
|
||||
defineSymbol("nimHasExceptionsQuery")
|
||||
defineSymbol("nimHasIsNamedTuple")
|
||||
defineSymbol("nimHashOrdinalFixed")
|
||||
|
||||
when defined(nimHasLibFFI):
|
||||
# Renaming as we can't conflate input vs output define flags; e.g. this
|
||||
# will report the right thing regardless of whether user adds
|
||||
# `-d:nimHasLibFFI` in his user config.
|
||||
defineSymbol("nimHasLibFFIEnabled")
|
||||
defineSymbol("nimHasLibFFIEnabled") # deadcode
|
||||
|
||||
defineSymbol("nimHasSinkInference")
|
||||
defineSymbol("nimNewIntegerOps")
|
||||
defineSymbol("nimHasInvariant")
|
||||
defineSymbol("nimHasStacktraceMsgs")
|
||||
defineSymbol("nimHasStacktraceMsgs") # deadcode
|
||||
defineSymbol("nimDoesntTrackDefects")
|
||||
defineSymbol("nimHasLentIterators")
|
||||
defineSymbol("nimHasDeclaredMagic")
|
||||
defineSymbol("nimHasStacktracesModule")
|
||||
defineSymbol("nimHasLentIterators") # deadcode
|
||||
defineSymbol("nimHasDeclaredMagic") # deadcode
|
||||
defineSymbol("nimHasStacktracesModule") # deadcode
|
||||
defineSymbol("nimHasEffectTraitsModule")
|
||||
defineSymbol("nimHasCastPragmaBlocks")
|
||||
defineSymbol("nimHasDeclaredLocs")
|
||||
@@ -133,8 +134,8 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
defineSymbol("nimHasCustomLiterals")
|
||||
defineSymbol("nimHasUnifiedTuple")
|
||||
defineSymbol("nimHasIterable")
|
||||
defineSymbol("nimHasTypeofVoid")
|
||||
defineSymbol("nimHasDragonBox")
|
||||
defineSymbol("nimHasTypeofVoid") # deadcode
|
||||
defineSymbol("nimHasDragonBox") # deadcode
|
||||
defineSymbol("nimHasHintAll")
|
||||
defineSymbol("nimHasTrace")
|
||||
defineSymbol("nimHasEffectsOf")
|
||||
|
||||
@@ -100,9 +100,6 @@ proc generateDot*(graph: ModuleGraph; project: AbsoluteFile) =
|
||||
rope(project.splitFile.name), b.dotGraph],
|
||||
changeFileExt(project, "dot"))
|
||||
|
||||
when not defined(nimHasSinkInference):
|
||||
{.pragma: nosinks.}
|
||||
|
||||
proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} =
|
||||
var g: PGen
|
||||
new(g)
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
|
||||
# This module implements the renderer of the standard Nim representation.
|
||||
|
||||
when defined(nimHasUsed):
|
||||
# 'import renderer' is so useful for debugging
|
||||
# that Nim shouldn't produce a warning for that:
|
||||
{.used.}
|
||||
# 'import renderer' is so useful for debugging
|
||||
# that Nim shouldn't produce a warning for that:
|
||||
{.used.}
|
||||
|
||||
import
|
||||
lexer, options, idents, strutils, ast, msgs, lineinfos
|
||||
|
||||
@@ -405,9 +405,6 @@ proc semExprFlagDispatched(c: PContext, n: PNode, flags: TExprFlags; expectedTyp
|
||||
evaluated = evalAtCompileTime(c, result)
|
||||
if evaluated != nil: return evaluated
|
||||
|
||||
when not defined(nimHasSinkInference):
|
||||
{.pragma: nosinks.}
|
||||
|
||||
include hlo, seminst, semcall
|
||||
|
||||
proc resetSemFlag(n: PNode) =
|
||||
|
||||
@@ -2661,8 +2661,6 @@ proc argtypeMatches*(c: PContext, f, a: PType, fromHlo = false): bool =
|
||||
# pattern templates do not allow for conversions except from int literal
|
||||
res != nil and m.convMatches == 0 and m.intConvMatches in [0, 256]
|
||||
|
||||
when not defined(nimHasSinkInference):
|
||||
{.pragma: nosinks.}
|
||||
|
||||
proc instTypeBoundOp*(c: PContext; dc: PSym; t: PType; info: TLineInfo;
|
||||
op: TTypeAttachedOp; col: int): PSym {.nosinks.} =
|
||||
|
||||
@@ -32,8 +32,6 @@ const
|
||||
when hasFFI:
|
||||
import evalffi
|
||||
|
||||
when not defined(nimHasCursor):
|
||||
{.pragma: cursor.}
|
||||
|
||||
proc stackTraceAux(c: PCtx; x: PStackFrame; pc: int; recursionLimit=100) =
|
||||
if x != nil:
|
||||
@@ -533,9 +531,6 @@ template maybeHandlePtr(node2: PNode, reg: TFullReg, isAssign2: bool): bool =
|
||||
else:
|
||||
false
|
||||
|
||||
when not defined(nimHasSinkInference):
|
||||
{.pragma: nosinks.}
|
||||
|
||||
template takeAddress(reg, source) =
|
||||
reg.nodeAddr = addr source
|
||||
GC_ref source
|
||||
|
||||
@@ -141,41 +141,40 @@ proc staticWalkDirImpl(path: string, relative: bool): PNode =
|
||||
for k, f in walkDir(path, relative):
|
||||
result.add toLit((k, f))
|
||||
|
||||
when defined(nimHasInvariant):
|
||||
from std / compilesettings import SingleValueSetting, MultipleValueSetting
|
||||
from std / compilesettings import SingleValueSetting, MultipleValueSetting
|
||||
|
||||
proc querySettingImpl(conf: ConfigRef, switch: BiggestInt): string =
|
||||
{.push warning[Deprecated]:off.}
|
||||
case SingleValueSetting(switch)
|
||||
of arguments: result = conf.arguments
|
||||
of outFile: result = conf.outFile.string
|
||||
of outDir: result = conf.outDir.string
|
||||
of nimcacheDir: result = conf.getNimcacheDir().string
|
||||
of projectName: result = conf.projectName
|
||||
of projectPath: result = conf.projectPath.string
|
||||
of projectFull: result = conf.projectFull.string
|
||||
of command: result = conf.command
|
||||
of commandLine: result = conf.commandLine
|
||||
of linkOptions: result = conf.linkOptions
|
||||
of compileOptions: result = conf.compileOptions
|
||||
of ccompilerPath: result = conf.cCompilerPath
|
||||
of backend: result = $conf.backend
|
||||
of libPath: result = conf.libpath.string
|
||||
of gc: result = $conf.selectedGC
|
||||
of mm: result = $conf.selectedGC
|
||||
{.pop.}
|
||||
proc querySettingImpl(conf: ConfigRef, switch: BiggestInt): string =
|
||||
{.push warning[Deprecated]:off.}
|
||||
case SingleValueSetting(switch)
|
||||
of arguments: result = conf.arguments
|
||||
of outFile: result = conf.outFile.string
|
||||
of outDir: result = conf.outDir.string
|
||||
of nimcacheDir: result = conf.getNimcacheDir().string
|
||||
of projectName: result = conf.projectName
|
||||
of projectPath: result = conf.projectPath.string
|
||||
of projectFull: result = conf.projectFull.string
|
||||
of command: result = conf.command
|
||||
of commandLine: result = conf.commandLine
|
||||
of linkOptions: result = conf.linkOptions
|
||||
of compileOptions: result = conf.compileOptions
|
||||
of ccompilerPath: result = conf.cCompilerPath
|
||||
of backend: result = $conf.backend
|
||||
of libPath: result = conf.libpath.string
|
||||
of gc: result = $conf.selectedGC
|
||||
of mm: result = $conf.selectedGC
|
||||
{.pop.}
|
||||
|
||||
proc querySettingSeqImpl(conf: ConfigRef, switch: BiggestInt): seq[string] =
|
||||
template copySeq(field: untyped): untyped =
|
||||
for i in field: result.add i.string
|
||||
proc querySettingSeqImpl(conf: ConfigRef, switch: BiggestInt): seq[string] =
|
||||
template copySeq(field: untyped): untyped =
|
||||
for i in field: result.add i.string
|
||||
|
||||
case MultipleValueSetting(switch)
|
||||
of nimblePaths: copySeq(conf.nimblePaths)
|
||||
of searchPaths: copySeq(conf.searchPaths)
|
||||
of lazyPaths: copySeq(conf.lazyPaths)
|
||||
of commandArgs: result = conf.commandArgs
|
||||
of cincludes: copySeq(conf.cIncludes)
|
||||
of clibs: copySeq(conf.cLibs)
|
||||
case MultipleValueSetting(switch)
|
||||
of nimblePaths: copySeq(conf.nimblePaths)
|
||||
of searchPaths: copySeq(conf.searchPaths)
|
||||
of lazyPaths: copySeq(conf.lazyPaths)
|
||||
of commandArgs: result = conf.commandArgs
|
||||
of cincludes: copySeq(conf.cIncludes)
|
||||
of clibs: copySeq(conf.cLibs)
|
||||
|
||||
proc stackTrace2(c: PCtx, msg: string, n: PNode) =
|
||||
stackTrace(c, PStackFrame(prc: c.prc.sym, comesFrom: 0, next: nil), c.exceptionInstr, msg, n.info)
|
||||
@@ -257,11 +256,10 @@ proc registerAdditionalOps*(c: PCtx) =
|
||||
systemop getCurrentException
|
||||
registerCallback c, "stdlib.*.staticWalkDir", proc (a: VmArgs) {.nimcall.} =
|
||||
setResult(a, staticWalkDirImpl(getString(a, 0), getBool(a, 1)))
|
||||
when defined(nimHasInvariant):
|
||||
registerCallback c, "stdlib.compilesettings.querySetting", proc (a: VmArgs) =
|
||||
setResult(a, querySettingImpl(c.config, getInt(a, 0)))
|
||||
registerCallback c, "stdlib.compilesettings.querySettingSeq", proc (a: VmArgs) =
|
||||
setResult(a, querySettingSeqImpl(c.config, getInt(a, 0)))
|
||||
registerCallback c, "stdlib.compilesettings.querySetting", proc (a: VmArgs) =
|
||||
setResult(a, querySettingImpl(c.config, getInt(a, 0)))
|
||||
registerCallback c, "stdlib.compilesettings.querySettingSeq", proc (a: VmArgs) =
|
||||
setResult(a, querySettingSeqImpl(c.config, getInt(a, 0)))
|
||||
|
||||
if defined(nimsuggest) or c.config.cmd == cmdCheck:
|
||||
discard "don't run staticExec for 'nim suggest'"
|
||||
|
||||
@@ -1519,11 +1519,10 @@ proc boolVal*(n: NimNode): bool {.noSideEffect.} =
|
||||
if n.kind == nnkIntLit: n.intVal != 0
|
||||
else: n == bindSym"true" # hacky solution for now
|
||||
|
||||
when defined(nimMacrosGetNodeId):
|
||||
proc nodeID*(n: NimNode): int {.magic: "NodeId".}
|
||||
## Returns the id of `n`, when the compiler has been compiled
|
||||
## with the flag `-d:useNodeids`, otherwise returns `-1`. This
|
||||
## proc is for the purpose to debug the compiler only.
|
||||
proc nodeID*(n: NimNode): int {.magic: "NodeId".}
|
||||
## Returns the id of `n`, when the compiler has been compiled
|
||||
## with the flag `-d:useNodeids`, otherwise returns `-1`. This
|
||||
## proc is for the purpose to debug the compiler only.
|
||||
|
||||
macro expandMacros*(body: typed): untyped =
|
||||
## Expands one level of macro - useful for debugging.
|
||||
|
||||
@@ -62,9 +62,6 @@ import std/private/since
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
when not defined(nimHasCursor):
|
||||
{.pragma: cursor.}
|
||||
|
||||
type
|
||||
DoublyLinkedNodeObj*[T] = object
|
||||
## A node of a doubly linked list.
|
||||
|
||||
@@ -380,16 +380,10 @@ proc hash*(x: string): Hash =
|
||||
runnableExamples:
|
||||
doAssert hash("abracadabra") != hash("AbracadabrA")
|
||||
|
||||
when not defined(nimToOpenArrayCString):
|
||||
result = 0
|
||||
for c in x:
|
||||
result = result !& ord(c)
|
||||
result = !$result
|
||||
when nimvm:
|
||||
result = hashVmImpl(x, 0, high(x))
|
||||
else:
|
||||
when nimvm:
|
||||
result = hashVmImpl(x, 0, high(x))
|
||||
else:
|
||||
result = murmurHash(toOpenArrayByte(x, 0, high(x)))
|
||||
result = murmurHash(toOpenArrayByte(x, 0, high(x)))
|
||||
|
||||
proc hash*(x: cstring): Hash =
|
||||
## Efficient hashing of null-terminated strings.
|
||||
@@ -398,22 +392,14 @@ proc hash*(x: cstring): Hash =
|
||||
doAssert hash(cstring"AbracadabrA") == hash("AbracadabrA")
|
||||
doAssert hash(cstring"abracadabra") != hash(cstring"AbracadabrA")
|
||||
|
||||
when not defined(nimToOpenArrayCString):
|
||||
result = 0
|
||||
var i = 0
|
||||
while x[i] != '\0':
|
||||
result = result !& ord(x[i])
|
||||
inc i
|
||||
result = !$result
|
||||
when nimvm:
|
||||
hashVmImpl(x, 0, high(x))
|
||||
else:
|
||||
when nimvm:
|
||||
hashVmImpl(x, 0, high(x))
|
||||
when not defined(js):
|
||||
murmurHash(toOpenArrayByte(x, 0, x.high))
|
||||
else:
|
||||
when not defined(js) and defined(nimToOpenArrayCString):
|
||||
murmurHash(toOpenArrayByte(x, 0, x.high))
|
||||
else:
|
||||
let xx = $x
|
||||
murmurHash(toOpenArrayByte(xx, 0, high(xx)))
|
||||
let xx = $x
|
||||
murmurHash(toOpenArrayByte(xx, 0, high(xx)))
|
||||
|
||||
proc hash*(sBuf: string, sPos, ePos: int): Hash =
|
||||
## Efficient hashing of a string buffer, from starting
|
||||
@@ -424,13 +410,7 @@ proc hash*(sBuf: string, sPos, ePos: int): Hash =
|
||||
var a = "abracadabra"
|
||||
doAssert hash(a, 0, 3) == hash(a, 7, 10)
|
||||
|
||||
when not defined(nimToOpenArrayCString):
|
||||
result = 0
|
||||
for i in sPos..ePos:
|
||||
result = result !& ord(sBuf[i])
|
||||
result = !$result
|
||||
else:
|
||||
murmurHash(toOpenArrayByte(sBuf, sPos, ePos))
|
||||
murmurHash(toOpenArrayByte(sBuf, sPos, ePos))
|
||||
|
||||
proc hashIgnoreStyle*(x: string): Hash =
|
||||
## Efficient hashing of strings; style is ignored.
|
||||
|
||||
@@ -1059,310 +1059,308 @@ template verifyJsonKind(node: JsonNode, kinds: set[JsonNodeKind],
|
||||
]
|
||||
raise newException(JsonKindError, msg)
|
||||
|
||||
when defined(nimFixedForwardGeneric):
|
||||
macro isRefSkipDistinct*(arg: typed): untyped =
|
||||
## internal only, do not use
|
||||
var impl = getTypeImpl(arg)
|
||||
if impl.kind == nnkBracketExpr and impl[0].eqIdent("typeDesc"):
|
||||
impl = getTypeImpl(impl[1])
|
||||
while impl.kind == nnkDistinctTy:
|
||||
impl = getTypeImpl(impl[0])
|
||||
result = newLit(impl.kind == nnkRefTy)
|
||||
|
||||
macro isRefSkipDistinct*(arg: typed): untyped =
|
||||
## internal only, do not use
|
||||
var impl = getTypeImpl(arg)
|
||||
if impl.kind == nnkBracketExpr and impl[0].eqIdent("typeDesc"):
|
||||
impl = getTypeImpl(impl[1])
|
||||
while impl.kind == nnkDistinctTy:
|
||||
impl = getTypeImpl(impl[0])
|
||||
result = newLit(impl.kind == nnkRefTy)
|
||||
# The following forward declarations don't work in older versions of Nim
|
||||
|
||||
# The following forward declarations don't work in older versions of Nim
|
||||
# forward declare all initFromJson
|
||||
|
||||
# forward declare all initFromJson
|
||||
proc initFromJson(dst: var string; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson(dst: var bool; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson(dst: var JsonNode; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T: SomeInteger](dst: var T; jsonNode: JsonNode, jsonPath: var string)
|
||||
proc initFromJson[T: SomeFloat](dst: var T; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T: enum](dst: var T; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T](dst: var seq[T]; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[S, T](dst: var array[S, T]; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T](dst: var Table[string, T]; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T](dst: var OrderedTable[string, T]; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T](dst: var ref T; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T](dst: var Option[T]; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T: distinct](dst: var T; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T: object|tuple](dst: var T; jsonNode: JsonNode; jsonPath: var string)
|
||||
|
||||
proc initFromJson(dst: var string; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson(dst: var bool; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson(dst: var JsonNode; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T: SomeInteger](dst: var T; jsonNode: JsonNode, jsonPath: var string)
|
||||
proc initFromJson[T: SomeFloat](dst: var T; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T: enum](dst: var T; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T](dst: var seq[T]; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[S, T](dst: var array[S, T]; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T](dst: var Table[string, T]; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T](dst: var OrderedTable[string, T]; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T](dst: var ref T; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T](dst: var Option[T]; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T: distinct](dst: var T; jsonNode: JsonNode; jsonPath: var string)
|
||||
proc initFromJson[T: object|tuple](dst: var T; jsonNode: JsonNode; jsonPath: var string)
|
||||
# initFromJson definitions
|
||||
|
||||
# initFromJson definitions
|
||||
proc initFromJson(dst: var string; jsonNode: JsonNode; jsonPath: var string) =
|
||||
verifyJsonKind(jsonNode, {JString, JNull}, jsonPath)
|
||||
# since strings don't have a nil state anymore, this mapping of
|
||||
# JNull to the default string is questionable. `none(string)` and
|
||||
# `some("")` have the same potentional json value `JNull`.
|
||||
if jsonNode.kind == JNull:
|
||||
dst = ""
|
||||
else:
|
||||
dst = jsonNode.str
|
||||
|
||||
proc initFromJson(dst: var string; jsonNode: JsonNode; jsonPath: var string) =
|
||||
verifyJsonKind(jsonNode, {JString, JNull}, jsonPath)
|
||||
# since strings don't have a nil state anymore, this mapping of
|
||||
# JNull to the default string is questionable. `none(string)` and
|
||||
# `some("")` have the same potentional json value `JNull`.
|
||||
if jsonNode.kind == JNull:
|
||||
dst = ""
|
||||
proc initFromJson(dst: var bool; jsonNode: JsonNode; jsonPath: var string) =
|
||||
verifyJsonKind(jsonNode, {JBool}, jsonPath)
|
||||
dst = jsonNode.bval
|
||||
|
||||
proc initFromJson(dst: var JsonNode; jsonNode: JsonNode; jsonPath: var string) =
|
||||
if jsonNode == nil:
|
||||
raise newException(KeyError, "key not found: " & jsonPath)
|
||||
dst = jsonNode.copy
|
||||
|
||||
proc initFromJson[T: SomeInteger](dst: var T; jsonNode: JsonNode, jsonPath: var string) =
|
||||
when T is uint|uint64 or (not defined(js) and int.sizeof == 4):
|
||||
verifyJsonKind(jsonNode, {JInt, JString}, jsonPath)
|
||||
case jsonNode.kind
|
||||
of JString:
|
||||
let x = parseBiggestUInt(jsonNode.str)
|
||||
dst = cast[T](x)
|
||||
else:
|
||||
dst = jsonNode.str
|
||||
dst = T(jsonNode.num)
|
||||
else:
|
||||
verifyJsonKind(jsonNode, {JInt}, jsonPath)
|
||||
dst = cast[T](jsonNode.num)
|
||||
|
||||
proc initFromJson(dst: var bool; jsonNode: JsonNode; jsonPath: var string) =
|
||||
verifyJsonKind(jsonNode, {JBool}, jsonPath)
|
||||
dst = jsonNode.bval
|
||||
|
||||
proc initFromJson(dst: var JsonNode; jsonNode: JsonNode; jsonPath: var string) =
|
||||
if jsonNode == nil:
|
||||
raise newException(KeyError, "key not found: " & jsonPath)
|
||||
dst = jsonNode.copy
|
||||
|
||||
proc initFromJson[T: SomeInteger](dst: var T; jsonNode: JsonNode, jsonPath: var string) =
|
||||
when T is uint|uint64 or (not defined(js) and int.sizeof == 4):
|
||||
verifyJsonKind(jsonNode, {JInt, JString}, jsonPath)
|
||||
case jsonNode.kind
|
||||
of JString:
|
||||
let x = parseBiggestUInt(jsonNode.str)
|
||||
dst = cast[T](x)
|
||||
else:
|
||||
dst = T(jsonNode.num)
|
||||
proc initFromJson[T: SomeFloat](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
|
||||
if jsonNode.kind == JString:
|
||||
case jsonNode.str
|
||||
of "nan":
|
||||
let b = NaN
|
||||
dst = T(b)
|
||||
# dst = NaN # would fail some tests because range conversions would cause CT error
|
||||
# in some cases; but this is not a hot-spot inside this branch and backend can optimize this.
|
||||
of "inf":
|
||||
let b = Inf
|
||||
dst = T(b)
|
||||
of "-inf":
|
||||
let b = -Inf
|
||||
dst = T(b)
|
||||
else: raise newException(JsonKindError, "expected 'nan|inf|-inf', got " & jsonNode.str)
|
||||
else:
|
||||
verifyJsonKind(jsonNode, {JInt, JFloat}, jsonPath)
|
||||
if jsonNode.kind == JFloat:
|
||||
dst = T(jsonNode.fnum)
|
||||
else:
|
||||
verifyJsonKind(jsonNode, {JInt}, jsonPath)
|
||||
dst = cast[T](jsonNode.num)
|
||||
dst = T(jsonNode.num)
|
||||
|
||||
proc initFromJson[T: SomeFloat](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
|
||||
if jsonNode.kind == JString:
|
||||
case jsonNode.str
|
||||
of "nan":
|
||||
let b = NaN
|
||||
dst = T(b)
|
||||
# dst = NaN # would fail some tests because range conversions would cause CT error
|
||||
# in some cases; but this is not a hot-spot inside this branch and backend can optimize this.
|
||||
of "inf":
|
||||
let b = Inf
|
||||
dst = T(b)
|
||||
of "-inf":
|
||||
let b = -Inf
|
||||
dst = T(b)
|
||||
else: raise newException(JsonKindError, "expected 'nan|inf|-inf', got " & jsonNode.str)
|
||||
proc initFromJson[T: enum](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
|
||||
verifyJsonKind(jsonNode, {JString}, jsonPath)
|
||||
dst = parseEnum[T](jsonNode.getStr)
|
||||
|
||||
proc initFromJson[T](dst: var seq[T]; jsonNode: JsonNode; jsonPath: var string) =
|
||||
verifyJsonKind(jsonNode, {JArray}, jsonPath)
|
||||
dst.setLen jsonNode.len
|
||||
let orignalJsonPathLen = jsonPath.len
|
||||
for i in 0 ..< jsonNode.len:
|
||||
jsonPath.add '['
|
||||
jsonPath.addInt i
|
||||
jsonPath.add ']'
|
||||
initFromJson(dst[i], jsonNode[i], jsonPath)
|
||||
jsonPath.setLen orignalJsonPathLen
|
||||
|
||||
proc initFromJson[S,T](dst: var array[S,T]; jsonNode: JsonNode; jsonPath: var string) =
|
||||
verifyJsonKind(jsonNode, {JArray}, jsonPath)
|
||||
let originalJsonPathLen = jsonPath.len
|
||||
for i in 0 ..< jsonNode.len:
|
||||
jsonPath.add '['
|
||||
jsonPath.addInt i
|
||||
jsonPath.add ']'
|
||||
initFromJson(dst[i.S], jsonNode[i], jsonPath) # `.S` for enum indexed arrays
|
||||
jsonPath.setLen originalJsonPathLen
|
||||
|
||||
proc initFromJson[T](dst: var Table[string,T]; jsonNode: JsonNode; jsonPath: var string) =
|
||||
dst = initTable[string, T]()
|
||||
verifyJsonKind(jsonNode, {JObject}, jsonPath)
|
||||
let originalJsonPathLen = jsonPath.len
|
||||
for key in keys(jsonNode.fields):
|
||||
jsonPath.add '.'
|
||||
jsonPath.add key
|
||||
initFromJson(mgetOrPut(dst, key, default(T)), jsonNode[key], jsonPath)
|
||||
jsonPath.setLen originalJsonPathLen
|
||||
|
||||
proc initFromJson[T](dst: var OrderedTable[string,T]; jsonNode: JsonNode; jsonPath: var string) =
|
||||
dst = initOrderedTable[string,T]()
|
||||
verifyJsonKind(jsonNode, {JObject}, jsonPath)
|
||||
let originalJsonPathLen = jsonPath.len
|
||||
for key in keys(jsonNode.fields):
|
||||
jsonPath.add '.'
|
||||
jsonPath.add key
|
||||
initFromJson(mgetOrPut(dst, key, default(T)), jsonNode[key], jsonPath)
|
||||
jsonPath.setLen originalJsonPathLen
|
||||
|
||||
proc initFromJson[T](dst: var ref T; jsonNode: JsonNode; jsonPath: var string) =
|
||||
verifyJsonKind(jsonNode, {JObject, JNull}, jsonPath)
|
||||
if jsonNode.kind == JNull:
|
||||
dst = nil
|
||||
else:
|
||||
dst = new(T)
|
||||
initFromJson(dst[], jsonNode, jsonPath)
|
||||
|
||||
proc initFromJson[T](dst: var Option[T]; jsonNode: JsonNode; jsonPath: var string) =
|
||||
if jsonNode != nil and jsonNode.kind != JNull:
|
||||
when T is ref:
|
||||
dst = some(new(T))
|
||||
else:
|
||||
verifyJsonKind(jsonNode, {JInt, JFloat}, jsonPath)
|
||||
if jsonNode.kind == JFloat:
|
||||
dst = T(jsonNode.fnum)
|
||||
else:
|
||||
dst = T(jsonNode.num)
|
||||
dst = some(default(T))
|
||||
initFromJson(dst.get, jsonNode, jsonPath)
|
||||
|
||||
proc initFromJson[T: enum](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
|
||||
verifyJsonKind(jsonNode, {JString}, jsonPath)
|
||||
dst = parseEnum[T](jsonNode.getStr)
|
||||
macro assignDistinctImpl[T: distinct](dst: var T;jsonNode: JsonNode; jsonPath: var string) =
|
||||
let typInst = getTypeInst(dst)
|
||||
let typImpl = getTypeImpl(dst)
|
||||
let baseTyp = typImpl[0]
|
||||
|
||||
proc initFromJson[T](dst: var seq[T]; jsonNode: JsonNode; jsonPath: var string) =
|
||||
verifyJsonKind(jsonNode, {JArray}, jsonPath)
|
||||
dst.setLen jsonNode.len
|
||||
let orignalJsonPathLen = jsonPath.len
|
||||
for i in 0 ..< jsonNode.len:
|
||||
jsonPath.add '['
|
||||
jsonPath.addInt i
|
||||
jsonPath.add ']'
|
||||
initFromJson(dst[i], jsonNode[i], jsonPath)
|
||||
jsonPath.setLen orignalJsonPathLen
|
||||
|
||||
proc initFromJson[S,T](dst: var array[S,T]; jsonNode: JsonNode; jsonPath: var string) =
|
||||
verifyJsonKind(jsonNode, {JArray}, jsonPath)
|
||||
let originalJsonPathLen = jsonPath.len
|
||||
for i in 0 ..< jsonNode.len:
|
||||
jsonPath.add '['
|
||||
jsonPath.addInt i
|
||||
jsonPath.add ']'
|
||||
initFromJson(dst[i.S], jsonNode[i], jsonPath) # `.S` for enum indexed arrays
|
||||
jsonPath.setLen originalJsonPathLen
|
||||
|
||||
proc initFromJson[T](dst: var Table[string,T]; jsonNode: JsonNode; jsonPath: var string) =
|
||||
dst = initTable[string, T]()
|
||||
verifyJsonKind(jsonNode, {JObject}, jsonPath)
|
||||
let originalJsonPathLen = jsonPath.len
|
||||
for key in keys(jsonNode.fields):
|
||||
jsonPath.add '.'
|
||||
jsonPath.add key
|
||||
initFromJson(mgetOrPut(dst, key, default(T)), jsonNode[key], jsonPath)
|
||||
jsonPath.setLen originalJsonPathLen
|
||||
|
||||
proc initFromJson[T](dst: var OrderedTable[string,T]; jsonNode: JsonNode; jsonPath: var string) =
|
||||
dst = initOrderedTable[string,T]()
|
||||
verifyJsonKind(jsonNode, {JObject}, jsonPath)
|
||||
let originalJsonPathLen = jsonPath.len
|
||||
for key in keys(jsonNode.fields):
|
||||
jsonPath.add '.'
|
||||
jsonPath.add key
|
||||
initFromJson(mgetOrPut(dst, key, default(T)), jsonNode[key], jsonPath)
|
||||
jsonPath.setLen originalJsonPathLen
|
||||
|
||||
proc initFromJson[T](dst: var ref T; jsonNode: JsonNode; jsonPath: var string) =
|
||||
verifyJsonKind(jsonNode, {JObject, JNull}, jsonPath)
|
||||
if jsonNode.kind == JNull:
|
||||
dst = nil
|
||||
result = quote do:
|
||||
when nimvm:
|
||||
# workaround #12282
|
||||
var tmp: `baseTyp`
|
||||
initFromJson( tmp, `jsonNode`, `jsonPath`)
|
||||
`dst` = `typInst`(tmp)
|
||||
else:
|
||||
dst = new(T)
|
||||
initFromJson(dst[], jsonNode, jsonPath)
|
||||
initFromJson( `baseTyp`(`dst`), `jsonNode`, `jsonPath`)
|
||||
|
||||
proc initFromJson[T](dst: var Option[T]; jsonNode: JsonNode; jsonPath: var string) =
|
||||
if jsonNode != nil and jsonNode.kind != JNull:
|
||||
when T is ref:
|
||||
dst = some(new(T))
|
||||
else:
|
||||
dst = some(default(T))
|
||||
initFromJson(dst.get, jsonNode, jsonPath)
|
||||
proc initFromJson[T: distinct](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
|
||||
assignDistinctImpl(dst, jsonNode, jsonPath)
|
||||
|
||||
macro assignDistinctImpl[T: distinct](dst: var T;jsonNode: JsonNode; jsonPath: var string) =
|
||||
let typInst = getTypeInst(dst)
|
||||
let typImpl = getTypeImpl(dst)
|
||||
let baseTyp = typImpl[0]
|
||||
proc detectIncompatibleType(typeExpr, lineinfoNode: NimNode) =
|
||||
if typeExpr.kind == nnkTupleConstr:
|
||||
error("Use a named tuple instead of: " & typeExpr.repr, lineinfoNode)
|
||||
|
||||
result = quote do:
|
||||
proc foldObjectBody(dst, typeNode, tmpSym, jsonNode, jsonPath, originalJsonPathLen: NimNode) =
|
||||
case typeNode.kind
|
||||
of nnkEmpty:
|
||||
discard
|
||||
of nnkRecList, nnkTupleTy:
|
||||
for it in typeNode:
|
||||
foldObjectBody(dst, it, tmpSym, jsonNode, jsonPath, originalJsonPathLen)
|
||||
|
||||
of nnkIdentDefs:
|
||||
typeNode.expectLen 3
|
||||
let fieldSym = typeNode[0]
|
||||
let fieldNameLit = newLit(fieldSym.strVal)
|
||||
let fieldPathLit = newLit("." & fieldSym.strVal)
|
||||
let fieldType = typeNode[1]
|
||||
|
||||
# Detecting incompatiple tuple types in `assignObjectImpl` only
|
||||
# would be much cleaner, but the ast for tuple types does not
|
||||
# contain usable type information.
|
||||
detectIncompatibleType(fieldType, fieldSym)
|
||||
|
||||
dst.add quote do:
|
||||
jsonPath.add `fieldPathLit`
|
||||
when nimvm:
|
||||
# workaround #12282
|
||||
var tmp: `baseTyp`
|
||||
initFromJson( tmp, `jsonNode`, `jsonPath`)
|
||||
`dst` = `typInst`(tmp)
|
||||
else:
|
||||
initFromJson( `baseTyp`(`dst`), `jsonNode`, `jsonPath`)
|
||||
|
||||
proc initFromJson[T: distinct](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
|
||||
assignDistinctImpl(dst, jsonNode, jsonPath)
|
||||
|
||||
proc detectIncompatibleType(typeExpr, lineinfoNode: NimNode) =
|
||||
if typeExpr.kind == nnkTupleConstr:
|
||||
error("Use a named tuple instead of: " & typeExpr.repr, lineinfoNode)
|
||||
|
||||
proc foldObjectBody(dst, typeNode, tmpSym, jsonNode, jsonPath, originalJsonPathLen: NimNode) =
|
||||
case typeNode.kind
|
||||
of nnkEmpty:
|
||||
discard
|
||||
of nnkRecList, nnkTupleTy:
|
||||
for it in typeNode:
|
||||
foldObjectBody(dst, it, tmpSym, jsonNode, jsonPath, originalJsonPathLen)
|
||||
|
||||
of nnkIdentDefs:
|
||||
typeNode.expectLen 3
|
||||
let fieldSym = typeNode[0]
|
||||
let fieldNameLit = newLit(fieldSym.strVal)
|
||||
let fieldPathLit = newLit("." & fieldSym.strVal)
|
||||
let fieldType = typeNode[1]
|
||||
|
||||
# Detecting incompatiple tuple types in `assignObjectImpl` only
|
||||
# would be much cleaner, but the ast for tuple types does not
|
||||
# contain usable type information.
|
||||
detectIncompatibleType(fieldType, fieldSym)
|
||||
|
||||
dst.add quote do:
|
||||
jsonPath.add `fieldPathLit`
|
||||
when nimvm:
|
||||
when isRefSkipDistinct(`tmpSym`.`fieldSym`):
|
||||
# workaround #12489
|
||||
var tmp: `fieldType`
|
||||
initFromJson(tmp, getOrDefault(`jsonNode`,`fieldNameLit`), `jsonPath`)
|
||||
`tmpSym`.`fieldSym` = tmp
|
||||
else:
|
||||
initFromJson(`tmpSym`.`fieldSym`, getOrDefault(`jsonNode`,`fieldNameLit`), `jsonPath`)
|
||||
when isRefSkipDistinct(`tmpSym`.`fieldSym`):
|
||||
# workaround #12489
|
||||
var tmp: `fieldType`
|
||||
initFromJson(tmp, getOrDefault(`jsonNode`,`fieldNameLit`), `jsonPath`)
|
||||
`tmpSym`.`fieldSym` = tmp
|
||||
else:
|
||||
initFromJson(`tmpSym`.`fieldSym`, getOrDefault(`jsonNode`,`fieldNameLit`), `jsonPath`)
|
||||
jsonPath.setLen `originalJsonPathLen`
|
||||
else:
|
||||
initFromJson(`tmpSym`.`fieldSym`, getOrDefault(`jsonNode`,`fieldNameLit`), `jsonPath`)
|
||||
jsonPath.setLen `originalJsonPathLen`
|
||||
|
||||
of nnkRecCase:
|
||||
let kindSym = typeNode[0][0]
|
||||
let kindNameLit = newLit(kindSym.strVal)
|
||||
let kindPathLit = newLit("." & kindSym.strVal)
|
||||
let kindType = typeNode[0][1]
|
||||
let kindOffsetLit = newLit(uint(getOffset(kindSym)))
|
||||
dst.add quote do:
|
||||
var kindTmp: `kindType`
|
||||
jsonPath.add `kindPathLit`
|
||||
initFromJson(kindTmp, `jsonNode`[`kindNameLit`], `jsonPath`)
|
||||
jsonPath.setLen `originalJsonPathLen`
|
||||
when defined js:
|
||||
of nnkRecCase:
|
||||
let kindSym = typeNode[0][0]
|
||||
let kindNameLit = newLit(kindSym.strVal)
|
||||
let kindPathLit = newLit("." & kindSym.strVal)
|
||||
let kindType = typeNode[0][1]
|
||||
let kindOffsetLit = newLit(uint(getOffset(kindSym)))
|
||||
dst.add quote do:
|
||||
var kindTmp: `kindType`
|
||||
jsonPath.add `kindPathLit`
|
||||
initFromJson(kindTmp, `jsonNode`[`kindNameLit`], `jsonPath`)
|
||||
jsonPath.setLen `originalJsonPathLen`
|
||||
when defined js:
|
||||
`tmpSym`.`kindSym` = kindTmp
|
||||
else:
|
||||
when nimvm:
|
||||
`tmpSym`.`kindSym` = kindTmp
|
||||
else:
|
||||
when nimvm:
|
||||
`tmpSym`.`kindSym` = kindTmp
|
||||
else:
|
||||
# fuck it, assign kind field anyway
|
||||
((cast[ptr `kindType`](cast[uint](`tmpSym`.addr) + `kindOffsetLit`))[]) = kindTmp
|
||||
dst.add nnkCaseStmt.newTree(nnkDotExpr.newTree(tmpSym, kindSym))
|
||||
for i in 1 ..< typeNode.len:
|
||||
foldObjectBody(dst, typeNode[i], tmpSym, jsonNode, jsonPath, originalJsonPathLen)
|
||||
# fuck it, assign kind field anyway
|
||||
((cast[ptr `kindType`](cast[uint](`tmpSym`.addr) + `kindOffsetLit`))[]) = kindTmp
|
||||
dst.add nnkCaseStmt.newTree(nnkDotExpr.newTree(tmpSym, kindSym))
|
||||
for i in 1 ..< typeNode.len:
|
||||
foldObjectBody(dst, typeNode[i], tmpSym, jsonNode, jsonPath, originalJsonPathLen)
|
||||
|
||||
of nnkOfBranch, nnkElse:
|
||||
let ofBranch = newNimNode(typeNode.kind)
|
||||
for i in 0 ..< typeNode.len-1:
|
||||
ofBranch.add copyNimTree(typeNode[i])
|
||||
let dstInner = newNimNode(nnkStmtListExpr)
|
||||
foldObjectBody(dstInner, typeNode[^1], tmpSym, jsonNode, jsonPath, originalJsonPathLen)
|
||||
# resOuter now contains the inner stmtList
|
||||
ofBranch.add dstInner
|
||||
dst[^1].expectKind nnkCaseStmt
|
||||
dst[^1].add ofBranch
|
||||
of nnkOfBranch, nnkElse:
|
||||
let ofBranch = newNimNode(typeNode.kind)
|
||||
for i in 0 ..< typeNode.len-1:
|
||||
ofBranch.add copyNimTree(typeNode[i])
|
||||
let dstInner = newNimNode(nnkStmtListExpr)
|
||||
foldObjectBody(dstInner, typeNode[^1], tmpSym, jsonNode, jsonPath, originalJsonPathLen)
|
||||
# resOuter now contains the inner stmtList
|
||||
ofBranch.add dstInner
|
||||
dst[^1].expectKind nnkCaseStmt
|
||||
dst[^1].add ofBranch
|
||||
|
||||
of nnkObjectTy:
|
||||
typeNode[0].expectKind nnkEmpty
|
||||
typeNode[1].expectKind {nnkEmpty, nnkOfInherit}
|
||||
if typeNode[1].kind == nnkOfInherit:
|
||||
let base = typeNode[1][0]
|
||||
var impl = getTypeImpl(base)
|
||||
while impl.kind in {nnkRefTy, nnkPtrTy}:
|
||||
impl = getTypeImpl(impl[0])
|
||||
foldObjectBody(dst, impl, tmpSym, jsonNode, jsonPath, originalJsonPathLen)
|
||||
let body = typeNode[2]
|
||||
foldObjectBody(dst, body, tmpSym, jsonNode, jsonPath, originalJsonPathLen)
|
||||
of nnkObjectTy:
|
||||
typeNode[0].expectKind nnkEmpty
|
||||
typeNode[1].expectKind {nnkEmpty, nnkOfInherit}
|
||||
if typeNode[1].kind == nnkOfInherit:
|
||||
let base = typeNode[1][0]
|
||||
var impl = getTypeImpl(base)
|
||||
while impl.kind in {nnkRefTy, nnkPtrTy}:
|
||||
impl = getTypeImpl(impl[0])
|
||||
foldObjectBody(dst, impl, tmpSym, jsonNode, jsonPath, originalJsonPathLen)
|
||||
let body = typeNode[2]
|
||||
foldObjectBody(dst, body, tmpSym, jsonNode, jsonPath, originalJsonPathLen)
|
||||
|
||||
else:
|
||||
error("unhandled kind: " & $typeNode.kind, typeNode)
|
||||
else:
|
||||
error("unhandled kind: " & $typeNode.kind, typeNode)
|
||||
|
||||
macro assignObjectImpl[T](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
|
||||
let typeSym = getTypeInst(dst)
|
||||
let originalJsonPathLen = genSym(nskLet, "originalJsonPathLen")
|
||||
result = newStmtList()
|
||||
result.add quote do:
|
||||
let `originalJsonPathLen` = len(`jsonPath`)
|
||||
if typeSym.kind in {nnkTupleTy, nnkTupleConstr}:
|
||||
# both, `dst` and `typeSym` don't have good lineinfo. But nothing
|
||||
# else is available here.
|
||||
detectIncompatibleType(typeSym, dst)
|
||||
foldObjectBody(result, typeSym, dst, jsonNode, jsonPath, originalJsonPathLen)
|
||||
else:
|
||||
foldObjectBody(result, typeSym.getTypeImpl, dst, jsonNode, jsonPath, originalJsonPathLen)
|
||||
macro assignObjectImpl[T](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
|
||||
let typeSym = getTypeInst(dst)
|
||||
let originalJsonPathLen = genSym(nskLet, "originalJsonPathLen")
|
||||
result = newStmtList()
|
||||
result.add quote do:
|
||||
let `originalJsonPathLen` = len(`jsonPath`)
|
||||
if typeSym.kind in {nnkTupleTy, nnkTupleConstr}:
|
||||
# both, `dst` and `typeSym` don't have good lineinfo. But nothing
|
||||
# else is available here.
|
||||
detectIncompatibleType(typeSym, dst)
|
||||
foldObjectBody(result, typeSym, dst, jsonNode, jsonPath, originalJsonPathLen)
|
||||
else:
|
||||
foldObjectBody(result, typeSym.getTypeImpl, dst, jsonNode, jsonPath, originalJsonPathLen)
|
||||
|
||||
proc initFromJson[T: object|tuple](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
|
||||
assignObjectImpl(dst, jsonNode, jsonPath)
|
||||
proc initFromJson[T: object|tuple](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
|
||||
assignObjectImpl(dst, jsonNode, jsonPath)
|
||||
|
||||
proc to*[T](node: JsonNode, t: typedesc[T]): T =
|
||||
## `Unmarshals`:idx: the specified node into the object type specified.
|
||||
##
|
||||
## Known limitations:
|
||||
##
|
||||
## * Heterogeneous arrays are not supported.
|
||||
## * Sets in object variants are not supported.
|
||||
## * Not nil annotations are not supported.
|
||||
##
|
||||
runnableExamples:
|
||||
let jsonNode = parseJson("""
|
||||
{
|
||||
"person": {
|
||||
"name": "Nimmer",
|
||||
"age": 21
|
||||
},
|
||||
"list": [1, 2, 3, 4]
|
||||
}
|
||||
""")
|
||||
proc to*[T](node: JsonNode, t: typedesc[T]): T =
|
||||
## `Unmarshals`:idx: the specified node into the object type specified.
|
||||
##
|
||||
## Known limitations:
|
||||
##
|
||||
## * Heterogeneous arrays are not supported.
|
||||
## * Sets in object variants are not supported.
|
||||
## * Not nil annotations are not supported.
|
||||
##
|
||||
runnableExamples:
|
||||
let jsonNode = parseJson("""
|
||||
{
|
||||
"person": {
|
||||
"name": "Nimmer",
|
||||
"age": 21
|
||||
},
|
||||
"list": [1, 2, 3, 4]
|
||||
}
|
||||
""")
|
||||
|
||||
type
|
||||
Person = object
|
||||
name: string
|
||||
age: int
|
||||
type
|
||||
Person = object
|
||||
name: string
|
||||
age: int
|
||||
|
||||
Data = object
|
||||
person: Person
|
||||
list: seq[int]
|
||||
Data = object
|
||||
person: Person
|
||||
list: seq[int]
|
||||
|
||||
var data = to(jsonNode, Data)
|
||||
doAssert data.person.name == "Nimmer"
|
||||
doAssert data.person.age == 21
|
||||
doAssert data.list == @[1, 2, 3, 4]
|
||||
var data = to(jsonNode, Data)
|
||||
doAssert data.person.name == "Nimmer"
|
||||
doAssert data.person.age == 21
|
||||
doAssert data.list == @[1, 2, 3, 4]
|
||||
|
||||
var jsonPath = ""
|
||||
initFromJson(result, node, jsonPath)
|
||||
var jsonPath = ""
|
||||
initFromJson(result, node, jsonPath)
|
||||
|
||||
when false:
|
||||
import os
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
when not defined(profiler) and not defined(memProfiler):
|
||||
{.error: "Profiling support is turned off! Enable profiling by passing `--profiler:on --stackTrace:on` to the compiler (see the Nim Compiler User Guide for more options).".}
|
||||
|
||||
when defined(nimHasUsed):
|
||||
{.used.}
|
||||
{.used.}
|
||||
|
||||
# We don't want to profile the profiling code ...
|
||||
{.push profiler: off.}
|
||||
|
||||
@@ -23,8 +23,6 @@ proc `$`(info: InstantiationInfo): string =
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
when not defined(nimHasSinkInference):
|
||||
{.pragma: nosinks.}
|
||||
|
||||
proc raiseAssert*(msg: string) {.noinline, noreturn, nosinks.} =
|
||||
## Raises an `AssertionDefect` with `msg`.
|
||||
|
||||
@@ -37,22 +37,8 @@ from typetraits import OrdinalEnum, tupleLen
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
when not defined(nimFixedForwardGeneric):
|
||||
# xxx remove pending csources_v1 update >= 1.2.0
|
||||
proc to[T](node: JsonNode, t: typedesc[T]): T =
|
||||
when T is string: node.getStr
|
||||
elif T is bool: node.getBool
|
||||
else: static: doAssert false, $T # support as needed (only needed during bootstrap)
|
||||
proc isNamedTuple(T: typedesc): bool = # old implementation
|
||||
when T isnot tuple: result = false
|
||||
else:
|
||||
var t: T
|
||||
for name, _ in t.fieldPairs:
|
||||
when name == "Field0": return compiles(t.Field0)
|
||||
else: return true
|
||||
return false
|
||||
else:
|
||||
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
|
||||
|
||||
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
|
||||
|
||||
type
|
||||
Joptions* = object # xxx rename FromJsonOptions
|
||||
|
||||
@@ -13,21 +13,7 @@ template toLocation*(result: var string, file: string | cstring, line: int, col:
|
||||
addInt(result, col)
|
||||
result.add ")"
|
||||
|
||||
when defined(nimHasIsNamedTuple):
|
||||
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
|
||||
else:
|
||||
# for bootstrap; remove after release 1.2
|
||||
proc isNamedTuple(T: typedesc): bool =
|
||||
# Taken from typetraits.
|
||||
when T isnot tuple: result = false
|
||||
else:
|
||||
var t: T
|
||||
for name, _ in t.fieldPairs:
|
||||
when name == "Field0":
|
||||
return compiles(t.Field0)
|
||||
else:
|
||||
return true
|
||||
return false
|
||||
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
|
||||
|
||||
template tupleObjectDollar*[T: tuple | object](result: var string, x: T) =
|
||||
result = "("
|
||||
|
||||
@@ -85,17 +85,12 @@ when defined(nimHasIterable):
|
||||
type
|
||||
iterable*[T] {.magic: IterableType.} ## Represents an expression that yields `T`
|
||||
|
||||
when defined(nimHashOrdinalFixed):
|
||||
type
|
||||
Ordinal*[T] {.magic: Ordinal.} ## Generic ordinal type. Includes integer,
|
||||
## bool, character, and enumeration types
|
||||
## as well as their subtypes. See also
|
||||
## `SomeOrdinal`.
|
||||
else:
|
||||
# bootstrap < 1.2.0
|
||||
type
|
||||
OrdinalImpl[T] {.magic: Ordinal.}
|
||||
Ordinal* = OrdinalImpl | uint | uint64
|
||||
type
|
||||
Ordinal*[T] {.magic: Ordinal.} ## Generic ordinal type. Includes integer,
|
||||
## bool, character, and enumeration types
|
||||
## as well as their subtypes. See also
|
||||
## `SomeOrdinal`.
|
||||
|
||||
|
||||
proc `addr`*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} =
|
||||
## Builtin `addr` operator for taking the address of a memory location.
|
||||
@@ -451,9 +446,7 @@ type
|
||||
## However, objects that have no ancestor are also allowed.
|
||||
RootRef* = ref RootObj ## Reference to `RootObj`.
|
||||
|
||||
const NimStackTraceMsgs =
|
||||
when defined(nimHasStacktraceMsgs): compileOption("stacktraceMsgs")
|
||||
else: false
|
||||
const NimStackTraceMsgs = compileOption("stacktraceMsgs")
|
||||
|
||||
type
|
||||
RootEffect* {.compilerproc.} = object of RootObj ## \
|
||||
@@ -2113,10 +2106,7 @@ when notJSnotNims:
|
||||
|
||||
# we cannot compile this with stack tracing on
|
||||
# as it would recurse endlessly!
|
||||
when defined(nimNewIntegerOps):
|
||||
include "system/integerops"
|
||||
else:
|
||||
include "system/arithm"
|
||||
include "system/integerops"
|
||||
{.pop.}
|
||||
|
||||
|
||||
@@ -2660,11 +2650,10 @@ when defined(nimconfig):
|
||||
when not defined(js):
|
||||
proc toOpenArray*[T](x: ptr UncheckedArray[T]; first, last: int): openArray[T] {.
|
||||
magic: "Slice".}
|
||||
when defined(nimToOpenArrayCString):
|
||||
proc toOpenArray*(x: cstring; first, last: int): openArray[char] {.
|
||||
magic: "Slice".}
|
||||
proc toOpenArrayByte*(x: cstring; first, last: int): openArray[byte] {.
|
||||
magic: "Slice".}
|
||||
proc toOpenArray*(x: cstring; first, last: int): openArray[char] {.
|
||||
magic: "Slice".}
|
||||
proc toOpenArrayByte*(x: cstring; first, last: int): openArray[byte] {.
|
||||
magic: "Slice".}
|
||||
|
||||
proc toOpenArray*[T](x: seq[T]; first, last: int): openArray[T] {.
|
||||
magic: "Slice".}
|
||||
|
||||
@@ -95,17 +95,11 @@ type
|
||||
acc: int # accumulator for small object allocation
|
||||
when defined(gcDestructors):
|
||||
sharedFreeList: ptr FreeCell # make no attempt at avoiding false sharing for now for this object field
|
||||
when defined(nimAlignPragma):
|
||||
data {.align: MemAlign.}: UncheckedArray[byte] # start of usable memory
|
||||
else:
|
||||
data: UncheckedArray[byte]
|
||||
data {.align: MemAlign.}: UncheckedArray[byte] # start of usable memory
|
||||
|
||||
BigChunk = object of BaseChunk # not necessarily > PageSize!
|
||||
next, prev: PBigChunk # chunks of the same (or bigger) size
|
||||
when defined(nimAlignPragma):
|
||||
data {.align: MemAlign.}: UncheckedArray[byte] # start of usable memory
|
||||
else:
|
||||
data: UncheckedArray[byte]
|
||||
data {.align: MemAlign.}: UncheckedArray[byte] # start of usable memory
|
||||
|
||||
HeapLinks = object
|
||||
len: int
|
||||
|
||||
@@ -1,425 +0,0 @@
|
||||
#
|
||||
#
|
||||
# Nim's Runtime Library
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
# simple integer arithmetic with overflow checking
|
||||
|
||||
proc raiseOverflow {.compilerproc, noinline.} =
|
||||
# a single proc to reduce code size to a minimum
|
||||
sysFatal(OverflowDefect, "over- or underflow")
|
||||
|
||||
proc raiseDivByZero {.compilerproc, noinline.} =
|
||||
sysFatal(DivByZeroDefect, "division by zero")
|
||||
|
||||
when defined(builtinOverflow):
|
||||
# Builtin compiler functions for improved performance
|
||||
when sizeof(clong) == 8:
|
||||
proc addInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
|
||||
importc: "__builtin_saddl_overflow", nodecl, nosideeffect.}
|
||||
|
||||
proc subInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
|
||||
importc: "__builtin_ssubl_overflow", nodecl, nosideeffect.}
|
||||
|
||||
proc mulInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
|
||||
importc: "__builtin_smull_overflow", nodecl, nosideeffect.}
|
||||
|
||||
elif sizeof(clonglong) == 8:
|
||||
proc addInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
|
||||
importc: "__builtin_saddll_overflow", nodecl, nosideeffect.}
|
||||
|
||||
proc subInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
|
||||
importc: "__builtin_ssubll_overflow", nodecl, nosideeffect.}
|
||||
|
||||
proc mulInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
|
||||
importc: "__builtin_smulll_overflow", nodecl, nosideeffect.}
|
||||
|
||||
when sizeof(int) == 8:
|
||||
proc addIntOverflow(a, b: int, c: var int): bool {.inline.} =
|
||||
addInt64Overflow(a, b, c)
|
||||
|
||||
proc subIntOverflow(a, b: int, c: var int): bool {.inline.} =
|
||||
subInt64Overflow(a, b, c)
|
||||
|
||||
proc mulIntOverflow(a, b: int, c: var int): bool {.inline.} =
|
||||
mulInt64Overflow(a, b, c)
|
||||
|
||||
elif sizeof(int) == 4 and sizeof(cint) == 4:
|
||||
proc addIntOverflow(a, b: int, c: var int): bool {.
|
||||
importc: "__builtin_sadd_overflow", nodecl, nosideeffect.}
|
||||
|
||||
proc subIntOverflow(a, b: int, c: var int): bool {.
|
||||
importc: "__builtin_ssub_overflow", nodecl, nosideeffect.}
|
||||
|
||||
proc mulIntOverflow(a, b: int, c: var int): bool {.
|
||||
importc: "__builtin_smul_overflow", nodecl, nosideeffect.}
|
||||
|
||||
proc addInt64(a, b: int64): int64 {.compilerproc, inline.} =
|
||||
if addInt64Overflow(a, b, result):
|
||||
raiseOverflow()
|
||||
|
||||
proc subInt64(a, b: int64): int64 {.compilerproc, inline.} =
|
||||
if subInt64Overflow(a, b, result):
|
||||
raiseOverflow()
|
||||
|
||||
proc mulInt64(a, b: int64): int64 {.compilerproc, inline.} =
|
||||
if mulInt64Overflow(a, b, result):
|
||||
raiseOverflow()
|
||||
else:
|
||||
proc addInt64(a, b: int64): int64 {.compilerproc, inline.} =
|
||||
result = a +% b
|
||||
if (result xor a) >= int64(0) or (result xor b) >= int64(0):
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
||||
proc subInt64(a, b: int64): int64 {.compilerproc, inline.} =
|
||||
result = a -% b
|
||||
if (result xor a) >= int64(0) or (result xor not b) >= int64(0):
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
||||
#
|
||||
# This code has been inspired by Python's source code.
|
||||
# The native int product x*y is either exactly right or *way* off, being
|
||||
# just the last n bits of the true product, where n is the number of bits
|
||||
# in an int (the delivered product is the true product plus i*2**n for
|
||||
# some integer i).
|
||||
#
|
||||
# The native float64 product x*y is subject to three
|
||||
# rounding errors: on a sizeof(int)==8 box, each cast to double can lose
|
||||
# info, and even on a sizeof(int)==4 box, the multiplication can lose info.
|
||||
# But, unlike the native int product, it's not in *range* trouble: even
|
||||
# if sizeof(int)==32 (256-bit ints), the product easily fits in the
|
||||
# dynamic range of a float64. So the leading 50 (or so) bits of the float64
|
||||
# product are correct.
|
||||
#
|
||||
# We check these two ways against each other, and declare victory if they're
|
||||
# approximately the same. Else, because the native int product is the only
|
||||
# one that can lose catastrophic amounts of information, it's the native int
|
||||
# product that must have overflowed.
|
||||
#
|
||||
proc mulInt64(a, b: int64): int64 {.compilerproc.} =
|
||||
var
|
||||
resAsFloat, floatProd: float64
|
||||
result = a *% b
|
||||
floatProd = toBiggestFloat(a) # conversion
|
||||
floatProd = floatProd * toBiggestFloat(b)
|
||||
resAsFloat = toBiggestFloat(result)
|
||||
|
||||
# Fast path for normal case: small multiplicands, and no info
|
||||
# is lost in either method.
|
||||
if resAsFloat == floatProd: return result
|
||||
|
||||
# Somebody somewhere lost info. Close enough, or way off? Note
|
||||
# that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
|
||||
# The difference either is or isn't significant compared to the
|
||||
# true value (of which floatProd is a good approximation).
|
||||
|
||||
# abs(diff)/abs(prod) <= 1/32 iff
|
||||
# 32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
|
||||
if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
||||
proc negInt64(a: int64): int64 {.compilerproc, inline.} =
|
||||
if a != low(int64): return -a
|
||||
raiseOverflow()
|
||||
|
||||
proc absInt64(a: int64): int64 {.compilerproc, inline.} =
|
||||
if a != low(int64):
|
||||
if a >= 0: return a
|
||||
else: return -a
|
||||
raiseOverflow()
|
||||
|
||||
proc divInt64(a, b: int64): int64 {.compilerproc, inline.} =
|
||||
if b == int64(0):
|
||||
raiseDivByZero()
|
||||
if a == low(int64) and b == int64(-1):
|
||||
raiseOverflow()
|
||||
return a div b
|
||||
|
||||
proc modInt64(a, b: int64): int64 {.compilerproc, inline.} =
|
||||
if b == int64(0):
|
||||
raiseDivByZero()
|
||||
return a mod b
|
||||
|
||||
proc absInt(a: int): int {.compilerproc, inline.} =
|
||||
if a != low(int):
|
||||
if a >= 0: return a
|
||||
else: return -a
|
||||
raiseOverflow()
|
||||
|
||||
const
|
||||
asmVersion = defined(i386) and (defined(vcc) or defined(wcc) or
|
||||
defined(dmc) or defined(gcc) or defined(llvm_gcc))
|
||||
# my Version of Borland C++Builder does not have
|
||||
# tasm32, which is needed for assembler blocks
|
||||
# this is why Borland is not included in the 'when'
|
||||
|
||||
when asmVersion and not defined(gcc) and not defined(llvm_gcc):
|
||||
# assembler optimized versions for compilers that
|
||||
# have an intel syntax assembler:
|
||||
proc addInt(a, b: int): int {.compilerproc, asmNoStackFrame.} =
|
||||
# a in eax, and b in edx
|
||||
asm """
|
||||
mov eax, ecx
|
||||
add eax, edx
|
||||
jno theEnd
|
||||
call `raiseOverflow`
|
||||
theEnd:
|
||||
ret
|
||||
"""
|
||||
|
||||
proc subInt(a, b: int): int {.compilerproc, asmNoStackFrame.} =
|
||||
asm """
|
||||
mov eax, ecx
|
||||
sub eax, edx
|
||||
jno theEnd
|
||||
call `raiseOverflow`
|
||||
theEnd:
|
||||
ret
|
||||
"""
|
||||
|
||||
proc negInt(a: int): int {.compilerproc, asmNoStackFrame.} =
|
||||
asm """
|
||||
mov eax, ecx
|
||||
neg eax
|
||||
jno theEnd
|
||||
call `raiseOverflow`
|
||||
theEnd:
|
||||
ret
|
||||
"""
|
||||
|
||||
proc divInt(a, b: int): int {.compilerproc, asmNoStackFrame.} =
|
||||
asm """
|
||||
test edx, edx
|
||||
jne L_NOT_ZERO
|
||||
call `raiseDivByZero`
|
||||
L_NOT_ZERO:
|
||||
cmp ecx, 0x80000000
|
||||
jne L_DO_DIV
|
||||
cmp edx, -1
|
||||
jne L_DO_DIV
|
||||
call `raiseOverflow`
|
||||
L_DO_DIV:
|
||||
mov eax, ecx
|
||||
mov ecx, edx
|
||||
cdq
|
||||
idiv ecx
|
||||
ret
|
||||
"""
|
||||
|
||||
proc modInt(a, b: int): int {.compilerproc, asmNoStackFrame.} =
|
||||
asm """
|
||||
test edx, edx
|
||||
jne L_NOT_ZERO
|
||||
call `raiseDivByZero`
|
||||
L_NOT_ZERO:
|
||||
cmp ecx, 0x80000000
|
||||
jne L_DO_DIV
|
||||
cmp edx, -1
|
||||
jne L_DO_DIV
|
||||
call `raiseOverflow`
|
||||
L_DO_DIV:
|
||||
mov eax, ecx
|
||||
mov ecx, edx
|
||||
cdq
|
||||
idiv ecx
|
||||
mov eax, edx
|
||||
ret
|
||||
"""
|
||||
|
||||
proc mulInt(a, b: int): int {.compilerproc, asmNoStackFrame.} =
|
||||
asm """
|
||||
mov eax, ecx
|
||||
mov ecx, edx
|
||||
xor edx, edx
|
||||
imul ecx
|
||||
jno theEnd
|
||||
call `raiseOverflow`
|
||||
theEnd:
|
||||
ret
|
||||
"""
|
||||
|
||||
elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)):
|
||||
proc addInt(a, b: int): int {.compilerproc, inline.} =
|
||||
# don't use a pure proc here!
|
||||
asm """
|
||||
"addl %%ecx, %%eax\n"
|
||||
"jno 1\n"
|
||||
"call _raiseOverflow\n"
|
||||
"1: \n"
|
||||
:"=a"(`result`)
|
||||
:"a"(`a`), "c"(`b`)
|
||||
"""
|
||||
#".intel_syntax noprefix"
|
||||
#/* Intel syntax here */
|
||||
#".att_syntax"
|
||||
|
||||
proc subInt(a, b: int): int {.compilerproc, inline.} =
|
||||
asm """ "subl %%ecx,%%eax\n"
|
||||
"jno 1\n"
|
||||
"call _raiseOverflow\n"
|
||||
"1: \n"
|
||||
:"=a"(`result`)
|
||||
:"a"(`a`), "c"(`b`)
|
||||
"""
|
||||
|
||||
proc mulInt(a, b: int): int {.compilerproc, inline.} =
|
||||
asm """ "xorl %%edx, %%edx\n"
|
||||
"imull %%ecx\n"
|
||||
"jno 1\n"
|
||||
"call _raiseOverflow\n"
|
||||
"1: \n"
|
||||
:"=a"(`result`)
|
||||
:"a"(`a`), "c"(`b`)
|
||||
:"%edx"
|
||||
"""
|
||||
|
||||
proc negInt(a: int): int {.compilerproc, inline.} =
|
||||
asm """ "negl %%eax\n"
|
||||
"jno 1\n"
|
||||
"call _raiseOverflow\n"
|
||||
"1: \n"
|
||||
:"=a"(`result`)
|
||||
:"a"(`a`)
|
||||
"""
|
||||
|
||||
proc divInt(a, b: int): int {.compilerproc, inline.} =
|
||||
asm """ "xorl %%edx, %%edx\n"
|
||||
"idivl %%ecx\n"
|
||||
"jno 1\n"
|
||||
"call _raiseOverflow\n"
|
||||
"1: \n"
|
||||
:"=a"(`result`)
|
||||
:"a"(`a`), "c"(`b`)
|
||||
:"%edx"
|
||||
"""
|
||||
|
||||
proc modInt(a, b: int): int {.compilerproc, inline.} =
|
||||
asm """ "xorl %%edx, %%edx\n"
|
||||
"idivl %%ecx\n"
|
||||
"jno 1\n"
|
||||
"call _raiseOverflow\n"
|
||||
"1: \n"
|
||||
"movl %%edx, %%eax"
|
||||
:"=a"(`result`)
|
||||
:"a"(`a`), "c"(`b`)
|
||||
:"%edx"
|
||||
"""
|
||||
|
||||
when not declared(addInt) and defined(builtinOverflow):
|
||||
proc addInt(a, b: int): int {.compilerproc, inline.} =
|
||||
if addIntOverflow(a, b, result):
|
||||
raiseOverflow()
|
||||
|
||||
when not declared(subInt) and defined(builtinOverflow):
|
||||
proc subInt(a, b: int): int {.compilerproc, inline.} =
|
||||
if subIntOverflow(a, b, result):
|
||||
raiseOverflow()
|
||||
|
||||
when not declared(mulInt) and defined(builtinOverflow):
|
||||
proc mulInt(a, b: int): int {.compilerproc, inline.} =
|
||||
if mulIntOverflow(a, b, result):
|
||||
raiseOverflow()
|
||||
|
||||
# Platform independent versions of the above (slower!)
|
||||
when not declared(addInt):
|
||||
proc addInt(a, b: int): int {.compilerproc, inline.} =
|
||||
result = a +% b
|
||||
if (result xor a) >= 0 or (result xor b) >= 0:
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
||||
when not declared(subInt):
|
||||
proc subInt(a, b: int): int {.compilerproc, inline.} =
|
||||
result = a -% b
|
||||
if (result xor a) >= 0 or (result xor not b) >= 0:
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
||||
when not declared(negInt):
|
||||
proc negInt(a: int): int {.compilerproc, inline.} =
|
||||
if a != low(int): return -a
|
||||
raiseOverflow()
|
||||
|
||||
when not declared(divInt):
|
||||
proc divInt(a, b: int): int {.compilerproc, inline.} =
|
||||
if b == 0:
|
||||
raiseDivByZero()
|
||||
if a == low(int) and b == -1:
|
||||
raiseOverflow()
|
||||
return a div b
|
||||
|
||||
when not declared(modInt):
|
||||
proc modInt(a, b: int): int {.compilerproc, inline.} =
|
||||
if b == 0:
|
||||
raiseDivByZero()
|
||||
return a mod b
|
||||
|
||||
when not declared(mulInt):
|
||||
#
|
||||
# This code has been inspired by Python's source code.
|
||||
# The native int product x*y is either exactly right or *way* off, being
|
||||
# just the last n bits of the true product, where n is the number of bits
|
||||
# in an int (the delivered product is the true product plus i*2**n for
|
||||
# some integer i).
|
||||
#
|
||||
# The native float64 product x*y is subject to three
|
||||
# rounding errors: on a sizeof(int)==8 box, each cast to double can lose
|
||||
# info, and even on a sizeof(int)==4 box, the multiplication can lose info.
|
||||
# But, unlike the native int product, it's not in *range* trouble: even
|
||||
# if sizeof(int)==32 (256-bit ints), the product easily fits in the
|
||||
# dynamic range of a float64. So the leading 50 (or so) bits of the float64
|
||||
# product are correct.
|
||||
#
|
||||
# We check these two ways against each other, and declare victory if
|
||||
# they're approximately the same. Else, because the native int product is
|
||||
# the only one that can lose catastrophic amounts of information, it's the
|
||||
# native int product that must have overflowed.
|
||||
#
|
||||
proc mulInt(a, b: int): int {.compilerproc.} =
|
||||
var
|
||||
resAsFloat, floatProd: float
|
||||
|
||||
result = a *% b
|
||||
floatProd = toFloat(a) * toFloat(b)
|
||||
resAsFloat = toFloat(result)
|
||||
|
||||
# Fast path for normal case: small multiplicands, and no info
|
||||
# is lost in either method.
|
||||
if resAsFloat == floatProd: return result
|
||||
|
||||
# Somebody somewhere lost info. Close enough, or way off? Note
|
||||
# that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
|
||||
# The difference either is or isn't significant compared to the
|
||||
# true value (of which floatProd is a good approximation).
|
||||
|
||||
# abs(diff)/abs(prod) <= 1/32 iff
|
||||
# 32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
|
||||
if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
||||
# We avoid setting the FPU control word here for compatibility with libraries
|
||||
# written in other languages.
|
||||
|
||||
proc raiseFloatInvalidOp {.compilerproc, noinline.} =
|
||||
sysFatal(FloatInvalidOpDefect, "FPU operation caused a NaN result")
|
||||
|
||||
proc nanCheck(x: float64) {.compilerproc, inline.} =
|
||||
if x != x: raiseFloatInvalidOp()
|
||||
|
||||
proc raiseFloatOverflow(x: float64) {.compilerproc, noinline.} =
|
||||
if x > 0.0:
|
||||
sysFatal(FloatOverflowDefect, "FPU operation caused an overflow")
|
||||
else:
|
||||
sysFatal(FloatUnderflowDefect, "FPU operations caused an underflow")
|
||||
|
||||
proc infCheck(x: float64) {.compilerproc, inline.} =
|
||||
if x != 0.0 and x*0.5 == x: raiseFloatOverflow(x)
|
||||
@@ -405,105 +405,57 @@ proc `%%`*(x, y: int32): int32 {.inline.} = cast[int32](cast[uint32](x) mod cast
|
||||
proc `%%`*(x, y: int64): int64 {.inline.} = cast[int64](cast[uint64](x) mod cast[uint64](y))
|
||||
|
||||
when not defined(nimPreviewSlimSystem):
|
||||
when defined(nimNoZeroExtendMagic):
|
||||
proc ze*(x: int8): int {.deprecated.} =
|
||||
## zero extends a smaller integer type to `int`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int](uint(cast[uint8](x)))
|
||||
proc ze*(x: int8): int {.deprecated.} =
|
||||
## zero extends a smaller integer type to `int`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int](uint(cast[uint8](x)))
|
||||
|
||||
proc ze*(x: int16): int {.deprecated.} =
|
||||
## zero extends a smaller integer type to `int`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int](uint(cast[uint16](x)))
|
||||
proc ze*(x: int16): int {.deprecated.} =
|
||||
## zero extends a smaller integer type to `int`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int](uint(cast[uint16](x)))
|
||||
|
||||
proc ze64*(x: int8): int64 {.deprecated.} =
|
||||
## zero extends a smaller integer type to `int64`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int64](uint64(cast[uint8](x)))
|
||||
proc ze64*(x: int8): int64 {.deprecated.} =
|
||||
## zero extends a smaller integer type to `int64`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int64](uint64(cast[uint8](x)))
|
||||
|
||||
proc ze64*(x: int16): int64 {.deprecated.} =
|
||||
## zero extends a smaller integer type to `int64`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int64](uint64(cast[uint16](x)))
|
||||
proc ze64*(x: int16): int64 {.deprecated.} =
|
||||
## zero extends a smaller integer type to `int64`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int64](uint64(cast[uint16](x)))
|
||||
|
||||
proc ze64*(x: int32): int64 {.deprecated.} =
|
||||
## zero extends a smaller integer type to `int64`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int64](uint64(cast[uint32](x)))
|
||||
proc ze64*(x: int32): int64 {.deprecated.} =
|
||||
## zero extends a smaller integer type to `int64`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int64](uint64(cast[uint32](x)))
|
||||
|
||||
proc ze64*(x: int): int64 {.deprecated.} =
|
||||
## zero extends a smaller integer type to `int64`. This treats `x` as
|
||||
## unsigned. Does nothing if the size of an `int` is the same as `int64`.
|
||||
## (This is the case on 64 bit processors.)
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int64](uint64(cast[uint](x)))
|
||||
proc ze64*(x: int): int64 {.deprecated.} =
|
||||
## zero extends a smaller integer type to `int64`. This treats `x` as
|
||||
## unsigned. Does nothing if the size of an `int` is the same as `int64`.
|
||||
## (This is the case on 64 bit processors.)
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int64](uint64(cast[uint](x)))
|
||||
|
||||
proc toU8*(x: int): int8 {.deprecated.} =
|
||||
## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
|
||||
## from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int8](x)
|
||||
proc toU8*(x: int): int8 {.deprecated.} =
|
||||
## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
|
||||
## from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int8](x)
|
||||
|
||||
proc toU16*(x: int): int16 {.deprecated.} =
|
||||
## treats `x` as unsigned and converts it to an `int16` by taking the last
|
||||
## 16 bits from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int16](x)
|
||||
proc toU16*(x: int): int16 {.deprecated.} =
|
||||
## treats `x` as unsigned and converts it to an `int16` by taking the last
|
||||
## 16 bits from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int16](x)
|
||||
|
||||
proc toU32*(x: int64): int32 {.deprecated.} =
|
||||
## treats `x` as unsigned and converts it to an `int32` by taking the
|
||||
## last 32 bits from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int32](x)
|
||||
|
||||
elif not defined(js):
|
||||
proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect, deprecated.}
|
||||
## zero extends a smaller integer type to `int`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect, deprecated.}
|
||||
## zero extends a smaller integer type to `int`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect, deprecated.}
|
||||
## zero extends a smaller integer type to `int64`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect, deprecated.}
|
||||
## zero extends a smaller integer type to `int64`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect, deprecated.}
|
||||
## zero extends a smaller integer type to `int64`. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc ze64*(x: int): int64 {.magic: "ZeIToI64", noSideEffect, deprecated.}
|
||||
## zero extends a smaller integer type to `int64`. This treats `x` as
|
||||
## unsigned. Does nothing if the size of an `int` is the same as `int64`.
|
||||
## (This is the case on 64 bit processors.)
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect, deprecated.}
|
||||
## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
|
||||
## from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect, deprecated.}
|
||||
## treats `x` as unsigned and converts it to an `int16` by taking the last
|
||||
## 16 bits from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc toU32*(x: int64): int32 {.magic: "ToU32", noSideEffect, deprecated.}
|
||||
## treats `x` as unsigned and converts it to an `int32` by taking the
|
||||
## last 32 bits from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
proc toU32*(x: int64): int32 {.deprecated.} =
|
||||
## treats `x` as unsigned and converts it to an `int32` by taking the
|
||||
## last 32 bits from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int32](x)
|
||||
|
||||
@@ -51,30 +51,24 @@ proc defined*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.}
|
||||
## * `compileOption <#compileOption,string,string>`_ for enum options
|
||||
## * `define pragmas <manual.html#implementation-specific-pragmas-compileminustime-define-pragmas>`_
|
||||
|
||||
when defined(nimHasDeclaredMagic):
|
||||
proc declared*(x: untyped): bool {.magic: "Declared", noSideEffect, compileTime.}
|
||||
## Special compile-time procedure that checks whether `x` is
|
||||
## declared. `x` has to be an identifier or a qualified identifier.
|
||||
##
|
||||
## This can be used to check whether a library provides a certain
|
||||
## feature or not:
|
||||
## ```
|
||||
## when not declared(strutils.toUpper):
|
||||
## # provide our own toUpper proc here, because strutils is
|
||||
## # missing it.
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `declaredInScope <#declaredInScope,untyped>`_
|
||||
else:
|
||||
proc declared*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.}
|
||||
proc declared*(x: untyped): bool {.magic: "Declared", noSideEffect, compileTime.}
|
||||
## Special compile-time procedure that checks whether `x` is
|
||||
## declared. `x` has to be an identifier or a qualified identifier.
|
||||
##
|
||||
## This can be used to check whether a library provides a certain
|
||||
## feature or not:
|
||||
## ```
|
||||
## when not declared(strutils.toUpper):
|
||||
## # provide our own toUpper proc here, because strutils is
|
||||
## # missing it.
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `declaredInScope <#declaredInScope,untyped>`_
|
||||
|
||||
when defined(nimHasDeclaredMagic):
|
||||
proc declaredInScope*(x: untyped): bool {.magic: "DeclaredInScope", noSideEffect, compileTime.}
|
||||
## Special compile-time procedure that checks whether `x` is
|
||||
## declared in the current scope. `x` has to be an identifier.
|
||||
else:
|
||||
proc declaredInScope*(x: untyped): bool {.magic: "DefinedInScope", noSideEffect, compileTime.}
|
||||
proc declaredInScope*(x: untyped): bool {.magic: "DeclaredInScope", noSideEffect, compileTime.}
|
||||
## Special compile-time procedure that checks whether `x` is
|
||||
## declared in the current scope. `x` has to be an identifier.
|
||||
|
||||
proc compiles*(x: untyped): bool {.magic: "Compiles", noSideEffect, compileTime.} =
|
||||
## Special compile-time procedure that checks whether `x` can be compiled
|
||||
|
||||
@@ -9,10 +9,7 @@
|
||||
|
||||
{.push profiler: off.}
|
||||
|
||||
when defined(nimHasExceptionsQuery):
|
||||
const gotoBasedExceptions = compileOption("exceptions", "goto")
|
||||
else:
|
||||
const gotoBasedExceptions = false
|
||||
const gotoBasedExceptions = compileOption("exceptions", "goto")
|
||||
|
||||
when hostOS == "standalone":
|
||||
include "$projectpath/panicoverride"
|
||||
|
||||
@@ -47,5 +47,4 @@ else:
|
||||
|
||||
{.pragma: benign, gcsafe.}
|
||||
|
||||
when defined(nimHasSinkInference):
|
||||
{.push sinkInference: on.}
|
||||
{.push sinkInference: on.}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
when defined(nimHasLentIterators) and not defined(nimNoLentIterators):
|
||||
when not defined(nimNoLentIterators):
|
||||
template lent2(T): untyped = lent T
|
||||
else:
|
||||
template lent2(T): untyped = T
|
||||
|
||||
@@ -503,28 +503,6 @@ proc absInt(a: int): int {.compilerproc.} =
|
||||
proc absInt64(a: int64): int64 {.compilerproc.} =
|
||||
result = if a < 0: a*(-1) else: a
|
||||
|
||||
when not defined(nimNoZeroExtendMagic):
|
||||
proc ze*(a: int): int {.compilerproc.} =
|
||||
result = a
|
||||
|
||||
proc ze64*(a: int64): int64 {.compilerproc.} =
|
||||
result = a
|
||||
|
||||
proc toU8*(a: int): int8 {.asmNoStackFrame, compilerproc.} =
|
||||
asm """
|
||||
return `a`;
|
||||
"""
|
||||
|
||||
proc toU16*(a: int): int16 {.asmNoStackFrame, compilerproc.} =
|
||||
asm """
|
||||
return `a`;
|
||||
"""
|
||||
|
||||
proc toU32*(a: int64): int32 {.asmNoStackFrame, compilerproc.} =
|
||||
asm """
|
||||
return `a`;
|
||||
"""
|
||||
|
||||
proc nimMin(a, b: int): int {.compilerproc.} = return if a <= b: a else: b
|
||||
proc nimMax(a, b: int): int {.compilerproc.} = return if a >= b: a else: b
|
||||
|
||||
|
||||
@@ -75,8 +75,8 @@ const
|
||||
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
|
||||
1e20, 1e21, 1e22]
|
||||
|
||||
when defined(nimHasInvariant):
|
||||
{.push staticBoundChecks: off.}
|
||||
|
||||
{.push staticBoundChecks: off.}
|
||||
|
||||
proc nimParseBiggestFloat(s: openArray[char], number: var BiggestFloat,
|
||||
): int {.compilerproc.} =
|
||||
@@ -234,8 +234,7 @@ proc nimParseBiggestFloat(s: openArray[char], number: var BiggestFloat,
|
||||
t[ti-3] = ('0'.ord + absExponent mod 10).char
|
||||
number = c_strtod(cast[cstring](addr t), nil)
|
||||
|
||||
when defined(nimHasInvariant):
|
||||
{.pop.} # staticBoundChecks
|
||||
{.pop.} # staticBoundChecks
|
||||
|
||||
proc nimBoolToStr(x: bool): string {.compilerRtl.} =
|
||||
return if x: "true" else: "false"
|
||||
|
||||
Reference in New Issue
Block a user