Merge remote-tracking branch 'origin/devel' into pr_quote_do_r

This commit is contained in:
ringabout
2025-02-04 18:27:47 +08:00
23 changed files with 910 additions and 786 deletions

View File

@@ -500,6 +500,21 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
dec(c.config.evalTemplateCounter)
discard c.friendModules.pop()
proc getLineInfo(n: PNode): TLineInfo =
case n.kind
of nkPostfix:
if len(n) > 1:
result = getLineInfo(n[1])
else:
result = n.info
of nkAccQuoted, nkPragmaExpr:
if len(n) > 0:
result = getLineInfo(n[0])
else:
result = n.info
else:
result = n.info
const
errMissingGenericParamsForTemplate = "'$1' has unspecified generic parameters"

View File

@@ -492,19 +492,8 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind, reportToNimsuggest = tru
incl(result.flags, sfGlobal)
result.options = c.config.options
proc getLineInfo(n: PNode): TLineInfo =
case n.kind
of nkPostfix:
if len(n) > 1:
return getLineInfo(n[1])
of nkAccQuoted, nkPragmaExpr:
if len(n) > 0:
return getLineInfo(n[0])
else:
discard
result = n.info
let info = getLineInfo(n)
if reportToNimsuggest:
let info = getLineInfo(n)
suggestSym(c.graph, info, result, c.graph.usageSym)
proc checkNilable(c: PContext; v: PSym) =
@@ -1787,6 +1776,17 @@ proc typeSectionFinalPass(c: PContext, n: PNode) =
# check the style here after the pragmas have been processed:
styleCheckDef(c, s)
# compute the type's size and check for illegal recursions:
if a[0].kind == nkPragmaExpr:
let pragmas = a[0][1]
for i in 0 ..< pragmas.len:
if pragmas[i].kind == nkExprColonExpr and
pragmas[i][0].kind == nkIdent and
whichKeyword(pragmas[i][0].ident) == wSize:
if s.typ.kind != tyEnum and sfImportc notin s.flags:
# EventType* {.size: sizeof(uint32).} = enum
# AtomicFlag* {.importc: "atomic_flag", header: "<stdatomic.h>", size: 1.} = object
localError(c.config, pragmas[i].info, "size pragma only allowed for enum types and imported types")
if a[1].kind == nkEmpty:
var x = a[2]
if x.kind in nkCallKinds and nfSem in x.flags:
@@ -2351,7 +2351,7 @@ proc semCppMember(c: PContext; s: PSym; n: PNode) =
isInitializer = false
break
var j = 0
while p[j].sym.kind == skParam:
while p[j].kind == nkSym and p[j].sym.kind == skParam:
initializerCall.add val
inc j
if isInitializer:

View File

@@ -67,7 +67,12 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
# for instance 'nextTry' is both in tables.nim and astalgo.nim ...
if not isField or sfGenSym notin s.flags:
result = newSymNode(s, info)
markUsed(c, info, s)
if isField:
# possibly not final field sym
incl(s.flags, sfUsed)
markOwnerModuleAsUsed(c, s)
else:
markUsed(c, info, s)
onUse(info, s)
else:
result = n
@@ -691,6 +696,9 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
s = semIdentVis(c, skTemplate, n[namePos], {})
assert s.kind == skTemplate
let info = getLineInfo(n[namePos])
suggestSym(c.graph, info, s, c.graph.usageSym)
styleCheckDef(c, s)
onDef(n[namePos].info, s)
# check parameter list:

View File

@@ -1671,6 +1671,11 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
var err = "cannot instantiate "
err.addTypeHeader(c.config, t)
err.add "\ngot: <$1>\nbut expected: <$2>" % [describeArgs(c, n), describeArgs(c, t.n, 0)]
if m.firstMismatch.kind == kTypeMismatch and m.firstMismatch.arg < n.len:
let nArg = n[m.firstMismatch.arg]
if nArg.kind in nkSymChoices:
err.add "\n"
err.add ambiguousIdentifierMsg(nArg)
localError(c.config, n.info, errGenerated, err)
return newOrPrevType(tyError, prev, c)

View File

@@ -263,7 +263,7 @@ proc registerAdditionalOps*(c: PCtx) =
wrap2si(readLines, ioop)
systemop getCurrentExceptionMsg
systemop getCurrentException
registerCallback c, "stdlib.osdirs.staticWalkDir", proc (a: VmArgs) {.nimcall.} =
registerCallback c, "stdlib.staticos.staticWalkDir", proc (a: VmArgs) {.nimcall.} =
setResult(a, staticWalkDirImpl(getString(a, 0), getBool(a, 1)))
registerCallback c, "stdlib.staticos.staticDirExists", proc (a: VmArgs) {.nimcall.} =
setResult(a, dirExists(getString(a, 0)))

View File

@@ -30,28 +30,30 @@ a working NodeJS on `PATH`.
Commands
========
========================== ==========================
p|pat|pattern <glob> run all the tests matching the given pattern
all run all tests inside of category folders
c|cat|category <category> run all the tests of a certain category
r|run <test> run single test file
html generate testresults.html from the database
========================== ==========================
Options
=======
--print print results to the console
--verbose print commands (compiling and running tests)
--simulate see what tests would be run but don't run them (for debugging)
--failing only show failing/ignored tests
--targets:"c cpp js objc" run tests for specified targets (default: c)
--nim:path use a particular nim executable (default: $PATH/nim)
--directory:dir Change to directory dir before reading the tests or doing anything else.
--colors:on|off Turn messages coloring on|off.
--backendLogging:on|off Disable or enable backend logging. By default turned on.
--megatest:on|off Enable or disable megatest. Default is on.
--valgrind:on|off Enable or disable valgrind support. Default is on.
--skipFrom:file Read tests to skip from `file` - one test per line, # comments ignored
--print print results to the console
--verbose print commands (compiling and running tests)
--simulate see what tests would be run but don't run them (for debugging)
--failing only show failing/ignored tests
--targets:"c cpp js objc" run tests for specified targets (default: c)
--nim:path use a particular nim executable (default: $PATH/nim)
--directory:dir Change to directory dir before reading the tests or doing anything else.
--colors:on|off Turn messages coloring on|off.
--backendLogging:on|off Disable or enable backend logging. By default turned on.
--megatest:on|off Enable or disable megatest. Default is on.
--valgrind:on|off Enable or disable valgrind support. Default is on.
--skipFrom:file Read tests to skip from `file` - one test per line, # comments ignored
Running a single test

View File

@@ -1490,7 +1490,9 @@ proc clearInterval*(i: Interval) {.importc, nodecl.}
proc addEventListener*(et: EventTarget, ev: cstring, cb: proc(ev: Event), useCapture: bool = false)
proc addEventListener*(et: EventTarget, ev: cstring, cb: proc(ev: Event), options: AddEventListenerOptions)
proc dispatchEvent*(et: EventTarget, ev: Event)
proc removeEventListener*(et: EventTarget; ev: cstring; cb: proc(ev: Event))
proc removeEventListener*(et: EventTarget, ev: cstring, cb: proc(ev: Event), useCapture: bool = false)
proc removeEventListener*(et: EventTarget, ev: cstring, cb: proc(ev: Event), options: AddEventListenerOptions)
# Window "methods"
proc alert*(w: Window, msg: cstring)

File diff suppressed because it is too large Load Diff

View File

