Merge branch 'devel' of https://github.com/Araq/Nimrod into devel

This commit is contained in:
Araq 2014-04-21 00:07:40 +02:00
commit 2c97242739
13 changed files with 369 additions and 59 deletions

View file

@ -404,7 +404,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
mExit, mInc, ast.mDec, mEcho, mSwap, mAppendStrCh, mExit, mInc, ast.mDec, mEcho, mSwap, mAppendStrCh,
mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq, mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
mParseExprToAst, mParseStmtToAst, mExpandToAst, mTypeTrait, mParseExprToAst, mParseStmtToAst, mExpandToAst, mTypeTrait,
mNLen..mNError, mEqRef, mSlurp, mStaticExec, mNGenSym: mNLen..mNError, mEqRef, mSlurp, mStaticExec, mNGenSym, mSpawn:
discard discard
of mRand: of mRand:
result = newIntNodeT(math.random(a.getInt.int), n) result = newIntNodeT(math.random(a.getInt.int), n)

View file

@ -253,6 +253,7 @@ proc findUsages(node: PNode, s: PSym) =
lastLineInfo = node.info lastLineInfo = node.info
proc findDefinition(node: PNode, s: PSym) = proc findDefinition(node: PNode, s: PSym) =
if node.isNil or s.isNil: return
if isTracked(node.info, s.name.s.len): if isTracked(node.info, s.name.s.len):
suggestWriteln(symToStr(s, isLocal=false, sectionDef)) suggestWriteln(symToStr(s, isLocal=false, sectionDef))
suggestQuit() suggestQuit()

View file

@ -354,6 +354,11 @@ template handleJmpBack() {.dirty.} =
globalError(c.debug[pc], errTooManyIterations) globalError(c.debug[pc], errTooManyIterations)
dec(c.loopIterations) 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 = proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
var pc = start var pc = start
var tos = tos var tos = tos
@ -454,7 +459,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
decodeBC(rkNode) decodeBC(rkNode)
let src = regs[rb].node let src = regs[rb].node
if src.kind notin {nkEmpty..nkNilLit}: if src.kind notin {nkEmpty..nkNilLit}:
let n = src.sons[rc] let n = src.sons[rc].skipColon
regs[ra].node = n regs[ra].node = n
else: else:
stackTrace(c, tos, pc, errNilAccess) stackTrace(c, tos, pc, errNilAccess)
@ -1099,6 +1104,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
c.module) c.module)
of opcGorge: of opcGorge:
decodeBC(rkNode) decodeBC(rkNode)
createStr regs[ra]
regs[ra].node.strVal = opGorge(regs[rb].node.strVal, regs[ra].node.strVal = opGorge(regs[rb].node.strVal,
regs[rc].node.strVal) regs[rc].node.strVal)
of opcNError: of opcNError:

View file

@ -70,6 +70,9 @@ proc echoCode*(c: PCtx, start=0) {.deprecated.} =
echo buf echo buf
proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) = 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 assert opc.ord < 255
let ins = (opc.uint32 or (a.uint32 shl 8'u32) or let ins = (opc.uint32 or (a.uint32 shl 8'u32) or
(b.uint32 shl 16'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) ctx.debug.add(n.info)
proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: BiggestInt) = 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 let ins = (opc.uint32 or (a.uint32 shl 8'u32) or
(b.uint32 shl 16'u32) or (b.uint32 shl 16'u32) or
(imm+byteExcess).uint32 shl 24'u32).TInstr (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) c.debug.add(n.info)
proc gABx(c: PCtx; n: PNode; opc: TOpcode; a: TRegister = 0; bx: int) = 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 let ins = (opc.uint32 or a.uint32 shl 8'u32 or
(bx+wordExcess).uint32 shl 16'u32).TInstr (bx+wordExcess).uint32 shl 16'u32).TInstr
c.code.add(ins) c.code.add(ins)
@ -316,15 +326,7 @@ proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
c.patch(L1) c.patch(L1)
proc canonValue*(n: PNode): PNode = proc canonValue*(n: PNode): PNode =
if n.kind == nkExprColonExpr: result = n
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
proc rawGenLiteral(c: PCtx; n: PNode): int = proc rawGenLiteral(c: PCtx; n: PNode): int =
result = c.constants.len result = c.constants.len

View file

@ -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 **Note**: To comment out a large piece of code, it is often better to use a
``when false:`` statement. ``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 Numbers
------- -------
@ -575,27 +587,46 @@ Some terminology: in the example ``question`` is called a (formal) *parameter*,
Result variable Result variable
--------------- ---------------
A procedure that returns a value has an implicit ``result`` variable that A procedure that returns a value has an implicit ``result`` variable declared
represents the return value. A ``return`` statement with no expression is a that represents the return value. A ``return`` statement with no expression is a
shorthand for ``return result``. So all three code snippets are equivalent: 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 .. code-block:: nimrod
return 42 proc sumTillNegative(x: varargs[int]): int =
for i in x:
if i < 0:
return
result = result + i
.. code-block:: nimrod echo sumTillNegative() # echos 0
result = 42 echo sumTillNegative(3, 4, 5) # echos 12
return echo sumTillNegative(3, 4 , -1 , 6) # echos 7
.. code-block:: nimrod The ``result`` variable is already implicitly declared at the start of the
result = 42 function, so declaring it again with 'var result', for example, would shadow it
return result 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
---------- ----------
Parameters are constant in the procedure body. Their value cannot be changed Parameters are constant in the procedure body. By default, their value cannot be
because this allows the compiler to implement parameter passing in the most changed because this allows the compiler to implement parameter passing in the
efficient way. If the procedure needs to modify the argument for 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: caller, a ``var`` parameter can be used:
.. code-block:: nimrod .. code-block:: nimrod
@ -634,6 +665,9 @@ been declared with the ``discardable`` pragma:
p(3, 4) # now valid p(3, 4) # now valid
The discard statement can also be used to create block comments as described
in the `Comments`_.
Named arguments Named arguments
--------------- ---------------

View file

@ -26,8 +26,15 @@ proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} =
for i in 0 .. <p.len: for i in 0 .. <p.len:
let ident = p[i] let ident = p[i]
var identDefs = newNimNode(nnkIdentDefs) var identDefs = newNimNode(nnkIdentDefs)
identDefs.add newIdentNode("i" & $i) case ident.kind
identDefs.add(ident) 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() identDefs.add newEmptyNode()
formalParams.add identDefs formalParams.add identDefs
of nnkIdent: of nnkIdent:
@ -47,7 +54,7 @@ proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} =
macro `=>`*(p, b: expr): expr {.immediate.} = macro `=>`*(p, b: expr): expr {.immediate.} =
## Syntax sugar for anonymous procedures. ## Syntax sugar for anonymous procedures.
## ##
## ..code-block:: nimrod ## .. code-block:: nimrod
## ##
## proc passTwoAndTwo(f: (int, int) -> int): int = ## proc passTwoAndTwo(f: (int, int) -> int): int =
## f(2, 2) ## f(2, 2)
@ -98,7 +105,7 @@ macro `=>`*(p, b: expr): expr {.immediate.} =
macro `->`*(p, b: expr): expr {.immediate.} = macro `->`*(p, b: expr): expr {.immediate.} =
## Syntax sugar for procedure types. ## Syntax sugar for procedure types.
## ##
## ..code-block:: nimrod ## .. code-block:: nimrod
## ##
## proc pass2(f: (float, float) -> float): float = ## proc pass2(f: (float, float) -> float): float =
## f(2, 2) ## f(2, 2)

View file

@ -448,6 +448,8 @@ proc getLastAccessTime*(file: string): TTime {.rtl, extern: "nos$1".} =
proc getCreationTime*(file: string): TTime {.rtl, extern: "nos$1".} = proc getCreationTime*(file: string): TTime {.rtl, extern: "nos$1".} =
## Returns the `file`'s creation time. ## 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): when defined(posix):
var res: TStat var res: TStat
if stat(file, res) < 0'i32: osError(osLastError()) 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): elif defined(posix):
result = path[0] == '/' 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", proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
tags: [FReadDir].} = tags: [FReadDir].} =
## Returns True if both pathname arguments refer to the same physical ## 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. ## sym-linked paths to the same file or directory.
when defined(Windows): when defined(Windows):
var success = true var success = true
var f1 = openHandle(path1)
when useWinUnicode: var f2 = openHandle(path2)
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 lastErr: TOSErrorCode var lastErr: TOSErrorCode
if f1 != INVALID_HANDLE_VALUE and f2 != INVALID_HANDLE_VALUE: if f1 != INVALID_HANDLE_VALUE and f2 != INVALID_HANDLE_VALUE:
@ -1747,4 +1750,140 @@ proc expandTilde*(path: string): string =
else: else:
result = path 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.} {.pop.}

View file

@ -252,10 +252,8 @@ proc nimIntToStr(x: int): string {.compilerRtl.} =
proc nimFloatToStr(x: float): string {.compilerproc.} = proc nimFloatToStr(x: float): string {.compilerproc.} =
var buf: array [0..59, char] var buf: array [0..59, char]
c_sprintf(buf, "%#.f", x) c_sprintf(buf, "%#.16e", x)
result = $buf return $buf
if result[len(result)-1] == '.':
result.add("0")
proc nimInt64ToStr(x: int64): string {.compilerRtl.} = proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
result = newString(sizeof(x)*4) result = newString(sizeof(x)*4)

View file

@ -581,6 +581,7 @@ const
INVALID_FILE_SIZE* = -1'i32 INVALID_FILE_SIZE* = -1'i32
FILE_FLAG_BACKUP_SEMANTICS* = 33554432'i32 FILE_FLAG_BACKUP_SEMANTICS* = 33554432'i32
FILE_FLAG_OPEN_REPARSE_POINT* = 0x00200000'i32
# Error Constants # Error Constants
const const
@ -715,3 +716,6 @@ proc WSASend*(s: TSocketHandle, buf: ptr TWSABuf, bufCount: DWORD,
bytesSent: PDWord, flags: DWORD, lpOverlapped: POverlapped, bytesSent: PDWord, flags: DWORD, lpOverlapped: POverlapped,
completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {. completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {.
stdcall, importc: "WSASend", dynlib: "Ws2_32.dll".} stdcall, importc: "WSASend", dynlib: "Ws2_32.dll".}
proc get_osfhandle*(fd:TFileHandle): THandle {.
importc:"_get_osfhandle", header:"<io.h>".}

View file

@ -5,6 +5,7 @@ discard """
3 3
3 3
noReturn noReturn
6
''' '''
""" """
@ -36,8 +37,7 @@ echo doWithOneAndTwo((x, y) => x + y)
noReturn(() -> void => echo("noReturn")) noReturn(() -> void => echo("noReturn"))
when false: proc pass2(f: (int, int) -> int): (int) -> int =
proc pass2(f: (int, int) -> int): (int) -> int = (x: int) -> int => f(2, x)
(x: int) -> int => f(2, x)
#echo pass2((x, y) => x + y) echo pass2((x, y) => x + y)(4)

View 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

View 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()

View 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)