mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-18 02:54:52 +00:00
Merge branch 'devel' of github.com:nim-lang/Nim into devel
This commit is contained in:
@@ -187,3 +187,6 @@ let
|
||||
mySeq = @[1, 2, 1, 3, 1, 4]
|
||||
myCounter = mySeq.toCountTable()
|
||||
```
|
||||
|
||||
- Added support for casting between integers of same bitsize in VM (compile time and nimscript).
|
||||
This allow to among other things to reinterpret signed integers as unsigned.
|
||||
|
||||
@@ -1258,7 +1258,7 @@ proc resetModule*(m: BModule) =
|
||||
|
||||
# indicate that this is now cached module
|
||||
# the cache will be invalidated by nullifying gModules
|
||||
m.fromCache = true
|
||||
#m.fromCache = true
|
||||
m.g = nil
|
||||
|
||||
# we keep only the "merge info" information for the module
|
||||
@@ -1390,7 +1390,7 @@ proc writeModule(m: BModule, pending: bool) =
|
||||
# generate code for the init statements of the module:
|
||||
let cfile = getCFile(m)
|
||||
|
||||
if not m.fromCache or optForceFullMake in gGlobalOptions:
|
||||
if m.rd == nil or optForceFullMake in gGlobalOptions:
|
||||
genInitCode(m)
|
||||
finishTypeDescriptions(m)
|
||||
if sfMainModule in m.module.flags:
|
||||
@@ -1465,10 +1465,10 @@ proc cgenWriteModules*(backend: RootRef, config: ConfigRef) =
|
||||
if g.generatedHeader != nil: finishModule(g.generatedHeader)
|
||||
while g.forwardedProcsCounter > 0:
|
||||
for m in cgenModules(g):
|
||||
if not m.fromCache:
|
||||
if m.rd == nil:
|
||||
finishModule(m)
|
||||
for m in cgenModules(g):
|
||||
if m.fromCache:
|
||||
if m.rd != nil:
|
||||
m.updateCachedModule
|
||||
else:
|
||||
m.writeModule(pending=true)
|
||||
|
||||
@@ -253,7 +253,7 @@ compiler tcc:
|
||||
compilerExe: "tcc",
|
||||
cppCompiler: "",
|
||||
compileTmpl: "-c $options $include -o $objfile $file",
|
||||
buildGui: "UNAVAILABLE!",
|
||||
buildGui: "-Wl,-subsystem=gui",
|
||||
buildDll: " -shared",
|
||||
buildLib: "", # XXX: not supported yet
|
||||
linkerExe: "tcc",
|
||||
|
||||
@@ -2051,10 +2051,10 @@ proc genConv(p: PProc, n: PNode, r: var TCompRes) =
|
||||
return
|
||||
case dest.kind:
|
||||
of tyBool:
|
||||
r.res = "(($1)? 1:0)" % [r.res]
|
||||
r.res = "(!!($1))" % [r.res]
|
||||
r.kind = resExpr
|
||||
of tyInt:
|
||||
r.res = "($1|0)" % [r.res]
|
||||
r.res = "(($1)|0)" % [r.res]
|
||||
else:
|
||||
# TODO: What types must we handle here?
|
||||
discard
|
||||
|
||||
@@ -18,7 +18,7 @@ import
|
||||
|
||||
type
|
||||
TPassContext* = object of RootObj # the pass's context
|
||||
fromCache*: bool # true if created by "openCached"
|
||||
rd*: PRodReader # != nil if created by "openCached"
|
||||
|
||||
PPassContext* = ref TPassContext
|
||||
|
||||
@@ -118,7 +118,7 @@ proc openPassesCached(g: ModuleGraph; a: var TPassContextArray, module: PSym,
|
||||
if not isNil(gPasses[i].openCached):
|
||||
a[i] = gPasses[i].openCached(g, module, rd)
|
||||
if a[i] != nil:
|
||||
a[i].fromCache = true
|
||||
a[i].rd = rd
|
||||
else:
|
||||
a[i] = nil
|
||||
|
||||
|
||||
@@ -719,6 +719,7 @@ proc gcase(g: var TSrcGen, n: PNode) =
|
||||
var c: TContext
|
||||
initContext(c)
|
||||
var length = sonsLen(n)
|
||||
if length == 0: return
|
||||
var last = if n.sons[length-1].kind == nkElse: -2 else: -1
|
||||
if longMode(g, n, 0, last): incl(c.flags, rfLongMode)
|
||||
putWithSpace(g, tkCase, "case")
|
||||
|
||||
@@ -74,7 +74,7 @@ proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
|
||||
localError(arg.info, errExprXHasNoType,
|
||||
renderTree(arg, {renderNoComments}))
|
||||
# error correction:
|
||||
result = copyNode(arg)
|
||||
result = copyTree(arg)
|
||||
result.typ = formal
|
||||
else:
|
||||
result = indexTypesMatch(c, formal, arg.typ, arg)
|
||||
@@ -168,9 +168,9 @@ proc commonType*(x, y: PType): PType =
|
||||
proc endsInNoReturn(n: PNode): bool =
|
||||
# check if expr ends in raise exception or call of noreturn proc
|
||||
var it = n
|
||||
while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0:
|
||||
while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0:
|
||||
it = it.lastSon
|
||||
result = it.kind == nkRaiseStmt or
|
||||
result = it.kind == nkRaiseStmt or
|
||||
it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags
|
||||
|
||||
proc commonType*(x: PType, y: PNode): PType =
|
||||
@@ -501,6 +501,8 @@ proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
|
||||
|
||||
proc myOpenCached(graph: ModuleGraph; module: PSym; rd: PRodReader): PPassContext =
|
||||
result = myOpen(graph, module, rd.cache)
|
||||
|
||||
proc replayMethodDefs(graph: ModuleGraph; rd: PRodReader) =
|
||||
for m in items(rd.methods): methodDef(graph, m, true)
|
||||
|
||||
proc isImportSystemStmt(n: PNode): bool =
|
||||
@@ -607,6 +609,8 @@ proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
|
||||
addCodeForGenerics(c, result)
|
||||
if c.module.ast != nil:
|
||||
result.add(c.module.ast)
|
||||
if c.rd != nil:
|
||||
replayMethodDefs(graph, c.rd)
|
||||
popOwner(c)
|
||||
popProcCon(c)
|
||||
if c.runnableExamples != nil: testExamples(c)
|
||||
|
||||
@@ -1425,11 +1425,7 @@ proc semProcBody(c: PContext, n: PNode): PNode =
|
||||
openScope(c)
|
||||
result = semExpr(c, n)
|
||||
if c.p.resultSym != nil and not isEmptyType(result.typ):
|
||||
# transform ``expr`` to ``result = expr``, but not if the expr is already
|
||||
# ``result``:
|
||||
if result.kind == nkSym and result.sym == c.p.resultSym:
|
||||
discard
|
||||
elif result.kind == nkNilLit:
|
||||
if result.kind == nkNilLit:
|
||||
# or ImplicitlyDiscardable(result):
|
||||
# new semantic: 'result = x' triggers the void context
|
||||
result.typ = nil
|
||||
|
||||
@@ -914,7 +914,7 @@ proc processTransf(c: PTransf, n: PNode, owner: PSym): PNode =
|
||||
# Note: For interactive mode we cannot call 'passes.skipCodegen' and skip
|
||||
# this step! We have to rely that the semantic pass transforms too errornous
|
||||
# nodes into an empty node.
|
||||
if c.fromCache or nfTransf in n.flags: return n
|
||||
if c.rd != nil or nfTransf in n.flags: return n
|
||||
pushTransCon(c, newTransCon(owner))
|
||||
result = PNode(transform(c, n))
|
||||
popTransCon(c)
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
import
|
||||
strutils, ast, astalgo, types, msgs, renderer, vmdef,
|
||||
trees, intsets, rodread, magicsys, options, lowerings
|
||||
|
||||
import platform
|
||||
from os import splitFile
|
||||
|
||||
when hasFFI:
|
||||
@@ -761,6 +761,49 @@ proc genCard(c: PCtx; n: PNode; dest: var TDest) =
|
||||
c.gABC(n, opcCard, dest, tmp)
|
||||
c.freeTemp(tmp)
|
||||
|
||||
proc genIntCast(c: PCtx; n: PNode; dest: var TDest) =
|
||||
const allowedIntegers = {tyInt..tyInt64, tyUInt..tyUInt64, tyChar}
|
||||
var signedIntegers = {tyInt8..tyInt32}
|
||||
var unsignedIntegers = {tyUInt8..tyUInt32, tyChar}
|
||||
let src = n.sons[1].typ.skipTypes(abstractRange)#.kind
|
||||
let dst = n.sons[0].typ.skipTypes(abstractRange)#.kind
|
||||
let src_size = src.getSize
|
||||
|
||||
if platform.intSize < 8:
|
||||
signedIntegers.incl(tyInt)
|
||||
unsignedIntegers.incl(tyUInt)
|
||||
if src_size == dst.getSize and src.kind in allowedIntegers and
|
||||
dst.kind in allowedIntegers:
|
||||
let tmp = c.genx(n.sons[1])
|
||||
var tmp2 = c.getTemp(n.sons[1].typ)
|
||||
let tmp3 = c.getTemp(n.sons[1].typ)
|
||||
if dest < 0: dest = c.getTemp(n[0].typ)
|
||||
proc mkIntLit(ival: int): int =
|
||||
result = genLiteral(c, newIntTypeNode(nkIntLit, ival, getSysType(tyInt)))
|
||||
if src.kind in unsignedIntegers and dst.kind in signedIntegers:
|
||||
# cast unsigned to signed integer of same size
|
||||
# signedVal = (unsignedVal xor offset) -% offset
|
||||
let offset = 1 shl (src_size * 8 - 1)
|
||||
c.gABx(n, opcLdConst, tmp2, mkIntLit(offset))
|
||||
c.gABC(n, opcBitxorInt, tmp3, tmp, tmp2)
|
||||
c.gABC(n, opcSubInt, dest, tmp3, tmp2)
|
||||
elif src.kind in signedIntegers and dst.kind in unsignedIntegers:
|
||||
# cast signed to unsigned integer of same size
|
||||
# unsignedVal = (offset +% signedVal +% 1) and offset
|
||||
let offset = (1 shl (src_size * 8)) - 1
|
||||
c.gABx(n, opcLdConst, tmp2, mkIntLit(offset))
|
||||
c.gABx(n, opcLdConst, dest, mkIntLit(offset+1))
|
||||
c.gABC(n, opcAddu, tmp3, tmp, dest)
|
||||
c.gABC(n, opcNarrowU, tmp3, TRegister(src_size*8))
|
||||
c.gABC(n, opcBitandInt, dest, tmp3, tmp2)
|
||||
else:
|
||||
c.gABC(n, opcAsgnInt, dest, tmp)
|
||||
c.freeTemp(tmp)
|
||||
c.freeTemp(tmp2)
|
||||
c.freeTemp(tmp3)
|
||||
else:
|
||||
globalError(n.info, errGenerated, "VM is only allowed to 'cast' between integers of same size")
|
||||
|
||||
proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
case m
|
||||
of mAnd: c.genAndOr(n, opcFJmp, dest)
|
||||
@@ -1844,7 +1887,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
if allowCast in c.features:
|
||||
genConv(c, n, n.sons[1], dest, opcCast)
|
||||
else:
|
||||
globalError(n.info, errGenerated, "VM is not allowed to 'cast'")
|
||||
genIntCast(c, n, dest)
|
||||
of nkTypeOfExpr:
|
||||
genTypeLit(c, n.typ, dest)
|
||||
of nkComesFrom:
|
||||
|
||||
@@ -92,6 +92,10 @@ Collections and algorithms
|
||||
* `sequtils <sequtils.html>`_
|
||||
This module implements operations for the built-in seq type
|
||||
which were inspired by functional programming languages.
|
||||
* `sharedtables <sharedtables.html>`_
|
||||
Nim shared hash table support. Contains shared tables.
|
||||
* `sharedlist <sharedlist.html>`_
|
||||
Nim shared linked list support. Contains shared singly linked list.
|
||||
|
||||
|
||||
String handling
|
||||
|
||||
@@ -296,6 +296,10 @@ empty ``discard`` statement should be used.
|
||||
For non ordinal types it is not possible to list every possible value and so
|
||||
these always require an ``else`` part.
|
||||
|
||||
As case statements perform compile-time exhaustiveness checks, the value in
|
||||
every ``of`` branch must be known at compile time. This fact is also exploited
|
||||
to generate more performant code.
|
||||
|
||||
As a special semantic extension, an expression in an ``of`` branch of a case
|
||||
statement may evaluate to a set or array constructor; the set or array is then
|
||||
expanded into a list of its elements:
|
||||
|
||||
2
koch.nim
2
koch.nim
@@ -260,7 +260,7 @@ proc buildTools(latest: bool) =
|
||||
" nimsuggest/nimsuggest.nim"
|
||||
|
||||
let nimgrepExe = "bin/nimgrep".exe
|
||||
nimexec "c -o:" & nimgrepExe & " tools/nimgrep.nim"
|
||||
nimexec "c -d:release -o:" & nimgrepExe & " tools/nimgrep.nim"
|
||||
when defined(windows): buildVccTool()
|
||||
|
||||
#nimexec "c -o:" & ("bin/nimresolve".exe) & " tools/nimresolve.nim"
|
||||
|
||||
@@ -400,11 +400,11 @@ typedef struct TStringDesc* string;
|
||||
|
||||
// NAN definition copied from math.h included in the Windows SDK version 10.0.14393.0
|
||||
#ifndef NAN
|
||||
#ifndef _HUGE_ENUF
|
||||
#define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow
|
||||
#endif
|
||||
#define NAN_INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
|
||||
#define NAN ((float)(NAN_INFINITY * 0.0F))
|
||||
# ifndef _HUGE_ENUF
|
||||
# define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow
|
||||
# endif
|
||||
# define NAN_INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
|
||||
# define NAN ((float)(NAN_INFINITY * 0.0F))
|
||||
#endif
|
||||
|
||||
#ifndef INF
|
||||
@@ -482,7 +482,6 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); }
|
||||
On disagreement, your C compiler will say something like:
|
||||
"error: 'Nim_and_C_compiler_disagree_on_target_architecture' declared as an array with a negative size" */
|
||||
typedef int Nim_and_C_compiler_disagree_on_target_architecture[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define NIM_EXTERNC extern "C"
|
||||
@@ -509,3 +508,5 @@ extern Libc::Env *genodeEnv;
|
||||
/* Compile with -d:checkAbi and a sufficiently C11:ish compiler to enable */
|
||||
#define NIM_CHECK_SIZE(typ, sz) \
|
||||
_Static_assert(sizeof(typ) == sz, "Nim & C disagree on type size")
|
||||
|
||||
#endif /* NIMBASE_H */
|
||||
|
||||
@@ -34,7 +34,7 @@ type
|
||||
{.deprecated: [TSocketHandle: SocketHandle].}
|
||||
|
||||
type
|
||||
Time* {.importc: "time_t", header: "<time.h>".} = distinct int
|
||||
Time* {.importc: "time_t", header: "<time.h>".} = distinct clong
|
||||
|
||||
Timespec* {.importc: "struct timespec",
|
||||
header: "<time.h>", final, pure.} = object ## struct timespec
|
||||
|
||||
@@ -1487,7 +1487,7 @@ proc drain*(timeout = 500) =
|
||||
## if there are no pending operations. In contrast to ``poll`` this
|
||||
## processes as many events as are available.
|
||||
if runOnce(timeout):
|
||||
while runOnce(0): discard
|
||||
while hasPendingOperations() and runOnce(0): discard
|
||||
|
||||
proc poll*(timeout = 500) =
|
||||
## Waits for completion events and processes them. Raises ``ValueError``
|
||||
|
||||
@@ -73,10 +73,10 @@ proc add*[A](x: var SharedList[A]; y: A) =
|
||||
node.d[node.dataLen] = y
|
||||
inc(node.dataLen)
|
||||
|
||||
proc initSharedList*[A](): SharedList[A] =
|
||||
initLock result.lock
|
||||
result.head = nil
|
||||
result.tail = nil
|
||||
proc init*[A](t: var SharedList[A]) =
|
||||
initLock t.lock
|
||||
t.head = nil
|
||||
t.tail = nil
|
||||
|
||||
proc clear*[A](t: var SharedList[A]) =
|
||||
withLock(t):
|
||||
@@ -92,4 +92,11 @@ proc deinitSharedList*[A](t: var SharedList[A]) =
|
||||
clear(t)
|
||||
deinitLock t.lock
|
||||
|
||||
proc initSharedList*[A](): SharedList[A] {.deprecated.} =
|
||||
## Deprecated. Use `init` instead.
|
||||
## This is not posix compliant, may introduce undefined behavior.
|
||||
initLock result.lock
|
||||
result.head = nil
|
||||
result.tail = nil
|
||||
|
||||
{.pop.}
|
||||
|
||||
@@ -192,19 +192,29 @@ proc del*[A, B](t: var SharedTable[A, B], key: A) =
|
||||
withLock t:
|
||||
delImpl()
|
||||
|
||||
proc initSharedTable*[A, B](initialSize=64): SharedTable[A, B] =
|
||||
proc init*[A, B](t: var SharedTable[A, B], initialSize=64) =
|
||||
## creates a new hash table that is empty.
|
||||
##
|
||||
## `initialSize` needs to be a power of two. If you need to accept runtime
|
||||
## values for this you could use the ``nextPowerOfTwo`` proc from the
|
||||
## `math <math.html>`_ module or the ``rightSize`` proc from this module.
|
||||
assert isPowerOfTwo(initialSize)
|
||||
result.counter = 0
|
||||
result.dataLen = initialSize
|
||||
result.data = cast[KeyValuePairSeq[A, B]](allocShared0(
|
||||
t.counter = 0
|
||||
t.dataLen = initialSize
|
||||
t.data = cast[KeyValuePairSeq[A, B]](allocShared0(
|
||||
sizeof(KeyValuePair[A, B]) * initialSize))
|
||||
initLock result.lock
|
||||
initLock t.lock
|
||||
|
||||
proc deinitSharedTable*[A, B](t: var SharedTable[A, B]) =
|
||||
deallocShared(t.data)
|
||||
deinitLock t.lock
|
||||
|
||||
proc initSharedTable*[A, B](initialSize=64): SharedTable[A, B] {.deprecated.} =
|
||||
## Deprecated. Use `init` instead.
|
||||
## This is not posix compliant, may introduce undefined behavior.
|
||||
assert isPowerOfTwo(initialSize)
|
||||
result.counter = 0
|
||||
result.dataLen = initialSize
|
||||
result.data = cast[KeyValuePairSeq[A, B]](allocShared0(
|
||||
sizeof(KeyValuePair[A, B]) * initialSize))
|
||||
initLock result.lock
|
||||
|
||||
@@ -257,10 +257,13 @@ proc close*(f: var MemFile) =
|
||||
when defined(windows):
|
||||
if f.wasOpened:
|
||||
error = unmapViewOfFile(f.mem) == 0
|
||||
lastErr = osLastError()
|
||||
error = (closeHandle(f.mapHandle) == 0) or error
|
||||
if f.fHandle != INVALID_HANDLE_VALUE:
|
||||
error = (closeHandle(f.fHandle) == 0) or error
|
||||
if not error:
|
||||
error = closeHandle(f.mapHandle) == 0
|
||||
if not error and f.fHandle != INVALID_HANDLE_VALUE:
|
||||
discard closeHandle(f.fHandle)
|
||||
f.fHandle = INVALID_HANDLE_VALUE
|
||||
if error:
|
||||
lastErr = osLastError()
|
||||
else:
|
||||
error = munmap(f.mem, f.size) != 0
|
||||
lastErr = osLastError()
|
||||
|
||||
@@ -39,7 +39,7 @@ proc toRational*[T:SomeInteger](x: T): Rational[T] =
|
||||
result.num = x
|
||||
result.den = 1
|
||||
|
||||
proc toRational*(x: float, n: int = high(int32)): Rational[int] =
|
||||
proc toRational*(x: float, n: int = high(int) shr (sizeof(int) div 2 * 8)): Rational[int] =
|
||||
## Calculates the best rational numerator and denominator
|
||||
## that approximates to `x`, where the denominator is
|
||||
## smaller than `n` (default is the largest possible
|
||||
@@ -323,8 +323,13 @@ when isMainModule:
|
||||
assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7
|
||||
assert toInt(z) == 0
|
||||
|
||||
assert toRational(0.98765432) == 2111111029 // 2137499919
|
||||
assert toRational(PI) == 817696623 // 260280919
|
||||
when sizeof(int) == 8:
|
||||
assert toRational(0.98765432) == 2111111029 // 2137499919
|
||||
assert toRational(PI) == 817696623 // 260280919
|
||||
when sizeof(int) == 4:
|
||||
assert toRational(0.98765432) == 80 // 81
|
||||
assert toRational(PI) == 355 // 113
|
||||
|
||||
assert toRational(0.1) == 1 // 10
|
||||
assert toRational(0.9) == 9 // 10
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ proc assertValidDate(monthday: MonthdayRange, month: Month, year: int) {.inline.
|
||||
assert monthday <= getDaysInMonth(month, year),
|
||||
$year & "-" & $ord(month) & "-" & $monthday & " is not a valid date"
|
||||
|
||||
proc toEpochDay*(monthday: MonthdayRange, month: Month, year: int): int64 =
|
||||
proc toEpochDay(monthday: MonthdayRange, month: Month, year: int): int64 =
|
||||
## Get the epoch day from a year/month/day date.
|
||||
## The epoch day is the number of days since 1970/01/01 (it might be negative).
|
||||
assertValidDate monthday, month, year
|
||||
@@ -191,7 +191,7 @@ proc toEpochDay*(monthday: MonthdayRange, month: Month, year: int): int64 =
|
||||
let doe = yoe * 365 + yoe div 4 - yoe div 100 + doy
|
||||
return era * 146097 + doe - 719468
|
||||
|
||||
proc fromEpochDay*(epochday: int64): tuple[monthday: MonthdayRange, month: Month, year: int] =
|
||||
proc fromEpochDay(epochday: int64): tuple[monthday: MonthdayRange, month: Month, year: int] =
|
||||
## Get the year/month/day date from a epoch day.
|
||||
## The epoch day is the number of days since 1970/01/01 (it might be negative).
|
||||
# Based on http://howardhinnant.github.io/date_algorithms.html
|
||||
@@ -1352,29 +1352,42 @@ else:
|
||||
proc fromSeconds*(since1970: float): Time {.tags: [], raises: [], benign, deprecated.} =
|
||||
## Takes a float which contains the number of seconds since the unix epoch and
|
||||
## returns a time object.
|
||||
##
|
||||
## **Deprecated since v0.18.0:** use ``fromUnix`` instead
|
||||
Time(since1970)
|
||||
|
||||
proc fromSeconds*(since1970: int64): Time {.tags: [], raises: [], benign, deprecated.} =
|
||||
## Takes an int which contains the number of seconds since the unix epoch and
|
||||
## returns a time object.
|
||||
##
|
||||
## **Deprecated since v0.18.0:** use ``fromUnix`` instead
|
||||
Time(since1970)
|
||||
|
||||
proc toSeconds*(time: Time): float {.tags: [], raises: [], benign, deprecated.} =
|
||||
## Returns the time in seconds since the unix epoch.
|
||||
##
|
||||
## **Deprecated since v0.18.0:** use ``toUnix`` instead
|
||||
float(time)
|
||||
|
||||
proc getLocalTime*(time: Time): DateTime {.tags: [], raises: [], benign, deprecated.} =
|
||||
## Converts the calendar time `time` to broken-time representation,
|
||||
## expressed relative to the user's specified time zone.
|
||||
##
|
||||
## **Deprecated since v0.18.0:** use ``local`` instead
|
||||
time.local
|
||||
|
||||
proc getGMTime*(time: Time): DateTime {.tags: [], raises: [], benign, deprecated.} =
|
||||
## Converts the calendar time `time` to broken-down time representation,
|
||||
## expressed in Coordinated Universal Time (UTC).
|
||||
## expressed in Coordinated Universal Time (UTC).
|
||||
##
|
||||
## **Deprecated since v0.18.0:** use ``utc`` instead
|
||||
time.utc
|
||||
|
||||
proc getTimezone*(): int {.tags: [TimeEffect], raises: [], benign, deprecated.} =
|
||||
## Returns the offset of the local (non-DST) timezone in seconds west of UTC.
|
||||
##
|
||||
## **Deprecated since v0.18.0:** use ``now().utcOffset`` to get the current
|
||||
## utc offset (including DST).
|
||||
when defined(JS):
|
||||
return newDate().getTimezoneOffset() * 60
|
||||
elif defined(freebsd) or defined(netbsd) or defined(openbsd):
|
||||
@@ -1468,4 +1481,4 @@ proc getDayOfWeekJulian*(day, month, year: int): WeekDay {.deprecated.} =
|
||||
y = year - a
|
||||
m = month + (12*a) - 2
|
||||
d = (5 + day + y + (y div 4) + (31*m) div 12) mod 7
|
||||
result = d.WeekDay
|
||||
result = d.WeekDay
|
||||
|
||||
@@ -743,6 +743,18 @@ proc newSeqOfCap*[T](cap: Natural): seq[T] {.
|
||||
## ``cap``.
|
||||
discard
|
||||
|
||||
when not defined(JS):
|
||||
proc newSeqUninitialized*[T: SomeNumber](len: Natural): seq[T] =
|
||||
## creates a new sequence of type ``seq[T]`` with length ``len``.
|
||||
##
|
||||
## Only available for numbers types. Note that the sequence will be
|
||||
## uninitialized. After the creation of the sequence you should assign
|
||||
## entries to the sequence instead of adding them.
|
||||
|
||||
result = newSeqOfCap[T](len)
|
||||
var s = cast[PGenericSeq](result)
|
||||
s.len = len
|
||||
|
||||
proc len*[TOpenArray: openArray|varargs](x: TOpenArray): int {.
|
||||
magic: "LengthOpenArray", noSideEffect.}
|
||||
proc len*(x: string): int {.magic: "LengthStr", noSideEffect.}
|
||||
|
||||
@@ -318,7 +318,7 @@ proc initGC() =
|
||||
init(gch.marked)
|
||||
init(gch.additionalRoots)
|
||||
when hasThreadSupport:
|
||||
gch.toDispose = initSharedList[pointer]()
|
||||
init(gch.toDispose)
|
||||
|
||||
when useMarkForDebug or useBackupGc:
|
||||
type
|
||||
|
||||
@@ -133,7 +133,7 @@ proc initGC() =
|
||||
init(gch.additionalRoots)
|
||||
init(gch.greyStack)
|
||||
when hasThreadSupport:
|
||||
gch.toDispose = initSharedList[pointer]()
|
||||
init(gch.toDispose)
|
||||
|
||||
# Which color to use for new objects is tricky: When we're marking,
|
||||
# they have to be *white* so that everything is marked that is only
|
||||
|
||||
@@ -233,7 +233,7 @@ proc initGC() =
|
||||
init(gch.allocated)
|
||||
init(gch.marked)
|
||||
when hasThreadSupport:
|
||||
gch.toDispose = initSharedList[pointer]()
|
||||
init(gch.toDispose)
|
||||
|
||||
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} =
|
||||
var d = cast[ByteAddress](dest)
|
||||
|
||||
@@ -213,7 +213,8 @@ block clearCountTableTest:
|
||||
assert t.len() == 0
|
||||
|
||||
block withKeyTest:
|
||||
var t = initSharedTable[int, int]()
|
||||
var t: SharedTable[int, int]
|
||||
t.init()
|
||||
t.withKey(1) do (k: int, v: var int, pairExists: var bool):
|
||||
assert(v == 0)
|
||||
pairExists = true
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
discard """
|
||||
file: "tmemfiles2.nim"
|
||||
disabled: true
|
||||
output: '''Full read size: 20
|
||||
Half read size: 10 Data: Hello'''
|
||||
"""
|
||||
# doesn't work on windows. fmReadWrite doesn't create a file.
|
||||
import memfiles, os
|
||||
var
|
||||
mm, mm_full, mm_half: MemFile
|
||||
|
||||
@@ -290,20 +290,6 @@ proc compilerOutputTests(test: TTest, target: TTarget, given: var TSpec,
|
||||
if given.err == reSuccess: inc(r.passed)
|
||||
r.addResult(test, target, expectedmsg, givenmsg, given.err)
|
||||
|
||||
proc analyzeAndConsolidateOutput(s: string): string =
|
||||
result = ""
|
||||
let rows = s.splitLines
|
||||
for i in 0 ..< rows.len:
|
||||
if (let pos = find(rows[i], "Traceback (most recent call last)"); pos != -1):
|
||||
result = substr(rows[i], pos) & "\n"
|
||||
for i in i+1 ..< rows.len:
|
||||
result.add rows[i] & "\n"
|
||||
if not (rows[i] =~ peg"['(']+ '(' \d+ ')' \s+"):
|
||||
return
|
||||
elif (let pos = find(rows[i], "SIGSEGV: Illegal storage access."); pos != -1):
|
||||
result = substr(rows[i], pos)
|
||||
return
|
||||
|
||||
proc testSpec(r: var TResults, test: TTest, target = targetC) =
|
||||
let tname = test.name.addFileExt(".nim")
|
||||
#echo "TESTING ", tname
|
||||
@@ -376,8 +362,7 @@ proc testSpec(r: var TResults, test: TTest, target = targetC) =
|
||||
if exitCode != expected.exitCode:
|
||||
r.addResult(test, target, "exitcode: " & $expected.exitCode,
|
||||
"exitcode: " & $exitCode & "\n\nOutput:\n" &
|
||||
analyzeAndConsolidateOutput(bufB),
|
||||
reExitCodesDiffer)
|
||||
bufB, reExitCodesDiffer)
|
||||
continue
|
||||
|
||||
if bufB != expectedOut and expected.action != actionRunNoSpec:
|
||||
|
||||
120
tests/vm/tcastint.nim
Normal file
120
tests/vm/tcastint.nim
Normal file
@@ -0,0 +1,120 @@
|
||||
discard """
|
||||
file: "tcastint.nim"
|
||||
output: "OK"
|
||||
"""
|
||||
|
||||
type
|
||||
Dollar = distinct int
|
||||
XCoord = distinct int32
|
||||
Digit = range[-9..0]
|
||||
|
||||
# those are necessary for comparisons below.
|
||||
proc `==`(x, y: Dollar): bool {.borrow.}
|
||||
proc `==`(x, y: XCoord): bool {.borrow.}
|
||||
|
||||
proc dummy[T](x: T): T = x
|
||||
|
||||
proc test() =
|
||||
let U8 = 0b1011_0010'u8
|
||||
let I8 = 0b1011_0010'i8
|
||||
let C8 = 0b1011_0010'u8.char
|
||||
let C8_1 = 0b1011_0011'u8.char
|
||||
let U16 = 0b10100111_00101000'u16
|
||||
let I16 = 0b10100111_00101000'i16
|
||||
let U32 = 0b11010101_10011100_11011010_01010000'u32
|
||||
let I32 = 0b11010101_10011100_11011010_01010000'i32
|
||||
let U64A = 0b11000100_00111111_01111100_10001010_10011001_01001000_01111010_00010001'u64
|
||||
let I64A = 0b11000100_00111111_01111100_10001010_10011001_01001000_01111010_00010001'i64
|
||||
let U64B = 0b00110010_11011101_10001111_00101000_00000000_00000000_00000000_00000000'u64
|
||||
let I64B = 0b00110010_11011101_10001111_00101000_00000000_00000000_00000000_00000000'i64
|
||||
when sizeof(int) == 8:
|
||||
let UX = U64A.uint
|
||||
let IX = I64A.int
|
||||
elif sizeof(int) == 4:
|
||||
let UX = U32.uint
|
||||
let IX = I32.int
|
||||
elif sizeof(int) == 2:
|
||||
let UX = U16.uint
|
||||
let IX = I16.int
|
||||
else:
|
||||
let UX = U8.uint
|
||||
let IX = I8.int
|
||||
|
||||
doAssert(cast[char](I8) == C8)
|
||||
doAssert(cast[uint8](I8) == U8)
|
||||
doAssert(cast[uint16](I16) == U16)
|
||||
doAssert(cast[uint32](I32) == U32)
|
||||
doAssert(cast[uint64](I64A) == U64A)
|
||||
doAssert(cast[uint64](I64B) == U64B)
|
||||
doAssert(cast[int8](U8) == I8)
|
||||
doAssert(cast[int16](U16) == I16)
|
||||
doAssert(cast[int32](U32) == I32)
|
||||
doAssert(cast[int64](U64A) == I64A)
|
||||
doAssert(cast[int64](U64B) == I64B)
|
||||
doAssert(cast[uint](IX) == UX)
|
||||
doAssert(cast[int](UX) == IX)
|
||||
|
||||
doAssert(cast[char](I8 + 1) == C8_1)
|
||||
doAssert(cast[uint8](I8 + 1) == U8 + 1)
|
||||
doAssert(cast[uint16](I16 + 1) == U16 + 1)
|
||||
doAssert(cast[uint32](I32 + 1) == U32 + 1)
|
||||
doAssert(cast[uint64](I64A + 1) == U64A + 1)
|
||||
doAssert(cast[uint64](I64B + 1) == U64B + 1)
|
||||
doAssert(cast[int8](U8 + 1) == I8 + 1)
|
||||
doAssert(cast[int16](U16 + 1) == I16 + 1)
|
||||
doAssert(cast[int32](U32 + 1) == I32 + 1)
|
||||
doAssert(cast[int64](U64A + 1) == I64A + 1)
|
||||
doAssert(cast[int64](U64B + 1) == I64B + 1)
|
||||
doAssert(cast[uint](IX + 1) == UX + 1)
|
||||
doAssert(cast[int](UX + 1) == IX + 1)
|
||||
|
||||
doAssert(cast[char](I8.dummy) == C8.dummy)
|
||||
doAssert(cast[uint8](I8.dummy) == U8.dummy)
|
||||
doAssert(cast[uint16](I16.dummy) == U16.dummy)
|
||||
doAssert(cast[uint32](I32.dummy) == U32.dummy)
|
||||
doAssert(cast[uint64](I64A.dummy) == U64A.dummy)
|
||||
doAssert(cast[uint64](I64B.dummy) == U64B.dummy)
|
||||
doAssert(cast[int8](U8.dummy) == I8.dummy)
|
||||
doAssert(cast[int16](U16.dummy) == I16.dummy)
|
||||
doAssert(cast[int32](U32.dummy) == I32.dummy)
|
||||
doAssert(cast[int64](U64A.dummy) == I64A.dummy)
|
||||
doAssert(cast[int64](U64B.dummy) == I64B.dummy)
|
||||
doAssert(cast[uint](IX.dummy) == UX.dummy)
|
||||
doAssert(cast[int](UX.dummy) == IX.dummy)
|
||||
|
||||
|
||||
doAssert(cast[int64](if false: U64B else: 0'u64) == (if false: I64B else: 0'i64))
|
||||
|
||||
block:
|
||||
let raw = 3
|
||||
let money = Dollar(raw) # this must be a variable, is otherwise constant folded.
|
||||
doAssert(cast[int](money) == raw)
|
||||
doAssert(cast[Dollar](raw) == money)
|
||||
block:
|
||||
let raw = 150'i32
|
||||
let position = XCoord(raw) # this must be a variable, is otherwise constant folded.
|
||||
doAssert(cast[int32](position) == raw)
|
||||
doAssert(cast[XCoord](raw) == position)
|
||||
block:
|
||||
let raw = -2
|
||||
let digit = Digit(raw)
|
||||
doAssert(cast[int](digit) == raw)
|
||||
doAssert(cast[Digit](raw) == digit)
|
||||
|
||||
when defined nimvm:
|
||||
doAssert(not compiles(cast[float](I64A)))
|
||||
doAssert(not compiles(cast[float32](I64A)))
|
||||
|
||||
doAssert(not compiles(cast[char](I64A)))
|
||||
doAssert(not compiles(cast[uint16](I64A)))
|
||||
doAssert(not compiles(cast[uint32](I64A)))
|
||||
|
||||
doAssert(not compiles(cast[uint16](I8)))
|
||||
doAssert(not compiles(cast[uint32](I8)))
|
||||
doAssert(not compiles(cast[uint64](I8)))
|
||||
|
||||
test()
|
||||
static:
|
||||
test()
|
||||
|
||||
echo "OK"
|
||||
@@ -45,6 +45,9 @@ type
|
||||
TOptions = set[TOption]
|
||||
TConfirmEnum = enum
|
||||
ceAbort, ceYes, ceAll, ceNo, ceNone
|
||||
Pattern = Regex | Peg
|
||||
|
||||
using pattern: Pattern
|
||||
|
||||
var
|
||||
filenames: seq[string] = @[]
|
||||
@@ -118,7 +121,7 @@ proc highlight(s, match, repl: string, t: tuple[first, last: int],
|
||||
stdout.write("\n")
|
||||
stdout.flushFile()
|
||||
|
||||
proc processFile(filename: string) =
|
||||
proc processFile(pattern; filename: string) =
|
||||
var filenameShown = false
|
||||
template beforeHighlight =
|
||||
if not filenameShown and optVerbose notin options:
|
||||
@@ -135,18 +138,8 @@ proc processFile(filename: string) =
|
||||
if optVerbose in options:
|
||||
stdout.writeLine(filename)
|
||||
stdout.flushFile()
|
||||
var pegp: Peg
|
||||
var rep: Regex
|
||||
var result: string
|
||||
|
||||
if optRegex in options:
|
||||
if {optIgnoreCase, optIgnoreStyle} * options != {}:
|
||||
rep = re(pattern, {reExtended, reIgnoreCase})
|
||||
else:
|
||||
rep = re(pattern)
|
||||
else:
|
||||
pegp = peg(pattern)
|
||||
|
||||
if optReplace in options:
|
||||
result = newStringOfCap(buffer.len)
|
||||
|
||||
@@ -156,11 +149,7 @@ proc processFile(filename: string) =
|
||||
for j in 0..high(matches): matches[j] = ""
|
||||
var reallyReplace = true
|
||||
while i < buffer.len:
|
||||
var t: tuple[first, last: int]
|
||||
if optRegex notin options:
|
||||
t = findBounds(buffer, pegp, matches, i)
|
||||
else:
|
||||
t = findBounds(buffer, rep, matches, i)
|
||||
let t = findBounds(buffer, pattern, matches, i)
|
||||
if t.first < 0: break
|
||||
inc(line, countLines(buffer, i, t.first-1))
|
||||
|
||||
@@ -170,11 +159,7 @@ proc processFile(filename: string) =
|
||||
if optReplace notin options:
|
||||
highlight(buffer, wholeMatch, "", t, line, showRepl=false)
|
||||
else:
|
||||
var r: string
|
||||
if optRegex notin options:
|
||||
r = replace(wholeMatch, pegp, replacement % matches)
|
||||
else:
|
||||
r = replace(wholeMatch, rep, replacement % matches)
|
||||
let r = replace(wholeMatch, pattern, replacement % matches)
|
||||
if optConfirm in options:
|
||||
highlight(buffer, wholeMatch, r, t, line, showRepl=true)
|
||||
case confirm()
|
||||
@@ -246,17 +231,17 @@ proc styleInsensitive(s: string): string =
|
||||
addx()
|
||||
else: addx()
|
||||
|
||||
proc walker(dir: string) =
|
||||
proc walker(pattern; dir: string) =
|
||||
for kind, path in walkDir(dir):
|
||||
case kind
|
||||
of pcFile:
|
||||
if extensions.len == 0 or path.hasRightExt(extensions):
|
||||
processFile(path)
|
||||
processFile(pattern, path)
|
||||
of pcDir:
|
||||
if optRecursive in options:
|
||||
walker(path)
|
||||
walker(pattern, path)
|
||||
else: discard
|
||||
if existsFile(dir): processFile(dir)
|
||||
if existsFile(dir): processFile(pattern, dir)
|
||||
|
||||
proc writeHelp() =
|
||||
stdout.write(Usage)
|
||||
@@ -332,11 +317,18 @@ else:
|
||||
pattern = "\\y " & pattern
|
||||
elif optIgnoreCase in options:
|
||||
pattern = "\\i " & pattern
|
||||
let pegp = peg(pattern)
|
||||
for f in items(filenames):
|
||||
walker(pegp, f)
|
||||
else:
|
||||
var reflags = {reStudy, reExtended}
|
||||
if optIgnoreStyle in options:
|
||||
pattern = styleInsensitive(pattern)
|
||||
if optWord in options:
|
||||
pattern = r"\b (:?" & pattern & r") \b"
|
||||
for f in items(filenames):
|
||||
walker(f)
|
||||
if {optIgnoreCase, optIgnoreStyle} * options != {}:
|
||||
reflags.incl reIgnoreCase
|
||||
let rep = re(pattern, reflags)
|
||||
for f in items(filenames):
|
||||
walker(rep, f)
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ srcdoc2: "pure/ropes;pure/unidecode/unidecode;pure/xmldom;pure/xmldomparser"
|
||||
srcdoc2: "pure/xmlparser;pure/htmlparser;pure/xmltree;pure/colors;pure/mimetypes"
|
||||
srcdoc2: "pure/json;pure/base64;pure/scgi"
|
||||
srcdoc2: "pure/collections/tables;pure/collections/sets;pure/collections/lists"
|
||||
srcdoc2: "pure/collections/sharedlist;pure/collections/sharedtables"
|
||||
srcdoc2: "pure/collections/intsets;pure/collections/queues;pure/collections/deques;pure/encodings"
|
||||
srcdoc2: "pure/events;pure/collections/sequtils;pure/cookies"
|
||||
srcdoc2: "pure/memfiles;pure/subexes;pure/collections/critbits"
|
||||
|
||||
Reference in New Issue
Block a user