diff options
-rw-r--r-- | lib/pure/times.nim | 507 | ||||
-rw-r--r-- | lib/system/excpt.nim | 5 | ||||
-rw-r--r-- | tests/exception/tdont_overwrite_typename.nim | 29 | ||||
-rw-r--r-- | tests/js/ttimes.nim | 26 | ||||
-rw-r--r-- | web/download.rst | 20 |
5 files changed, 318 insertions, 269 deletions
diff --git a/lib/pure/times.nim b/lib/pure/times.nim index fe35c404c..1b088c0ac 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -385,260 +385,6 @@ proc `miliseconds=`*(t: var TimeInterval, milliseconds: int) {.deprecated.} = ## version. t.milliseconds = milliseconds -when not defined(JS): - proc epochTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].} - ## gets time after the UNIX epoch (1970) in seconds. It is a float - ## because sub-second resolution is likely to be supported (depending - ## on the hardware/OS). - - proc cpuTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].} - ## gets time spent that the CPU spent to run the current process in - ## seconds. This may be more useful for benchmarking than ``epochTime``. - ## However, it may measure the real time instead (depending on the OS). - ## The value of the result has no meaning. - ## To generate useful timing values, take the difference between - ## the results of two ``cpuTime`` calls: - ## - ## .. code-block:: nim - ## var t0 = cpuTime() - ## doWork() - ## echo "CPU time [s] ", cpuTime() - t0 - -when not defined(JS): - # C wrapper: - when defined(freebsd) or defined(netbsd) or defined(openbsd) or - defined(macosx): - type - StructTM {.importc: "struct tm", final.} = object - second {.importc: "tm_sec".}, - minute {.importc: "tm_min".}, - hour {.importc: "tm_hour".}, - monthday {.importc: "tm_mday".}, - month {.importc: "tm_mon".}, - year {.importc: "tm_year".}, - weekday {.importc: "tm_wday".}, - yearday {.importc: "tm_yday".}, - isdst {.importc: "tm_isdst".}: cint - gmtoff {.importc: "tm_gmtoff".}: clong - else: - type - StructTM {.importc: "struct tm", final.} = object - second {.importc: "tm_sec".}, - minute {.importc: "tm_min".}, - hour {.importc: "tm_hour".}, - monthday {.importc: "tm_mday".}, - month {.importc: "tm_mon".}, - year {.importc: "tm_year".}, - weekday {.importc: "tm_wday".}, - yearday {.importc: "tm_yday".}, - isdst {.importc: "tm_isdst".}: cint - type - TimeInfoPtr = ptr StructTM - Clock {.importc: "clock_t".} = distinct int - - when not defined(windows): - # This is not ANSI C, but common enough - proc timegm(t: StructTM): Time {. - importc: "timegm", header: "<time.h>", tags: [].} - - proc localtime(timer: ptr Time): TimeInfoPtr {. - importc: "localtime", header: "<time.h>", tags: [].} - proc gmtime(timer: ptr Time): TimeInfoPtr {. - importc: "gmtime", header: "<time.h>", tags: [].} - proc timec(timer: ptr Time): Time {. - importc: "time", header: "<time.h>", tags: [].} - proc mktime(t: StructTM): Time {. - importc: "mktime", header: "<time.h>", tags: [].} - proc getClock(): Clock {.importc: "clock", header: "<time.h>", tags: [TimeEffect].} - proc difftime(a, b: Time): float {.importc: "difftime", header: "<time.h>", - tags: [].} - - var - clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int - - # our own procs on top of that: - proc tmToTimeInfo(tm: StructTM, local: bool): TimeInfo = - const - weekDays: array[0..6, WeekDay] = [ - dSun, dMon, dTue, dWed, dThu, dFri, dSat] - TimeInfo(second: int(tm.second), - minute: int(tm.minute), - hour: int(tm.hour), - monthday: int(tm.monthday), - month: Month(tm.month), - year: tm.year + 1900'i32, - weekday: weekDays[int(tm.weekday)], - yearday: int(tm.yearday), - isDST: tm.isdst > 0, - timezone: if local: getTimezone() else: 0 - ) - - - proc timeInfoToTM(t: TimeInfo): StructTM = - const - weekDays: array[WeekDay, int8] = [1'i8,2'i8,3'i8,4'i8,5'i8,6'i8,0'i8] - result.second = t.second - result.minute = t.minute - result.hour = t.hour - result.monthday = t.monthday - result.month = ord(t.month) - result.year = cint(t.year - 1900) - result.weekday = weekDays[t.weekday] - result.yearday = t.yearday - result.isdst = if t.isDST: 1 else: 0 - - when not defined(useNimRtl): - proc `-` (a, b: Time): int64 = - return toBiggestInt(difftime(a, b)) - - proc getStartMilsecs(): int = - #echo "clocks per sec: ", clocksPerSec, "clock: ", int(getClock()) - #return getClock() div (clocksPerSec div 1000) - when defined(macosx): - result = toInt(toFloat(int(getClock())) / (toFloat(clocksPerSec) / 1000.0)) - else: - result = int(getClock()) div (clocksPerSec div 1000) - when false: - var a: Timeval - posix_gettimeofday(a) - result = a.tv_sec * 1000'i64 + a.tv_usec div 1000'i64 - #echo "result: ", result - - proc getTime(): Time = return timec(nil) - proc getLocalTime(t: Time): TimeInfo = - var a = t - let lt = localtime(addr(a)) - assert(not lt.isNil) - result = tmToTimeInfo(lt[], true) - # copying is needed anyway to provide reentrancity; thus - # the conversion is not expensive - - proc getGMTime(t: Time): TimeInfo = - var a = t - result = tmToTimeInfo(gmtime(addr(a))[], false) - # copying is needed anyway to provide reentrancity; thus - # the conversion is not expensive - - proc toTime(timeInfo: TimeInfo): Time = - var cTimeInfo = timeInfo # for C++ we have to make a copy - # because the header of mktime is broken in my version of libc - - result = mktime(timeInfoToTM(cTimeInfo)) - # mktime is defined to interpret the input as local time. As timeInfoToTM - # does ignore the timezone, we need to adjust this here. - result = Time(TimeImpl(result) - getTimezone() + timeInfo.timezone) - - proc timeInfoToTime(timeInfo: TimeInfo): Time = toTime(timeInfo) - - const - epochDiff = 116444736000000000'i64 - rateDiff = 10000000'i64 # 100 nsecs - - proc unixTimeToWinTime*(t: Time): int64 = - ## converts a UNIX `Time` (``time_t``) to a Windows file time - result = int64(t) * rateDiff + epochDiff - - proc winTimeToUnixTime*(t: int64): Time = - ## converts a Windows time to a UNIX `Time` (``time_t``) - result = Time((t - epochDiff) div rateDiff) - - proc getTimezone(): int = - when defined(freebsd) or defined(netbsd) or defined(openbsd): - var a = timec(nil) - let lt = localtime(addr(a)) - # BSD stores in `gmtoff` offset east of UTC in seconds, - # but posix systems using west of UTC in seconds - return -(lt.gmtoff) - else: - return timezone - - proc fromSeconds(since1970: float): Time = Time(since1970) - - proc toSeconds(time: Time): float = float(time) - - when not defined(useNimRtl): - proc epochTime(): float = - when defined(posix): - var a: Timeval - posix_gettimeofday(a) - result = toFloat(a.tv_sec) + toFloat(a.tv_usec)*0.00_0001 - elif defined(windows): - var f: winlean.FILETIME - getSystemTimeAsFileTime(f) - var i64 = rdFileTime(f) - epochDiff - var secs = i64 div rateDiff - var subsecs = i64 mod rateDiff - result = toFloat(int(secs)) + toFloat(int(subsecs)) * 0.0000001 - else: - {.error: "unknown OS".} - - proc cpuTime(): float = - result = toFloat(int(getClock())) / toFloat(clocksPerSec) - -elif defined(JS): - proc newDate(): Time {.importc: "new Date".} - proc internGetTime(): Time {.importc: "new Date", tags: [].} - - proc newDate(value: float): Time {.importc: "new Date".} - proc newDate(value: string): Time {.importc: "new Date".} - proc getTime(): Time = - # Warning: This is something different in JS. - return newDate() - - const - weekDays: array[0..6, WeekDay] = [ - dSun, dMon, dTue, dWed, dThu, dFri, dSat] - - proc getLocalTime(t: Time): TimeInfo = - result.second = t.getSeconds() - result.minute = t.getMinutes() - result.hour = t.getHours() - result.monthday = t.getDate() - result.month = Month(t.getMonth()) - result.year = t.getFullYear() - result.weekday = weekDays[t.getDay()] - result.yearday = 0 - result.timezone = getTimezone() - - proc getGMTime(t: Time): TimeInfo = - result.second = t.getUTCSeconds() - result.minute = t.getUTCMinutes() - result.hour = t.getUTCHours() - result.monthday = t.getUTCDate() - result.month = Month(t.getUTCMonth()) - result.year = t.getUTCFullYear() - result.weekday = weekDays[t.getUTCDay()] - result.yearday = 0 - - proc timeInfoToTime(timeInfo: TimeInfo): Time = toTime(timeInfo) - - proc toTime*(timeInfo: TimeInfo): Time = - result = internGetTime() - result.setMinutes(timeInfo.minute) - result.setHours(timeInfo.hour) - result.setMonth(ord(timeInfo.month)) - result.setFullYear(timeInfo.year) - result.setDate(timeInfo.monthday) - result.setSeconds(timeInfo.second + timeInfo.timezone) - - proc `-` (a, b: Time): int64 = - return a.getTime() - b.getTime() - - var - startMilsecs = getTime() - - proc getStartMilsecs(): int = - ## get the milliseconds from the start of the program - return int(getTime() - startMilsecs) - - proc fromSeconds(since1970: float): Time = result = newDate(since1970 * 1000) - - proc toSeconds(time: Time): float = result = time.getTime() / 1000 - - proc getTimezone(): int = result = newDate().getTimezoneOffset() * 60 - - proc epochTime*(): float {.tags: [TimeEffect].} = newDate().toSeconds() - proc getDateStr*(): string {.rtl, extern: "nt$1", tags: [TimeEffect].} = ## gets the current date as a string of the format ``YYYY-MM-DD``. var ti = getLocalTime(getTime()) @@ -1333,6 +1079,259 @@ proc toTimeInterval*(t: Time): TimeInterval = var tInfo = t.getLocalTime() initInterval(0, tInfo.second, tInfo.minute, tInfo.hour, tInfo.weekday.ord, tInfo.month.ord, tInfo.year) +when not defined(JS): + proc epochTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].} + ## gets time after the UNIX epoch (1970) in seconds. It is a float + ## because sub-second resolution is likely to be supported (depending + ## on the hardware/OS). + + proc cpuTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].} + ## gets time spent that the CPU spent to run the current process in + ## seconds. This may be more useful for benchmarking than ``epochTime``. + ## However, it may measure the real time instead (depending on the OS). + ## The value of the result has no meaning. + ## To generate useful timing values, take the difference between + ## the results of two ``cpuTime`` calls: + ## + ## .. code-block:: nim + ## var t0 = cpuTime() + ## doWork() + ## echo "CPU time [s] ", cpuTime() - t0 + +when not defined(JS): + # C wrapper: + when defined(freebsd) or defined(netbsd) or defined(openbsd) or + defined(macosx): + type + StructTM {.importc: "struct tm", final.} = object + second {.importc: "tm_sec".}, + minute {.importc: "tm_min".}, + hour {.importc: "tm_hour".}, + monthday {.importc: "tm_mday".}, + month {.importc: "tm_mon".}, + year {.importc: "tm_year".}, + weekday {.importc: "tm_wday".}, + yearday {.importc: "tm_yday".}, + isdst {.importc: "tm_isdst".}: cint + gmtoff {.importc: "tm_gmtoff".}: clong + else: + type + StructTM {.importc: "struct tm", final.} = object + second {.importc: "tm_sec".}, + minute {.importc: "tm_min".}, + hour {.importc: "tm_hour".}, + monthday {.importc: "tm_mday".}, + month {.importc: "tm_mon".}, + year {.importc: "tm_year".}, + weekday {.importc: "tm_wday".}, + yearday {.importc: "tm_yday".}, + isdst {.importc: "tm_isdst".}: cint + type + TimeInfoPtr = ptr StructTM + Clock {.importc: "clock_t".} = distinct int + + when not defined(windows): + # This is not ANSI C, but common enough + proc timegm(t: StructTM): Time {. + importc: "timegm", header: "<time.h>", tags: [].} + + proc localtime(timer: ptr Time): TimeInfoPtr {. + importc: "localtime", header: "<time.h>", tags: [].} + proc gmtime(timer: ptr Time): TimeInfoPtr {. + importc: "gmtime", header: "<time.h>", tags: [].} + proc timec(timer: ptr Time): Time {. + importc: "time", header: "<time.h>", tags: [].} + proc mktime(t: StructTM): Time {. + importc: "mktime", header: "<time.h>", tags: [].} + proc getClock(): Clock {.importc: "clock", header: "<time.h>", tags: [TimeEffect].} + proc difftime(a, b: Time): float {.importc: "difftime", header: "<time.h>", + tags: [].} + + var + clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int + + # our own procs on top of that: + proc tmToTimeInfo(tm: StructTM, local: bool): TimeInfo = + const + weekDays: array[0..6, WeekDay] = [ + dSun, dMon, dTue, dWed, dThu, dFri, dSat] + TimeInfo(second: int(tm.second), + minute: int(tm.minute), + hour: int(tm.hour), + monthday: int(tm.monthday), + month: Month(tm.month), + year: tm.year + 1900'i32, + weekday: weekDays[int(tm.weekday)], + yearday: int(tm.yearday), + isDST: tm.isdst > 0, + timezone: if local: getTimezone() else: 0 + ) + + + proc timeInfoToTM(t: TimeInfo): StructTM = + const + weekDays: array[WeekDay, int8] = [1'i8,2'i8,3'i8,4'i8,5'i8,6'i8,0'i8] + result.second = t.second + result.minute = t.minute + result.hour = t.hour + result.monthday = t.monthday + result.month = ord(t.month) + result.year = cint(t.year - 1900) + result.weekday = weekDays[t.weekday] + result.yearday = t.yearday + result.isdst = if t.isDST: 1 else: 0 + + when not defined(useNimRtl): + proc `-` (a, b: Time): int64 = + return toBiggestInt(difftime(a, b)) + + proc getStartMilsecs(): int = + #echo "clocks per sec: ", clocksPerSec, "clock: ", int(getClock()) + #return getClock() div (clocksPerSec div 1000) + when defined(macosx): + result = toInt(toFloat(int(getClock())) / (toFloat(clocksPerSec) / 1000.0)) + else: + result = int(getClock()) div (clocksPerSec div 1000) + when false: + var a: Timeval + posix_gettimeofday(a) + result = a.tv_sec * 1000'i64 + a.tv_usec div 1000'i64 + #echo "result: ", result + + proc getTime(): Time = return timec(nil) + proc getLocalTime(t: Time): TimeInfo = + var a = t + let lt = localtime(addr(a)) + assert(not lt.isNil) + result = tmToTimeInfo(lt[], true) + # copying is needed anyway to provide reentrancity; thus + # the conversion is not expensive + + proc getGMTime(t: Time): TimeInfo = + var a = t + result = tmToTimeInfo(gmtime(addr(a))[], false) + # copying is needed anyway to provide reentrancity; thus + # the conversion is not expensive + + proc toTime(timeInfo: TimeInfo): Time = + var cTimeInfo = timeInfo # for C++ we have to make a copy + # because the header of mktime is broken in my version of libc + + result = mktime(timeInfoToTM(cTimeInfo)) + # mktime is defined to interpret the input as local time. As timeInfoToTM + # does ignore the timezone, we need to adjust this here. + result = Time(TimeImpl(result) - getTimezone() + timeInfo.timezone) + + proc timeInfoToTime(timeInfo: TimeInfo): Time = toTime(timeInfo) + + const + epochDiff = 116444736000000000'i64 + rateDiff = 10000000'i64 # 100 nsecs + + proc unixTimeToWinTime*(t: Time): int64 = + ## converts a UNIX `Time` (``time_t``) to a Windows file time + result = int64(t) * rateDiff + epochDiff + + proc winTimeToUnixTime*(t: int64): Time = + ## converts a Windows time to a UNIX `Time` (``time_t``) + result = Time((t - epochDiff) div rateDiff) + + proc getTimezone(): int = + when defined(freebsd) or defined(netbsd) or defined(openbsd): + var a = timec(nil) + let lt = localtime(addr(a)) + # BSD stores in `gmtoff` offset east of UTC in seconds, + # but posix systems using west of UTC in seconds + return -(lt.gmtoff) + else: + return timezone + + proc fromSeconds(since1970: float): Time = Time(since1970) + + proc toSeconds(time: Time): float = float(time) + + when not defined(useNimRtl): + proc epochTime(): float = + when defined(posix): + var a: Timeval + posix_gettimeofday(a) + result = toFloat(a.tv_sec) + toFloat(a.tv_usec)*0.00_0001 + elif defined(windows): + var f: winlean.FILETIME + getSystemTimeAsFileTime(f) + var i64 = rdFileTime(f) - epochDiff + var secs = i64 div rateDiff + var subsecs = i64 mod rateDiff + result = toFloat(int(secs)) + toFloat(int(subsecs)) * 0.0000001 + else: + {.error: "unknown OS".} + + proc cpuTime(): float = + result = toFloat(int(getClock())) / toFloat(clocksPerSec) + +elif defined(JS): + proc newDate(): Time {.importc: "new Date".} + proc internGetTime(): Time {.importc: "new Date", tags: [].} + + proc newDate(value: float): Time {.importc: "new Date".} + proc newDate(value: cstring): Time {.importc: "new Date".} + proc getTime(): Time = + # Warning: This is something different in JS. + return newDate() + + const + weekDays: array[0..6, WeekDay] = [ + dSun, dMon, dTue, dWed, dThu, dFri, dSat] + + proc getLocalTime(t: Time): TimeInfo = + result.second = t.getSeconds() + result.minute = t.getMinutes() + result.hour = t.getHours() + result.monthday = t.getDate() + result.month = Month(t.getMonth()) + result.year = t.getFullYear() + result.weekday = weekDays[t.getDay()] + result.timezone = getTimezone() + + result.yearday = result.monthday - 1 + for month in mJan..<result.month: + result.yearday += getDaysInMonth(month, result.year) + + proc getGMTime(t: Time): TimeInfo = + result.second = t.getUTCSeconds() + result.minute = t.getUTCMinutes() + result.hour = t.getUTCHours() + result.monthday = t.getUTCDate() + result.month = Month(t.getUTCMonth()) + result.year = t.getUTCFullYear() + result.weekday = weekDays[t.getUTCDay()] + + result.yearday = result.monthday - 1 + for month in mJan..<result.month: + result.yearday += getDaysInMonth(month, result.year) + + proc timeInfoToTime(timeInfo: TimeInfo): Time = toTime(timeInfo) + + proc toTime*(timeInfo: TimeInfo): Time = newDate($timeInfo) + + proc `-` (a, b: Time): int64 = + return a.getTime() - b.getTime() + + var + startMilsecs = getTime() + + proc getStartMilsecs(): int = + ## get the milliseconds from the start of the program + return int(getTime() - startMilsecs) + + proc fromSeconds(since1970: float): Time = result = newDate(since1970 * 1000) + + proc toSeconds(time: Time): float = result = time.getTime() / 1000 + + proc getTimezone(): int = result = newDate().getTimezoneOffset() * 60 + + proc epochTime*(): float {.tags: [TimeEffect].} = newDate().toSeconds() + when isMainModule: # this is testing non-exported function diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index bae5de9d3..8ed1fbb38 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -73,7 +73,8 @@ proc popSafePoint {.compilerRtl, inl.} = excHandler = excHandler.prev proc pushCurrentException(e: ref Exception) {.compilerRtl, inl.} = - e.parent = currException + #if e.parent.isNil: + # e.parent = currException currException = e proc popCurrentException {.compilerRtl, inl.} = @@ -279,7 +280,7 @@ proc raiseExceptionAux(e: ref Exception) = quitOrDebug() proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} = - e.name = ename + if e.name.isNil: e.name = ename when hasSomeStackTrace: e.trace = "" rawWriteStackTrace(e.trace) diff --git a/tests/exception/tdont_overwrite_typename.nim b/tests/exception/tdont_overwrite_typename.nim new file mode 100644 index 000000000..147ccc001 --- /dev/null +++ b/tests/exception/tdont_overwrite_typename.nim @@ -0,0 +1,29 @@ +discard """ + output: '''Check passed +Check passed''' +""" + +# bug #5628 + +proc checkException(ex: ref Exception) = + doAssert(ex.name == "ValueError") + doAssert(ex.msg == "SecondException") + doAssert(ex.parent != nil) + doAssert(ex.parent.name == "KeyError") + doAssert(ex.parent.msg == "FirstException") + echo "Check passed" + +var e: ref Exception +try: + try: + raise newException(KeyError, "FirstException") + except: + raise newException(ValueError, "SecondException", getCurrentException()) +except: + e = getCurrentException() + +try: + checkException(e) # passes here + raise e +except ValueError: + checkException(getCurrentException()) # fails here diff --git a/tests/js/ttimes.nim b/tests/js/ttimes.nim new file mode 100644 index 000000000..20ba14245 --- /dev/null +++ b/tests/js/ttimes.nim @@ -0,0 +1,26 @@ +# test times module with js +discard """ + action: run +""" + +import times + +# $ date --date='@2147483647' +# Tue 19 Jan 03:14:07 GMT 2038 + +block yeardayTest: + # check if yearday attribute is properly set on TimeInfo creation + doAssert fromSeconds(2147483647).getGMTime().yearday == 18 + +block localTimezoneTest: + # check if timezone is properly set during Time to TimeInfo conversion + doAssert fromSeconds(2147483647).getLocalTime().timezone == getTimezone() + +block timestampPersistenceTest: + # check if timestamp persists during TimeInfo to Time conversion + const + timeString = "2017-03-21T12:34:56+03:00" + timeStringGmt = "2017-03-21T09:34:56+00:00" + fmt = "yyyy-MM-dd'T'HH:mm:sszzz" + + doAssert $timeString.parse(fmt).toTime().getGMTime() == timeStringGmt diff --git a/web/download.rst b/web/download.rst index d2c6a0fc2..dd086cbaa 100644 --- a/web/download.rst +++ b/web/download.rst @@ -9,7 +9,8 @@ Windows Zips %%%% -We now encourage you to install via the provided zipfiles: +Since the website moved to https, only installation via the provided zipfiles +is supported: * | 32 bit: `nim-0.16.0_x32.zip <download/nim-0.16.0_x32.zip>`_ | SHA-256 69af94a6875a02543c1bf0fa03c665f126f8500a2c0e226c32571e64c6842e57 @@ -25,21 +26,14 @@ You can find the required DLLs here, if you lack them for some reason: | SHA-256 198112d3d6dc74d7964ba452158d44bfa57adef4dc47be8c39903f2a24e4a555 -Exes -%%%% +These versions of mingw are known to work: -You can download an installer for both 32 bit and 64 bit versions of -Windows below. Note that these installers have some known issues and -so will unlikely to be provided further in the future. These -installers have everything you need to use Nim, including a C compiler. +* | 32 bit: `mingw32-6.3.0 <download/mingw32-6.3.0.7z>`_ + | SHA-256 1239a56d4c42e146b2cb25dc4d0871bd83f569d0a51a9198e84d010e0a75745a +* | 64 bit: `mingw64-6.3.0 <download/mingw64-6.3.0.7z>`_ + | SHA-256 9a23d12d96a10e67093c1f2042275c6a7d29da9e2ead573d0f24f4a6d53761a1 -* | 32 bit: `nim-0.16.0_x32.exe <download/nim-0.16.0_x32.exe>`_ - | SHA-256 37c55d9f9b3a2947559901c8bbd10b6a16191b562ca2bebdc145a6c24f5d004e -* | 64 bit: `nim-0.16.0_x64.exe <download/nim-0.16.0_x64.exe>`_ - | SHA-256 13934282b01cbcaf7ad7aecb67e954dd0ea2b576c6c8102016cb9a9a30cce744 -These installers also include Aporia, Nimble and other useful Nim tools to get -you started with Nim development! Installation based on generated C code -------------------------------------- |