mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 12:07:51 +00:00
Merge branch 'devel' of https://github.com/Araq/Nimrod into devel
This commit is contained in:
@@ -404,7 +404,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||
mExit, mInc, ast.mDec, mEcho, mSwap, mAppendStrCh,
|
||||
mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
|
||||
mParseExprToAst, mParseStmtToAst, mExpandToAst, mTypeTrait,
|
||||
mNLen..mNError, mEqRef, mSlurp, mStaticExec, mNGenSym:
|
||||
mNLen..mNError, mEqRef, mSlurp, mStaticExec, mNGenSym, mSpawn:
|
||||
discard
|
||||
of mRand:
|
||||
result = newIntNodeT(math.random(a.getInt.int), n)
|
||||
|
||||
@@ -253,6 +253,7 @@ proc findUsages(node: PNode, s: PSym) =
|
||||
lastLineInfo = node.info
|
||||
|
||||
proc findDefinition(node: PNode, s: PSym) =
|
||||
if node.isNil or s.isNil: return
|
||||
if isTracked(node.info, s.name.s.len):
|
||||
suggestWriteln(symToStr(s, isLocal=false, sectionDef))
|
||||
suggestQuit()
|
||||
|
||||
@@ -354,6 +354,11 @@ template handleJmpBack() {.dirty.} =
|
||||
globalError(c.debug[pc], errTooManyIterations)
|
||||
dec(c.loopIterations)
|
||||
|
||||
proc skipColon(n: PNode): PNode =
|
||||
result = n
|
||||
if n.kind == nkExprColonExpr:
|
||||
result = n.sons[1]
|
||||
|
||||
proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
var pc = start
|
||||
var tos = tos
|
||||
@@ -454,7 +459,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
decodeBC(rkNode)
|
||||
let src = regs[rb].node
|
||||
if src.kind notin {nkEmpty..nkNilLit}:
|
||||
let n = src.sons[rc]
|
||||
let n = src.sons[rc].skipColon
|
||||
regs[ra].node = n
|
||||
else:
|
||||
stackTrace(c, tos, pc, errNilAccess)
|
||||
@@ -1099,6 +1104,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
c.module)
|
||||
of opcGorge:
|
||||
decodeBC(rkNode)
|
||||
createStr regs[ra]
|
||||
regs[ra].node.strVal = opGorge(regs[rb].node.strVal,
|
||||
regs[rc].node.strVal)
|
||||
of opcNError:
|
||||
|
||||
@@ -70,6 +70,9 @@ proc echoCode*(c: PCtx, start=0) {.deprecated.} =
|
||||
echo buf
|
||||
|
||||
proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) =
|
||||
## Takes the registers `b` and `c`, applies the operation `opc` to them, and
|
||||
## stores the result into register `a`
|
||||
## The node is needed for debug information
|
||||
assert opc.ord < 255
|
||||
let ins = (opc.uint32 or (a.uint32 shl 8'u32) or
|
||||
(b.uint32 shl 16'u32) or
|
||||
@@ -78,6 +81,10 @@ proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) =
|
||||
ctx.debug.add(n.info)
|
||||
|
||||
proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: BiggestInt) =
|
||||
# Takes the `b` register and the immediate `imm`, appies the operation `opc`,
|
||||
# and stores the output value into `a`.
|
||||
# `imm` is signed and must be within [-127, 128]
|
||||
assert(imm >= -127 and imm <= 128)
|
||||
let ins = (opc.uint32 or (a.uint32 shl 8'u32) or
|
||||
(b.uint32 shl 16'u32) or
|
||||
(imm+byteExcess).uint32 shl 24'u32).TInstr
|
||||
@@ -85,6 +92,9 @@ proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: BiggestInt) =
|
||||
c.debug.add(n.info)
|
||||
|
||||
proc gABx(c: PCtx; n: PNode; opc: TOpcode; a: TRegister = 0; bx: int) =
|
||||
# Applies `opc` to `bx` and stores it into register `a`
|
||||
# `bx` must be signed and in the range [-32767, 32768]
|
||||
assert(bx >= -32767 and bx <= 32768)
|
||||
let ins = (opc.uint32 or a.uint32 shl 8'u32 or
|
||||
(bx+wordExcess).uint32 shl 16'u32).TInstr
|
||||
c.code.add(ins)
|
||||
@@ -316,15 +326,7 @@ proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
|
||||
c.patch(L1)
|
||||
|
||||
proc canonValue*(n: PNode): PNode =
|
||||
if n.kind == nkExprColonExpr:
|
||||
result = n.sons[1]
|
||||
elif n.hasSubnodeWith(nkExprColonExpr):
|
||||
result = n.copyNode
|
||||
newSeq(result.sons, n.len)
|
||||
for i in 0.. <n.len:
|
||||
result.sons[i] = canonValue(n.sons[i])
|
||||
else:
|
||||
result = n
|
||||
result = n
|
||||
|
||||
proc rawGenLiteral(c: PCtx; n: PNode): int =
|
||||
result = c.constants.len
|
||||
|
||||
66
doc/tut1.txt
66
doc/tut1.txt
@@ -132,7 +132,7 @@ a backslash:
|
||||
TMyObject {.final, pure, acyclic.} = object # comment continues: \
|
||||
# we have lots of space here to comment 'TMyObject'.
|
||||
# This line belongs to the comment as it's properly aligned.
|
||||
|
||||
|
||||
|
||||
Comments are tokens; they are only allowed at certain places in the input file
|
||||
as they belong to the syntax tree! This feature enables perfect source-to-source
|
||||
@@ -150,6 +150,18 @@ the syntax, watch their indentation:
|
||||
**Note**: To comment out a large piece of code, it is often better to use a
|
||||
``when false:`` statement.
|
||||
|
||||
.. code-block:: nimrod
|
||||
when false:
|
||||
brokenCode()
|
||||
|
||||
Another option is to use the `discard`_ statement together with
|
||||
*long string literals* to create block comments:
|
||||
|
||||
.. code-block:: nimrod
|
||||
discard """ You can have any nimrod code text commented
|
||||
out inside this with no indentation restrictions.
|
||||
yes("May I ask a pointless question?") """
|
||||
|
||||
|
||||
Numbers
|
||||
-------
|
||||
@@ -575,27 +587,46 @@ Some terminology: in the example ``question`` is called a (formal) *parameter*,
|
||||
|
||||
Result variable
|
||||
---------------
|
||||
A procedure that returns a value has an implicit ``result`` variable that
|
||||
represents the return value. A ``return`` statement with no expression is a
|
||||
shorthand for ``return result``. So all three code snippets are equivalent:
|
||||
A procedure that returns a value has an implicit ``result`` variable declared
|
||||
that represents the return value. A ``return`` statement with no expression is a
|
||||
shorthand for ``return result``. The ``result`` value is always returned
|
||||
automatically at the end a procedure if there is no ``return`` statement at
|
||||
the exit.
|
||||
|
||||
.. code-block:: nimrod
|
||||
return 42
|
||||
|
||||
.. code-block:: nimrod
|
||||
result = 42
|
||||
return
|
||||
|
||||
.. code-block:: nimrod
|
||||
result = 42
|
||||
return result
|
||||
proc sumTillNegative(x: varargs[int]): int =
|
||||
for i in x:
|
||||
if i < 0:
|
||||
return
|
||||
result = result + i
|
||||
|
||||
echo sumTillNegative() # echos 0
|
||||
echo sumTillNegative(3, 4, 5) # echos 12
|
||||
echo sumTillNegative(3, 4 , -1 , 6) # echos 7
|
||||
|
||||
The ``result`` variable is already implicitly declared at the start of the
|
||||
function, so declaring it again with 'var result', for example, would shadow it
|
||||
with a normal variable of the same name. The result variable is also already
|
||||
initialised with the type's default value. Note that referential data types will
|
||||
be ``nil`` at the start of the procedure, and thus may require manual
|
||||
initialisation.
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
Parameters are constant in the procedure body. Their value cannot be changed
|
||||
because this allows the compiler to implement parameter passing in the most
|
||||
efficient way. If the procedure needs to modify the argument for the
|
||||
Parameters are constant in the procedure body. By default, their value cannot be
|
||||
changed because this allows the compiler to implement parameter passing in the
|
||||
most efficient way. If a mutable variable is needed inside the procedure, it has
|
||||
to be declared with ``var`` in the procedure body. Shadowing the parameter name
|
||||
is possible, and actually an idiom:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc printSeq(s: seq, nprinted: int = -1) =
|
||||
var nprinted = if nprinted == -1: s.len else: min(nprinted, s.len)
|
||||
for i in 0 .. <nprinted:
|
||||
echo s[i]
|
||||
|
||||
If the procedure needs to modify the argument for the
|
||||
caller, a ``var`` parameter can be used:
|
||||
|
||||
.. code-block:: nimrod
|
||||
@@ -634,6 +665,9 @@ been declared with the ``discardable`` pragma:
|
||||
|
||||
p(3, 4) # now valid
|
||||
|
||||
The discard statement can also be used to create block comments as described
|
||||
in the `Comments`_.
|
||||
|
||||
|
||||
Named arguments
|
||||
---------------
|
||||
|
||||
@@ -26,8 +26,15 @@ proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
for i in 0 .. <p.len:
|
||||
let ident = p[i]
|
||||
var identDefs = newNimNode(nnkIdentDefs)
|
||||
identDefs.add newIdentNode("i" & $i)
|
||||
identDefs.add(ident)
|
||||
case ident.kind
|
||||
of nnkExprColonExpr:
|
||||
identDefs.add ident[0]
|
||||
identDefs.add ident[1]
|
||||
of nnkIdent:
|
||||
identDefs.add newIdentNode("i" & $i)
|
||||
identDefs.add(ident)
|
||||
else:
|
||||
error("Incorrect type list in proc type declaration.")
|
||||
identDefs.add newEmptyNode()
|
||||
formalParams.add identDefs
|
||||
of nnkIdent:
|
||||
@@ -47,7 +54,7 @@ proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
macro `=>`*(p, b: expr): expr {.immediate.} =
|
||||
## Syntax sugar for anonymous procedures.
|
||||
##
|
||||
## ..code-block:: nimrod
|
||||
## .. code-block:: nimrod
|
||||
##
|
||||
## proc passTwoAndTwo(f: (int, int) -> int): int =
|
||||
## f(2, 2)
|
||||
@@ -98,7 +105,7 @@ macro `=>`*(p, b: expr): expr {.immediate.} =
|
||||
macro `->`*(p, b: expr): expr {.immediate.} =
|
||||
## Syntax sugar for procedure types.
|
||||
##
|
||||
## ..code-block:: nimrod
|
||||
## .. code-block:: nimrod
|
||||
##
|
||||
## proc pass2(f: (float, float) -> float): float =
|
||||
## f(2, 2)
|
||||
|
||||
179
lib/pure/os.nim
179
lib/pure/os.nim
@@ -448,6 +448,8 @@ proc getLastAccessTime*(file: string): TTime {.rtl, extern: "nos$1".} =
|
||||
|
||||
proc getCreationTime*(file: string): TTime {.rtl, extern: "nos$1".} =
|
||||
## Returns the `file`'s creation time.
|
||||
## Note that under posix OS's, the returned time may actually be the time at
|
||||
## which the file's attribute's were last modified.
|
||||
when defined(posix):
|
||||
var res: TStat
|
||||
if stat(file, res) < 0'i32: osError(osLastError())
|
||||
@@ -777,6 +779,25 @@ proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} =
|
||||
elif defined(posix):
|
||||
result = path[0] == '/'
|
||||
|
||||
when defined(Windows):
|
||||
proc openHandle(path: string, followSymlink=true): THandle =
|
||||
var flags = FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL
|
||||
if not followSymlink:
|
||||
flags = flags or FILE_FLAG_OPEN_REPARSE_POINT
|
||||
|
||||
when useWinUnicode:
|
||||
result = createFileW(
|
||||
newWideCString(path), 0'i32,
|
||||
FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE,
|
||||
nil, OPEN_EXISTING, flags, 0
|
||||
)
|
||||
else:
|
||||
result = createFileA(
|
||||
path, 0'i32,
|
||||
FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE,
|
||||
nil, OPEN_EXISTING, flags, 0
|
||||
)
|
||||
|
||||
proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
|
||||
tags: [FReadDir].} =
|
||||
## Returns True if both pathname arguments refer to the same physical
|
||||
@@ -787,26 +808,8 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
|
||||
## sym-linked paths to the same file or directory.
|
||||
when defined(Windows):
|
||||
var success = true
|
||||
|
||||
when useWinUnicode:
|
||||
var p1 = newWideCString(path1)
|
||||
var p2 = newWideCString(path2)
|
||||
template openHandle(path: expr): expr =
|
||||
createFileW(path, 0'i32, FILE_SHARE_DELETE or FILE_SHARE_READ or
|
||||
FILE_SHARE_WRITE, nil, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL, 0)
|
||||
|
||||
var f1 = openHandle(p1)
|
||||
var f2 = openHandle(p2)
|
||||
|
||||
else:
|
||||
template openHandle(path: expr): expr =
|
||||
createFileA(path, 0'i32, FILE_SHARE_DELETE or FILE_SHARE_READ or
|
||||
FILE_SHARE_WRITE, nil, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL, 0)
|
||||
|
||||
var f1 = openHandle(path1)
|
||||
var f2 = openHandle(path2)
|
||||
var f1 = openHandle(path1)
|
||||
var f2 = openHandle(path2)
|
||||
|
||||
var lastErr: TOSErrorCode
|
||||
if f1 != INVALID_HANDLE_VALUE and f2 != INVALID_HANDLE_VALUE:
|
||||
@@ -1747,4 +1750,140 @@ proc expandTilde*(path: string): string =
|
||||
else:
|
||||
result = path
|
||||
|
||||
when defined(Windows):
|
||||
type
|
||||
DeviceId = int32
|
||||
FileId = int64
|
||||
else:
|
||||
type
|
||||
DeviceId = TDev
|
||||
FileId = TIno
|
||||
|
||||
type
|
||||
FileInfo = object
|
||||
## Contains information associated with a file object.
|
||||
id: tuple[device: DeviceId, file: FileId] # Device and file id.
|
||||
kind: TPathComponent # Kind of file object - directory, symlink, etc.
|
||||
size: BiggestInt # Size of file.
|
||||
permissions: set[TFilePermission] # File permissions
|
||||
linkCount: BiggestInt # Number of hard links the file object has.
|
||||
lastAccessTime: TTime # Time file was last accessed.
|
||||
lastWriteTime: TTime # Time file was last modified/written to.
|
||||
creationTime: TTime # Time file was created. Not supported on all systems!
|
||||
|
||||
template rawToFormalFileInfo(rawInfo, formalInfo): expr =
|
||||
## Transforms the native file info structure into the one nimrod uses.
|
||||
## 'rawInfo' is either a 'TBY_HANDLE_FILE_INFORMATION' structure on Windows,
|
||||
## or a 'TStat' structure on posix
|
||||
when defined(Windows):
|
||||
template toTime(e): expr = winTimeToUnixTime(rdFileTime(e))
|
||||
template merge(a, b): expr = a or (b shl 32)
|
||||
formalInfo.id.device = rawInfo.dwVolumeSerialNumber
|
||||
formalInfo.id.file = merge(rawInfo.nFileIndexLow, rawInfo.nFileIndexHigh)
|
||||
formalInfo.size = merge(rawInfo.nFileSizeLow, rawInfo.nFileSizeHigh)
|
||||
formalInfo.linkCount = rawInfo.nNumberOfLinks
|
||||
formalInfo.lastAccessTime = toTime(rawInfo.ftLastAccessTime)
|
||||
formalInfo.lastWriteTime = toTime(rawInfo.ftLastWriteTime)
|
||||
formalInfo.creationTime = toTime(rawInfo.ftCreationTime)
|
||||
|
||||
# Retrieve basic permissions
|
||||
if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_READONLY) != 0'i32:
|
||||
formalInfo.permissions = {fpUserExec, fpUserRead, fpGroupExec,
|
||||
fpGroupRead, fpOthersExec, fpOthersRead}
|
||||
else:
|
||||
result.permissions = {fpUserExec..fpOthersRead}
|
||||
|
||||
# Retrieve basic file kind
|
||||
result.kind = pcFile
|
||||
if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32:
|
||||
formalInfo.kind = pcDir
|
||||
if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32:
|
||||
formalInfo.kind = succ(result.kind)
|
||||
|
||||
else:
|
||||
template checkAndIncludeMode(rawMode, formalMode: expr) =
|
||||
if (rawInfo.st_mode and rawMode) != 0'i32:
|
||||
formalInfo.permissions.incl(formalMode)
|
||||
formalInfo.id = (rawInfo.st_dev, rawInfo.st_ino)
|
||||
formalInfo.size = rawInfo.st_size
|
||||
formalInfo.linkCount = rawInfo.st_Nlink
|
||||
formalInfo.lastAccessTime = rawInfo.st_atime
|
||||
formalInfo.lastWriteTime = rawInfo.st_mtime
|
||||
formalInfo.creationTime = rawInfo.st_ctime
|
||||
|
||||
result.permissions = {}
|
||||
checkAndIncludeMode(S_IRUSR, fpUserRead)
|
||||
checkAndIncludeMode(S_IWUSR, fpUserWrite)
|
||||
checkAndIncludeMode(S_IXUSR, fpUserExec)
|
||||
|
||||
checkAndIncludeMode(S_IRGRP, fpGroupRead)
|
||||
checkAndIncludeMode(S_IWGRP, fpGroupWrite)
|
||||
checkAndIncludeMode(S_IXGRP, fpGroupExec)
|
||||
|
||||
checkAndIncludeMode(S_IROTH, fpOthersRead)
|
||||
checkAndIncludeMode(S_IWOTH, fpOthersWrite)
|
||||
checkAndIncludeMode(S_IXOTH, fpOthersExec)
|
||||
|
||||
formalInfo.kind = pcFile
|
||||
if S_ISDIR(rawInfo.st_mode): formalInfo.kind = pcDir
|
||||
if S_ISLNK(rawInfo.st_mode): formalInfo.kind.inc()
|
||||
|
||||
proc getFileInfo*(handle: TFileHandle): FileInfo =
|
||||
## Retrieves file information for the file object represented by the given
|
||||
## handle.
|
||||
##
|
||||
## If the information cannot be retrieved, such as when the file handle
|
||||
## is invalid, an error will be thrown.
|
||||
# Done: ID, Kind, Size, Permissions, Link Count
|
||||
when defined(Windows):
|
||||
var rawInfo: TBY_HANDLE_FILE_INFORMATION
|
||||
# We have to use the super special '_get_osfhandle' call (wrapped above)
|
||||
# To transform the C file descripter to a native file handle.
|
||||
var realHandle = get_osfhandle(handle)
|
||||
if getFileInformationByHandle(realHandle, addr rawInfo) == 0:
|
||||
osError(osLastError())
|
||||
rawToFormalFileInfo(rawInfo, result)
|
||||
else:
|
||||
var rawInfo: TStat
|
||||
if fstat(handle, rawInfo) < 0'i32:
|
||||
osError(osLastError())
|
||||
rawToFormalFileInfo(rawInfo, result)
|
||||
|
||||
proc getFileInfo*(file: TFile): FileInfo =
|
||||
result = getFileInfo(file.fileHandle())
|
||||
|
||||
proc getFileInfo*(path: string, followSymlink = true): FileInfo =
|
||||
## Retrieves file information for the file object pointed to by `path`.
|
||||
##
|
||||
## Due to intrinsic differences between operating systems, the information
|
||||
## contained by the returned `FileInfo` structure will be slightly different
|
||||
## across platforms, and in some cases, incomplete or inaccurate.
|
||||
##
|
||||
## When `followSymlink` is true, symlinks are followed and the information
|
||||
## retrieved is information related to the symlink's target. Otherwise,
|
||||
## information on the symlink itself is retrieved.
|
||||
##
|
||||
## If the information cannot be retrieved, such as when the path doesn't
|
||||
## exist, or when permission restrictions prevent the program from retrieving
|
||||
## file information, an error will be thrown.
|
||||
when defined(Windows):
|
||||
var
|
||||
handle = openHandle(path, followSymlink)
|
||||
rawInfo: TBY_HANDLE_FILE_INFORMATION
|
||||
if handle == INVALID_HANDLE_VALUE:
|
||||
osError(osLastError())
|
||||
if getFileInformationByHandle(handle, addr rawInfo) == 0:
|
||||
osError(osLastError())
|
||||
rawToFormalFileInfo(rawInfo, result)
|
||||
discard closeHandle(handle)
|
||||
else:
|
||||
var rawInfo: TStat
|
||||
if followSymlink:
|
||||
if lstat(path, rawInfo) < 0'i32:
|
||||
osError(osLastError())
|
||||
else:
|
||||
if stat(path, rawInfo) < 0'i32:
|
||||
osError(osLastError())
|
||||
rawToFormalFileInfo(rawInfo, result)
|
||||
|
||||
{.pop.}
|
||||
|
||||
@@ -252,10 +252,8 @@ proc nimIntToStr(x: int): string {.compilerRtl.} =
|
||||
|
||||
proc nimFloatToStr(x: float): string {.compilerproc.} =
|
||||
var buf: array [0..59, char]
|
||||
c_sprintf(buf, "%#.f", x)
|
||||
result = $buf
|
||||
if result[len(result)-1] == '.':
|
||||
result.add("0")
|
||||
c_sprintf(buf, "%#.16e", x)
|
||||
return $buf
|
||||
|
||||
proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
|
||||
result = newString(sizeof(x)*4)
|
||||
|
||||
@@ -581,6 +581,7 @@ const
|
||||
INVALID_FILE_SIZE* = -1'i32
|
||||
|
||||
FILE_FLAG_BACKUP_SEMANTICS* = 33554432'i32
|
||||
FILE_FLAG_OPEN_REPARSE_POINT* = 0x00200000'i32
|
||||
|
||||
# Error Constants
|
||||
const
|
||||
@@ -715,3 +716,6 @@ proc WSASend*(s: TSocketHandle, buf: ptr TWSABuf, bufCount: DWORD,
|
||||
bytesSent: PDWord, flags: DWORD, lpOverlapped: POverlapped,
|
||||
completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {.
|
||||
stdcall, importc: "WSASend", dynlib: "Ws2_32.dll".}
|
||||
|
||||
proc get_osfhandle*(fd:TFileHandle): THandle {.
|
||||
importc:"_get_osfhandle", header:"<io.h>".}
|
||||
|
||||
@@ -5,6 +5,7 @@ discard """
|
||||
3
|
||||
3
|
||||
noReturn
|
||||
6
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -36,8 +37,7 @@ echo doWithOneAndTwo((x, y) => x + y)
|
||||
|
||||
noReturn(() -> void => echo("noReturn"))
|
||||
|
||||
when false:
|
||||
proc pass2(f: (int, int) -> int): (int) -> int =
|
||||
(x: int) -> int => f(2, x)
|
||||
proc pass2(f: (int, int) -> int): (int) -> int =
|
||||
(x: int) -> int => f(2, x)
|
||||
|
||||
#echo pass2((x, y) => x + y)
|
||||
echo pass2((x, y) => x + y)(4)
|
||||
|
||||
19
tests/macros/texprcolonexpr.nim
Normal file
19
tests/macros/texprcolonexpr.nim
Normal file
@@ -0,0 +1,19 @@
|
||||
discard """
|
||||
msg: '''
|
||||
Infix
|
||||
Ident !"=>"
|
||||
Call
|
||||
Ident !"name"
|
||||
Ident !"a"
|
||||
ExprColonExpr
|
||||
Ident !"b"
|
||||
Ident !"cint"
|
||||
NilLit nil
|
||||
'''
|
||||
"""
|
||||
import macros
|
||||
|
||||
macro def(x: stmt): stmt {.immediate.} =
|
||||
echo treeRepr(x)
|
||||
|
||||
def name(a, b:cint) => nil
|
||||
93
tests/stdlib/tgetfileinfo.nim
Normal file
93
tests/stdlib/tgetfileinfo.nim
Normal file
@@ -0,0 +1,93 @@
|
||||
discard """
|
||||
output: ""
|
||||
"""
|
||||
|
||||
import os, strutils
|
||||
# Cases
|
||||
# 1 - String : Existing File : Symlink true
|
||||
# 2 - String : Existing File : Symlink false
|
||||
# 3 - String : Non-existing File : Symlink true
|
||||
# 4 - String : Non-existing File : Symlink false
|
||||
# 5 - Handle : Valid File
|
||||
# 6 - Handle : Invalid File
|
||||
# 7 - Handle : Valid Handle
|
||||
# 8 - Handle : Invalid Handle
|
||||
|
||||
proc genBadFileName(limit = 100): string =
|
||||
## Generates a filename of a nonexistant file.
|
||||
## Returns "" if generation fails.
|
||||
result = "a"
|
||||
var hitLimit = true
|
||||
|
||||
for i in 0..100:
|
||||
if existsFile(result):
|
||||
result.add("a")
|
||||
else:
|
||||
hitLimit = false
|
||||
break
|
||||
if hitLimit:
|
||||
result = ""
|
||||
|
||||
proc caseOneAndTwo(followLink: bool) =
|
||||
try:
|
||||
discard getFileInfo(getAppFilename(), followLink)
|
||||
#echo("String : Existing File : Symlink $# : Success" % $followLink)
|
||||
except EOS:
|
||||
echo("String : Existing File : Symlink $# : Failure" % $followLink)
|
||||
|
||||
proc caseThreeAndFour(followLink: bool) =
|
||||
var invalidName = genBadFileName()
|
||||
try:
|
||||
discard getFileInfo(invalidName, true)
|
||||
echo("String : Non-existing File : Symlink $# : Failure" % $followLink)
|
||||
except EOS:
|
||||
#echo("String : Non-existing File : Symlink $# : Success" % $followLink)
|
||||
|
||||
proc testGetFileInfo =
|
||||
# Case 1
|
||||
caseOneAndTwo(true)
|
||||
|
||||
# Case 2
|
||||
caseOneAndTwo(false)
|
||||
|
||||
# Case 3
|
||||
caseThreeAndFour(true)
|
||||
|
||||
# Case 4
|
||||
caseThreeAndFour(false)
|
||||
|
||||
# Case 5 and 7
|
||||
block:
|
||||
let
|
||||
testFile = open(getAppFilename())
|
||||
testHandle = fileHandle(testFile)
|
||||
try:
|
||||
discard getFileInfo(testFile)
|
||||
#echo("Handle : Valid File : Success")
|
||||
except EIO:
|
||||
echo("Handle : Valid File : Failure")
|
||||
|
||||
try:
|
||||
discard getFileInfo(testHandle)
|
||||
#echo("Handle : Valid File : Success")
|
||||
except EIO:
|
||||
echo("Handle : Valid File : Failure")
|
||||
|
||||
# Case 6 and 8
|
||||
block:
|
||||
let
|
||||
testFile: TFile = nil
|
||||
testHandle = TFileHandle(-1)
|
||||
try:
|
||||
discard getFileInfo(testFile)
|
||||
echo("Handle : Invalid File : Failure")
|
||||
except EIO, EOS:
|
||||
#echo("Handle : Invalid File : Success")
|
||||
|
||||
try:
|
||||
discard getFileInfo(testHandle)
|
||||
echo("Handle : Invalid File : Failure")
|
||||
except EIO, EOS:
|
||||
#echo("Handle : Invalid File : Success")
|
||||
|
||||
testGetFileInfo()
|
||||
7
tests/system/tsysspawnbadarg.nim
Normal file
7
tests/system/tsysspawnbadarg.nim
Normal file
@@ -0,0 +1,7 @@
|
||||
discard """
|
||||
line: 7
|
||||
errormsg: "'spawn' takes a call expression of type void"
|
||||
cmd: "nimrod $target --threads:on $options $file"
|
||||
"""
|
||||
|
||||
spawn(1)
|
||||
Reference in New Issue
Block a user