doc updates; fixes 'inc' for 'char'
This commit is contained in:
parent
165619552a
commit
edc4940c26
8 changed files with 97 additions and 191 deletions
|
|
@ -492,7 +492,7 @@ proc binaryArithOverflowRaw(p: BProc, t: PType, a, b: TLoc;
|
||||||
else: getTypeDesc(p.module, t)
|
else: getTypeDesc(p.module, t)
|
||||||
result = getTempName()
|
result = getTempName()
|
||||||
linefmt(p, cpsLocals, "$1 $2;$n", storage, result)
|
linefmt(p, cpsLocals, "$1 $2;$n", storage, result)
|
||||||
lineCg(p, cpsStmts, frmt, result, rdLoc(a), rdLoc(b))
|
lineCg(p, cpsStmts, frmt, result, rdCharLoc(a), rdCharLoc(b))
|
||||||
if size < platform.intSize or t.kind in {tyRange, tyEnum}:
|
if size < platform.intSize or t.kind in {tyRange, tyEnum}:
|
||||||
linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseOverflow();$n",
|
linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseOverflow();$n",
|
||||||
result, intLiteral(firstOrd(t)), intLiteral(lastOrd(t)))
|
result, intLiteral(firstOrd(t)), intLiteral(lastOrd(t)))
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
os, lists, strutils, strtabs, osproc, sets
|
os, lists, strutils, strtabs, osproc, sets
|
||||||
|
|
||||||
const
|
const
|
||||||
hasTinyCBackend* = defined(tinyc)
|
hasTinyCBackend* = defined(tinyc)
|
||||||
useEffectSystem* = true
|
useEffectSystem* = true
|
||||||
|
|
@ -21,10 +21,10 @@ const
|
||||||
type # please make sure we have under 32 options
|
type # please make sure we have under 32 options
|
||||||
# (improves code efficiency a lot!)
|
# (improves code efficiency a lot!)
|
||||||
TOption* = enum # **keep binary compatible**
|
TOption* = enum # **keep binary compatible**
|
||||||
optNone, optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck,
|
optNone, optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck,
|
||||||
optOverflowCheck, optNilCheck,
|
optOverflowCheck, optNilCheck,
|
||||||
optNaNCheck, optInfCheck,
|
optNaNCheck, optInfCheck,
|
||||||
optAssert, optLineDir, optWarns, optHints,
|
optAssert, optLineDir, optWarns, optHints,
|
||||||
optOptimizeSpeed, optOptimizeSize, optStackTrace, # stack tracing support
|
optOptimizeSpeed, optOptimizeSize, optStackTrace, # stack tracing support
|
||||||
optLineTrace, # line tracing support (includes stack tracing)
|
optLineTrace, # line tracing support (includes stack tracing)
|
||||||
optEndb, # embedded debugger
|
optEndb, # embedded debugger
|
||||||
|
|
@ -37,8 +37,8 @@ type # please make sure we have under 32 options
|
||||||
|
|
||||||
TOptions* = set[TOption]
|
TOptions* = set[TOption]
|
||||||
TGlobalOption* = enum # **keep binary compatible**
|
TGlobalOption* = enum # **keep binary compatible**
|
||||||
gloptNone, optForceFullMake, optDeadCodeElim,
|
gloptNone, optForceFullMake, optDeadCodeElim,
|
||||||
optListCmd, optCompileOnly, optNoLinking,
|
optListCmd, optCompileOnly, optNoLinking,
|
||||||
optSafeCode, # only allow safe code
|
optSafeCode, # only allow safe code
|
||||||
optCDebug, # turn on debugging information
|
optCDebug, # turn on debugging information
|
||||||
optGenDynLib, # generate a dynamic library
|
optGenDynLib, # generate a dynamic library
|
||||||
|
|
@ -67,9 +67,9 @@ type # please make sure we have under 32 options
|
||||||
TGlobalOptions* = set[TGlobalOption]
|
TGlobalOptions* = set[TGlobalOption]
|
||||||
TCommands* = enum # Nim's commands
|
TCommands* = enum # Nim's commands
|
||||||
# **keep binary compatible**
|
# **keep binary compatible**
|
||||||
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
||||||
cmdCompileToJS, cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc,
|
cmdCompileToJS, cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc,
|
||||||
cmdGenDepend, cmdDump,
|
cmdGenDepend, cmdDump,
|
||||||
cmdCheck, # semantic checking for whole project
|
cmdCheck, # semantic checking for whole project
|
||||||
cmdParse, # parse a single file (for debugging)
|
cmdParse, # parse a single file (for debugging)
|
||||||
cmdScan, # scan a single file (for debugging)
|
cmdScan, # scan a single file (for debugging)
|
||||||
|
|
@ -90,12 +90,12 @@ var
|
||||||
gIdeCmd*: TIdeCmd
|
gIdeCmd*: TIdeCmd
|
||||||
|
|
||||||
const
|
const
|
||||||
ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck,
|
ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck,
|
||||||
optOverflowCheck, optBoundsCheck, optAssert, optNaNCheck, optInfCheck}
|
optOverflowCheck, optBoundsCheck, optAssert, optNaNCheck, optInfCheck}
|
||||||
|
|
||||||
var
|
var
|
||||||
gOptions*: TOptions = {optObjCheck, optFieldCheck, optRangeCheck,
|
gOptions*: TOptions = {optObjCheck, optFieldCheck, optRangeCheck,
|
||||||
optBoundsCheck, optOverflowCheck, optAssert, optWarns,
|
optBoundsCheck, optOverflowCheck, optAssert, optWarns,
|
||||||
optHints, optStackTrace, optLineTrace,
|
optHints, optStackTrace, optLineTrace,
|
||||||
optPatterns, optNilCheck}
|
optPatterns, optNilCheck}
|
||||||
gGlobalOptions*: TGlobalOptions = {optThreadAnalysis}
|
gGlobalOptions*: TGlobalOptions = {optThreadAnalysis}
|
||||||
|
|
@ -129,7 +129,7 @@ template optPreserveOrigSource*: expr =
|
||||||
template optPrintSurroundingSrc*: expr =
|
template optPrintSurroundingSrc*: expr =
|
||||||
gVerbosity >= 2
|
gVerbosity >= 2
|
||||||
|
|
||||||
const
|
const
|
||||||
genSubDir* = "nimcache"
|
genSubDir* = "nimcache"
|
||||||
NimExt* = "nim"
|
NimExt* = "nim"
|
||||||
RodExt* = "rod"
|
RodExt* = "rod"
|
||||||
|
|
@ -168,20 +168,20 @@ proc mainCommandArg*: string =
|
||||||
else:
|
else:
|
||||||
result = gProjectName
|
result = gProjectName
|
||||||
|
|
||||||
proc existsConfigVar*(key: string): bool =
|
proc existsConfigVar*(key: string): bool =
|
||||||
result = hasKey(gConfigVars, key)
|
result = hasKey(gConfigVars, key)
|
||||||
|
|
||||||
proc getConfigVar*(key: string): string =
|
proc getConfigVar*(key: string): string =
|
||||||
result = gConfigVars[key]
|
result = gConfigVars[key]
|
||||||
|
|
||||||
proc setConfigVar*(key, val: string) =
|
proc setConfigVar*(key, val: string) =
|
||||||
gConfigVars[key] = val
|
gConfigVars[key] = val
|
||||||
|
|
||||||
proc getOutFile*(filename, ext: string): string =
|
proc getOutFile*(filename, ext: string): string =
|
||||||
if options.outFile != "": result = options.outFile
|
if options.outFile != "": result = options.outFile
|
||||||
else: result = changeFileExt(filename, ext)
|
else: result = changeFileExt(filename, ext)
|
||||||
|
|
||||||
proc getPrefixDir*(): string =
|
proc getPrefixDir*(): string =
|
||||||
## gets the application directory
|
## gets the application directory
|
||||||
result = splitPath(getAppDir()).head
|
result = splitPath(getAppDir()).head
|
||||||
|
|
||||||
|
|
@ -189,22 +189,22 @@ proc canonicalizePath*(path: string): string =
|
||||||
when not FileSystemCaseSensitive: result = path.expandFilename.toLower
|
when not FileSystemCaseSensitive: result = path.expandFilename.toLower
|
||||||
else: result = path.expandFilename
|
else: result = path.expandFilename
|
||||||
|
|
||||||
proc shortenDir*(dir: string): string =
|
proc shortenDir*(dir: string): string =
|
||||||
## returns the interesting part of a dir
|
## returns the interesting part of a dir
|
||||||
var prefix = getPrefixDir() & DirSep
|
var prefix = getPrefixDir() & DirSep
|
||||||
if startsWith(dir, prefix):
|
if startsWith(dir, prefix):
|
||||||
return substr(dir, len(prefix))
|
return substr(dir, len(prefix))
|
||||||
prefix = gProjectPath & DirSep
|
prefix = gProjectPath & DirSep
|
||||||
if startsWith(dir, prefix):
|
if startsWith(dir, prefix):
|
||||||
return substr(dir, len(prefix))
|
return substr(dir, len(prefix))
|
||||||
result = dir
|
result = dir
|
||||||
|
|
||||||
proc removeTrailingDirSep*(path: string): string =
|
proc removeTrailingDirSep*(path: string): string =
|
||||||
if (len(path) > 0) and (path[len(path) - 1] == DirSep):
|
if (len(path) > 0) and (path[len(path) - 1] == DirSep):
|
||||||
result = substr(path, 0, len(path) - 2)
|
result = substr(path, 0, len(path) - 2)
|
||||||
else:
|
else:
|
||||||
result = path
|
result = path
|
||||||
|
|
||||||
proc getGeneratedPath: string =
|
proc getGeneratedPath: string =
|
||||||
result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir /
|
result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir /
|
||||||
genSubDir
|
genSubDir
|
||||||
|
|
@ -257,7 +257,7 @@ proc withPackageName*(path: string): string =
|
||||||
let (p, file, ext) = path.splitFile
|
let (p, file, ext) = path.splitFile
|
||||||
result = (p / (x & '_' & file)) & ext
|
result = (p / (x & '_' & file)) & ext
|
||||||
|
|
||||||
proc toGeneratedFile*(path, ext: string): string =
|
proc toGeneratedFile*(path, ext: string): string =
|
||||||
## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
|
## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
|
||||||
var (head, tail) = splitPath(path)
|
var (head, tail) = splitPath(path)
|
||||||
#if len(head) > 0: head = shortenDir(head & dirSep)
|
#if len(head) > 0: head = shortenDir(head & dirSep)
|
||||||
|
|
@ -301,7 +301,7 @@ proc completeGeneratedFilePath*(f: string, createSubDir: bool = true): string =
|
||||||
result = joinPath(subdir, tail)
|
result = joinPath(subdir, tail)
|
||||||
#echo "completeGeneratedFilePath(", f, ") = ", result
|
#echo "completeGeneratedFilePath(", f, ") = ", result
|
||||||
|
|
||||||
iterator iterSearchPath*(searchPaths: TLinkedList): string =
|
iterator iterSearchPath*(searchPaths: TLinkedList): string =
|
||||||
var it = PStrEntry(searchPaths.head)
|
var it = PStrEntry(searchPaths.head)
|
||||||
while it != nil:
|
while it != nil:
|
||||||
yield it.data
|
yield it.data
|
||||||
|
|
@ -324,7 +324,7 @@ proc rawFindFile2(f: string): string =
|
||||||
it = PStrEntry(it.next)
|
it = PStrEntry(it.next)
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
proc findFile*(f: string): string {.procvar.} =
|
proc findFile*(f: string): string {.procvar.} =
|
||||||
result = f.rawFindFile
|
result = f.rawFindFile
|
||||||
if result.len == 0:
|
if result.len == 0:
|
||||||
result = f.toLower.rawFindFile
|
result = f.toLower.rawFindFile
|
||||||
|
|
@ -351,7 +351,7 @@ proc findModule*(modulename, currentModule: string): string =
|
||||||
if not existsFile(result):
|
if not existsFile(result):
|
||||||
result = findFile(m)
|
result = findFile(m)
|
||||||
|
|
||||||
proc libCandidates*(s: string, dest: var seq[string]) =
|
proc libCandidates*(s: string, dest: var seq[string]) =
|
||||||
var le = strutils.find(s, '(')
|
var le = strutils.find(s, '(')
|
||||||
var ri = strutils.find(s, ')', le+1)
|
var ri = strutils.find(s, ')', le+1)
|
||||||
if le >= 0 and ri > le:
|
if le >= 0 and ri > le:
|
||||||
|
|
@ -359,7 +359,7 @@ proc libCandidates*(s: string, dest: var seq[string]) =
|
||||||
var suffix = substr(s, ri + 1)
|
var suffix = substr(s, ri + 1)
|
||||||
for middle in split(substr(s, le + 1, ri - 1), '|'):
|
for middle in split(substr(s, le + 1, ri - 1), '|'):
|
||||||
libCandidates(prefix & middle & suffix, dest)
|
libCandidates(prefix & middle & suffix, dest)
|
||||||
else:
|
else:
|
||||||
add(dest, s)
|
add(dest, s)
|
||||||
|
|
||||||
proc canonDynlibName(s: string): string =
|
proc canonDynlibName(s: string): string =
|
||||||
|
|
@ -376,17 +376,17 @@ proc inclDynlibOverride*(lib: string) =
|
||||||
proc isDynlibOverride*(lib: string): bool =
|
proc isDynlibOverride*(lib: string): bool =
|
||||||
result = gDllOverrides.hasKey(lib.canonDynlibName)
|
result = gDllOverrides.hasKey(lib.canonDynlibName)
|
||||||
|
|
||||||
proc binaryStrSearch*(x: openArray[string], y: string): int =
|
proc binaryStrSearch*(x: openArray[string], y: string): int =
|
||||||
var a = 0
|
var a = 0
|
||||||
var b = len(x) - 1
|
var b = len(x) - 1
|
||||||
while a <= b:
|
while a <= b:
|
||||||
var mid = (a + b) div 2
|
var mid = (a + b) div 2
|
||||||
var c = cmpIgnoreCase(x[mid], y)
|
var c = cmpIgnoreCase(x[mid], y)
|
||||||
if c < 0:
|
if c < 0:
|
||||||
a = mid + 1
|
a = mid + 1
|
||||||
elif c > 0:
|
elif c > 0:
|
||||||
b = mid - 1
|
b = mid - 1
|
||||||
else:
|
else:
|
||||||
return mid
|
return mid
|
||||||
result = - 1
|
result = - 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ deprecated pragma
|
||||||
|
|
||||||
The deprecated pragma is used to mark a symbol as deprecated:
|
The deprecated pragma is used to mark a symbol as deprecated:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nim
|
||||||
proc p() {.deprecated.}
|
proc p() {.deprecated.}
|
||||||
var x {.deprecated.}: char
|
var x {.deprecated.}: char
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ It can also be used as a statement. Then it takes a list of *renamings*. The
|
||||||
upcoming ``nimfix`` tool can automatically update the code and perform these
|
upcoming ``nimfix`` tool can automatically update the code and perform these
|
||||||
renamings:
|
renamings:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nim
|
||||||
type
|
type
|
||||||
File = object
|
File = object
|
||||||
Stream = ref object
|
Stream = ref object
|
||||||
|
|
@ -78,7 +78,7 @@ as helpers for macros.
|
||||||
|
|
||||||
noReturn pragma
|
noReturn pragma
|
||||||
---------------
|
---------------
|
||||||
The ``noreturn`` pragma is used to mark a proc that never returns.
|
The ``noreturn`` pragma is used to mark a proc that never returns.
|
||||||
|
|
||||||
|
|
||||||
acyclic pragma
|
acyclic pragma
|
||||||
|
|
@ -122,25 +122,25 @@ shallow pragma
|
||||||
--------------
|
--------------
|
||||||
The ``shallow`` pragma affects the semantics of a type: The compiler is
|
The ``shallow`` pragma affects the semantics of a type: The compiler is
|
||||||
allowed to make a shallow copy. This can cause serious semantic issues and
|
allowed to make a shallow copy. This can cause serious semantic issues and
|
||||||
break memory safety! However, it can speed up assignments considerably,
|
break memory safety! However, it can speed up assignments considerably,
|
||||||
because the semantics of Nim require deep copying of sequences and strings.
|
because the semantics of Nim require deep copying of sequences and strings.
|
||||||
This can be expensive, especially if sequences are used to build a tree
|
This can be expensive, especially if sequences are used to build a tree
|
||||||
structure:
|
structure:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
type
|
type
|
||||||
NodeKind = enum nkLeaf, nkInner
|
NodeKind = enum nkLeaf, nkInner
|
||||||
Node {.final, shallow.} = object
|
Node {.final, shallow.} = object
|
||||||
case kind: NodeKind
|
case kind: NodeKind
|
||||||
of nkLeaf:
|
of nkLeaf:
|
||||||
strVal: string
|
strVal: string
|
||||||
of nkInner:
|
of nkInner:
|
||||||
children: seq[Node]
|
children: seq[Node]
|
||||||
|
|
||||||
|
|
||||||
pure pragma
|
pure pragma
|
||||||
-----------
|
-----------
|
||||||
An object type can be marked with the ``pure`` pragma so that its type
|
An object type can be marked with the ``pure`` pragma so that its type
|
||||||
field which is used for runtime type identification is omitted. This used to be
|
field which is used for runtime type identification is omitted. This used to be
|
||||||
necessary for binary compatibility with other compiled languages.
|
necessary for binary compatibility with other compiled languages.
|
||||||
|
|
||||||
|
|
@ -163,12 +163,12 @@ error pragma
|
||||||
------------
|
------------
|
||||||
The ``error`` pragma is used to make the compiler output an error message
|
The ``error`` pragma is used to make the compiler output an error message
|
||||||
with the given content. Compilation does not necessarily abort after an error
|
with the given content. Compilation does not necessarily abort after an error
|
||||||
though.
|
though.
|
||||||
|
|
||||||
The ``error`` pragma can also be used to
|
The ``error`` pragma can also be used to
|
||||||
annotate a symbol (like an iterator or proc). The *usage* of the symbol then
|
annotate a symbol (like an iterator or proc). The *usage* of the symbol then
|
||||||
triggers a compile-time error. This is especially useful to rule out that some
|
triggers a compile-time error. This is especially useful to rule out that some
|
||||||
operation is valid due to overloading and type conversions:
|
operation is valid due to overloading and type conversions:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
## check that underlying int values are compared and not the pointers:
|
## check that underlying int values are compared and not the pointers:
|
||||||
|
|
@ -201,7 +201,7 @@ The ``line`` pragma can be used to affect line information of the annotated
|
||||||
statement as seen in stack backtraces:
|
statement as seen in stack backtraces:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
template myassert*(cond: expr, msg = "") =
|
template myassert*(cond: expr, msg = "") =
|
||||||
if not cond:
|
if not cond:
|
||||||
# change run-time line information of the 'raise' statement:
|
# change run-time line information of the 'raise' statement:
|
||||||
|
|
@ -215,26 +215,26 @@ If the ``line`` pragma is used with a parameter, the parameter needs be a
|
||||||
|
|
||||||
linearScanEnd pragma
|
linearScanEnd pragma
|
||||||
--------------------
|
--------------------
|
||||||
The ``linearScanEnd`` pragma can be used to tell the compiler how to
|
The ``linearScanEnd`` pragma can be used to tell the compiler how to
|
||||||
compile a Nim `case`:idx: statement. Syntactically it has to be used as a
|
compile a Nim `case`:idx: statement. Syntactically it has to be used as a
|
||||||
statement:
|
statement:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
case myInt
|
case myInt
|
||||||
of 0:
|
of 0:
|
||||||
echo "most common case"
|
echo "most common case"
|
||||||
of 1:
|
of 1:
|
||||||
{.linearScanEnd.}
|
{.linearScanEnd.}
|
||||||
echo "second most common case"
|
echo "second most common case"
|
||||||
of 2: echo "unlikely: use branch table"
|
of 2: echo "unlikely: use branch table"
|
||||||
else: echo "unlikely too: use branch table for ", myInt
|
else: echo "unlikely too: use branch table for ", myInt
|
||||||
|
|
||||||
In the example, the case branches ``0`` and ``1`` are much more common than
|
In the example, the case branches ``0`` and ``1`` are much more common than
|
||||||
the other cases. Therefore the generated assembler code should test for these
|
the other cases. Therefore the generated assembler code should test for these
|
||||||
values first, so that the CPU's branch predictor has a good chance to succeed
|
values first, so that the CPU's branch predictor has a good chance to succeed
|
||||||
(avoiding an expensive CPU pipeline stall). The other cases might be put into a
|
(avoiding an expensive CPU pipeline stall). The other cases might be put into a
|
||||||
jump table for O(1) overhead, but at the cost of a (very likely) pipeline
|
jump table for O(1) overhead, but at the cost of a (very likely) pipeline
|
||||||
stall.
|
stall.
|
||||||
|
|
||||||
The ``linearScanEnd`` pragma should be put into the last branch that should be
|
The ``linearScanEnd`` pragma should be put into the last branch that should be
|
||||||
tested against via linear scanning. If put into the last branch of the
|
tested against via linear scanning. If put into the last branch of the
|
||||||
|
|
@ -243,8 +243,8 @@ whole ``case`` statement, the whole ``case`` statement uses linear scanning.
|
||||||
|
|
||||||
computedGoto pragma
|
computedGoto pragma
|
||||||
-------------------
|
-------------------
|
||||||
The ``computedGoto`` pragma can be used to tell the compiler how to
|
The ``computedGoto`` pragma can be used to tell the compiler how to
|
||||||
compile a Nim `case`:idx: in a ``while true`` statement.
|
compile a Nim `case`:idx: in a ``while true`` statement.
|
||||||
Syntactically it has to be used as a statement inside the loop:
|
Syntactically it has to be used as a statement inside the loop:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -278,21 +278,21 @@ Syntactically it has to be used as a statement inside the loop:
|
||||||
of enumE:
|
of enumE:
|
||||||
break
|
break
|
||||||
inc(pc)
|
inc(pc)
|
||||||
|
|
||||||
vm()
|
vm()
|
||||||
|
|
||||||
As the example shows ``computedGoto`` is mostly useful for interpreters. If
|
As the example shows ``computedGoto`` is mostly useful for interpreters. If
|
||||||
the underlying backend (C compiler) does not support the computed goto
|
the underlying backend (C compiler) does not support the computed goto
|
||||||
extension the pragma is simply ignored.
|
extension the pragma is simply ignored.
|
||||||
|
|
||||||
|
|
||||||
unroll pragma
|
unroll pragma
|
||||||
-------------
|
-------------
|
||||||
The ``unroll`` pragma can be used to tell the compiler that it should unroll
|
The ``unroll`` pragma can be used to tell the compiler that it should unroll
|
||||||
a `for`:idx: or `while`:idx: loop for runtime efficiency:
|
a `for`:idx: or `while`:idx: loop for runtime efficiency:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
proc searchChar(s: string, c: char): int =
|
proc searchChar(s: string, c: char): int =
|
||||||
for i in 0 .. s.high:
|
for i in 0 .. s.high:
|
||||||
{.unroll: 4.}
|
{.unroll: 4.}
|
||||||
if s[i] == c: return i
|
if s[i] == c: return i
|
||||||
|
|
@ -440,7 +440,7 @@ Example:
|
||||||
|
|
||||||
Please note that if a callable symbol is never used in this scenario, its body
|
Please note that if a callable symbol is never used in this scenario, its body
|
||||||
will never be compiled. This is the default behavior leading to best compilation
|
will never be compiled. This is the default behavior leading to best compilation
|
||||||
times, but if exhaustive compilation of all definitions is required, using
|
times, but if exhaustive compilation of all definitions is required, using
|
||||||
``nim check`` provides this option as well.
|
``nim check`` provides this option as well.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
@ -461,9 +461,9 @@ Example:
|
||||||
pragma pragma
|
pragma pragma
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
The ``pragma`` pragma can be used to declare user defined pragmas. This is
|
The ``pragma`` pragma can be used to declare user defined pragmas. This is
|
||||||
useful because Nim's templates and macros do not affect pragmas. User
|
useful because Nim's templates and macros do not affect pragmas. User
|
||||||
defined pragmas are in a different module-wide scope than all other symbols.
|
defined pragmas are in a different module-wide scope than all other symbols.
|
||||||
They cannot be imported from a module.
|
They cannot be imported from a module.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
@ -473,8 +473,8 @@ Example:
|
||||||
{.pragma: rtl, exportc, dynlib, cdecl.}
|
{.pragma: rtl, exportc, dynlib, cdecl.}
|
||||||
else:
|
else:
|
||||||
{.pragma: rtl, importc, dynlib: "client.dll", cdecl.}
|
{.pragma: rtl, importc, dynlib: "client.dll", cdecl.}
|
||||||
|
|
||||||
proc p*(a, b: int): int {.rtl.} =
|
proc p*(a, b: int): int {.rtl.} =
|
||||||
result = a+b
|
result = a+b
|
||||||
|
|
||||||
In the example a new pragma named ``rtl`` is introduced that either imports
|
In the example a new pragma named ``rtl`` is introduced that either imports
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
Threads
|
Threads
|
||||||
=======
|
=======
|
||||||
|
|
||||||
To enable thread support the ``--threads:on`` command line switch needs to
|
To enable thread support the ``--threads:on`` command line switch needs to
|
||||||
be used. The ``system`` module then contains several threading primitives.
|
be used. The ``system`` module then contains several threading primitives.
|
||||||
See the `threads <threads.html>`_ and `channels <channels.html>`_ modules
|
See the `threads <threads.html>`_ and `channels <channels.html>`_ modules
|
||||||
for the low level thread API. There are also high level parallelism constructs
|
for the low level thread API. There are also high level parallelism constructs
|
||||||
available. See `spawn`_ for further details.
|
available. See `spawn`_ for further details.
|
||||||
|
|
||||||
Nim's memory model for threads is quite different than that of other common
|
Nim's memory model for threads is quite different than that of other common
|
||||||
programming languages (C, Pascal, Java): Each thread has its own (garbage
|
programming languages (C, Pascal, Java): Each thread has its own (garbage
|
||||||
collected) heap and sharing of memory is restricted to global variables. This
|
collected) heap and sharing of memory is restricted to global variables. This
|
||||||
helps to prevent race conditions. GC efficiency is improved quite a lot,
|
helps to prevent race conditions. GC efficiency is improved quite a lot,
|
||||||
because the GC never has to stop other threads and see what they reference.
|
because the GC never has to stop other threads and see what they reference.
|
||||||
Memory allocation requires no lock at all! This design easily scales to massive
|
Memory allocation requires no lock at all! This design easily scales to massive
|
||||||
multicore processors that are becoming the norm.
|
multicore processors that are becoming the norm.
|
||||||
|
|
@ -22,10 +22,10 @@ Thread pragma
|
||||||
A proc that is executed as a new thread of execution should be marked by the
|
A proc that is executed as a new thread of execution should be marked by the
|
||||||
``thread`` pragma for reasons of readability. The compiler checks for
|
``thread`` pragma for reasons of readability. The compiler checks for
|
||||||
violations of the `no heap sharing restriction`:idx:\: This restriction implies
|
violations of the `no heap sharing restriction`:idx:\: This restriction implies
|
||||||
that it is invalid to construct a data structure that consists of memory
|
that it is invalid to construct a data structure that consists of memory
|
||||||
allocated from different (thread local) heaps.
|
allocated from different (thread local) heaps.
|
||||||
|
|
||||||
A thread proc is passed to ``createThread`` or ``spawn`` and invoked
|
A thread proc is passed to ``createThread`` or ``spawn`` and invoked
|
||||||
indirectly; so the ``thread`` pragma implies ``procvar``.
|
indirectly; so the ``thread`` pragma implies ``procvar``.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ GC safety
|
||||||
|
|
||||||
We call a proc ``p`` `GC safe`:idx: when it doesn't access any global variable
|
We call a proc ``p`` `GC safe`:idx: when it doesn't access any global variable
|
||||||
that contains GC'ed memory (``string``, ``seq``, ``ref`` or a closure) either
|
that contains GC'ed memory (``string``, ``seq``, ``ref`` or a closure) either
|
||||||
directly or indirectly through a call to a GC unsafe proc.
|
directly or indirectly through a call to a GC unsafe proc.
|
||||||
|
|
||||||
The `gcsafe`:idx: annotation can be used to mark a proc to be gcsafe,
|
The `gcsafe`:idx: annotation can be used to mark a proc to be gcsafe,
|
||||||
otherwise this property is inferred by the compiler. Note that ``noSideEfect``
|
otherwise this property is inferred by the compiler. Note that ``noSideEfect``
|
||||||
|
|
@ -45,10 +45,9 @@ contain a ``ref`` or ``closure`` type. This enforces
|
||||||
the *no heap sharing restriction*.
|
the *no heap sharing restriction*.
|
||||||
|
|
||||||
Routines that are imported from C are always assumed to be ``gcsafe``.
|
Routines that are imported from C are always assumed to be ``gcsafe``.
|
||||||
To enable the GC-safety checking the ``--threadAnalysis:on`` command line
|
To disable the GC-safety checking the ``--threadAnalysis:off`` command line
|
||||||
switch must be used. This is a temporary workaround to ease the porting effort
|
switch can be used. This is a temporary workaround to ease the porting effort
|
||||||
from old code to the new threading model. In the future the thread analysis
|
from old code to the new threading model.
|
||||||
will always be performed.
|
|
||||||
|
|
||||||
|
|
||||||
Future directions:
|
Future directions:
|
||||||
|
|
@ -59,13 +58,13 @@ Future directions:
|
||||||
Threadvar pragma
|
Threadvar pragma
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
A global variable can be marked with the ``threadvar`` pragma; it is
|
A global variable can be marked with the ``threadvar`` pragma; it is
|
||||||
a `thread-local`:idx: variable then:
|
a `thread-local`:idx: variable then:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
var checkpoints* {.threadvar.}: seq[string]
|
var checkpoints* {.threadvar.}: seq[string]
|
||||||
|
|
||||||
Due to implementation restrictions thread local variables cannot be
|
Due to implementation restrictions thread local variables cannot be
|
||||||
initialized within the ``var`` section. (Every thread local variable needs to
|
initialized within the ``var`` section. (Every thread local variable needs to
|
||||||
be replicated at thread creation.)
|
be replicated at thread creation.)
|
||||||
|
|
||||||
|
|
@ -73,7 +72,7 @@ be replicated at thread creation.)
|
||||||
Threads and exceptions
|
Threads and exceptions
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
The interaction between threads and exceptions is simple: A *handled* exception
|
The interaction between threads and exceptions is simple: A *handled* exception
|
||||||
in one thread cannot affect any other thread. However, an *unhandled* exception
|
in one thread cannot affect any other thread. However, an *unhandled* exception
|
||||||
in one thread terminates the whole *process*!
|
in one thread terminates the whole *process*!
|
||||||
|
|
||||||
|
|
@ -82,7 +81,7 @@ in one thread terminates the whole *process*!
|
||||||
Parallel & Spawn
|
Parallel & Spawn
|
||||||
================
|
================
|
||||||
|
|
||||||
Nim has two flavors of parallelism:
|
Nim has two flavors of parallelism:
|
||||||
1) `Structured`:idx: parallelism via the ``parallel`` statement.
|
1) `Structured`:idx: parallelism via the ``parallel`` statement.
|
||||||
2) `Unstructured`:idx: parallelism via the standalone ``spawn`` statement.
|
2) `Unstructured`:idx: parallelism via the standalone ``spawn`` statement.
|
||||||
|
|
||||||
|
|
@ -115,7 +114,7 @@ Spawn statement
|
||||||
|
|
||||||
proc processLine(line: string) =
|
proc processLine(line: string) =
|
||||||
discard "do some heavy lifting here"
|
discard "do some heavy lifting here"
|
||||||
|
|
||||||
for x in lines("myinput.txt"):
|
for x in lines("myinput.txt"):
|
||||||
spawn processLine(x)
|
spawn processLine(x)
|
||||||
sync()
|
sync()
|
||||||
|
|
@ -144,7 +143,7 @@ wait on multiple flow variables at the same time:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
import threadpool, ...
|
import threadpool, ...
|
||||||
|
|
||||||
# wait until 2 out of 3 servers received the update:
|
# wait until 2 out of 3 servers received the update:
|
||||||
proc main =
|
proc main =
|
||||||
var responses = newSeq[RawFlowVar](3)
|
var responses = newSeq[RawFlowVar](3)
|
||||||
|
|
@ -203,8 +202,7 @@ restrictions / changes:
|
||||||
the ``parallel`` section. This is called the *immutability check*. Currently
|
the ``parallel`` section. This is called the *immutability check*. Currently
|
||||||
it is not specified what exactly "complex location" means. We need to make
|
it is not specified what exactly "complex location" means. We need to make
|
||||||
this an optimization!
|
this an optimization!
|
||||||
* Every array access has to be provably within bounds. This is called
|
* Every array access has to be provably within bounds. This is called
|
||||||
the *bounds check*.
|
the *bounds check*.
|
||||||
* Slices are optimized so that no copy is performed. This optimization is not
|
* Slices are optimized so that no copy is performed. This optimization is not
|
||||||
yet performed for ordinary slices outside of a ``parallel`` section. Slices
|
yet performed for ordinary slices outside of a ``parallel`` section.
|
||||||
are also special in that they currently do not support negative indexes!
|
|
||||||
|
|
|
||||||
10
tests/misc/tcharinc.nim
Normal file
10
tests/misc/tcharinc.nim
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
discard """
|
||||||
|
output: "1"
|
||||||
|
"""
|
||||||
|
|
||||||
|
var c = '\0'
|
||||||
|
while true:
|
||||||
|
if c == '\xFF': break
|
||||||
|
inc c
|
||||||
|
|
||||||
|
echo "1"
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
discard """
|
|
||||||
disabled: true
|
|
||||||
"""
|
|
||||||
import
|
|
||||||
gtk2, glib2, atk, gdk2, gdk2pixbuf, libglade2, pango,
|
|
||||||
pangoutils
|
|
||||||
|
|
||||||
proc hello(widget: PWidget, data: pointer) {.cdecl.} =
|
|
||||||
write(stdout, "Hello World\n")
|
|
||||||
|
|
||||||
proc delete_event(widget: PWidget, event: PEvent,
|
|
||||||
data: pointer): bool {.cdecl.} =
|
|
||||||
# If you return FALSE in the "delete_event" signal handler,
|
|
||||||
# GTK will emit the "destroy" signal. Returning TRUE means
|
|
||||||
# you don't want the window to be destroyed.
|
|
||||||
# This is useful for popping up 'are you sure you want to quit?'
|
|
||||||
# type dialogs.
|
|
||||||
write(stdout, "delete event occurred\n")
|
|
||||||
# Change TRUE to FALSE and the main window will be destroyed with
|
|
||||||
# a "delete_event".
|
|
||||||
return false
|
|
||||||
|
|
||||||
# Another callback
|
|
||||||
proc mydestroy(widget: PWidget, data: pointer) {.cdecl.} =
|
|
||||||
gtk2.main_quit()
|
|
||||||
|
|
||||||
proc mymain() =
|
|
||||||
# GtkWidget is the storage type for widgets
|
|
||||||
gtk2.nimrod_init()
|
|
||||||
var window = window_new(gtk2.WINDOW_TOPLEVEL)
|
|
||||||
discard g_signal_connect(window, "delete_event",
|
|
||||||
Gcallback(delete_event), nil)
|
|
||||||
discard g_signal_connect(window, "destroy", Gcallback(mydestroy), nil)
|
|
||||||
# Sets the border width of the window.
|
|
||||||
set_border_width(window, 10)
|
|
||||||
|
|
||||||
# Creates a new button with the label "Hello World".
|
|
||||||
var button = button_new("Hello World")
|
|
||||||
|
|
||||||
discard g_signal_connect(button, "clicked", Gcallback(hello), nil)
|
|
||||||
|
|
||||||
# This packs the button into the window (a gtk container).
|
|
||||||
add(window, button)
|
|
||||||
|
|
||||||
# The final step is to display this newly created widget.
|
|
||||||
show(button)
|
|
||||||
|
|
||||||
# and the window
|
|
||||||
show(window)
|
|
||||||
|
|
||||||
gtk2.main()
|
|
||||||
|
|
||||||
mymain()
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
discard """
|
|
||||||
disabled: true
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Test wether the bindings at least compile...
|
|
||||||
|
|
||||||
import
|
|
||||||
unicode, cgi, terminal, libcurl,
|
|
||||||
parsexml, parseopt, parsecfg,
|
|
||||||
osproc, complex,
|
|
||||||
sdl, smpeg, sdl_gfx, sdl_net, sdl_mixer, sdl_ttf,
|
|
||||||
sdl_image, sdl_mixer_nosmpeg,
|
|
||||||
cursorfont, xatom, xf86vmode, xkb, xrandr, xshm, xvlib, keysym, xcms, xi,
|
|
||||||
xkblib, xrender, xutil, x, xf86dga, xinerama, xlib, xresource, xv,
|
|
||||||
gtk2, glib2, pango, gdk2,
|
|
||||||
cairowin32, cairoxlib,
|
|
||||||
odbcsql,
|
|
||||||
gl, glut, glu, glx, glext, wingl,
|
|
||||||
lua, lualib, lauxlib, mysql, sqlite3, python, tcl,
|
|
||||||
db_postgres, db_mysql, db_sqlite, ropes, sockets, browsers, httpserver,
|
|
||||||
httpclient, parseutils, unidecode, xmldom, xmldomparser, xmltree, xmlparser,
|
|
||||||
htmlparser, re, graphics, colors, pegs, subexes, dialogs
|
|
||||||
|
|
||||||
when defined(linux):
|
|
||||||
import
|
|
||||||
zlib, zipfiles
|
|
||||||
|
|
||||||
writeln(stdout, "test compilation of binding modules")
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
discard """
|
|
||||||
disabled: true
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Test wether the bindings at least compile...
|
|
||||||
|
|
||||||
import
|
|
||||||
tcl,
|
|
||||||
sdl, smpeg, sdl_gfx, sdl_net, sdl_mixer, sdl_ttf,
|
|
||||||
sdl_image, sdl_mixer_nosmpeg,
|
|
||||||
gtk2, glib2, pango, gdk2,
|
|
||||||
unicode, cgi, terminal, libcurl,
|
|
||||||
parsexml, parseopt, parsecfg,
|
|
||||||
osproc,
|
|
||||||
cairowin32, cairoxlib,
|
|
||||||
gl, glut, glu, glx, glext, wingl,
|
|
||||||
lua, lualib, lauxlib, mysql, sqlite3, db_mongo, md5, asyncio, mimetypes,
|
|
||||||
cookies, events, ftpclient, scgi, irc
|
|
||||||
|
|
||||||
|
|
||||||
writeln(stdout, "test compilation of binding modules")
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue