# # # The Nim Compiler # (c) Copyright 2020 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # from typetraits import supportsCopyMem type RodSection* = enum versionSection configSection stringsSection checkSumsSection depsSection integersSection floatsSection exportsSection reexportsSection compilerProcsSection trmacrosSection convertersSection methodsSection pureEnumsSection macroUsagesSection toReplaySection topLevelSection bodiesSection symsSection typesSection typeInstCacheSection procInstCacheSection attachedOpsSection methodsPerTypeSection enumToStringProcsSection aliveSymsSection # beware, this is stored in a `.alivesyms` file. RodFileError* = enum ok, tooBig, cannotOpen, ioFailure, wrongHeader, wrongSection, configMismatch, includeFileChanged RodFile* = object f*: File currentSection*: RodSection # for error checking err*: RodFileError # little experiment to see if this works # better than exceptions. const RodVersion = 1 cookie = [byte(0), byte('R'), byte('O'), byte('D'), byte(sizeof(int)*8), byte(system.cpuEndian), byte(0), byte(RodVersion)] proc setError(f: var RodFile; err: RodFileError) {.inline.} = f.err = err #raise newException(IOError, "IO error") proc storePrim*(f: var RodFile; s: string) = if f.err != ok: return if s.len >= high(int32): setError f, tooBig return var lenPrefix = int32(s.len) if writeBuffer(f.f, addr lenPrefix, sizeof(lenPrefix)) != sizeof(lenPrefix): setError f, ioFailure else: if s.len != 0: if writeBuffer(f.f, unsafeAddr(s[0]), s.len) != s.len: setError f, ioFailure proc storePrim*[T](f: var RodFile; x: T) = if f.err != ok: return when supportsCopyMem(T): if writeBuffer(f.f, unsafeAddr(x), sizeof(x)) != sizeof(x): setError f, ioFailure elif T is tuple: for y in fields(x): storePrim(f, y) elif T is object: for y in fields(x): when y is seq: storeSeq(f, y) else: storePrim(f, y) else: {.error: "unsupported type for 'storePrim'".} proc storeSeq*[T](f: var RodFile; s: seq[T]) = if f.err != ok: return if s.len >= high(int32): setError f, tooBig return var lenPrefix = int32(s.len) if writeBuffer(f.f, addr lenPrefix, sizeof(lenPrefix)) != sizeof(lenPrefix): setError f, ioFailure else: for i in 0.. 0: if readBuffer(f.f, unsafeAddr(s[0]), s.len) != s.len: setError f, ioFailure proc loadPrim*[T](f: var RodFile; x: var T) = if f.err != ok: return when supportsCopyMem(T): if readBuffer(f.f, unsafeAddr(x), sizeof(x)) != sizeof(x): setError f, ioFailure elif T is tuple: for y in fields(x): loadPrim(f, y) elif T is object: for y in fields(x): when y is seq: loadSeq(f, y) else: loadPrim(f, y) else: {.error: "unsupported type for 'loadPrim'".} proc loadSeq*[T](f: var RodFile; s: var seq[T]) = if f.err != ok: return var lenPrefix = int32(0) if readBuffer(f.f, addr lenPrefix, sizeof(lenPrefix)) != sizeof(lenPrefix): setError f, ioFailure else: s = newSeq[T](lenPrefix) for i in 0..