@@ -527,7 +527,6 @@ proc parseSaturatedNatural*(s: openArray[char], b: var int): int {.
proc rawParseUInt(s: openArray[char], b: var BiggestUInt): int =
var
res = 0.BiggestUInt
prev = 0.BiggestUInt
i = 0
if i < s.len - 1 and s[i] == '-' and s[i + 1] in {'0'..'9'}:
integerOutOfRangeError()
@@ -535,8 +534,11 @@ proc rawParseUInt(s: openArray[char], b: var BiggestUInt): int =
if i < s.len and s[i] in {'0'..'9'}:
b = 0
while i < s.len and s[i] in {'0'..'9'}:
prev = res
res = res * 10 + (ord(s[i]) - ord('0')).BiggestUInt
if res > BiggestUInt.high div 10: # Highest value that you can multiply 10 without overflow
integerOutOfRangeError()
res = res * 10
let prev = res
res += (ord(s[i]) - ord('0')).BiggestUInt
if prev > res:
integerOutOfRangeError()
inc(i)

View File

@@ -19,7 +19,7 @@ include system/inclrtl
when defined(nimPreviewSlimSystem):
import std/widestrs
when defined(nodejs):
from std/private/oscommon import ReadDirEffect
@@ -33,8 +33,6 @@ elif defined(windows):
import std/winlean
elif defined(posix):
import std/posix
else:
{.error: "The cmdline module has not been implemented for the target platform.".}
# Needed by windows in order to obtain the command line for targets

View File

@@ -5,9 +5,13 @@ import std/[oserrors]
when defined(nimPreviewSlimSystem):
import std/[syncio, assertions, widestrs]
from std/staticos import PathComponent
## .. importdoc:: osdirs.nim, os.nim
const weirdTarget* = defined(nimscript) or defined(js)
const
weirdTarget* = defined(nimscript) or defined(js)
supportedSystem* = weirdTarget or defined(windows) or defined(posix)
type
@@ -27,8 +31,6 @@ elif defined(posix):
import std/posix
proc c_rename(oldname, newname: cstring): cint {.
importc: "rename", header: "<stdio.h>".}
else:
{.error: "OS module not ported to your operating system!".}
when weirdTarget:
@@ -65,122 +67,110 @@ when defined(windows) and not weirdTarget:
result = f.cFileName[0].int == dot and (f.cFileName[1].int == 0 or
f.cFileName[1].int == dot and f.cFileName[2].int == 0)
when supportedSystem:
when defined(posix) and not weirdTarget:
proc getSymlinkFileKind*(path: string):
tuple[pc: PathComponent, isSpecial: bool] =
# Helper function.
var s: Stat
assert(path != "")
result = (pcLinkToFile, false)
if stat(path, s) == 0'i32:
if S_ISDIR(s.st_mode):
result = (pcLinkToDir, false)
elif not S_ISREG(s.st_mode):
result = (pcLinkToFile, true)
type
PathComponent* = enum ## Enumeration specifying a path component.
proc tryMoveFSObject*(source, dest: string, isDir: bool): bool {.noWeirdTarget.} =
## Moves a file (or directory if `isDir` is true) from `source` to `dest`.
##
## Returns false in case of `EXDEV` error or `AccessDeniedError` on Windows (if `isDir` is true).
## In case of other errors `OSError` is raised.
## Returns true in case of success.
when defined(windows):
let s = newWideCString(source)
let d = newWideCString(dest)
result = moveFileExW(s, d, MOVEFILE_COPY_ALLOWED or MOVEFILE_REPLACE_EXISTING) != 0'i32
else:
result = c_rename(source, dest) == 0'i32
if not result:
let err = osLastError()
let isAccessDeniedError =
when defined(windows):
const AccessDeniedError = OSErrorCode(5)
isDir and err == AccessDeniedError
else:
err == EXDEV.OSErrorCode
if not isAccessDeniedError:
raiseOSError(err, $(source, dest))
when not defined(windows):
const maxSymlinkLen* = 1024
proc fileExists*(filename: string): bool {.rtl, extern: "nos$1",
tags: [ReadDirEffect], noNimJs, sideEffect.} =
## Returns true if `filename` exists and is a regular file or symlink.
##
## Directories, device files, named pipes and sockets return false.
##
## See also:
## * `walkDirRec iterator`_
## * `FileInfo object`_
pcFile, ## path refers to a file
pcLinkToFile, ## path refers to a symbolic link to a file
pcDir, ## path refers to a directory
pcLinkToDir ## path refers to a symbolic link to a directory
## * `dirExists proc`_
## * `symlinkExists proc`_
when defined(windows):
wrapUnary(a, getFileAttributesW, filename)
if a != -1'i32:
result = (a and FILE_ATTRIBUTE_DIRECTORY) == 0'i32
else:
var res: Stat
return stat(filename, res) >= 0'i32 and S_ISREG(res.st_mode)
when defined(posix) and not weirdTarget:
proc getSymlinkFileKind*(path: string):
tuple[pc: PathComponent, isSpecial: bool] =
# Helper function.
var s: Stat
assert(path != "")
result = (pcLinkToFile, false)
if stat(path, s) == 0'i32:
if S_ISDIR(s.st_mode):
result = (pcLinkToDir, false)
elif not S_ISREG(s.st_mode):
result = (pcLinkToFile, true)
proc tryMoveFSObject*(source, dest: string, isDir: bool): bool {.noWeirdTarget.} =
## Moves a file (or directory if `isDir` is true) from `source` to `dest`.
##
## Returns false in case of `EXDEV` error or `AccessDeniedError` on Windows (if `isDir` is true).
## In case of other errors `OSError` is raised.
## Returns true in case of success.
when defined(windows):
let s = newWideCString(source)
let d = newWideCString(dest)
result = moveFileExW(s, d, MOVEFILE_COPY_ALLOWED or MOVEFILE_REPLACE_EXISTING) != 0'i32
else:
result = c_rename(source, dest) == 0'i32
if not result:
let err = osLastError()
let isAccessDeniedError =
when defined(windows):
const AccessDeniedError = OSErrorCode(5)
isDir and err == AccessDeniedError
else:
err == EXDEV.OSErrorCode
if not isAccessDeniedError:
raiseOSError(err, $(source, dest))
when not defined(windows):
const maxSymlinkLen* = 1024
proc fileExists*(filename: string): bool {.rtl, extern: "nos$1",
tags: [ReadDirEffect], noNimJs, sideEffect.} =
## Returns true if `filename` exists and is a regular file or symlink.
##
## Directories, device files, named pipes and sockets return false.
##
## See also:
## * `dirExists proc`_
## * `symlinkExists proc`_
when defined(windows):
wrapUnary(a, getFileAttributesW, filename)
if a != -1'i32:
result = (a and FILE_ATTRIBUTE_DIRECTORY) == 0'i32
else:
var res: Stat
return stat(filename, res) >= 0'i32 and S_ISREG(res.st_mode)
proc dirExists*(dir: string): bool {.rtl, extern: "nos$1", tags: [ReadDirEffect],
noNimJs, sideEffect.} =
## Returns true if the directory `dir` exists. If `dir` is a file, false
## is returned. Follows symlinks.
##
## See also:
## * `fileExists proc`_
## * `symlinkExists proc`_
when defined(windows):
wrapUnary(a, getFileAttributesW, dir)
if a != -1'i32:
result = (a and FILE_ATTRIBUTE_DIRECTORY) != 0'i32
else:
var res: Stat
result = stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode)
proc dirExists*(dir: string): bool {.rtl, extern: "nos$1", tags: [ReadDirEffect],
noNimJs, sideEffect.} =
## Returns true if the directory `dir` exists. If `dir` is a file, false
## is returned. Follows symlinks.
##
## See also:
## * `fileExists proc`_
## * `symlinkExists proc`_
when defined(windows):
wrapUnary(a, getFileAttributesW, dir)
if a != -1'i32:
result = (a and FILE_ATTRIBUTE_DIRECTORY) != 0'i32
else:
var res: Stat
result = stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode)
proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1",
tags: [ReadDirEffect],
noWeirdTarget, sideEffect.} =
## Returns true if the symlink `link` exists. Will return true
## regardless of whether the link points to a directory or file.
##
## See also:
## * `fileExists proc`_
## * `dirExists proc`_
when defined(windows):
wrapUnary(a, getFileAttributesW, link)
if a != -1'i32:
# xxx see: bug #16784 (bug9); checking `IO_REPARSE_TAG_SYMLINK`
# may also be needed.
result = (a and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32
else:
var res: Stat
result = lstat(link, res) >= 0'i32 and S_ISLNK(res.st_mode)
when defined(windows) and not weirdTarget:
proc openHandle*(path: string, followSymlink=true, writeAccess=false): Handle =
var flags = FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL
if not followSymlink:
flags = flags or FILE_FLAG_OPEN_REPARSE_POINT
let access = if writeAccess: GENERIC_WRITE else: 0'i32
proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1",
tags: [ReadDirEffect],
noWeirdTarget, sideEffect.} =
## Returns true if the symlink `link` exists. Will return true
## regardless of whether the link points to a directory or file.
##
## See also:
## * `fileExists proc`_
## * `dirExists proc`_
when defined(windows):
wrapUnary(a, getFileAttributesW, link)
if a != -1'i32:
# xxx see: bug #16784 (bug9); checking `IO_REPARSE_TAG_SYMLINK`
# may also be needed.
result = (a and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32
else:
var res: Stat
result = lstat(link, res) >= 0'i32 and S_ISLNK(res.st_mode)
when defined(windows) and not weirdTarget:
proc openHandle*(path: string, followSymlink=true, writeAccess=false): Handle =
var flags = FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL
if not followSymlink:
flags = flags or FILE_FLAG_OPEN_REPARSE_POINT
let access = if writeAccess: GENERIC_WRITE else: 0'i32
result = createFileW(
newWideCString(path), access,
FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE,
nil, OPEN_EXISTING, flags, 0
)
result = createFileW(
newWideCString(path), access,
FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE,
nil, OPEN_EXISTING, flags, 0
)

View File

@@ -6,7 +6,9 @@ import std/oserrors
import ospaths2, osfiles
import oscommon
export dirExists, PathComponent
import std/staticos
when supportedSystem:
export dirExists, PathComponent
when defined(nimPreviewSlimSystem):
@@ -20,9 +22,6 @@ elif defined(windows):
elif defined(posix):
import std/[posix, times]
else:
{.error: "OS module not ported to your operating system!".}
when weirdTarget:
{.pragma: noWeirdTarget, error: "this proc is not available on the NimScript/js target".}
@@ -152,10 +151,6 @@ iterator walkDirs*(pattern: string): string {.tags: [ReadDirEffect], noWeirdTarg
assert "lib/pure/concurrency".unixToNativePath in paths
walkCommon(pattern, isDir)
proc staticWalkDir(dir: string; relative: bool): seq[
tuple[kind: PathComponent, path: string]] =
discard
iterator walkDir*(dir: string; relative = false, checkDir = false,
skipSpecial = false):
tuple[kind: PathComponent, path: string] {.tags: [ReadDirEffect].} =
@@ -325,7 +320,6 @@ iterator walkDirRec*(dir: string,
# continue iteration.
# Future work can provide a way to customize this and do error reporting.
proc rawRemoveDir(dir: string) {.noWeirdTarget.} =
when defined(windows):
wrapUnary(res, removeDirectoryW, dir)

View File

@@ -21,8 +21,6 @@ elif defined(posix):
proc toTime(ts: Timespec): times.Time {.inline.} =
result = initTime(ts.tv_sec.int64, ts.tv_nsec.int)
else:
{.error: "OS module not ported to your operating system!".}
when weirdTarget:

View File

@@ -20,8 +20,6 @@ elif defined(windows):
import std/winlean
elif defined(posix):
import std/posix, system/ansi_c
else:
{.error: "OS module not ported to your operating system!".}
when weirdTarget:
{.pragma: noWeirdTarget, error: "this proc is not available on the NimScript/js target".}
@@ -840,7 +838,7 @@ proc unixToNativePath*(path: string, drive=""): string {.
inc(i)
when not defined(nimscript):
when not defined(nimscript) and supportedSystem:
proc getCurrentDir*(): string {.rtl, extern: "nos$1", tags: [].} =
## Returns the `current working directory`:idx: i.e. where the built
## binary is run.
@@ -889,7 +887,7 @@ when not defined(nimscript):
else:
raiseOSError(osLastError())
proc absolutePath*(path: string, root = getCurrentDir()): string =
proc absolutePath*(path: string, root = when supportedSystem: getCurrentDir() else: ""): string =
## Returns the absolute path of `path`, rooted at `root` (which must be absolute;
## default: current directory).
## If `path` is absolute, return it, ignoring `root`.
@@ -907,7 +905,7 @@ proc absolutePath*(path: string, root = getCurrentDir()): string =
joinPath(root, path)
proc absolutePathInternal(path: string): string =
absolutePath(path, getCurrentDir())
absolutePath(path)
proc normalizePath*(path: var string) {.rtl, extern: "nos$1", tags: [].} =
@@ -984,48 +982,49 @@ proc normalizeExe*(file: var string) {.since: (1, 3, 5).} =
if file.len > 0 and DirSep notin file and file != "." and file != "..":
file = "./" & file
proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
tags: [ReadDirEffect], noWeirdTarget.} =
## Returns true if both pathname arguments refer to the same physical
## file or directory.
##
## Raises `OSError` if any of the files does not
## exist or information about it can not be obtained.
##
## This proc will return true if given two alternative hard-linked or
## sym-linked paths to the same file or directory.
##
## See also:
## * `sameFileContent proc`_
result = false
when defined(windows):
var success = true
var f1 = openHandle(path1)
var f2 = openHandle(path2)
when supportedSystem:
proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
tags: [ReadDirEffect], noWeirdTarget.} =
## Returns true if both pathname arguments refer to the same physical
## file or directory.
##
## Raises `OSError` if any of the files does not
## exist or information about it can not be obtained.
##
## This proc will return true if given two alternative hard-linked or
## sym-linked paths to the same file or directory.
##
## See also:
## * `sameFileContent proc`_
result = false
when defined(windows):
var success = true
var f1 = openHandle(path1)
var f2 = openHandle(path2)
var lastErr: OSErrorCode
if f1 != INVALID_HANDLE_VALUE and f2 != INVALID_HANDLE_VALUE:
var fi1, fi2: BY_HANDLE_FILE_INFORMATION
var lastErr: OSErrorCode
if f1 != INVALID_HANDLE_VALUE and f2 != INVALID_HANDLE_VALUE:
var fi1, fi2: BY_HANDLE_FILE_INFORMATION
if getFileInformationByHandle(f1, addr(fi1)) != 0 and
getFileInformationByHandle(f2, addr(fi2)) != 0:
result = fi1.dwVolumeSerialNumber == fi2.dwVolumeSerialNumber and
fi1.nFileIndexHigh == fi2.nFileIndexHigh and
fi1.nFileIndexLow == fi2.nFileIndexLow
if getFileInformationByHandle(f1, addr(fi1)) != 0 and
getFileInformationByHandle(f2, addr(fi2)) != 0:
result = fi1.dwVolumeSerialNumber == fi2.dwVolumeSerialNumber and
fi1.nFileIndexHigh == fi2.nFileIndexHigh and
fi1.nFileIndexLow == fi2.nFileIndexLow
else:
lastErr = osLastError()
success = false
else:
lastErr = osLastError()
success = false
else:
lastErr = osLastError()
success = false
discard closeHandle(f1)
discard closeHandle(f2)
discard closeHandle(f1)
discard closeHandle(f2)
if not success: raiseOSError(lastErr, $(path1, path2))
else:
var a, b: Stat
if stat(path1, a) < 0'i32 or stat(path2, b) < 0'i32:
raiseOSError(osLastError(), $(path1, path2))
if not success: raiseOSError(lastErr, $(path1, path2))
else:
result = a.st_dev == b.st_dev and a.st_ino == b.st_ino
var a, b: Stat
if stat(path1, a) < 0'i32 or stat(path2, b) < 0'i32:
raiseOSError(osLastError(), $(path1, path2))
else:
result = a.st_dev == b.st_dev and a.st_ino == b.st_ino

View File

@@ -2,7 +2,8 @@ include system/inclrtl
import std/oserrors
import oscommon
export symlinkExists
when supportedSystem:
export symlinkExists
when defined(nimPreviewSlimSystem):
import std/[syncio, assertions, widestrs]
@@ -13,8 +14,6 @@ elif defined(windows):
import std/[winlean, times]
elif defined(posix):
import std/posix
else:
{.error: "OS module not ported to your operating system!".}
when weirdTarget:

View File

@@ -14,3 +14,25 @@ proc staticDirExists*(dir: string): bool {.compileTime.} =
## Returns true if the directory `dir` exists. If `dir` is a file, false
## is returned. Follows symlinks.
raiseAssert "implemented in the vmops"
type
PathComponent* = enum ## Enumeration specifying a path component.
##
## See also:
## * `walkDirRec iterator`_
## * `FileInfo object`_
pcFile, ## path refers to a file
pcLinkToFile, ## path refers to a symbolic link to a file
pcDir, ## path refers to a directory
pcLinkToDir ## path refers to a symbolic link to a directory
proc staticWalkDir*(dir: string; relative = false): seq[
tuple[kind: PathComponent, path: string]] {.compileTime.} =
## Walks over the directory `dir` and returns a seq with each directory or
## file in `dir`. The component type and full path for each item are returned.
##
## Walking is not recursive.
## * If `relative` is true (default: false)
## the resulting path is shortened to be relative to ``dir``,
## otherwise the full path is returned.
raiseAssert "implemented in the vmops"

View File

@@ -128,7 +128,7 @@ proc genTempPath*(prefix, suffix: string, dir = ""): string =
##
## The path begins with `prefix` and ends with `suffix`.
##
## .. note:: `dir` must exist (empty `dir` will resolve to `getTempDir <os.html#getTempDir>`_).
## .. note:: `dir` must exist (empty `dir` will resolve to `getTempDir <appdirs.html#getTempDir>`_).
let dir = getTempDirImpl(dir)
result = dir / (prefix & randomPathName(nimTempPathLength) & suffix)
@@ -143,7 +143,7 @@ proc createTempFile*(prefix, suffix: string, dir = ""): tuple[cfile: File, path:
##
## .. note:: It is the caller's responsibility to close `result.cfile` and
## remove `result.file` when no longer needed.
## .. note:: `dir` must exist (empty `dir` will resolve to `getTempDir <os.html#getTempDir>`_).
## .. note:: `dir` must exist (empty `dir` will resolve to `getTempDir <appdirs.html#getTempDir>`_).
runnableExamples:
import std/os
doAssertRaises(OSError): discard createTempFile("", "", "nonexistent")
@@ -176,7 +176,7 @@ proc createTempDir*(prefix, suffix: string, dir = ""): string =
## If failing to create a temporary directory, `OSError` will be raised.
##
## .. note:: It is the caller's responsibility to remove the directory when no longer needed.
## .. note:: `dir` must exist (empty `dir` will resolve to `getTempDir <os.html#getTempDir>`_).
## .. note:: `dir` must exist (empty `dir` will resolve to `getTempDir <appdirs.html#getTempDir>`_).
runnableExamples:
import std/os
doAssertRaises(OSError): discard createTempDir("", "", "nonexistent")

View File

@@ -0,0 +1,15 @@
discard """
$nimsuggest --tester $file
>outline $file
outline;;skProc;;t21923.foo;;proc (x: int){.gcsafe, raises: <inferred> [].};;$file;;8;;5;;"";;100
outline;;skTemplate;;t21923.foo2;;;;$file;;11;;9;;"";;100
"""
proc foo(x: int) =
echo "foo"
template foo2(x: int) =
echo "foo2"
foo(12)
foo2(12)

View File

@@ -6,7 +6,7 @@ tmp#[!]#
discard """
$nimsuggest --tester $file
>sug $1
sug;;skTemplate;;tsug_template.tmpa;;template ();;$file;;1;;9;;"";;100;;Prefix
sug;;skMacro;;tsug_template.tmpb;;macro (){.noSideEffect, gcsafe, raises: <inferred> [].};;$file;;2;;6;;"";;100;;Prefix
sug;;skConverter;;tsug_template.tmpc;;converter ();;$file;;3;;10;;"";;100;;Prefix
sug;;skTemplate;;tsug_template.tmpa;;template ();;$file;;1;;9;;"";;100;;Prefix
"""

View File

@@ -128,4 +128,10 @@ block:
var b = makeBoo()
var b2 = makeBoo2()
main()
main()
block: # bug #24658
type
A {.importcpp: "A".} = object
proc a(something: ptr cint = nil): A {.cdecl, constructor, importcpp: "A(@)".}

View File

@@ -0,0 +1,11 @@
import "."/[mambtype1, mambtype2]
type H[K] = object
proc b(_: int) = # slightly different, still not useful, error message if `b` generic
proc r(): H[Y] = discard #[tt.Error
^ cannot instantiate H [type declared in tambtypegeneric.nim(2, 6)]
got: <typedesc[Y] | typedesc[Y]>
but expected: <K>
ambiguous identifier: 'Y' -- use one of the following:
mambtype1.Y: Y
mambtype2.Y: Y]#
b(0)

View File

@@ -6,6 +6,54 @@ import unittest, strutils
block: # parseutils
check: parseBiggestUInt("0") == 0'u64
check: parseBiggestUInt("1") == 1'u64
check: parseBiggestUInt("2") == 2'u64
check: parseBiggestUInt("10") == 10'u64
check: parseBiggestUInt("11") == 11'u64
check: parseBiggestUInt("99") == 99'u64
check: parseBiggestUInt("123") == 123'u64
check: parseBiggestUInt("9876") == 9876'u64
check: parseBiggestUInt("1_234") == 1234'u64
check: parseBiggestUInt("123__4") == 1234'u64
for i in 1.BiggestUInt .. 9.BiggestUInt:
var x = i
for j in 1 .. 19:
check parseBiggestUInt((i + '0'.uint).char.repeat j) == x
x *= 10
x += i
check: parseBiggestUInt("18446744073709551609") == 0xFFFF_FFFF_FFFF_FFF9'u64
check: parseBiggestUInt("18446744073709551610") == 0xFFFF_FFFF_FFFF_FFFA'u64
check: parseBiggestUInt("18446744073709551611") == 0xFFFF_FFFF_FFFF_FFFB'u64
check: parseBiggestUInt("18446744073709551612") == 0xFFFF_FFFF_FFFF_FFFC'u64
check: parseBiggestUInt("18446744073709551613") == 0xFFFF_FFFF_FFFF_FFFD'u64
check: parseBiggestUInt("18446744073709551614") == 0xFFFF_FFFF_FFFF_FFFE'u64
check: parseBiggestUInt("18446744073709551615") == 0xFFFF_FFFF_FFFF_FFFF'u64
expect(ValueError):
discard parseBiggestUInt("18446744073709551616")
expect(ValueError):
discard parseBiggestUInt("18446744073709551617")
expect(ValueError):
discard parseBiggestUInt("18446744073709551618")
expect(ValueError):
discard parseBiggestUInt("18446744073709551619")
expect(ValueError):
discard parseBiggestUInt("18446744073709551620")
expect(ValueError):
discard parseBiggestUInt("18446744073709551621")
expect(ValueError):
discard parseBiggestUInt("18446744073709551622")
expect(ValueError):
discard parseBiggestUInt("18446744073709551623")
expect(ValueError):
for i in 0 .. 999:
discard parseBiggestUInt("18446744073709552" & intToStr(i, 3))
expect(ValueError):
discard parseBiggestUInt("22751622367522324480000000")
expect(ValueError):
discard parseBiggestUInt("41404969074137497600000000")
expect(ValueError):
discard parseBiggestUInt("20701551093035827200000000000000000")
expect(ValueError):
discard parseBiggestUInt("225462255024603136000000000000000000")
expect(ValueError):
discard parseBiggestUInt("204963831854661632000000000000000000")

View File

@@ -0,0 +1,9 @@
# issue #24657
proc g() {.error.} = discard
type T = object
g: int
template B(): untyped = typeof(T.g)
type _ = B()