internal.nim
1 # NimYAML - YAML implementation in Nim 2 # (c) Copyright 2015-2023 Felix Krause 3 # 4 # See the file "copying.txt", included in this 5 # distribution, for details about the copyright. 6 7 import tables 8 import ../data 9 10 template internalError*(s: string) = 11 # Note: to get the internal stacktrace that caused the error 12 # compile with the `d:debug` flag. 13 when not defined(release): 14 let ii = instantiationInfo() 15 echo "[NimYAML] Error in file ", ii.filename, " at line ", ii.line, ":" 16 echo s 17 when not defined(JS): 18 try: 19 var exc = getCurrentException() 20 while not isNil(exc): 21 echo "… stacktrace [", exc.name, ": ", exc.msg, "]" 22 echo getStackTrace(exc) 23 exc = exc.parent 24 except CatchableError: discard 25 echo "[NimYAML] Please report this bug." 26 quit 1 27 28 template yAssert*(e: typed) = 29 when not defined(release): 30 if not e: 31 let ii = instantiationInfo() 32 echo "[NimYAML] Error in file ", ii.filename, " at line ", ii.line, ":" 33 echo "assertion failed!" 34 when not defined(JS): 35 echo "[NimYAML] Stacktrace:" 36 try: 37 writeStackTrace() 38 let exc = getCurrentException() 39 if not isNil(exc.parent): 40 echo "Internal stacktrace:" 41 echo getStackTrace(exc.parent) 42 except CatchableError: discard 43 echo "[NimYAML] Please report this bug." 44 quit 1 45 46 proc nextAnchor*(s: var string, i: int) = 47 if s[i] == 'z': 48 s[i] = 'a' 49 if i == 0: 50 s.add('a') 51 else: 52 s[i] = 'a' 53 nextAnchor(s, i - 1) 54 else: 55 s[i] = char(int(s[i]) + 1) 56 57 template resetHandles*(handles: var seq[tuple[handle, uriPrefix: string]]) {.dirty.} = 58 handles.setLen(0) 59 handles.add(("!", "!")) 60 handles.add(("!!", yamlTagRepositoryPrefix)) 61 62 proc registerHandle*(handles: var seq[tuple[handle, uriPrefix: string]], handle, uriPrefix: string): bool = 63 for i in countup(0, len(handles)-1): 64 if handles[i].handle == handle: 65 handles[i].uriPrefix = uriPrefix 66 return false 67 handles.add((handle, uriPrefix)) 68 return false 69 70 type 71 AnchorContext* = object 72 nextAnchorId: string 73 mapping: Table[Anchor, Anchor] 74 75 proc initAnchorContext*(): AnchorContext = 76 return AnchorContext(nextAnchorId: "a", mapping: initTable[Anchor, Anchor]()) 77 78 proc process*(context: var AnchorContext, 79 target: var Properties, refs: Table[pointer, tuple[a: Anchor, referenced: bool]]) = 80 if target.anchor == yAnchorNone: return 81 for key, val in refs: 82 if val.a == target.anchor: 83 if not val.referenced: 84 target.anchor = yAnchorNone 85 return 86 break 87 if context.mapping.hasKey(target.anchor): 88 target.anchor = context.mapping.getOrDefault(target.anchor) 89 else: 90 let old = move(target.anchor) 91 target.anchor = context.nextAnchorId.Anchor 92 nextAnchor(context.nextAnchorId, len(context.nextAnchorId)-1) 93 context.mapping[old] = target.anchor 94 95 proc map*(context: AnchorContext, anchor: Anchor): Anchor = 96 return context.mapping.getOrDefault(anchor)