Merge branch 'devel'
This commit is contained in:
commit
ac1fbf1469
24 changed files with 339 additions and 181 deletions
|
|
@ -964,8 +964,11 @@ proc genEcho(p: BProc, n: PNode) =
|
||||||
var args: Rope = nil
|
var args: Rope = nil
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
for i in countup(0, n.len-1):
|
for i in countup(0, n.len-1):
|
||||||
initLocExpr(p, n.sons[i], a)
|
if n.sons[i].skipConv.kind == nkNilLit:
|
||||||
addf(args, ", $1? ($1)->data:\"nil\"", [rdLoc(a)])
|
add(args, ", \"nil\"")
|
||||||
|
else:
|
||||||
|
initLocExpr(p, n.sons[i], a)
|
||||||
|
addf(args, ", $1? ($1)->data:\"nil\"", [rdLoc(a)])
|
||||||
linefmt(p, cpsStmts, "printf($1$2);$n",
|
linefmt(p, cpsStmts, "printf($1$2);$n",
|
||||||
makeCString(repeat("%s", n.len) & tnl), args)
|
makeCString(repeat("%s", n.len) & tnl), args)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ Start: "doc/overview.html"
|
||||||
|
|
||||||
[Other]
|
[Other]
|
||||||
Files: "readme.txt;install.txt;contributors.txt;copying.txt"
|
Files: "readme.txt;install.txt;contributors.txt;copying.txt"
|
||||||
Files: "configure;makefile"
|
Files: "makefile"
|
||||||
Files: "*.ini"
|
Files: "*.ini"
|
||||||
Files: "koch.nim"
|
Files: "koch.nim"
|
||||||
|
|
||||||
|
|
@ -70,6 +70,10 @@ Files: "doc/*.nim"
|
||||||
Files: "doc/*.cfg"
|
Files: "doc/*.cfg"
|
||||||
Files: "compiler/nimfix/*.nim"
|
Files: "compiler/nimfix/*.nim"
|
||||||
Files: "compiler/nimfix/*.cfg"
|
Files: "compiler/nimfix/*.cfg"
|
||||||
|
Files: "compiler/nimsuggest/*.nim"
|
||||||
|
Files: "compiler/nimsuggest/*.cfg"
|
||||||
|
Files: "compiler/plugins/locals/*.nim"
|
||||||
|
Files: "compiler/plugins/active.nim"
|
||||||
Files: "tools/*.nim"
|
Files: "tools/*.nim"
|
||||||
Files: "tools/*.cfg"
|
Files: "tools/*.cfg"
|
||||||
Files: "tools/*.tmpl"
|
Files: "tools/*.tmpl"
|
||||||
|
|
@ -97,13 +101,8 @@ Files: "lib/pure/concurrency/*.cfg"
|
||||||
Files: "lib/impure/*.nim"
|
Files: "lib/impure/*.nim"
|
||||||
Files: "lib/wrappers/*.nim"
|
Files: "lib/wrappers/*.nim"
|
||||||
|
|
||||||
Files: "lib/wrappers/cairo/*.nim"
|
|
||||||
Files: "lib/wrappers/gtk/*.nim"
|
|
||||||
Files: "lib/wrappers/lua/*.nim"
|
|
||||||
Files: "lib/wrappers/opengl/*.nim"
|
|
||||||
Files: "lib/wrappers/readline/*.nim"
|
Files: "lib/wrappers/readline/*.nim"
|
||||||
Files: "lib/wrappers/sdl/*.nim"
|
Files: "lib/wrappers/sdl/*.nim"
|
||||||
Files: "lib/wrappers/x11/*.nim"
|
|
||||||
Files: "lib/wrappers/zip/*.nim"
|
Files: "lib/wrappers/zip/*.nim"
|
||||||
Files: "lib/wrappers/zip/libzip_all.c"
|
Files: "lib/wrappers/zip/libzip_all.c"
|
||||||
|
|
||||||
|
|
@ -115,8 +114,6 @@ Files: "lib/packages/docutils/*.nim"
|
||||||
|
|
||||||
[Other]
|
[Other]
|
||||||
Files: "examples/*.nim"
|
Files: "examples/*.nim"
|
||||||
Files: "examples/gtk/*.nim"
|
|
||||||
Files: "examples/0mq/*.nim"
|
|
||||||
Files: "examples/c++iface/*.nim"
|
Files: "examples/c++iface/*.nim"
|
||||||
Files: "examples/objciface/*.nim"
|
Files: "examples/objciface/*.nim"
|
||||||
Files: "examples/cross_calculator/"
|
Files: "examples/cross_calculator/"
|
||||||
|
|
@ -239,7 +236,7 @@ BinPath: r"bin;dist\mingw\bin;dist"
|
||||||
; Section | dir | zipFile | size hint (in KB) | url | exe start menu entry
|
; Section | dir | zipFile | size hint (in KB) | url | exe start menu entry
|
||||||
Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip|overview.html"
|
Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip|overview.html"
|
||||||
Download: r"C Compiler (MingW)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip"
|
Download: r"C Compiler (MingW)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip"
|
||||||
Download: r"Aporia IDE|dist|aporia.zip|97997|http://nim-lang.org/download/aporia-0.3.0.zip|aporia\bin\aporia.exe"
|
Download: r"Aporia IDE|dist|aporia.zip|97997|http://nim-lang.org/download/aporia-0.3.0.zip|aporia-0.3.0\bin\aporia.exe"
|
||||||
; for now only NSIS supports optional downloads
|
; for now only NSIS supports optional downloads
|
||||||
|
|
||||||
[UnixBin]
|
[UnixBin]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nim Compiler
|
# The Nim Compiler
|
||||||
# (c) Copyright 2013 Andreas Rumpf
|
# (c) Copyright 2015 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
|
||||||
|
|
@ -535,7 +535,18 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result.sons[i] = fitNode(c, typ, result.sons[i])
|
result.sons[i] = fitNode(c, typ, result.sons[i])
|
||||||
result.typ.sons[0] = makeRangeType(c, 0, sonsLen(result) - 1, n.info)
|
result.typ.sons[0] = makeRangeType(c, 0, sonsLen(result) - 1, n.info)
|
||||||
|
|
||||||
template fixAbstractType(c: PContext, n: PNode) =
|
proc fixAbstractType(c: PContext, n: PNode) =
|
||||||
|
for i in 1 .. < n.len:
|
||||||
|
let it = n.sons[i]
|
||||||
|
# do not get rid of nkHiddenSubConv for OpenArrays, the codegen needs it:
|
||||||
|
if it.kind == nkHiddenSubConv and
|
||||||
|
skipTypes(it.typ, abstractVar).kind notin {tyOpenArray, tyVarargs}:
|
||||||
|
if skipTypes(it.sons[1].typ, abstractVar).kind in
|
||||||
|
{tyNil, tyArrayConstr, tyTuple, tySet}:
|
||||||
|
var s = skipTypes(it.typ, abstractVar)
|
||||||
|
if s.kind != tyExpr:
|
||||||
|
changeType(it.sons[1], s, check=true)
|
||||||
|
n.sons[i] = it.sons[1]
|
||||||
when false:
|
when false:
|
||||||
# XXX finally rewrite that crap!
|
# XXX finally rewrite that crap!
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
|
|
@ -2042,7 +2053,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
of nkEmpty, nkNone, nkCommentStmt:
|
of nkEmpty, nkNone, nkCommentStmt:
|
||||||
discard
|
discard
|
||||||
of nkNilLit:
|
of nkNilLit:
|
||||||
result.typ = getSysType(tyNil)
|
if result.typ == nil: result.typ = getSysType(tyNil)
|
||||||
of nkIntLit:
|
of nkIntLit:
|
||||||
if result.typ == nil: setIntLitType(result)
|
if result.typ == nil: setIntLitType(result)
|
||||||
of nkInt8Lit:
|
of nkInt8Lit:
|
||||||
|
|
|
||||||
|
|
@ -286,10 +286,13 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||||
of mNot: result = newIntNodeT(1 - getInt(a), n)
|
of mNot: result = newIntNodeT(1 - getInt(a), n)
|
||||||
of mCard: result = newIntNodeT(nimsets.cardSet(a), n)
|
of mCard: result = newIntNodeT(nimsets.cardSet(a), n)
|
||||||
of mBitnotI, mBitnotI64: result = newIntNodeT(not getInt(a), n)
|
of mBitnotI, mBitnotI64: result = newIntNodeT(not getInt(a), n)
|
||||||
of mLengthStr, mXLenStr: result = newIntNodeT(len(getStr(a)), n)
|
of mLengthStr, mXLenStr:
|
||||||
|
if a.kind == nkNilLit: result = newIntNodeT(0, n)
|
||||||
|
else: result = newIntNodeT(len(getStr(a)), n)
|
||||||
of mLengthArray: result = newIntNodeT(lengthOrd(a.typ), n)
|
of mLengthArray: result = newIntNodeT(lengthOrd(a.typ), n)
|
||||||
of mLengthSeq, mLengthOpenArray, mXLenSeq:
|
of mLengthSeq, mLengthOpenArray, mXLenSeq:
|
||||||
result = newIntNodeT(sonsLen(a), n) # BUGFIX
|
if a.kind == nkNilLit: result = newIntNodeT(0, n)
|
||||||
|
else: result = newIntNodeT(sonsLen(a), n) # BUGFIX
|
||||||
of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away
|
of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away
|
||||||
of mToFloat, mToBiggestFloat:
|
of mToFloat, mToBiggestFloat:
|
||||||
result = newFloatNodeT(toFloat(int(getInt(a))), n)
|
result = newFloatNodeT(toFloat(int(getInt(a))), n)
|
||||||
|
|
@ -545,7 +548,7 @@ proc foldConv*(n, a: PNode; check = false): PNode =
|
||||||
discard
|
discard
|
||||||
else:
|
else:
|
||||||
result = a
|
result = a
|
||||||
result.typ = takeType(n.typ, a.typ)
|
result.typ = n.typ
|
||||||
|
|
||||||
proc getArrayConstr(m: PSym, n: PNode): PNode =
|
proc getArrayConstr(m: PSym, n: PNode): PNode =
|
||||||
if n.kind == nkBracket:
|
if n.kind == nkBracket:
|
||||||
|
|
@ -652,7 +655,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
of nkIfExpr:
|
of nkIfExpr:
|
||||||
result = getConstIfExpr(m, n)
|
result = getConstIfExpr(m, n)
|
||||||
of nkCall, nkCommand, nkCallStrLit, nkPrefix, nkInfix:
|
of nkCallKinds:
|
||||||
if n.sons[0].kind != nkSym: return
|
if n.sons[0].kind != nkSym: return
|
||||||
var s = n.sons[0].sym
|
var s = n.sons[0].sym
|
||||||
if s.kind != skProc: return
|
if s.kind != skProc: return
|
||||||
|
|
|
||||||
|
|
@ -716,8 +716,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
|
||||||
add(result, PTransNode(newSymNode(labl)))
|
add(result, PTransNode(newSymNode(labl)))
|
||||||
of nkBreakStmt: result = transformBreak(c, n)
|
of nkBreakStmt: result = transformBreak(c, n)
|
||||||
of nkWhileStmt: result = transformWhile(c, n)
|
of nkWhileStmt: result = transformWhile(c, n)
|
||||||
of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix,
|
of nkCallKinds:
|
||||||
nkCallStrLit:
|
|
||||||
result = transformCall(c, n)
|
result = transformCall(c, n)
|
||||||
of nkAddr, nkHiddenAddr:
|
of nkAddr, nkHiddenAddr:
|
||||||
result = transformAddrDeref(c, n, nkDerefExpr, nkHiddenDeref)
|
result = transformAddrDeref(c, n, nkDerefExpr, nkHiddenDeref)
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ path="$lib/pure/unidecode"
|
||||||
|
|
||||||
# Configuration for the GNU C/C++ compiler:
|
# Configuration for the GNU C/C++ compiler:
|
||||||
@if windows:
|
@if windows:
|
||||||
#gcc.path = r"$nimrod\dist\mingw\bin"
|
#gcc.path = r"$nim\dist\mingw\bin"
|
||||||
@if gcc:
|
@if gcc:
|
||||||
tlsEmulation:on
|
tlsEmulation:on
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
72
doc/tut1.txt
72
doc/tut1.txt
|
|
@ -16,7 +16,7 @@ Introduction
|
||||||
</p></blockquote>
|
</p></blockquote>
|
||||||
|
|
||||||
|
|
||||||
This document is a tutorial for the programming language *Nim*.
|
This document is a tutorial for the programming language *Nim*.
|
||||||
This tutorial assumes that you are familiar with basic programming concepts
|
This tutorial assumes that you are familiar with basic programming concepts
|
||||||
like variables, types or statements but is kept very basic. The `manual
|
like variables, types or statements but is kept very basic. The `manual
|
||||||
<manual.html>`_ contains many more examples of the advanced language features.
|
<manual.html>`_ contains many more examples of the advanced language features.
|
||||||
|
|
@ -50,7 +50,7 @@ Commonly used commands and switches have abbreviations, so you can also use::
|
||||||
nim c -r greetings.nim
|
nim c -r greetings.nim
|
||||||
|
|
||||||
To compile a release version use::
|
To compile a release version use::
|
||||||
|
|
||||||
nim c -d:release greetings.nim
|
nim c -d:release greetings.nim
|
||||||
|
|
||||||
By default the Nim compiler generates a large amount of runtime checks
|
By default the Nim compiler generates a large amount of runtime checks
|
||||||
|
|
@ -116,7 +116,7 @@ hash character ``#``. Documentation comments start with ``##``:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
# A comment.
|
# A comment.
|
||||||
|
|
||||||
var myVariable: int ## a documentation comment
|
var myVariable: int ## a documentation comment
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -200,7 +200,7 @@ constant declaration at compile time:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
const x = "abc" # the constant x contains the string "abc"
|
const x = "abc" # the constant x contains the string "abc"
|
||||||
|
|
||||||
Indentation can be used after the ``const`` keyword to list a whole section of
|
Indentation can be used after the ``const`` keyword to list a whole section of
|
||||||
constants:
|
constants:
|
||||||
|
|
||||||
|
|
@ -214,7 +214,7 @@ constants:
|
||||||
|
|
||||||
The let statement
|
The let statement
|
||||||
=================
|
=================
|
||||||
The ``let`` statement works like the ``var`` statement but the declared
|
The ``let`` statement works like the ``var`` statement but the declared
|
||||||
symbols are *single assignment* variables: After the initialization their
|
symbols are *single assignment* variables: After the initialization their
|
||||||
value cannot change:
|
value cannot change:
|
||||||
|
|
||||||
|
|
@ -228,7 +228,7 @@ and put it into a data section":
|
||||||
|
|
||||||
.. code-block::
|
.. code-block::
|
||||||
const input = readLine(stdin) # Error: constant expression expected
|
const input = readLine(stdin) # Error: constant expression expected
|
||||||
|
|
||||||
.. code-block::
|
.. code-block::
|
||||||
let input = readLine(stdin) # works
|
let input = readLine(stdin) # works
|
||||||
|
|
||||||
|
|
@ -310,8 +310,8 @@ the compiler that for every other value nothing should be done:
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
The empty `discard statement`_ is a *do nothing* statement. The compiler knows
|
The empty `discard statement`_ is a *do nothing* statement. The compiler knows
|
||||||
that a case statement with an else part cannot fail and thus the error
|
that a case statement with an else part cannot fail and thus the error
|
||||||
disappears. Note that it is impossible to cover all possible string values:
|
disappears. Note that it is impossible to cover all possible string values:
|
||||||
that is why string cases always need an ``else`` branch.
|
that is why string cases always need an ``else`` branch.
|
||||||
|
|
||||||
In general the case statement is used for subrange types or enumerations where
|
In general the case statement is used for subrange types or enumerations where
|
||||||
|
|
@ -406,7 +406,7 @@ The block's *label* (``myblock`` in the example) is optional.
|
||||||
Break statement
|
Break statement
|
||||||
---------------
|
---------------
|
||||||
A block can be left prematurely with a ``break`` statement. The break statement
|
A block can be left prematurely with a ``break`` statement. The break statement
|
||||||
can leave a ``while``, ``for``, or a ``block`` statement. It leaves the
|
can leave a ``while``, ``for``, or a ``block`` statement. It leaves the
|
||||||
innermost construct, unless a label of a block is given:
|
innermost construct, unless a label of a block is given:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -461,7 +461,7 @@ differences:
|
||||||
* The statements within a branch do not open a new scope.
|
* The statements within a branch do not open a new scope.
|
||||||
* The compiler checks the semantics and produces code *only* for the statements
|
* The compiler checks the semantics and produces code *only* for the statements
|
||||||
that belong to the first condition that evaluates to ``true``.
|
that belong to the first condition that evaluates to ``true``.
|
||||||
|
|
||||||
The ``when`` statement is useful for writing platform specific code, similar to
|
The ``when`` statement is useful for writing platform specific code, similar to
|
||||||
the ``#ifdef`` construct in the C programming language.
|
the ``#ifdef`` construct in the C programming language.
|
||||||
|
|
||||||
|
|
@ -486,14 +486,14 @@ to be indented, but single simple statements do not:
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
# no indentation needed for single assignment statement:
|
# no indentation needed for single assignment statement:
|
||||||
if x: x = false
|
if x: x = false
|
||||||
|
|
||||||
# indentation needed for nested if statement:
|
# indentation needed for nested if statement:
|
||||||
if x:
|
if x:
|
||||||
if y:
|
if y:
|
||||||
y = false
|
y = false
|
||||||
else:
|
else:
|
||||||
y = true
|
y = true
|
||||||
|
|
||||||
# indentation needed, because two statements follow the condition:
|
# indentation needed, because two statements follow the condition:
|
||||||
if x:
|
if x:
|
||||||
x = false
|
x = false
|
||||||
|
|
@ -514,7 +514,7 @@ contain indentation at certain places for better readability:
|
||||||
As a rule of thumb, indentation within expressions is allowed after operators,
|
As a rule of thumb, indentation within expressions is allowed after operators,
|
||||||
an open parenthesis and after commas.
|
an open parenthesis and after commas.
|
||||||
|
|
||||||
With parenthesis and semicolons ``(;)`` you can use statements where only
|
With parenthesis and semicolons ``(;)`` you can use statements where only
|
||||||
an expression is allowed:
|
an expression is allowed:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -560,45 +560,45 @@ 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 declared
|
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
|
that represents the return value. A ``return`` statement with no expression is a
|
||||||
shorthand for ``return result``. The ``result`` value is always returned
|
shorthand for ``return result``. The ``result`` value is always returned
|
||||||
automatically at the end a procedure if there is no ``return`` statement at
|
automatically at the end a procedure if there is no ``return`` statement at
|
||||||
the exit.
|
the exit.
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
proc sumTillNegative(x: varargs[int]): int =
|
proc sumTillNegative(x: varargs[int]): int =
|
||||||
for i in x:
|
for i in x:
|
||||||
if i < 0:
|
if i < 0:
|
||||||
return
|
return
|
||||||
result = result + i
|
result = result + i
|
||||||
|
|
||||||
echo sumTillNegative() # echos 0
|
echo sumTillNegative() # echos 0
|
||||||
echo sumTillNegative(3, 4, 5) # echos 12
|
echo sumTillNegative(3, 4, 5) # echos 12
|
||||||
echo sumTillNegative(3, 4 , -1 , 6) # echos 7
|
echo sumTillNegative(3, 4 , -1 , 6) # echos 7
|
||||||
|
|
||||||
The ``result`` variable is already implicitly declared at the start of the
|
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
|
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
|
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
|
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
|
be ``nil`` at the start of the procedure, and thus may require manual
|
||||||
initialisation.
|
initialisation.
|
||||||
|
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
Parameters are constant in the procedure body. By default, their value cannot be
|
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
|
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
|
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
|
to be declared with ``var`` in the procedure body. Shadowing the parameter name
|
||||||
is possible, and actually an idiom:
|
is possible, and actually an idiom:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
proc printSeq(s: seq, nprinted: int = -1) =
|
proc printSeq(s: seq, nprinted: int = -1) =
|
||||||
var nprinted = if nprinted == -1: s.len else: min(nprinted, s.len)
|
var nprinted = if nprinted == -1: s.len else: min(nprinted, s.len)
|
||||||
for i in 0 .. <nprinted:
|
for i in 0 .. <nprinted:
|
||||||
echo s[i]
|
echo s[i]
|
||||||
|
|
||||||
If the procedure needs to modify the argument for the
|
If the procedure needs to modify the argument for the
|
||||||
caller, a ``var`` parameter can be used:
|
caller, a ``var`` parameter can be used:
|
||||||
|
|
||||||
|
|
@ -630,12 +630,12 @@ allow to silently throw away a return value:
|
||||||
|
|
||||||
|
|
||||||
The return value can be ignored implicitly if the called proc/iterator has
|
The return value can be ignored implicitly if the called proc/iterator has
|
||||||
been declared with the ``discardable`` pragma:
|
been declared with the ``discardable`` pragma:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
proc p(x, y: int): int {.discardable.} =
|
proc p(x, y: int): int {.discardable.} =
|
||||||
return x + y
|
return x + y
|
||||||
|
|
||||||
p(3, 4) # now valid
|
p(3, 4) # now valid
|
||||||
|
|
||||||
The ``discard`` statement can also be used to create block comments as
|
The ``discard`` statement can also be used to create block comments as
|
||||||
|
|
@ -899,7 +899,7 @@ object on the heap, so there is a trade-off to be made here.
|
||||||
|
|
||||||
Integers
|
Integers
|
||||||
--------
|
--------
|
||||||
Nim has these integer types built-in:
|
Nim has these integer types built-in:
|
||||||
``int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64``.
|
``int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64``.
|
||||||
|
|
||||||
The default integer type is ``int``. Integer literals can have a *type suffix*
|
The default integer type is ``int``. Integer literals can have a *type suffix*
|
||||||
|
|
@ -1114,7 +1114,7 @@ Arrays
|
||||||
An array is a simple fixed length container. Each element in
|
An array is a simple fixed length container. Each element in
|
||||||
the array has the same type. The array's index type can be any ordinal type.
|
the array has the same type. The array's index type can be any ordinal type.
|
||||||
|
|
||||||
Arrays can be constructed via ``[]``:
|
Arrays can be constructed via ``[]``:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
|
|
@ -1370,12 +1370,12 @@ integer.
|
||||||
var building: tuple[street: string, number: int]
|
var building: tuple[street: string, number: int]
|
||||||
building = ("Rue del Percebe", 13)
|
building = ("Rue del Percebe", 13)
|
||||||
echo(building.street)
|
echo(building.street)
|
||||||
|
|
||||||
# The following line does not compile, they are different tuples!
|
# The following line does not compile, they are different tuples!
|
||||||
#person = building
|
#person = building
|
||||||
# --> Error: type mismatch: got (tuple[street: string, number: int])
|
# --> Error: type mismatch: got (tuple[street: string, number: int])
|
||||||
# but expected 'Person'
|
# but expected 'Person'
|
||||||
|
|
||||||
# The following works because the field names and types are the same.
|
# The following works because the field names and types are the same.
|
||||||
var teacher: tuple[name: string, age: int] = ("Mark", 42)
|
var teacher: tuple[name: string, age: int] = ("Mark", 42)
|
||||||
person = teacher
|
person = teacher
|
||||||
|
|
@ -1450,13 +1450,13 @@ operators perform implicit dereferencing operations for reference types:
|
||||||
|
|
||||||
type
|
type
|
||||||
Node = ref NodeObj
|
Node = ref NodeObj
|
||||||
NodeObj = object
|
NodeObj = object
|
||||||
le, ri: PNode
|
le, ri: Node
|
||||||
data: int
|
data: int
|
||||||
var
|
var
|
||||||
n: Node
|
n: Node
|
||||||
new(n)
|
new(n)
|
||||||
n.data = 9
|
n.data = 9
|
||||||
# no need to write n[].data; in fact n[].data is highly discouraged!
|
# no need to write n[].data; in fact n[].data is highly discouraged!
|
||||||
|
|
||||||
To allocate a new traced object, the built-in procedure ``new`` has to be used.
|
To allocate a new traced object, the built-in procedure ``new`` has to be used.
|
||||||
|
|
@ -1559,9 +1559,9 @@ This is best illustrated by an example:
|
||||||
|
|
||||||
|
|
||||||
A symbol of a module *can* be *qualified* with the ``module.symbol`` syntax. If
|
A symbol of a module *can* be *qualified* with the ``module.symbol`` syntax. If
|
||||||
the symbol is ambiguous, it even *has* to be qualified. A symbol is ambiguous
|
the symbol is ambiguous, it even *has* to be qualified. A symbol is ambiguous
|
||||||
if it is defined in two (or more) different modules and both modules are
|
if it is defined in two (or more) different modules and both modules are
|
||||||
imported by a third one:
|
imported by a third one:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
# Module A
|
# Module A
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
|
|
||||||
## This module implements a zip archive creator/reader/modifier.
|
## This module implements a zip archive creator/reader/modifier.
|
||||||
|
|
||||||
import
|
import
|
||||||
streams, libzip, times, os
|
streams, libzip, times, os, strutils
|
||||||
|
|
||||||
type
|
type
|
||||||
TZipArchive* = object of RootObj ## represents a zip archive
|
TZipArchive* = object of RootObj ## represents a zip archive
|
||||||
|
|
@ -18,14 +18,14 @@ type
|
||||||
w: PZip
|
w: PZip
|
||||||
|
|
||||||
|
|
||||||
proc zipError(z: var TZipArchive) =
|
proc zipError(z: var TZipArchive) =
|
||||||
var e: ref IOError
|
var e: ref IOError
|
||||||
new(e)
|
new(e)
|
||||||
e.msg = $zip_strerror(z.w)
|
e.msg = $zip_strerror(z.w)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
proc open*(z: var TZipArchive, filename: string, mode: FileMode = fmRead): bool =
|
proc open*(z: var TZipArchive, filename: string, mode: FileMode = fmRead): bool =
|
||||||
## Opens a zip file for reading, writing or appending. All file modes are
|
## Opens a zip file for reading, writing or appending. All file modes are
|
||||||
## supported. Returns true iff successful, false otherwise.
|
## supported. Returns true iff successful, false otherwise.
|
||||||
var err, flags: int32
|
var err, flags: int32
|
||||||
case mode
|
case mode
|
||||||
|
|
@ -41,21 +41,21 @@ proc open*(z: var TZipArchive, filename: string, mode: FileMode = fmRead): bool
|
||||||
proc close*(z: var TZipArchive) =
|
proc close*(z: var TZipArchive) =
|
||||||
## Closes a zip file.
|
## Closes a zip file.
|
||||||
zip_close(z.w)
|
zip_close(z.w)
|
||||||
|
|
||||||
proc createDir*(z: var TZipArchive, dir: string) =
|
proc createDir*(z: var TZipArchive, dir: string) =
|
||||||
## Creates a directory within the `z` archive. This does not fail if the
|
## Creates a directory within the `z` archive. This does not fail if the
|
||||||
## directory already exists. Note that for adding a file like
|
## directory already exists. Note that for adding a file like
|
||||||
## ``"path1/path2/filename"`` it is not necessary
|
## ``"path1/path2/filename"`` it is not necessary
|
||||||
## to create the ``"path/path2"`` subdirectories - it will be done
|
## to create the ``"path/path2"`` subdirectories - it will be done
|
||||||
## automatically by ``addFile``.
|
## automatically by ``addFile``.
|
||||||
assert(z.mode != fmRead)
|
assert(z.mode != fmRead)
|
||||||
discard zip_add_dir(z.w, dir)
|
discard zip_add_dir(z.w, dir)
|
||||||
zip_error_clear(z.w)
|
zip_error_clear(z.w)
|
||||||
|
|
||||||
proc addFile*(z: var TZipArchive, dest, src: string) =
|
proc addFile*(z: var TZipArchive, dest, src: string) =
|
||||||
## Adds the file `src` to the archive `z` with the name `dest`. `dest`
|
## Adds the file `src` to the archive `z` with the name `dest`. `dest`
|
||||||
## may contain a path that will be created.
|
## may contain a path that will be created.
|
||||||
assert(z.mode != fmRead)
|
assert(z.mode != fmRead)
|
||||||
if not fileExists(src):
|
if not fileExists(src):
|
||||||
raise newException(IOError, "File '" & src & "' does not exist")
|
raise newException(IOError, "File '" & src & "' does not exist")
|
||||||
var zipsrc = zip_source_file(z.w, src, 0, -1)
|
var zipsrc = zip_source_file(z.w, src, 0, -1)
|
||||||
|
|
@ -67,21 +67,21 @@ proc addFile*(z: var TZipArchive, dest, src: string) =
|
||||||
zip_source_free(zipsrc)
|
zip_source_free(zipsrc)
|
||||||
zipError(z)
|
zipError(z)
|
||||||
|
|
||||||
proc addFile*(z: var TZipArchive, file: string) =
|
proc addFile*(z: var TZipArchive, file: string) =
|
||||||
## A shortcut for ``addFile(z, file, file)``, i.e. the name of the source is
|
## A shortcut for ``addFile(z, file, file)``, i.e. the name of the source is
|
||||||
## the name of the destination.
|
## the name of the destination.
|
||||||
addFile(z, file, file)
|
addFile(z, file, file)
|
||||||
|
|
||||||
proc mySourceCallback(state, data: pointer, len: int,
|
proc mySourceCallback(state, data: pointer, len: int,
|
||||||
cmd: TZipSourceCmd): int {.cdecl.} =
|
cmd: TZipSourceCmd): int {.cdecl.} =
|
||||||
var src = cast[Stream](state)
|
var src = cast[Stream](state)
|
||||||
case cmd
|
case cmd
|
||||||
of ZIP_SOURCE_OPEN:
|
of ZIP_SOURCE_OPEN:
|
||||||
if src.setPositionImpl != nil: setPosition(src, 0) # reset
|
if src.setPositionImpl != nil: setPosition(src, 0) # reset
|
||||||
of ZIP_SOURCE_READ:
|
of ZIP_SOURCE_READ:
|
||||||
result = readData(src, data, len)
|
result = readData(src, data, len)
|
||||||
of ZIP_SOURCE_CLOSE: close(src)
|
of ZIP_SOURCE_CLOSE: close(src)
|
||||||
of ZIP_SOURCE_STAT:
|
of ZIP_SOURCE_STAT:
|
||||||
var stat = cast[PZipStat](data)
|
var stat = cast[PZipStat](data)
|
||||||
zip_stat_init(stat)
|
zip_stat_init(stat)
|
||||||
stat.size = high(int32)-1 # we don't know the size
|
stat.size = high(int32)-1 # we don't know the size
|
||||||
|
|
@ -94,8 +94,8 @@ proc mySourceCallback(state, data: pointer, len: int,
|
||||||
result = 2*sizeof(cint)
|
result = 2*sizeof(cint)
|
||||||
of constZIP_SOURCE_FREE: GC_unref(src)
|
of constZIP_SOURCE_FREE: GC_unref(src)
|
||||||
else: assert(false)
|
else: assert(false)
|
||||||
|
|
||||||
proc addFile*(z: var TZipArchive, dest: string, src: Stream) =
|
proc addFile*(z: var TZipArchive, dest: string, src: Stream) =
|
||||||
## Adds a file named with `dest` to the archive `z`. `dest`
|
## Adds a file named with `dest` to the archive `z`. `dest`
|
||||||
## may contain a path. The file's content is read from the `src` stream.
|
## may contain a path. The file's content is read from the `src` stream.
|
||||||
assert(z.mode != fmRead)
|
assert(z.mode != fmRead)
|
||||||
|
|
@ -105,39 +105,45 @@ proc addFile*(z: var TZipArchive, dest: string, src: Stream) =
|
||||||
if zip_add(z.w, dest, zipsrc) < 0'i32:
|
if zip_add(z.w, dest, zipsrc) < 0'i32:
|
||||||
zip_source_free(zipsrc)
|
zip_source_free(zipsrc)
|
||||||
zipError(z)
|
zipError(z)
|
||||||
|
|
||||||
# -------------- zip file stream ---------------------------------------------
|
# -------------- zip file stream ---------------------------------------------
|
||||||
|
|
||||||
type
|
type
|
||||||
TZipFileStream = object of StreamObj
|
TZipFileStream = object of StreamObj
|
||||||
f: PZipFile
|
f: PZipFile
|
||||||
|
atEnd: bool
|
||||||
|
|
||||||
PZipFileStream* =
|
PZipFileStream* =
|
||||||
ref TZipFileStream ## a reader stream of a file within a zip archive
|
ref TZipFileStream ## a reader stream of a file within a zip archive
|
||||||
|
|
||||||
proc fsClose(s: Stream) = zip_fclose(PZipFileStream(s).f)
|
proc fsClose(s: Stream) = zip_fclose(PZipFileStream(s).f)
|
||||||
proc fsReadData(s: Stream, buffer: pointer, bufLen: int): int =
|
proc fsAtEnd(s: Stream): bool = PZipFileStream(s).atEnd
|
||||||
|
proc fsReadData(s: Stream, buffer: pointer, bufLen: int): int =
|
||||||
result = zip_fread(PZipFileStream(s).f, buffer, bufLen)
|
result = zip_fread(PZipFileStream(s).f, buffer, bufLen)
|
||||||
|
if result == 0:
|
||||||
|
PZipFileStream(s).atEnd = true
|
||||||
|
|
||||||
proc newZipFileStream(f: PZipFile): PZipFileStream =
|
proc newZipFileStream(f: PZipFile): PZipFileStream =
|
||||||
new(result)
|
new(result)
|
||||||
result.f = f
|
result.f = f
|
||||||
|
result.atEnd = false
|
||||||
result.closeImpl = fsClose
|
result.closeImpl = fsClose
|
||||||
result.readDataImpl = fsReadData
|
result.readDataImpl = fsReadData
|
||||||
|
result.atEndImpl = fsAtEnd
|
||||||
# other methods are nil!
|
# other methods are nil!
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
proc getStream*(z: var TZipArchive, filename: string): PZipFileStream =
|
proc getStream*(z: var TZipArchive, filename: string): PZipFileStream =
|
||||||
## returns a stream that can be used to read the file named `filename`
|
## returns a stream that can be used to read the file named `filename`
|
||||||
## from the archive `z`. Returns nil in case of an error.
|
## from the archive `z`. Returns nil in case of an error.
|
||||||
## The returned stream does not support the `setPosition`, `getPosition`,
|
## The returned stream does not support the `setPosition`, `getPosition`,
|
||||||
## `writeData` or `atEnd` methods.
|
## `writeData` or `atEnd` methods.
|
||||||
var x = zip_fopen(z.w, filename, 0'i32)
|
var x = zip_fopen(z.w, filename, 0'i32)
|
||||||
if x != nil: result = newZipFileStream(x)
|
if x != nil: result = newZipFileStream(x)
|
||||||
|
|
||||||
iterator walkFiles*(z: var TZipArchive): string =
|
iterator walkFiles*(z: var TZipArchive): string =
|
||||||
## walks over all files in the archive `z` and returns the filename
|
## walks over all files in the archive `z` and returns the filename
|
||||||
## (including the path).
|
## (including the path).
|
||||||
var i = 0'i32
|
var i = 0'i32
|
||||||
var num = zip_get_num_files(z.w)
|
var num = zip_get_num_files(z.w)
|
||||||
|
|
@ -158,12 +164,20 @@ proc extractFile*(z: var TZipArchive, srcFile: string, dest: Stream) =
|
||||||
|
|
||||||
proc extractFile*(z: var TZipArchive, srcFile: string, dest: string) =
|
proc extractFile*(z: var TZipArchive, srcFile: string, dest: string) =
|
||||||
## extracts a file from the zip archive `z` to the destination filename.
|
## extracts a file from the zip archive `z` to the destination filename.
|
||||||
var file = newFileStream(dest, fmReadWrite)
|
var file = newFileStream(dest, fmWrite)
|
||||||
extractFile(z, srcFile, file)
|
extractFile(z, srcFile, file)
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
proc extractAll*(z: var TZipArchive, dest: string) =
|
proc extractAll*(z: var TZipArchive, dest: string) =
|
||||||
## extracts all files from archive `z` to the destination directory.
|
## extracts all files from archive `z` to the destination directory.
|
||||||
for file in walkFiles(z):
|
for file in walkFiles(z):
|
||||||
extractFile(z, file, dest / extractFilename(file))
|
if file.endsWith("/"):
|
||||||
|
createDir(dest / file)
|
||||||
|
else:
|
||||||
|
extractFile(z, file, dest / file)
|
||||||
|
|
||||||
|
when not defined(testing) and isMainModule:
|
||||||
|
var zip: TZipArchive
|
||||||
|
if not zip.open("nim-0.11.0.zip"):
|
||||||
|
raise newException(IOError, "opening zip failed")
|
||||||
|
zip.extractAll("test")
|
||||||
|
|
|
||||||
|
|
@ -152,10 +152,12 @@ type
|
||||||
DocumentObj {.importc.} = object of NodeObj
|
DocumentObj {.importc.} = object of NodeObj
|
||||||
alinkColor*: cstring
|
alinkColor*: cstring
|
||||||
bgColor*: cstring
|
bgColor*: cstring
|
||||||
|
body*: Element
|
||||||
charset*: cstring
|
charset*: cstring
|
||||||
cookie*: cstring
|
cookie*: cstring
|
||||||
defaultCharset*: cstring
|
defaultCharset*: cstring
|
||||||
fgColor*: cstring
|
fgColor*: cstring
|
||||||
|
head*: Element
|
||||||
lastModified*: cstring
|
lastModified*: cstring
|
||||||
linkColor*: cstring
|
linkColor*: cstring
|
||||||
referrer*: cstring
|
referrer*: cstring
|
||||||
|
|
|
||||||
|
|
@ -819,15 +819,18 @@ proc enlarge[A](t: var CountTable[A]) =
|
||||||
swap(t.data, n)
|
swap(t.data, n)
|
||||||
|
|
||||||
proc `[]=`*[A](t: var CountTable[A], key: A, val: int) =
|
proc `[]=`*[A](t: var CountTable[A], key: A, val: int) =
|
||||||
## puts a (key, value)-pair into `t`. `val` has to be positive.
|
## puts a (key, value)-pair into `t`.
|
||||||
assert val > 0
|
assert val > 0
|
||||||
var h = rawGet(t, key)
|
var h = rawGet(t, key)
|
||||||
if h >= 0:
|
if h >= 0:
|
||||||
t.data[h].val = val
|
t.data[h].val = val
|
||||||
else:
|
else:
|
||||||
h = -1 - h
|
if mustRehash(len(t.data), t.counter): enlarge(t)
|
||||||
t.data[h].key = key
|
rawInsert(t, t.data, key, val)
|
||||||
t.data[h].val = val
|
inc(t.counter)
|
||||||
|
#h = -1 - h
|
||||||
|
#t.data[h].key = key
|
||||||
|
#t.data[h].val = val
|
||||||
|
|
||||||
proc initCountTable*[A](initialSize=64): CountTable[A] =
|
proc initCountTable*[A](initialSize=64): CountTable[A] =
|
||||||
## creates a new count table that is empty.
|
## creates a new count table that is empty.
|
||||||
|
|
|
||||||
|
|
@ -1535,7 +1535,7 @@ const
|
||||||
NimMinor*: int = 11
|
NimMinor*: int = 11
|
||||||
## is the minor number of Nim's version.
|
## is the minor number of Nim's version.
|
||||||
|
|
||||||
NimPatch*: int = 0
|
NimPatch*: int = 2
|
||||||
## is the patch number of Nim's version.
|
## is the patch number of Nim's version.
|
||||||
|
|
||||||
NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch
|
NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
## This module implements a small wrapper for some needed Win API procedures,
|
## This module implements a small wrapper for some needed Win API procedures,
|
||||||
## so that the Nim compiler does not depend on the huge Windows module.
|
## so that the Nim compiler does not depend on the huge Windows module.
|
||||||
|
|
||||||
|
{.deadCodeElim:on.}
|
||||||
|
|
||||||
const
|
const
|
||||||
useWinUnicode* = not defined(useWinAnsi)
|
useWinUnicode* = not defined(useWinAnsi)
|
||||||
|
|
||||||
|
|
@ -29,7 +31,7 @@ type
|
||||||
nLength*: int32
|
nLength*: int32
|
||||||
lpSecurityDescriptor*: pointer
|
lpSecurityDescriptor*: pointer
|
||||||
bInheritHandle*: WINBOOL
|
bInheritHandle*: WINBOOL
|
||||||
|
|
||||||
TSTARTUPINFO* {.final, pure.} = object
|
TSTARTUPINFO* {.final, pure.} = object
|
||||||
cb*: int32
|
cb*: int32
|
||||||
lpReserved*: cstring
|
lpReserved*: cstring
|
||||||
|
|
@ -59,7 +61,7 @@ type
|
||||||
TFILETIME* {.final, pure.} = object ## CANNOT BE int64 BECAUSE OF ALIGNMENT
|
TFILETIME* {.final, pure.} = object ## CANNOT BE int64 BECAUSE OF ALIGNMENT
|
||||||
dwLowDateTime*: DWORD
|
dwLowDateTime*: DWORD
|
||||||
dwHighDateTime*: DWORD
|
dwHighDateTime*: DWORD
|
||||||
|
|
||||||
TBY_HANDLE_FILE_INFORMATION* {.final, pure.} = object
|
TBY_HANDLE_FILE_INFORMATION* {.final, pure.} = object
|
||||||
dwFileAttributes*: DWORD
|
dwFileAttributes*: DWORD
|
||||||
ftCreationTime*: TFILETIME
|
ftCreationTime*: TFILETIME
|
||||||
|
|
@ -94,26 +96,26 @@ const
|
||||||
STD_ERROR_HANDLE* = -12'i32
|
STD_ERROR_HANDLE* = -12'i32
|
||||||
|
|
||||||
DETACHED_PROCESS* = 8'i32
|
DETACHED_PROCESS* = 8'i32
|
||||||
|
|
||||||
SW_SHOWNORMAL* = 1'i32
|
SW_SHOWNORMAL* = 1'i32
|
||||||
INVALID_HANDLE_VALUE* = THandle(-1)
|
INVALID_HANDLE_VALUE* = THandle(-1)
|
||||||
|
|
||||||
CREATE_UNICODE_ENVIRONMENT* = 1024'i32
|
CREATE_UNICODE_ENVIRONMENT* = 1024'i32
|
||||||
|
|
||||||
proc closeHandle*(hObject: THandle): WINBOOL {.stdcall, dynlib: "kernel32",
|
proc closeHandle*(hObject: THandle): WINBOOL {.stdcall, dynlib: "kernel32",
|
||||||
importc: "CloseHandle".}
|
importc: "CloseHandle".}
|
||||||
|
|
||||||
proc readFile*(hFile: THandle, Buffer: pointer, nNumberOfBytesToRead: int32,
|
proc readFile*(hFile: THandle, Buffer: pointer, nNumberOfBytesToRead: int32,
|
||||||
lpNumberOfBytesRead: ptr int32, lpOverlapped: pointer): WINBOOL{.
|
lpNumberOfBytesRead: ptr int32, lpOverlapped: pointer): WINBOOL{.
|
||||||
stdcall, dynlib: "kernel32", importc: "ReadFile".}
|
stdcall, dynlib: "kernel32", importc: "ReadFile".}
|
||||||
|
|
||||||
proc writeFile*(hFile: THandle, Buffer: pointer, nNumberOfBytesToWrite: int32,
|
proc writeFile*(hFile: THandle, Buffer: pointer, nNumberOfBytesToWrite: int32,
|
||||||
lpNumberOfBytesWritten: ptr int32,
|
lpNumberOfBytesWritten: ptr int32,
|
||||||
lpOverlapped: pointer): WINBOOL{.
|
lpOverlapped: pointer): WINBOOL{.
|
||||||
stdcall, dynlib: "kernel32", importc: "WriteFile".}
|
stdcall, dynlib: "kernel32", importc: "WriteFile".}
|
||||||
|
|
||||||
proc createPipe*(hReadPipe, hWritePipe: var THandle,
|
proc createPipe*(hReadPipe, hWritePipe: var THandle,
|
||||||
lpPipeAttributes: var TSECURITY_ATTRIBUTES,
|
lpPipeAttributes: var TSECURITY_ATTRIBUTES,
|
||||||
nSize: int32): WINBOOL{.
|
nSize: int32): WINBOOL{.
|
||||||
stdcall, dynlib: "kernel32", importc: "CreatePipe".}
|
stdcall, dynlib: "kernel32", importc: "CreatePipe".}
|
||||||
|
|
||||||
|
|
@ -159,7 +161,7 @@ proc setStdHandle*(nStdHandle: int32, hHandle: THandle): WINBOOL {.stdcall,
|
||||||
proc flushFileBuffers*(hFile: THandle): WINBOOL {.stdcall, dynlib: "kernel32",
|
proc flushFileBuffers*(hFile: THandle): WINBOOL {.stdcall, dynlib: "kernel32",
|
||||||
importc: "FlushFileBuffers".}
|
importc: "FlushFileBuffers".}
|
||||||
|
|
||||||
proc getLastError*(): int32 {.importc: "GetLastError",
|
proc getLastError*(): int32 {.importc: "GetLastError",
|
||||||
stdcall, dynlib: "kernel32".}
|
stdcall, dynlib: "kernel32".}
|
||||||
|
|
||||||
when useWinUnicode:
|
when useWinUnicode:
|
||||||
|
|
@ -179,7 +181,7 @@ proc localFree*(p: pointer) {.
|
||||||
importc: "LocalFree", stdcall, dynlib: "kernel32".}
|
importc: "LocalFree", stdcall, dynlib: "kernel32".}
|
||||||
|
|
||||||
when useWinUnicode:
|
when useWinUnicode:
|
||||||
proc getCurrentDirectoryW*(nBufferLength: int32,
|
proc getCurrentDirectoryW*(nBufferLength: int32,
|
||||||
lpBuffer: WideCString): int32 {.
|
lpBuffer: WideCString): int32 {.
|
||||||
importc: "GetCurrentDirectoryW", dynlib: "kernel32", stdcall.}
|
importc: "GetCurrentDirectoryW", dynlib: "kernel32", stdcall.}
|
||||||
proc setCurrentDirectoryW*(lpPathName: WideCString): int32 {.
|
proc setCurrentDirectoryW*(lpPathName: WideCString): int32 {.
|
||||||
|
|
@ -191,8 +193,8 @@ when useWinUnicode:
|
||||||
proc setEnvironmentVariableW*(lpName, lpValue: WideCString): int32 {.
|
proc setEnvironmentVariableW*(lpName, lpValue: WideCString): int32 {.
|
||||||
stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableW".}
|
stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableW".}
|
||||||
|
|
||||||
proc getModuleFileNameW*(handle: THandle, buf: WideCString,
|
proc getModuleFileNameW*(handle: THandle, buf: WideCString,
|
||||||
size: int32): int32 {.importc: "GetModuleFileNameW",
|
size: int32): int32 {.importc: "GetModuleFileNameW",
|
||||||
dynlib: "kernel32", stdcall.}
|
dynlib: "kernel32", stdcall.}
|
||||||
else:
|
else:
|
||||||
proc getCurrentDirectoryA*(nBufferLength: int32, lpBuffer: cstring): int32 {.
|
proc getCurrentDirectoryA*(nBufferLength: int32, lpBuffer: cstring): int32 {.
|
||||||
|
|
@ -269,14 +271,14 @@ proc findClose*(hFindFile: THandle) {.stdcall, dynlib: "kernel32",
|
||||||
|
|
||||||
when useWinUnicode:
|
when useWinUnicode:
|
||||||
proc getFullPathNameW*(lpFileName: WideCString, nBufferLength: int32,
|
proc getFullPathNameW*(lpFileName: WideCString, nBufferLength: int32,
|
||||||
lpBuffer: WideCString,
|
lpBuffer: WideCString,
|
||||||
lpFilePart: var WideCString): int32 {.
|
lpFilePart: var WideCString): int32 {.
|
||||||
stdcall, dynlib: "kernel32",
|
stdcall, dynlib: "kernel32",
|
||||||
importc: "GetFullPathNameW".}
|
importc: "GetFullPathNameW".}
|
||||||
proc getFileAttributesW*(lpFileName: WideCString): int32 {.
|
proc getFileAttributesW*(lpFileName: WideCString): int32 {.
|
||||||
stdcall, dynlib: "kernel32",
|
stdcall, dynlib: "kernel32",
|
||||||
importc: "GetFileAttributesW".}
|
importc: "GetFileAttributesW".}
|
||||||
proc setFileAttributesW*(lpFileName: WideCString,
|
proc setFileAttributesW*(lpFileName: WideCString,
|
||||||
dwFileAttributes: int32): WINBOOL {.
|
dwFileAttributes: int32): WINBOOL {.
|
||||||
stdcall, dynlib: "kernel32", importc: "SetFileAttributesW".}
|
stdcall, dynlib: "kernel32", importc: "SetFileAttributesW".}
|
||||||
|
|
||||||
|
|
@ -299,12 +301,12 @@ when useWinUnicode:
|
||||||
else:
|
else:
|
||||||
proc getFullPathNameA*(lpFileName: cstring, nBufferLength: int32,
|
proc getFullPathNameA*(lpFileName: cstring, nBufferLength: int32,
|
||||||
lpBuffer: cstring, lpFilePart: var cstring): int32 {.
|
lpBuffer: cstring, lpFilePart: var cstring): int32 {.
|
||||||
stdcall, dynlib: "kernel32",
|
stdcall, dynlib: "kernel32",
|
||||||
importc: "GetFullPathNameA".}
|
importc: "GetFullPathNameA".}
|
||||||
proc getFileAttributesA*(lpFileName: cstring): int32 {.
|
proc getFileAttributesA*(lpFileName: cstring): int32 {.
|
||||||
stdcall, dynlib: "kernel32",
|
stdcall, dynlib: "kernel32",
|
||||||
importc: "GetFileAttributesA".}
|
importc: "GetFileAttributesA".}
|
||||||
proc setFileAttributesA*(lpFileName: cstring,
|
proc setFileAttributesA*(lpFileName: cstring,
|
||||||
dwFileAttributes: int32): WINBOOL {.
|
dwFileAttributes: int32): WINBOOL {.
|
||||||
stdcall, dynlib: "kernel32", importc: "SetFileAttributesA".}
|
stdcall, dynlib: "kernel32", importc: "SetFileAttributesA".}
|
||||||
|
|
||||||
|
|
@ -324,10 +326,10 @@ else:
|
||||||
proc getCommandLineA*(): cstring {.
|
proc getCommandLineA*(): cstring {.
|
||||||
importc: "GetCommandLineA", stdcall, dynlib: "kernel32".}
|
importc: "GetCommandLineA", stdcall, dynlib: "kernel32".}
|
||||||
|
|
||||||
proc rdFileTime*(f: TFILETIME): int64 =
|
proc rdFileTime*(f: TFILETIME): int64 =
|
||||||
result = ze64(f.dwLowDateTime) or (ze64(f.dwHighDateTime) shl 32)
|
result = ze64(f.dwLowDateTime) or (ze64(f.dwHighDateTime) shl 32)
|
||||||
|
|
||||||
proc rdFileSize*(f: TWIN32_FIND_DATA): int64 =
|
proc rdFileSize*(f: TWIN32_FIND_DATA): int64 =
|
||||||
result = ze64(f.nFileSizeLow) or (ze64(f.nFileSizeHigh) shl 32)
|
result = ze64(f.nFileSizeLow) or (ze64(f.nFileSizeHigh) shl 32)
|
||||||
|
|
||||||
proc getSystemTimeAsFileTime*(lpSystemTimeAsFileTime: var TFILETIME) {.
|
proc getSystemTimeAsFileTime*(lpSystemTimeAsFileTime: var TFILETIME) {.
|
||||||
|
|
@ -347,7 +349,7 @@ else:
|
||||||
lpParameters, lpDirectory: cstring,
|
lpParameters, lpDirectory: cstring,
|
||||||
nShowCmd: int32): THandle{.
|
nShowCmd: int32): THandle{.
|
||||||
stdcall, dynlib: "shell32.dll", importc: "ShellExecuteA".}
|
stdcall, dynlib: "shell32.dll", importc: "ShellExecuteA".}
|
||||||
|
|
||||||
proc getFileInformationByHandle*(hFile: THandle,
|
proc getFileInformationByHandle*(hFile: THandle,
|
||||||
lpFileInformation: ptr TBY_HANDLE_FILE_INFORMATION): WINBOOL{.
|
lpFileInformation: ptr TBY_HANDLE_FILE_INFORMATION): WINBOOL{.
|
||||||
stdcall, dynlib: "kernel32", importc: "GetFileInformationByHandle".}
|
stdcall, dynlib: "kernel32", importc: "GetFileInformationByHandle".}
|
||||||
|
|
@ -357,12 +359,12 @@ const
|
||||||
WSASYS_STATUS_LEN* = 128
|
WSASYS_STATUS_LEN* = 128
|
||||||
FD_SETSIZE* = 64
|
FD_SETSIZE* = 64
|
||||||
MSG_PEEK* = 2
|
MSG_PEEK* = 2
|
||||||
|
|
||||||
INADDR_ANY* = 0
|
INADDR_ANY* = 0
|
||||||
INADDR_LOOPBACK* = 0x7F000001
|
INADDR_LOOPBACK* = 0x7F000001
|
||||||
INADDR_BROADCAST* = -1
|
INADDR_BROADCAST* = -1
|
||||||
INADDR_NONE* = -1
|
INADDR_NONE* = -1
|
||||||
|
|
||||||
ws2dll = "Ws2_32.dll"
|
ws2dll = "Ws2_32.dll"
|
||||||
|
|
||||||
WSAEWOULDBLOCK* = 10035
|
WSAEWOULDBLOCK* = 10035
|
||||||
|
|
@ -376,31 +378,31 @@ type
|
||||||
{.deprecated: [TSocketHandle: SocketHandle].}
|
{.deprecated: [TSocketHandle: SocketHandle].}
|
||||||
|
|
||||||
type
|
type
|
||||||
WSAData* {.importc: "WSADATA", header: "winsock2.h".} = object
|
WSAData* {.importc: "WSADATA", header: "winsock2.h".} = object
|
||||||
wVersion, wHighVersion: int16
|
wVersion, wHighVersion: int16
|
||||||
szDescription: array[0..WSADESCRIPTION_LEN, char]
|
szDescription: array[0..WSADESCRIPTION_LEN, char]
|
||||||
szSystemStatus: array[0..WSASYS_STATUS_LEN, char]
|
szSystemStatus: array[0..WSASYS_STATUS_LEN, char]
|
||||||
iMaxSockets, iMaxUdpDg: int16
|
iMaxSockets, iMaxUdpDg: int16
|
||||||
lpVendorInfo: cstring
|
lpVendorInfo: cstring
|
||||||
|
|
||||||
SockAddr* {.importc: "SOCKADDR", header: "winsock2.h".} = object
|
SockAddr* {.importc: "SOCKADDR", header: "winsock2.h".} = object
|
||||||
sa_family*: int16 # unsigned
|
sa_family*: int16 # unsigned
|
||||||
sa_data: array[0..13, char]
|
sa_data: array[0..13, char]
|
||||||
|
|
||||||
InAddr* {.importc: "IN_ADDR", header: "winsock2.h".} = object
|
InAddr* {.importc: "IN_ADDR", header: "winsock2.h".} = object
|
||||||
s_addr*: int32 # IP address
|
s_addr*: int32 # IP address
|
||||||
|
|
||||||
Sockaddr_in* {.importc: "SOCKADDR_IN",
|
Sockaddr_in* {.importc: "SOCKADDR_IN",
|
||||||
header: "winsock2.h".} = object
|
header: "winsock2.h".} = object
|
||||||
sin_family*: int16
|
sin_family*: int16
|
||||||
sin_port*: int16 # unsigned
|
sin_port*: int16 # unsigned
|
||||||
sin_addr*: InAddr
|
sin_addr*: InAddr
|
||||||
sin_zero*: array[0..7, char]
|
sin_zero*: array[0..7, char]
|
||||||
|
|
||||||
In6_addr* {.importc: "IN6_ADDR", header: "winsock2.h".} = object
|
In6_addr* {.importc: "IN6_ADDR", header: "winsock2.h".} = object
|
||||||
bytes*: array[0..15, char]
|
bytes*: array[0..15, char]
|
||||||
|
|
||||||
Sockaddr_in6* {.importc: "SOCKADDR_IN6",
|
Sockaddr_in6* {.importc: "SOCKADDR_IN6",
|
||||||
header: "winsock2.h".} = object
|
header: "winsock2.h".} = object
|
||||||
sin6_family*: int16
|
sin6_family*: int16
|
||||||
sin6_port*: int16 # unsigned
|
sin6_port*: int16 # unsigned
|
||||||
|
|
@ -430,23 +432,23 @@ type
|
||||||
h_addrtype*: int16
|
h_addrtype*: int16
|
||||||
h_length*: int16
|
h_length*: int16
|
||||||
h_addr_list*: cstringArray
|
h_addr_list*: cstringArray
|
||||||
|
|
||||||
TFdSet* = object
|
TFdSet* = object
|
||||||
fd_count*: cint # unsigned
|
fd_count*: cint # unsigned
|
||||||
fd_array*: array[0..FD_SETSIZE-1, SocketHandle]
|
fd_array*: array[0..FD_SETSIZE-1, SocketHandle]
|
||||||
|
|
||||||
Timeval* = object
|
Timeval* = object
|
||||||
tv_sec*, tv_usec*: int32
|
tv_sec*, tv_usec*: int32
|
||||||
|
|
||||||
AddrInfo* = object
|
AddrInfo* = object
|
||||||
ai_flags*: cint ## Input flags.
|
ai_flags*: cint ## Input flags.
|
||||||
ai_family*: cint ## Address family of socket.
|
ai_family*: cint ## Address family of socket.
|
||||||
ai_socktype*: cint ## Socket type.
|
ai_socktype*: cint ## Socket type.
|
||||||
ai_protocol*: cint ## Protocol of socket.
|
ai_protocol*: cint ## Protocol of socket.
|
||||||
ai_addrlen*: int ## Length of socket address.
|
ai_addrlen*: int ## Length of socket address.
|
||||||
ai_canonname*: cstring ## Canonical name of service location.
|
ai_canonname*: cstring ## Canonical name of service location.
|
||||||
ai_addr*: ptr SockAddr ## Socket address of socket.
|
ai_addr*: ptr SockAddr ## Socket address of socket.
|
||||||
ai_next*: ptr AddrInfo ## Pointer to next in list.
|
ai_next*: ptr AddrInfo ## Pointer to next in list.
|
||||||
|
|
||||||
SockLen* = cuint
|
SockLen* = cuint
|
||||||
|
|
||||||
|
|
@ -501,7 +503,7 @@ proc bindSocket*(s: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint {.
|
||||||
stdcall, importc: "bind", dynlib: ws2dll.}
|
stdcall, importc: "bind", dynlib: ws2dll.}
|
||||||
proc connect*(s: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint {.
|
proc connect*(s: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint {.
|
||||||
stdcall, importc: "connect", dynlib: ws2dll.}
|
stdcall, importc: "connect", dynlib: ws2dll.}
|
||||||
proc getsockname*(s: SocketHandle, name: ptr SockAddr,
|
proc getsockname*(s: SocketHandle, name: ptr SockAddr,
|
||||||
namelen: ptr SockLen): cint {.
|
namelen: ptr SockLen): cint {.
|
||||||
stdcall, importc: "getsockname", dynlib: ws2dll.}
|
stdcall, importc: "getsockname", dynlib: ws2dll.}
|
||||||
proc getsockopt*(s: SocketHandle, level, optname: cint, optval: pointer,
|
proc getsockopt*(s: SocketHandle, level, optname: cint, optval: pointer,
|
||||||
|
|
@ -515,7 +517,7 @@ proc listen*(s: SocketHandle, backlog: cint): cint {.
|
||||||
stdcall, importc: "listen", dynlib: ws2dll.}
|
stdcall, importc: "listen", dynlib: ws2dll.}
|
||||||
proc recv*(s: SocketHandle, buf: pointer, len, flags: cint): cint {.
|
proc recv*(s: SocketHandle, buf: pointer, len, flags: cint): cint {.
|
||||||
stdcall, importc: "recv", dynlib: ws2dll.}
|
stdcall, importc: "recv", dynlib: ws2dll.}
|
||||||
proc recvfrom*(s: SocketHandle, buf: cstring, len, flags: cint,
|
proc recvfrom*(s: SocketHandle, buf: cstring, len, flags: cint,
|
||||||
fromm: ptr SockAddr, fromlen: ptr SockLen): cint {.
|
fromm: ptr SockAddr, fromlen: ptr SockLen): cint {.
|
||||||
stdcall, importc: "recvfrom", dynlib: ws2dll.}
|
stdcall, importc: "recvfrom", dynlib: ws2dll.}
|
||||||
proc select*(nfds: cint, readfds, writefds, exceptfds: ptr TFdSet,
|
proc select*(nfds: cint, readfds, writefds, exceptfds: ptr TFdSet,
|
||||||
|
|
@ -529,22 +531,22 @@ proc sendto*(s: SocketHandle, buf: pointer, len, flags: cint,
|
||||||
|
|
||||||
proc shutdown*(s: SocketHandle, how: cint): cint {.
|
proc shutdown*(s: SocketHandle, how: cint): cint {.
|
||||||
stdcall, importc: "shutdown", dynlib: ws2dll.}
|
stdcall, importc: "shutdown", dynlib: ws2dll.}
|
||||||
|
|
||||||
proc getnameinfo*(a1: ptr SockAddr, a2: SockLen,
|
proc getnameinfo*(a1: ptr SockAddr, a2: SockLen,
|
||||||
a3: cstring, a4: SockLen, a5: cstring,
|
a3: cstring, a4: SockLen, a5: cstring,
|
||||||
a6: SockLen, a7: cint): cint {.
|
a6: SockLen, a7: cint): cint {.
|
||||||
stdcall, importc: "getnameinfo", dynlib: ws2dll.}
|
stdcall, importc: "getnameinfo", dynlib: ws2dll.}
|
||||||
|
|
||||||
proc inet_addr*(cp: cstring): int32 {.
|
proc inet_addr*(cp: cstring): int32 {.
|
||||||
stdcall, importc: "inet_addr", dynlib: ws2dll.}
|
stdcall, importc: "inet_addr", dynlib: ws2dll.}
|
||||||
|
|
||||||
proc WSAFDIsSet(s: SocketHandle, set: var TFdSet): bool {.
|
proc WSAFDIsSet(s: SocketHandle, set: var TFdSet): bool {.
|
||||||
stdcall, importc: "__WSAFDIsSet", dynlib: ws2dll, noSideEffect.}
|
stdcall, importc: "__WSAFDIsSet", dynlib: ws2dll, noSideEffect.}
|
||||||
|
|
||||||
proc FD_ISSET*(socket: SocketHandle, set: var TFdSet): cint =
|
proc FD_ISSET*(socket: SocketHandle, set: var TFdSet): cint =
|
||||||
result = if WSAFDIsSet(socket, set): 1'i32 else: 0'i32
|
result = if WSAFDIsSet(socket, set): 1'i32 else: 0'i32
|
||||||
|
|
||||||
proc FD_SET*(socket: SocketHandle, s: var TFdSet) =
|
proc FD_SET*(socket: SocketHandle, s: var TFdSet) =
|
||||||
if s.fd_count < FD_SETSIZE:
|
if s.fd_count < FD_SETSIZE:
|
||||||
s.fd_array[int(s.fd_count)] = socket
|
s.fd_array[int(s.fd_count)] = socket
|
||||||
inc(s.fd_count)
|
inc(s.fd_count)
|
||||||
|
|
@ -575,8 +577,8 @@ type
|
||||||
proc waitForMultipleObjects*(nCount: DWORD, lpHandles: PWOHandleArray,
|
proc waitForMultipleObjects*(nCount: DWORD, lpHandles: PWOHandleArray,
|
||||||
bWaitAll: WINBOOL, dwMilliseconds: DWORD): DWORD{.
|
bWaitAll: WINBOOL, dwMilliseconds: DWORD): DWORD{.
|
||||||
stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
|
stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
|
||||||
|
|
||||||
|
|
||||||
# for memfiles.nim:
|
# for memfiles.nim:
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
@ -586,7 +588,7 @@ const
|
||||||
FILE_SHARE_READ* = 1'i32
|
FILE_SHARE_READ* = 1'i32
|
||||||
FILE_SHARE_DELETE* = 4'i32
|
FILE_SHARE_DELETE* = 4'i32
|
||||||
FILE_SHARE_WRITE* = 2'i32
|
FILE_SHARE_WRITE* = 2'i32
|
||||||
|
|
||||||
CREATE_ALWAYS* = 2'i32
|
CREATE_ALWAYS* = 2'i32
|
||||||
CREATE_NEW* = 1'i32
|
CREATE_NEW* = 1'i32
|
||||||
OPEN_EXISTING* = 3'i32
|
OPEN_EXISTING* = 3'i32
|
||||||
|
|
@ -628,7 +630,7 @@ proc setEndOfFile*(hFile: THandle): WINBOOL {.stdcall, dynlib: "kernel32",
|
||||||
importc: "SetEndOfFile".}
|
importc: "SetEndOfFile".}
|
||||||
|
|
||||||
proc setFilePointer*(hFile: THandle, lDistanceToMove: LONG,
|
proc setFilePointer*(hFile: THandle, lDistanceToMove: LONG,
|
||||||
lpDistanceToMoveHigh: ptr LONG,
|
lpDistanceToMoveHigh: ptr LONG,
|
||||||
dwMoveMethod: DWORD): DWORD {.
|
dwMoveMethod: DWORD): DWORD {.
|
||||||
stdcall, dynlib: "kernel32", importc: "SetFilePointer".}
|
stdcall, dynlib: "kernel32", importc: "SetFilePointer".}
|
||||||
|
|
||||||
|
|
@ -637,14 +639,14 @@ proc getFileSize*(hFile: THandle, lpFileSizeHigh: ptr DWORD): DWORD{.stdcall,
|
||||||
|
|
||||||
proc mapViewOfFileEx*(hFileMappingObject: THandle, dwDesiredAccess: DWORD,
|
proc mapViewOfFileEx*(hFileMappingObject: THandle, dwDesiredAccess: DWORD,
|
||||||
dwFileOffsetHigh, dwFileOffsetLow: DWORD,
|
dwFileOffsetHigh, dwFileOffsetLow: DWORD,
|
||||||
dwNumberOfBytesToMap: DWORD,
|
dwNumberOfBytesToMap: DWORD,
|
||||||
lpBaseAddress: pointer): pointer{.
|
lpBaseAddress: pointer): pointer{.
|
||||||
stdcall, dynlib: "kernel32", importc: "MapViewOfFileEx".}
|
stdcall, dynlib: "kernel32", importc: "MapViewOfFileEx".}
|
||||||
|
|
||||||
proc createFileMappingW*(hFile: THandle,
|
proc createFileMappingW*(hFile: THandle,
|
||||||
lpFileMappingAttributes: pointer,
|
lpFileMappingAttributes: pointer,
|
||||||
flProtect, dwMaximumSizeHigh: DWORD,
|
flProtect, dwMaximumSizeHigh: DWORD,
|
||||||
dwMaximumSizeLow: DWORD,
|
dwMaximumSizeLow: DWORD,
|
||||||
lpName: pointer): THandle {.
|
lpName: pointer): THandle {.
|
||||||
stdcall, dynlib: "kernel32", importc: "CreateFileMappingW".}
|
stdcall, dynlib: "kernel32", importc: "CreateFileMappingW".}
|
||||||
|
|
||||||
|
|
@ -702,7 +704,7 @@ proc getOverlappedResult*(hFile: THandle, lpOverlapped: TOVERLAPPED,
|
||||||
lpNumberOfBytesTransferred: var DWORD, bWait: WINBOOL): WINBOOL{.
|
lpNumberOfBytesTransferred: var DWORD, bWait: WINBOOL): WINBOOL{.
|
||||||
stdcall, dynlib: "kernel32", importc: "GetOverlappedResult".}
|
stdcall, dynlib: "kernel32", importc: "GetOverlappedResult".}
|
||||||
|
|
||||||
const
|
const
|
||||||
IOC_OUT* = 0x40000000
|
IOC_OUT* = 0x40000000
|
||||||
IOC_IN* = 0x80000000
|
IOC_IN* = 0x80000000
|
||||||
IOC_WS2* = 0x08000000
|
IOC_WS2* = 0x08000000
|
||||||
|
|
@ -725,7 +727,7 @@ var
|
||||||
proc WSAIoctl*(s: SocketHandle, dwIoControlCode: DWORD, lpvInBuffer: pointer,
|
proc WSAIoctl*(s: SocketHandle, dwIoControlCode: DWORD, lpvInBuffer: pointer,
|
||||||
cbInBuffer: DWORD, lpvOutBuffer: pointer, cbOutBuffer: DWORD,
|
cbInBuffer: DWORD, lpvOutBuffer: pointer, cbOutBuffer: DWORD,
|
||||||
lpcbBytesReturned: PDWORD, lpOverlapped: POVERLAPPED,
|
lpcbBytesReturned: PDWORD, lpOverlapped: POVERLAPPED,
|
||||||
lpCompletionRoutine: POVERLAPPED_COMPLETION_ROUTINE): cint
|
lpCompletionRoutine: POVERLAPPED_COMPLETION_ROUTINE): cint
|
||||||
{.stdcall, importc: "WSAIoctl", dynlib: "Ws2_32.dll".}
|
{.stdcall, importc: "WSAIoctl", dynlib: "Ws2_32.dll".}
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -746,7 +748,7 @@ proc WSASend*(s: SocketHandle, buf: ptr TWSABuf, bufCount: DWORD,
|
||||||
proc get_osfhandle*(fd:FileHandle): THandle {.
|
proc get_osfhandle*(fd:FileHandle): THandle {.
|
||||||
importc: "_get_osfhandle", header:"<io.h>".}
|
importc: "_get_osfhandle", header:"<io.h>".}
|
||||||
|
|
||||||
proc getSystemTimes*(lpIdleTime, lpKernelTime,
|
proc getSystemTimes*(lpIdleTime, lpKernelTime,
|
||||||
lpUserTime: var TFILETIME): WINBOOL {.stdcall,
|
lpUserTime: var TFILETIME): WINBOOL {.stdcall,
|
||||||
dynlib: "kernel32", importc: "GetSystemTimes".}
|
dynlib: "kernel32", importc: "GetSystemTimes".}
|
||||||
|
|
||||||
|
|
|
||||||
19
tests/collections/tcounttable.nim
Normal file
19
tests/collections/tcounttable.nim
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
discard """
|
||||||
|
output: "And we get here"
|
||||||
|
"""
|
||||||
|
|
||||||
|
# bug #2625
|
||||||
|
|
||||||
|
const s_len = 32
|
||||||
|
|
||||||
|
import tables
|
||||||
|
var substr_counts: CountTable[string] = initCountTable[string]()
|
||||||
|
var my_string = "Hello, this is sadly broken for strings over 64 characters. Note that it *does* appear to work for short strings."
|
||||||
|
for i in 0..(my_string.len - s_len):
|
||||||
|
let s = my_string[i..i+s_len-1]
|
||||||
|
substr_counts[s] = 1
|
||||||
|
# substr_counts[s] = substr_counts[s] + 1 # Also breaks, + 2 as well, etc.
|
||||||
|
# substr_counts.inc(s) # This works
|
||||||
|
#echo "Iteration ", i
|
||||||
|
|
||||||
|
echo "And we get here"
|
||||||
20
tests/distinct/tdistinct_consts.nim
Normal file
20
tests/distinct/tdistinct_consts.nim
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
# bug #2641
|
||||||
|
|
||||||
|
type MyChar = distinct char
|
||||||
|
const c:MyChar = MyChar('a')
|
||||||
|
|
||||||
|
type MyBool = distinct bool
|
||||||
|
const b:MyBool = MyBool(true)
|
||||||
|
|
||||||
|
type MyBoolSet = distinct set[bool]
|
||||||
|
const bs:MyBoolSet = MyBoolSet({true})
|
||||||
|
|
||||||
|
type MyCharSet= distinct set[char]
|
||||||
|
const cs:MyCharSet = MyCharSet({'a'})
|
||||||
|
|
||||||
|
type MyBoolSeq = distinct seq[bool]
|
||||||
|
const bseq:MyBoolSeq = MyBoolSeq(@[true, false])
|
||||||
|
|
||||||
|
type MyBoolArr = distinct array[3, bool]
|
||||||
|
const barr:MyBoolArr = MyBoolArr([true, false, true])
|
||||||
14
tests/template/tdefault_nil.nim
Normal file
14
tests/template/tdefault_nil.nim
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
# bug #2629
|
||||||
|
import sequtils, os
|
||||||
|
|
||||||
|
template glob_rst(basedir: string = nil): expr =
|
||||||
|
if baseDir.isNil:
|
||||||
|
to_seq(walk_files("*.rst"))
|
||||||
|
else:
|
||||||
|
to_seq(walk_files(basedir/"*.rst"))
|
||||||
|
|
||||||
|
let
|
||||||
|
rst_files = concat(glob_rst(), glob_rst("docs"))
|
||||||
|
|
||||||
|
when isMainModule: echo rst_files
|
||||||
46
tests/tuples/tuple_with_seq.nim
Normal file
46
tests/tuples/tuple_with_seq.nim
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
discard """
|
||||||
|
output: '''it's nil
|
||||||
|
@[1, 2, 3]'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
template foo(s: string = nil) =
|
||||||
|
if isNil(s):
|
||||||
|
echo "it's nil"
|
||||||
|
else:
|
||||||
|
echo s
|
||||||
|
|
||||||
|
foo
|
||||||
|
|
||||||
|
|
||||||
|
# bug #2632
|
||||||
|
|
||||||
|
proc takeTup(x: tuple[s: string;x: seq[int]]) =
|
||||||
|
discard
|
||||||
|
|
||||||
|
takeTup(("foo", @[]))
|
||||||
|
|
||||||
|
|
||||||
|
#proc foobar(): () =
|
||||||
|
|
||||||
|
proc f(xs: seq[int]) =
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc g(t: tuple[n:int, xs:seq[int]]) =
|
||||||
|
discard
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
f(@[]) # OK
|
||||||
|
g((1,@[1])) # OK
|
||||||
|
g((0,@[])) # NG
|
||||||
|
|
||||||
|
|
||||||
|
# bug #2630
|
||||||
|
type T = tuple[a: seq[int], b: int]
|
||||||
|
|
||||||
|
var t: T = (@[1,2,3], 7)
|
||||||
|
|
||||||
|
proc test(s: seq[int]): T =
|
||||||
|
echo s
|
||||||
|
(s, 7)
|
||||||
|
|
||||||
|
t = test(t.a)
|
||||||
14
todo.txt
14
todo.txt
|
|
@ -1,14 +1,14 @@
|
||||||
version 0.10.4
|
version 0.11.2
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
- The remaining bugs of the lambda lifting pass that is responsible to enable
|
||||||
|
closures and closure iterators need to be fixed.
|
||||||
version 0.10.6 (RC1?)
|
- ``concept`` needs to be refined, a nice name for the feature is not enough.
|
||||||
=====================
|
- Destructors need to be refined.
|
||||||
|
|
||||||
- make '--implicitStatic:on' the default; then we can also clean up the
|
- make '--implicitStatic:on' the default; then we can also clean up the
|
||||||
'static[T]' mess in the compiler!
|
'static[T]' mess in the compiler!
|
||||||
- finish 'parallel' or mark as experimental
|
|
||||||
|
- Finish the implementation of the 'parallel' statement.
|
||||||
- Deprecate ``immediate`` for templates and macros
|
- Deprecate ``immediate`` for templates and macros
|
||||||
- special case varargs[untyped] and varargs[typed]
|
- special case varargs[untyped] and varargs[typed]
|
||||||
- make 'nil' work for 'add':
|
- make 'nil' work for 'add':
|
||||||
|
|
|
||||||
|
|
@ -125,8 +125,8 @@ pre .end { background:url("images/tabEnd.png") no-repeat left bottom; }
|
||||||
opacity 1s ease-in-out; }
|
opacity 1s ease-in-out; }
|
||||||
#slideshow > div.active { visibility:visible; opacity:1; transition-delay:0s; }
|
#slideshow > div.active { visibility:visible; opacity:1; transition-delay:0s; }
|
||||||
#slideshow > div.init { transition-delay:0s; }
|
#slideshow > div.init { transition-delay:0s; }
|
||||||
#slideshow-nav { z-index:3; position:absolute; top:110px;; right:-12px; }
|
#slideshow-nav { z-index:3; position:absolute; top:341px; left:18px; }
|
||||||
#slideshow-nav > div { margin:5px 0; width:23px; height:23px; background:url("images/slideshow-nav.png") no-repeat; }
|
#slideshow-nav > div { display:inline-block; margin:5px 0; width:23px; height:23px; background:url("images/slideshow-nav.png") no-repeat; }
|
||||||
#slideshow-nav > div:hover { background-image:url("images/slideshow-nav_active.png"); opacity:0.5; }
|
#slideshow-nav > div:hover { background-image:url("images/slideshow-nav_active.png"); opacity:0.5; }
|
||||||
#slideshow-nav > div.active { background-image:url("images/slideshow-nav_active.png"); opacity:1; }
|
#slideshow-nav > div.active { background-image:url("images/slideshow-nav_active.png"); opacity:1; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@ Nim's Documentation
|
||||||
|
|
||||||
.. container:: libraries
|
.. container:: libraries
|
||||||
|
|
||||||
- | `Standard Library <0.11.0/lib.html>`_
|
- | `Standard Library <docs/lib.html>`_
|
||||||
| This document describes Nim's standard library.
|
| This document describes Nim's standard library.
|
||||||
|
|
||||||
- | `Language Manual <0.11.0/manual.html>`_
|
- | `Language Manual <docs/manual.html>`_
|
||||||
| The Nim manual is a draft that will evolve into a proper specification.
|
| The Nim manual is a draft that will evolve into a proper specification.
|
||||||
|
|
||||||
- | `Compiler User Guide <0.11.0/nimc.html>`_
|
- | `Compiler User Guide <docs/nimc.html>`_
|
||||||
| The user guide lists command line arguments, special features of the
|
| The user guide lists command line arguments, special features of the
|
||||||
compiler, etc.
|
compiler, etc.
|
||||||
|
|
||||||
|
|
@ -26,11 +26,11 @@ Nim's Documentation
|
||||||
|
|
||||||
.. container:: tools
|
.. container:: tools
|
||||||
|
|
||||||
- | `Source Code Filters <0.11.0/filters.html>`_
|
- | `Source Code Filters <docs/filters.html>`_
|
||||||
| The Nim compiler supports source code filters as a simple yet powerful
|
| The Nim compiler supports source code filters as a simple yet powerful
|
||||||
builtin templating system.
|
builtin templating system.
|
||||||
|
|
||||||
- | `Tools Documentation <0.11.0/tools.html>`_
|
- | `Tools Documentation <docs/tools.html>`_
|
||||||
| Description of some tools that come with the standard distribution.
|
| Description of some tools that come with the standard distribution.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -41,11 +41,11 @@ Nim's Documentation
|
||||||
|
|
||||||
.. container:: internals
|
.. container:: internals
|
||||||
|
|
||||||
- | `Garbage Collector <0.11.0/gc.html>`_
|
- | `Garbage Collector <docs/gc.html>`_
|
||||||
| Additional documentation about Nim's GC and how to operate it in a
|
| Additional documentation about Nim's GC and how to operate it in a
|
||||||
realtime setting.
|
realtime setting.
|
||||||
|
|
||||||
- | `Internal Documentation <0.11.0/intern.html>`_
|
- | `Internal Documentation <docs/intern.html>`_
|
||||||
| The internal documentation describes how the compiler is implemented.
|
| The internal documentation describes how the compiler is implemented.
|
||||||
Read this if you want to hack the compiler.
|
Read this if you want to hack the compiler.
|
||||||
|
|
||||||
|
|
@ -53,5 +53,5 @@ Nim's Documentation
|
||||||
Search Options
|
Search Options
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
`Documentation Index <0.11.0/theindex.html>`_ - The generated
|
`Documentation Index <docs/theindex.html>`_ - The generated
|
||||||
index. **Index + (Ctrl+F) == Joy**
|
index. **Index + (Ctrl+F) == Joy**
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ Binaries
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Unfortunately for now we only provide builds for Windows.
|
Unfortunately for now we only provide builds for Windows.
|
||||||
* 32 bit: `nim-0.11.0_x32.exe <download/nim-0.11.0_x32.exe>`_
|
* 32 bit: `nim-0.11.2_x32.exe <download/nim-0.11.2_x32.exe>`_
|
||||||
* 64 bit: `nim-0.11.0_x64.exe <download/nim-0.11.0_x64.exe>`_
|
* 64 bit: `nim-0.11.2_x64.exe <download/nim-0.11.2_x64.exe>`_
|
||||||
|
|
||||||
|
|
||||||
Installation based on generated C code
|
Installation based on generated C code
|
||||||
|
|
@ -26,8 +26,8 @@ like systems. Binary packages may be provided later.
|
||||||
|
|
||||||
Download one of these:
|
Download one of these:
|
||||||
|
|
||||||
* `nim-0.11.0.zip (28 MB) <download/nim-0.11.0.zip>`_
|
* `nim-0.11.2.zip (28 MB) <download/nim-0.11.2.zip>`_
|
||||||
* `nim-0.11.0.tar.xz (2.6MB) <download/nim-0.11.0.tar.xz>`_
|
* `nim-0.11.2.tar.xz (2.6MB) <download/nim-0.11.2.tar.xz>`_
|
||||||
|
|
||||||
Extract the file and follow these instructions:
|
Extract the file and follow these instructions:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@ Learning Nim
|
||||||
|
|
||||||
.. container:: tutorials
|
.. container:: tutorials
|
||||||
|
|
||||||
- | `Tutorial (part I) <0.11.0/tut1.html>`_
|
- | `Tutorial (part I) <docs/tut1.html>`_
|
||||||
| Learn the basics of Nim's types, variables, procedures, control flow, etc...
|
| Learn the basics of Nim's types, variables, procedures, control flow, etc...
|
||||||
|
|
||||||
- | `Tutorial (part II) <0.11.0/tut2.html>`_
|
- | `Tutorial (part II) <docs/tut2.html>`_
|
||||||
| Learn Nim's more advanced features such as OOP, generics, macros, etc...
|
| Learn Nim's more advanced features such as OOP, generics, macros, etc...
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -52,5 +52,5 @@ Learning Nim
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
More examples of Nim code can be found in the `Nim Language Documentation <0.11.0/manual.html>`_.
|
More examples of Nim code can be found in the `Nim Language Documentation <docs/manual.html>`_.
|
||||||
|
|
||||||
|
|
|
||||||
25
web/news.txt
25
web/news.txt
|
|
@ -2,6 +2,31 @@
|
||||||
News
|
News
|
||||||
====
|
====
|
||||||
|
|
||||||
|
..
|
||||||
|
2015-05-05 Version 0.11.2 released
|
||||||
|
==================================
|
||||||
|
|
||||||
|
Changes affecting backwards compatibility
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Language Additions
|
||||||
|
------------------
|
||||||
|
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
|
||||||
|
2015-05-04 Version 0.11.2 released
|
||||||
|
==================================
|
||||||
|
|
||||||
|
This is just a bugfix release that fixes the most pressing regressions we
|
||||||
|
introduced with version 0.11.0. The way types are computed was
|
||||||
|
changed significantly causing all sort of problems. Sorry for the
|
||||||
|
inconvenience; we grew overconfident our large test suite would prevent these
|
||||||
|
things.
|
||||||
|
|
||||||
|
|
||||||
2015-04-30 Version 0.11.0 released
|
2015-04-30 Version 0.11.0 released
|
||||||
==================================
|
==================================
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<a class="news" href="news.html#Z2015-04-30-version-0-11-0-released">
|
<a class="news" href="news.html#Z2015-05-04-version-0-11-2-released">
|
||||||
<h4>Apr 30, 2015</h4>
|
<h4>May 4, 2015</h4>
|
||||||
<p>Nim version 0.11.0 has been released!</p>
|
<p>Nim version 0.11.2 has been released!</p>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a class="news" href="news.html#Z2014-12-29-version-0-10-2-released">
|
<a class="news" href="news.html#Z2014-12-29-version-0-10-2-released">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue