renamed optional to discardable
This commit is contained in:
parent
72ceda98cb
commit
485c371942
15 changed files with 72 additions and 63 deletions
|
|
@ -227,7 +227,7 @@ type
|
||||||
# for interfacing with C++, JS
|
# for interfacing with C++, JS
|
||||||
sfNamedParamCall, # symbol needs named parameter call syntax in target
|
sfNamedParamCall, # symbol needs named parameter call syntax in target
|
||||||
# language; for interfacing with Objective C
|
# language; for interfacing with Objective C
|
||||||
sfOptional # returned value may be discarded implicitely
|
sfDiscardable # returned value may be discarded implicitely
|
||||||
|
|
||||||
TSymFlags* = set[TSymFlag]
|
TSymFlags* = set[TSymFlag]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,15 +23,15 @@ const
|
||||||
wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
|
wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
|
||||||
wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
||||||
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
||||||
wNoStackFrame, wError, wOptional}
|
wNoStackFrame, wError, wDiscardable}
|
||||||
converterPragmas* = procPragmas
|
converterPragmas* = procPragmas
|
||||||
methodPragmas* = procPragmas
|
methodPragmas* = procPragmas
|
||||||
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||||
wMagic, wNosideEffect, wCompilerProc, wDeprecated, wExtern,
|
wMagic, wNosideEffect, wCompilerProc, wDeprecated, wExtern,
|
||||||
wImportcpp, wImportobjc, wError, wOptional}
|
wImportcpp, wImportobjc, wError, wDiscardable}
|
||||||
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect,
|
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect,
|
||||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
||||||
wImportcpp, wImportobjc, wError, wOptional}
|
wImportcpp, wImportobjc, wError, wDiscardable}
|
||||||
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
|
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
|
||||||
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wLinedir,
|
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wLinedir,
|
||||||
wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal,
|
wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal,
|
||||||
|
|
@ -553,9 +553,9 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||||
of wPragma:
|
of wPragma:
|
||||||
processPragma(c, n, i)
|
processPragma(c, n, i)
|
||||||
break
|
break
|
||||||
of wOptional:
|
of wDiscardable:
|
||||||
noVal(it)
|
noVal(it)
|
||||||
if sym != nil: incl(sym.flags, sfOptional)
|
if sym != nil: incl(sym.flags, sfDiscardable)
|
||||||
of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
|
of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
|
||||||
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
|
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
|
||||||
wLinedir, wStacktrace, wLinetrace, wOptimization, wByRef,
|
wLinedir, wStacktrace, wLinetrace, wOptimization, wByRef,
|
||||||
|
|
|
||||||
|
|
@ -550,7 +550,7 @@ proc buildEchoStmt(c: PContext, n: PNode): PNode =
|
||||||
proc semExprNoType(c: PContext, n: PNode): PNode =
|
proc semExprNoType(c: PContext, n: PNode): PNode =
|
||||||
proc ImplicitelyDiscardable(n: PNode): bool {.inline.} =
|
proc ImplicitelyDiscardable(n: PNode): bool {.inline.} =
|
||||||
result = isCallExpr(n) and n.sons[0].kind == nkSym and
|
result = isCallExpr(n) and n.sons[0].kind == nkSym and
|
||||||
sfOptional in n.sons[0].sym.flags
|
sfDiscardable in n.sons[0].sym.flags
|
||||||
result = semExpr(c, n)
|
result = semExpr(c, n)
|
||||||
if result.typ != nil and result.typ.kind != tyStmt:
|
if result.typ != nil and result.typ.kind != tyStmt:
|
||||||
if gCmd == cmdInteractive:
|
if gCmd == cmdInteractive:
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ type
|
||||||
wDeadCodeElim, wSafecode,
|
wDeadCodeElim, wSafecode,
|
||||||
wPragma,
|
wPragma,
|
||||||
wCompileTime,
|
wCompileTime,
|
||||||
wPassc, wPassl, wBorrow, wOptional,
|
wPassc, wPassl, wBorrow, wDiscardable,
|
||||||
wFieldChecks,
|
wFieldChecks,
|
||||||
wCheckPoint, wSubsChar,
|
wCheckPoint, wSubsChar,
|
||||||
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
|
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
|
||||||
|
|
@ -96,7 +96,7 @@ const
|
||||||
"deadcodeelim", "safecode",
|
"deadcodeelim", "safecode",
|
||||||
"pragma",
|
"pragma",
|
||||||
"compiletime",
|
"compiletime",
|
||||||
"passc", "passl", "borrow", "optional", "fieldchecks",
|
"passc", "passl", "borrow", "discardable", "fieldchecks",
|
||||||
"checkpoint",
|
"checkpoint",
|
||||||
"subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
"subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
||||||
"write", "putenv", "prependenv", "appendenv", "threadvar", "emit",
|
"write", "putenv", "prependenv", "appendenv", "threadvar", "emit",
|
||||||
|
|
|
||||||
|
|
@ -1486,10 +1486,10 @@ Ignoring the return value of a procedure without using a discard statement is
|
||||||
a static error.
|
a static error.
|
||||||
|
|
||||||
The return value can be ignored implicitely if the called proc/iterator has
|
The return value can be ignored implicitely if the called proc/iterator has
|
||||||
been declared with the `optional`:idx: pragma:
|
been declared with the `discardable`:idx: pragma:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
proc p(x, y: int): int {.optional.} =
|
proc p(x, y: int): int {.discardable.} =
|
||||||
return x + y
|
return x + y
|
||||||
|
|
||||||
p(3, 4) # now valid
|
p(3, 4) # now valid
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ type
|
||||||
pos: int
|
pos: int
|
||||||
inShortState: bool
|
inShortState: bool
|
||||||
kind*: TCmdLineKind ## the dected command line token
|
kind*: TCmdLineKind ## the dected command line token
|
||||||
key*, val*: string ## key and value pair; ``key`` is the option
|
key*, val*: TaintedString ## key and value pair; ``key`` is the option
|
||||||
## or the argument, ``value`` is not "" if
|
## or the argument, ``value`` is not "" if
|
||||||
## the option was given a value
|
## the option was given a value
|
||||||
|
|
||||||
|
|
@ -50,8 +50,8 @@ when defined(os.ParamCount):
|
||||||
for i in countup(1, ParamCount()):
|
for i in countup(1, ParamCount()):
|
||||||
result.cmd = result.cmd & quoteIfContainsWhite(paramStr(i).string) & ' '
|
result.cmd = result.cmd & quoteIfContainsWhite(paramStr(i).string) & ' '
|
||||||
result.kind = cmdEnd
|
result.kind = cmdEnd
|
||||||
result.key = ""
|
result.key = TaintedString""
|
||||||
result.val = ""
|
result.val = TaintedString""
|
||||||
|
|
||||||
proc parseWord(s: string, i: int, w: var string,
|
proc parseWord(s: string, i: int, w: var string,
|
||||||
delim: TCharSet = {'\x09', ' ', '\0'}): int =
|
delim: TCharSet = {'\x09', ' ', '\0'}): int =
|
||||||
|
|
@ -70,7 +70,7 @@ proc parseWord(s: string, i: int, w: var string,
|
||||||
proc handleShortOption(p: var TOptParser) =
|
proc handleShortOption(p: var TOptParser) =
|
||||||
var i = p.pos
|
var i = p.pos
|
||||||
p.kind = cmdShortOption
|
p.kind = cmdShortOption
|
||||||
add(p.key, p.cmd[i])
|
add(p.key.string, p.cmd[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
p.inShortState = true
|
p.inShortState = true
|
||||||
while p.cmd[i] in {'\x09', ' '}:
|
while p.cmd[i] in {'\x09', ' '}:
|
||||||
|
|
@ -80,7 +80,7 @@ proc handleShortOption(p: var TOptParser) =
|
||||||
inc(i)
|
inc(i)
|
||||||
p.inShortState = false
|
p.inShortState = false
|
||||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||||
i = parseWord(p.cmd, i, p.val)
|
i = parseWord(p.cmd, i, p.val.string)
|
||||||
if p.cmd[i] == '\0': p.inShortState = false
|
if p.cmd[i] == '\0': p.inShortState = false
|
||||||
p.pos = i
|
p.pos = i
|
||||||
|
|
||||||
|
|
@ -91,8 +91,8 @@ proc next*(p: var TOptParser) {.
|
||||||
var i = p.pos
|
var i = p.pos
|
||||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||||
p.pos = i
|
p.pos = i
|
||||||
setlen(p.key, 0)
|
setlen(p.key.string, 0)
|
||||||
setlen(p.val, 0)
|
setlen(p.val.string, 0)
|
||||||
if p.inShortState:
|
if p.inShortState:
|
||||||
handleShortOption(p)
|
handleShortOption(p)
|
||||||
return
|
return
|
||||||
|
|
@ -104,29 +104,29 @@ proc next*(p: var TOptParser) {.
|
||||||
if p.cmd[i] == '-':
|
if p.cmd[i] == '-':
|
||||||
p.kind = cmdLongOption
|
p.kind = cmdLongOption
|
||||||
inc(i)
|
inc(i)
|
||||||
i = parseWord(p.cmd, i, p.key, {'\0', ' ', '\x09', ':', '='})
|
i = parseWord(p.cmd, i, p.key.string, {'\0', ' ', '\x09', ':', '='})
|
||||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||||
if p.cmd[i] in {':', '='}:
|
if p.cmd[i] in {':', '='}:
|
||||||
inc(i)
|
inc(i)
|
||||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||||
p.pos = parseWord(p.cmd, i, p.val)
|
p.pos = parseWord(p.cmd, i, p.val.string)
|
||||||
else:
|
else:
|
||||||
p.pos = i
|
p.pos = i
|
||||||
else:
|
else:
|
||||||
p.pos = i
|
p.pos = i
|
||||||
handleShortOption(p)
|
handleShortOption(p)
|
||||||
else:
|
else:
|
||||||
p.kind = cmdArgument
|
p.kind = cmdArgument
|
||||||
p.pos = parseWord(p.cmd, i, p.key)
|
p.pos = parseWord(p.cmd, i, p.key.string)
|
||||||
|
|
||||||
proc cmdLineRest*(p: TOptParser): string {.
|
proc cmdLineRest*(p: TOptParser): TaintedString {.
|
||||||
rtl, extern: "npo$1".} =
|
rtl, extern: "npo$1".} =
|
||||||
## retrieves the rest of the command line that has not been parsed yet.
|
## retrieves the rest of the command line that has not been parsed yet.
|
||||||
result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1))
|
result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1)).TaintedString
|
||||||
|
|
||||||
when defined(initOptParser):
|
when defined(initOptParser):
|
||||||
|
|
||||||
iterator getopt*(): tuple[kind: TCmdLineKind, key, val: string] =
|
iterator getopt*(): tuple[kind: TCmdLineKind, key, val: TaintedString] =
|
||||||
## This is an convenience iterator for iterating over the command line.
|
## This is an convenience iterator for iterating over the command line.
|
||||||
## This uses the TOptParser object. Example:
|
## This uses the TOptParser object. Example:
|
||||||
##
|
##
|
||||||
|
|
|
||||||
|
|
@ -525,11 +525,11 @@ proc select*(readfds: var seq[TSocket], timeout = 500): int =
|
||||||
pruneSocketSet(readfds, (rd))
|
pruneSocketSet(readfds, (rd))
|
||||||
|
|
||||||
|
|
||||||
proc recvLine*(socket: TSocket, line: var string): bool =
|
proc recvLine*(socket: TSocket, line: var TaintedString): bool =
|
||||||
## returns false if no further data is available. `Line` must be initialized
|
## returns false if no further data is available. `Line` must be initialized
|
||||||
## and not nil! This does not throw an EOS exception, therefore
|
## and not nil! This does not throw an EOS exception, therefore
|
||||||
## it can be used in both blocking and non-blocking sockets.
|
## it can be used in both blocking and non-blocking sockets.
|
||||||
setLen(line, 0)
|
setLen(line.string, 0)
|
||||||
while true:
|
while true:
|
||||||
var c: char
|
var c: char
|
||||||
var n = recv(cint(socket), addr(c), 1, 0'i32)
|
var n = recv(cint(socket), addr(c), 1, 0'i32)
|
||||||
|
|
@ -541,20 +541,20 @@ proc recvLine*(socket: TSocket, line: var string): bool =
|
||||||
elif n <= 0: return false
|
elif n <= 0: return false
|
||||||
return true
|
return true
|
||||||
elif c == '\L': return true
|
elif c == '\L': return true
|
||||||
add(line, c)
|
add(line.string, c)
|
||||||
|
|
||||||
proc recv*(socket: TSocket, data: pointer, size: int): int =
|
proc recv*(socket: TSocket, data: pointer, size: int): int =
|
||||||
## receives data from a socket
|
## receives data from a socket
|
||||||
result = recv(cint(socket), data, size, 0'i32)
|
result = recv(cint(socket), data, size, 0'i32)
|
||||||
|
|
||||||
proc recv*(socket: TSocket): string =
|
proc recv*(socket: TSocket): TaintedString =
|
||||||
## receives all the data from the socket.
|
## receives all the data from the socket.
|
||||||
## Socket errors will result in an ``EOS`` error.
|
## Socket errors will result in an ``EOS`` error.
|
||||||
## If socket is not a connectionless socket and socket is not connected
|
## If socket is not a connectionless socket and socket is not connected
|
||||||
## ``""`` will be returned.
|
## ``""`` will be returned.
|
||||||
const bufSize = 200
|
const bufSize = 1000
|
||||||
var buf = newString(bufSize)
|
var buf = newString(bufSize)
|
||||||
result = ""
|
result = TaintedString""
|
||||||
while true:
|
while true:
|
||||||
var bytesRead = recv(socket, cstring(buf), bufSize-1)
|
var bytesRead = recv(socket, cstring(buf), bufSize-1)
|
||||||
# Error
|
# Error
|
||||||
|
|
@ -562,16 +562,16 @@ proc recv*(socket: TSocket): string =
|
||||||
|
|
||||||
buf[bytesRead] = '\0' # might not be necessary
|
buf[bytesRead] = '\0' # might not be necessary
|
||||||
setLen(buf, bytesRead)
|
setLen(buf, bytesRead)
|
||||||
add(result, buf)
|
add(result.string, buf)
|
||||||
if bytesRead != bufSize-1: break
|
if bytesRead != bufSize-1: break
|
||||||
|
|
||||||
proc recvAsync*(socket: TSocket, s: var string): bool =
|
proc recvAsync*(socket: TSocket, s: var TaintedString): bool =
|
||||||
## receives all the data from a non-blocking socket. If socket is non-blocking
|
## receives all the data from a non-blocking socket. If socket is non-blocking
|
||||||
## and there are no messages available, `False` will be returned.
|
## and there are no messages available, `False` will be returned.
|
||||||
## Other socket errors will result in an ``EOS`` error.
|
## Other socket errors will result in an ``EOS`` error.
|
||||||
## If socket is not a connectionless socket and socket is not connected
|
## If socket is not a connectionless socket and socket is not connected
|
||||||
## ``s`` will be set to ``""``.
|
## ``s`` will be set to ``""``.
|
||||||
const bufSize = 200
|
const bufSize = 1000
|
||||||
var buf = newString(bufSize)
|
var buf = newString(bufSize)
|
||||||
s = ""
|
s = ""
|
||||||
while true:
|
while true:
|
||||||
|
|
@ -597,7 +597,7 @@ proc recvAsync*(socket: TSocket, s: var string): bool =
|
||||||
|
|
||||||
proc skip*(socket: TSocket) =
|
proc skip*(socket: TSocket) =
|
||||||
## skips all the data that is pending for the socket
|
## skips all the data that is pending for the socket
|
||||||
const bufSize = 200
|
const bufSize = 1000
|
||||||
var buf = alloc(bufSize)
|
var buf = alloc(bufSize)
|
||||||
while recv(socket, buf, bufSize) == bufSize: nil
|
while recv(socket, buf, bufSize) == bufSize: nil
|
||||||
dealloc(buf)
|
dealloc(buf)
|
||||||
|
|
|
||||||
|
|
@ -80,24 +80,24 @@ proc readFloat64*(s: PStream): float64 =
|
||||||
## reads a float64 from the stream `s`. Raises `EIO` if an error occured.
|
## reads a float64 from the stream `s`. Raises `EIO` if an error occured.
|
||||||
read(s, result)
|
read(s, result)
|
||||||
|
|
||||||
proc readStr*(s: PStream, length: int): string =
|
proc readStr*(s: PStream, length: int): TaintedString =
|
||||||
## reads a string of length `length` from the stream `s`. Raises `EIO` if
|
## reads a string of length `length` from the stream `s`. Raises `EIO` if
|
||||||
## an error occured.
|
## an error occured.
|
||||||
result = newString(length)
|
result = newString(length).TaintedString
|
||||||
var L = s.readData(s, addr(result[0]), length)
|
var L = s.readData(s, addr(string(result)[0]), length)
|
||||||
if L != length: setLen(result, L)
|
if L != length: setLen(result.string, L)
|
||||||
|
|
||||||
proc readLine*(s: PStream): string =
|
proc readLine*(s: PStream): TaintedString =
|
||||||
## Reads a line from a stream `s`. Note: This is not very efficient. Raises
|
## Reads a line from a stream `s`. Note: This is not very efficient. Raises
|
||||||
## `EIO` if an error occured.
|
## `EIO` if an error occured.
|
||||||
result = ""
|
result = TaintedString""
|
||||||
while not s.atEnd(s):
|
while not s.atEnd(s):
|
||||||
var c = readChar(s)
|
var c = readChar(s)
|
||||||
if c == '\c':
|
if c == '\c':
|
||||||
c = readChar(s)
|
c = readChar(s)
|
||||||
break
|
break
|
||||||
elif c == '\L' or c == '\0': break
|
elif c == '\L' or c == '\0': break
|
||||||
result.add(c)
|
result.string.add(c)
|
||||||
|
|
||||||
type
|
type
|
||||||
PStringStream* = ref TStringStream ## a stream that encapsulates a string
|
PStringStream* = ref TStringStream ## a stream that encapsulates a string
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,8 @@ proc RaiseFormatException(s: string) =
|
||||||
|
|
||||||
proc getValue(t: PStringTable, flags: set[TFormatFlag], key: string): string =
|
proc getValue(t: PStringTable, flags: set[TFormatFlag], key: string): string =
|
||||||
if hasKey(t, key): return t[key]
|
if hasKey(t, key): return t[key]
|
||||||
if useEnvironment in flags: result = os.getEnv(key)
|
# hm difficult: assume safety in taint mode here. XXX This is dangerous!
|
||||||
|
if useEnvironment in flags: result = os.getEnv(key).string
|
||||||
else: result = ""
|
else: result = ""
|
||||||
if result.len == 0:
|
if result.len == 0:
|
||||||
if useKey in flags: result = '$' & key
|
if useKey in flags: result = '$' & key
|
||||||
|
|
|
||||||
|
|
@ -787,9 +787,9 @@ proc compileOption*(option, arg: string): bool {.
|
||||||
const
|
const
|
||||||
hasThreadSupport = compileOption("threads")
|
hasThreadSupport = compileOption("threads")
|
||||||
hasSharedHeap = defined(boehmgc) # don't share heaps; every thread has its own
|
hasSharedHeap = defined(boehmgc) # don't share heaps; every thread has its own
|
||||||
# taintMode = compileOption("taintmode")
|
taintMode = compileOption("taintmode")
|
||||||
|
|
||||||
when defined(taintMode):
|
when taintMode:
|
||||||
# XXX use a compile time option for it!
|
# XXX use a compile time option for it!
|
||||||
type TaintedString* = distinct string ## a distinct string type that
|
type TaintedString* = distinct string ## a distinct string type that
|
||||||
## is `tainted`:idx:. It is an alias for
|
## is `tainted`:idx:. It is an alias for
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,12 @@ proc rawReadLine(f: TFile, result: var string) =
|
||||||
add result, chr(int(c))
|
add result, chr(int(c))
|
||||||
|
|
||||||
proc readLine(f: TFile): TaintedString =
|
proc readLine(f: TFile): TaintedString =
|
||||||
result = TaintedString("")
|
when taintMode:
|
||||||
rawReadLine(f, result)
|
result = TaintedString""
|
||||||
|
rawReadLine(f, result.string)
|
||||||
|
else:
|
||||||
|
result = ""
|
||||||
|
rawReadLine(f, result)
|
||||||
|
|
||||||
proc write(f: TFile, i: int) =
|
proc write(f: TFile, i: int) =
|
||||||
when sizeof(int) == 8:
|
when sizeof(int) == 8:
|
||||||
|
|
@ -86,9 +90,14 @@ proc readFile(filename: string): TaintedString =
|
||||||
try:
|
try:
|
||||||
var len = getFileSize(f)
|
var len = getFileSize(f)
|
||||||
if len < high(int):
|
if len < high(int):
|
||||||
result = newString(int(len))
|
when taintMode:
|
||||||
if readBuffer(f, addr(result[0]), int(len)) != len:
|
result = newString(int(len)).TaintedString
|
||||||
raiseEIO("error while reading from file")
|
if readBuffer(f, addr(string(result)[0]), int(len)) != len:
|
||||||
|
raiseEIO("error while reading from file")
|
||||||
|
else:
|
||||||
|
result = newString(int(len))
|
||||||
|
if readBuffer(f, addr(result[0]), int(len)) != len:
|
||||||
|
raiseEIO("error while reading from file")
|
||||||
else:
|
else:
|
||||||
raiseEIO("file too big to fit in memory")
|
raiseEIO("file too big to fit in memory")
|
||||||
finally:
|
finally:
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
# Test the optional pragma
|
# Test the discardable pragma
|
||||||
|
|
||||||
proc p(x, y: int): int {.optional.} =
|
proc p(x, y: int): int {.discardable.} =
|
||||||
return x + y
|
return x + y
|
||||||
|
|
||||||
# test that it is inherited from generic procs too:
|
# test that it is inherited from generic procs too:
|
||||||
proc q[T](x, y: T): T {.optional.} =
|
proc q[T](x, y: T): T {.discardable.} =
|
||||||
return x + y
|
return x + y
|
||||||
|
|
||||||
|
|
||||||
5
todo.txt
5
todo.txt
|
|
@ -1,14 +1,13 @@
|
||||||
Version 0.8.14
|
Version 0.8.14
|
||||||
==============
|
==============
|
||||||
|
|
||||||
- 'let x = y'
|
- taint mode
|
||||||
|
- 'let x = y'; const ptr/ref
|
||||||
- fix actors.nim
|
- fix actors.nim
|
||||||
- make threadvar efficient again on linux after testing
|
- make threadvar efficient again on linux after testing
|
||||||
- fix the 'const' issues
|
- fix the 'const' issues
|
||||||
- test the sort implementation again
|
- test the sort implementation again
|
||||||
- optional indentation for 'case' statement
|
- optional indentation for 'case' statement
|
||||||
- taint mode
|
|
||||||
- const ptr/ref
|
|
||||||
|
|
||||||
|
|
||||||
version 0.9.0
|
version 0.9.0
|
||||||
|
|
|
||||||
|
|
@ -126,22 +126,22 @@ proc parseCmdLine(c: var TConfigData) =
|
||||||
next(p)
|
next(p)
|
||||||
var kind = p.kind
|
var kind = p.kind
|
||||||
var key = p.key
|
var key = p.key
|
||||||
var val = p.val
|
var val = p.val.string
|
||||||
case kind
|
case kind
|
||||||
of cmdArgument:
|
of cmdArgument:
|
||||||
if c.actions == {}:
|
if c.actions == {}:
|
||||||
for a in split(normalize(key), {';', ','}):
|
for a in split(normalize(key.string), {';', ','}):
|
||||||
case a
|
case a
|
||||||
of "csource": incl(c.actions, actionCSource)
|
of "csource": incl(c.actions, actionCSource)
|
||||||
of "zip": incl(c.actions, actionZip)
|
of "zip": incl(c.actions, actionZip)
|
||||||
of "inno": incl(c.actions, actionInno)
|
of "inno": incl(c.actions, actionInno)
|
||||||
else: quit(Usage)
|
else: quit(Usage)
|
||||||
else:
|
else:
|
||||||
c.infile = addFileExt(key, "ini")
|
c.infile = addFileExt(key.string, "ini")
|
||||||
c.nimrodArgs = cmdLineRest(p)
|
c.nimrodArgs = cmdLineRest(p).string
|
||||||
break
|
break
|
||||||
of cmdLongOption, cmdShortOption:
|
of cmdLongOption, cmdShortOption:
|
||||||
case normalize(key)
|
case normalize(key.string)
|
||||||
of "help", "h":
|
of "help", "h":
|
||||||
stdout.write(Usage)
|
stdout.write(Usage)
|
||||||
quit(0)
|
quit(0)
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,8 @@ Language Additions
|
||||||
- Return types may be of the type ``var T`` to return an l-value.
|
- Return types may be of the type ``var T`` to return an l-value.
|
||||||
- The error pragma can now be used to mark symbols whose *usage* should trigger
|
- The error pragma can now be used to mark symbols whose *usage* should trigger
|
||||||
a compile-time error.
|
a compile-time error.
|
||||||
- There is a new ``optional`` pragma that can be used to mark a routine so that
|
- There is a new ``discardable`` pragma that can be used to mark a routine
|
||||||
its result can be discarded implicitely.
|
so that its result can be discarded implicitely.
|
||||||
|
|
||||||
|
|
||||||
Compiler Additions
|
Compiler Additions
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue