mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-21 16:31:39 +00:00
@@ -31,13 +31,13 @@ documentation with only their well-documented code.
|
||||
Example:
|
||||
|
||||
.. code-block:: nim
|
||||
type TPerson* = object
|
||||
type Person* = object
|
||||
## This type contains a description of a person
|
||||
name: string
|
||||
age: int
|
||||
|
||||
Outputs::
|
||||
TPerson* = object
|
||||
Person* = object
|
||||
name: string
|
||||
age: int
|
||||
|
||||
@@ -268,8 +268,8 @@ The relationship of type to suffix is made by the proc ``complexName`` in the
|
||||
``compiler/docgen.nim`` file. Here are some examples of complex names for
|
||||
symbols in the `system module <system.html>`_.
|
||||
|
||||
* ``type TSignedInt = int | int8 | int16 | int32 | int64`` **=>**
|
||||
`#TSignedInt <system.html#TSignedInt>`_
|
||||
* ``type SignedInt = int | int8 | int16 | int32 | int64`` **=>**
|
||||
`#SignedInt <system.html#SignedInt>`_
|
||||
* ``var globalRaiseHook: proc (e: ref E_Base): bool {.nimcall.}`` **=>**
|
||||
`#globalRaiseHook <system.html#globalRaiseHook>`_
|
||||
* ``const NimVersion = "0.0.0"`` **=>**
|
||||
@@ -307,7 +307,7 @@ columns is:
|
||||
Nim's rules (eg. \`^\` like in `the actors module
|
||||
<actors.html#^,ptr.TChannel[T]>`_).
|
||||
2. Base filename plus anchor hyper link (eg.
|
||||
``algorithm.html#*,int,TSortOrder``).
|
||||
``algorithm.html#*,int,SortOrder``).
|
||||
3. Optional human readable string to display as hyper link. If the value is not
|
||||
present or is the empty string, the hyper link will be rendered
|
||||
using the term. Prefix whitespace indicates that this entry is
|
||||
|
||||
@@ -173,7 +173,7 @@ The template engine is quite flexible. It is easy to produce a procedure that
|
||||
writes the template code directly to a file::
|
||||
|
||||
#! stdtmpl(emit="f.write") | standard
|
||||
#proc writeHTMLPage(f: TFile, title, currentTab, content: string,
|
||||
#proc writeHTMLPage(f: File, title, currentTab, content: string,
|
||||
# tabs: openArray[string]) =
|
||||
<head><title>$title</title></head>
|
||||
<body>
|
||||
|
||||
@@ -213,7 +213,7 @@ tab characters (``\t``). The values of each column are:
|
||||
``proj.symbolName``.
|
||||
4. Type/signature. For variables and enums this will contain the
|
||||
type of the symbol, for procs, methods and templates this will
|
||||
contain the full unique signature (e.g. ``proc (TFile)``).
|
||||
contain the full unique signature (e.g. ``proc (File)``).
|
||||
5. Full path to the file containing the symbol.
|
||||
6. Line where the symbol is located in the file. Lines start to
|
||||
count at **1**.
|
||||
@@ -258,8 +258,8 @@ skEnumField
|
||||
|
||||
.. code-block:: nim
|
||||
Open(filename, fmWrite)
|
||||
--> col 2: system.TFileMode.fmWrite
|
||||
col 3: TFileMode
|
||||
--> col 2: system.FileMode.fmWrite
|
||||
col 3: FileMode
|
||||
col 7: ""
|
||||
|
||||
|
||||
@@ -296,7 +296,7 @@ posterior instances of the iterator.
|
||||
text = "some text"
|
||||
letters = toSeq(runes(text))
|
||||
--> col 2: unicode.runes
|
||||
col 3: iterator (string): TRune
|
||||
col 3: iterator (string): Rune
|
||||
col 7: "iterates over any unicode character of the string `s`."
|
||||
|
||||
|
||||
@@ -423,7 +423,7 @@ returned by idetools returns also the pragmas for the proc.
|
||||
.. code-block:: nim
|
||||
Open(filename, fmWrite)
|
||||
--> col 2: system.Open
|
||||
col 3: proc (var TFile, string, TFileMode, int): bool
|
||||
col 3: proc (var File, string, FileMode, int): bool
|
||||
col 7:
|
||||
"Opens a file named `filename` with given `mode`.
|
||||
|
||||
@@ -487,9 +487,9 @@ skType
|
||||
|
||||
.. code-block:: nim
|
||||
proc writeTempFile() =
|
||||
var output: TFile
|
||||
--> col 2: system.TFile
|
||||
col 3: TFile
|
||||
var output: File
|
||||
--> col 2: system.File
|
||||
col 3: File
|
||||
col 7: ""
|
||||
|
||||
|
||||
@@ -502,11 +502,11 @@ skVar
|
||||
|
||||
.. code-block:: nim
|
||||
proc writeTempFile() =
|
||||
var output: TFile
|
||||
var output: File
|
||||
output.open("/tmp/somefile", fmWrite)
|
||||
output.write("test")
|
||||
--> col 2: $MODULE.writeTempFile.output
|
||||
col 3: TFile
|
||||
col 3: File
|
||||
col 7: ""
|
||||
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ compatibility:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TCallback = proc (s: string) {.raises: [IOError].}
|
||||
Callback = proc (s: string) {.raises: [IOError].}
|
||||
var
|
||||
c: TCallback
|
||||
c: Callback
|
||||
|
||||
proc p(x: string) =
|
||||
raise newException(OSError, "OS")
|
||||
|
||||
@@ -57,7 +57,7 @@ instructs the compiler to pass the type by value to procs:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TVector {.bycopy, pure.} = object
|
||||
Vector {.bycopy, pure.} = object
|
||||
x, y, z: float
|
||||
|
||||
|
||||
|
||||
@@ -9,17 +9,17 @@ The following example shows a generic binary tree can be modelled:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TBinaryTree[T] = object # TBinaryTree is a generic type with
|
||||
BinaryTreeObj[T] = object # BinaryTreeObj is a generic type with
|
||||
# with generic param ``T``
|
||||
le, ri: ref TBinaryTree[T] # left and right subtrees; may be nil
|
||||
le, ri: BinaryTree[T] # left and right subtrees; may be nil
|
||||
data: T # the data stored in a node
|
||||
PBinaryTree[T] = ref TBinaryTree[T] # a shorthand for notational convenience
|
||||
BinaryTree[T] = ref BinaryTreeObj[T] # a shorthand for notational convenience
|
||||
|
||||
proc newNode[T](data: T): PBinaryTree[T] = # constructor for a node
|
||||
proc newNode[T](data: T): BinaryTree[T] = # constructor for a node
|
||||
new(result)
|
||||
result.data = data
|
||||
|
||||
proc add[T](root: var PBinaryTree[T], n: PBinaryTree[T]) =
|
||||
proc add[T](root: var BinaryTree[T], n: BinaryTree[T]) =
|
||||
if root == nil:
|
||||
root = n
|
||||
else:
|
||||
@@ -40,7 +40,7 @@ The following example shows a generic binary tree can be modelled:
|
||||
return
|
||||
it = it.ri
|
||||
|
||||
iterator inorder[T](root: PBinaryTree[T]): T =
|
||||
iterator inorder[T](root: BinaryTree[T]): T =
|
||||
# inorder traversal of a binary tree
|
||||
# recursive iterators are not yet implemented, so this does not work in
|
||||
# the current compiler!
|
||||
@@ -49,7 +49,7 @@ The following example shows a generic binary tree can be modelled:
|
||||
if root.ri != nil: yield inorder(root.ri)
|
||||
|
||||
var
|
||||
root: PBinaryTree[string] # instantiate a PBinaryTree with the type string
|
||||
root: BinaryTree[string] # instantiate a BinaryTree with the type string
|
||||
add(root, newNode("hallo")) # instantiates generic procs ``newNode`` and
|
||||
add(root, newNode("world")) # ``add``
|
||||
for str in inorder(root):
|
||||
@@ -64,10 +64,10 @@ therefore very useful for type specialization within generic code:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TTable[TKey, TValue] = object
|
||||
keys: seq[TKey]
|
||||
values: seq[TValue]
|
||||
when not (TKey is string): # nil value for strings used for optimization
|
||||
Table[Key, Value] = object
|
||||
keys: seq[Key]
|
||||
values: seq[Value]
|
||||
when not (Key is string): # nil value for strings used for optimization
|
||||
deletedKeys: seq[bool]
|
||||
|
||||
|
||||
@@ -127,9 +127,9 @@ more complex type classes:
|
||||
|
||||
.. code-block:: nim
|
||||
# create a type class that will match all tuple and object types
|
||||
type TRecordType = tuple or object
|
||||
type RecordType = tuple or object
|
||||
|
||||
proc printFields(rec: TRecordType) =
|
||||
proc printFields(rec: RecordType) =
|
||||
for key, value in fieldPairs(rec):
|
||||
echo key, " = ", value
|
||||
|
||||
@@ -175,11 +175,11 @@ type parameters of the matched generic type. They can be easily accessed using
|
||||
the dot syntax:
|
||||
|
||||
.. code-block:: nim
|
||||
type TMatrix[T, Rows, Columns] = object
|
||||
type Matrix[T, Rows, Columns] = object
|
||||
...
|
||||
|
||||
proc `[]`(m: TMatrix, row, col: int): TMatrix.T =
|
||||
m.data[col * high(TMatrix.Columns) + row]
|
||||
proc `[]`(m: Matrix, row, col: int): Matrix.T =
|
||||
m.data[col * high(Matrix.Columns) + row]
|
||||
|
||||
Alternatively, the `type` operator can be used over the proc params for similar
|
||||
effect when anonymous or distinct type classes are used.
|
||||
@@ -195,7 +195,7 @@ type, this results in another more specific type class:
|
||||
# seq[T1] is the same as just `seq`, but T1 will be allowed to bind
|
||||
# to a single type, while the signature is being matched
|
||||
|
||||
TMatrix[Ordinal] # Any TMatrix instantiation using integer values
|
||||
Matrix[Ordinal] # Any Matrix instantiation using integer values
|
||||
|
||||
As seen in the previous example, in such instantiations, it's not necessary to
|
||||
supply all type parameters of the generic type, because any missing ones will
|
||||
@@ -292,18 +292,18 @@ at definition and the context at instantiation are considered:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TIndex = distinct int
|
||||
Index = distinct int
|
||||
|
||||
proc `==` (a, b: TIndex): bool {.borrow.}
|
||||
proc `==` (a, b: Index): bool {.borrow.}
|
||||
|
||||
var a = (0, 0.TIndex)
|
||||
var b = (0, 0.TIndex)
|
||||
var a = (0, 0.Index)
|
||||
var b = (0, 0.Index)
|
||||
|
||||
echo a == b # works!
|
||||
|
||||
In the example the generic ``==`` for tuples (as defined in the system module)
|
||||
uses the ``==`` operators of the tuple's components. However, the ``==`` for
|
||||
the ``TIndex`` type is defined *after* the ``==`` for tuples; yet the example
|
||||
the ``Index`` type is defined *after* the ``==`` for tuples; yet the example
|
||||
compiles as the instantiation takes the currently defined symbols into account
|
||||
too.
|
||||
|
||||
|
||||
@@ -261,9 +261,9 @@ A character is not an Unicode character but a single byte. The reason for this
|
||||
is efficiency: for the overwhelming majority of use-cases, the resulting
|
||||
programs will still handle UTF-8 properly as UTF-8 was specially designed for
|
||||
this. Another reason is that Nim can thus support ``array[char, int]`` or
|
||||
``set[char]`` efficiently as many algorithms rely on this feature. The `TRune`
|
||||
``set[char]`` efficiently as many algorithms rely on this feature. The `Rune`
|
||||
type is used for Unicode characters, it can represent any Unicode character.
|
||||
``TRune`` is declared in the `unicode module <unicode.html>`_.
|
||||
``Rune`` is declared in the `unicode module <unicode.html>`_.
|
||||
|
||||
|
||||
Numerical constants
|
||||
|
||||
@@ -128,22 +128,22 @@ modules don't need to import a module's dependencies:
|
||||
|
||||
.. code-block:: nim
|
||||
# module B
|
||||
type TMyObject* = object
|
||||
type MyObject* = object
|
||||
|
||||
.. code-block:: nim
|
||||
# module A
|
||||
import B
|
||||
export B.TMyObject
|
||||
export B.MyObject
|
||||
|
||||
proc `$`*(x: TMyObject): string = "my object"
|
||||
proc `$`*(x: MyObject): string = "my object"
|
||||
|
||||
|
||||
.. code-block:: nim
|
||||
# module C
|
||||
import A
|
||||
|
||||
# B.TMyObject has been imported implicitly here:
|
||||
var x: TMyObject
|
||||
# B.MyObject has been imported implicitly here:
|
||||
var x: MyObject
|
||||
echo($x)
|
||||
|
||||
|
||||
|
||||
@@ -89,12 +89,12 @@ collector to not consider objects of this type as part of a cycle:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
PNode = ref TNode
|
||||
TNode {.acyclic, final.} = object
|
||||
left, right: PNode
|
||||
Node = ref NodeObj
|
||||
NodeObj {.acyclic, final.} = object
|
||||
left, right: Node
|
||||
data: string
|
||||
|
||||
In the example a tree structure is declared with the ``TNode`` type. Note that
|
||||
In the example a tree structure is declared with the ``Node`` type. Note that
|
||||
the type definition is recursive and the GC has to assume that objects of
|
||||
this type may form a cyclic graph. The ``acyclic`` pragma passes the
|
||||
information that this cannot happen to the GC. If the programmer uses the
|
||||
@@ -106,9 +106,9 @@ memory, but nothing worse happens.
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
PNode = acyclic ref TNode
|
||||
TNode = object
|
||||
left, right: PNode
|
||||
Node = acyclic ref NodeObj
|
||||
NodeObj = object
|
||||
left, right: Node
|
||||
data: string
|
||||
|
||||
|
||||
@@ -129,13 +129,13 @@ structure:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TNodeKind = enum nkLeaf, nkInner
|
||||
TNode {.final, shallow.} = object
|
||||
case kind: TNodeKind
|
||||
NodeKind = enum nkLeaf, nkInner
|
||||
Node {.final, shallow.} = object
|
||||
case kind: NodeKind
|
||||
of nkLeaf:
|
||||
strVal: string
|
||||
of nkInner:
|
||||
children: seq[TNode]
|
||||
children: seq[Node]
|
||||
|
||||
|
||||
pure pragma
|
||||
|
||||
@@ -121,21 +121,21 @@ different; for this a special setter syntax is needed:
|
||||
.. code-block:: nim
|
||||
|
||||
type
|
||||
TSocket* = object of TObject
|
||||
Socket* = object of RootObj
|
||||
FHost: int # cannot be accessed from the outside of the module
|
||||
# the `F` prefix is a convention to avoid clashes since
|
||||
# the accessors are named `host`
|
||||
|
||||
proc `host=`*(s: var TSocket, value: int) {.inline.} =
|
||||
proc `host=`*(s: var Socket, value: int) {.inline.} =
|
||||
## setter of hostAddr
|
||||
s.FHost = value
|
||||
|
||||
proc host*(s: TSocket): int {.inline.} =
|
||||
proc host*(s: Socket): int {.inline.} =
|
||||
## getter of hostAddr
|
||||
s.FHost
|
||||
|
||||
var
|
||||
s: TSocket
|
||||
s: Socket
|
||||
s.host = 34 # same as `host=`(s, 34)
|
||||
|
||||
|
||||
|
||||
@@ -118,11 +118,11 @@ initialized and does not rely on syntactic properties:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TMyObject = object {.requiresInit.}
|
||||
MyObject = object {.requiresInit.}
|
||||
|
||||
proc p() =
|
||||
# the following is valid:
|
||||
var x: TMyObject
|
||||
var x: MyObject
|
||||
if someCondition():
|
||||
x = a()
|
||||
else:
|
||||
|
||||
@@ -67,7 +67,7 @@ special ``:`` syntax:
|
||||
.. code-block:: nim
|
||||
|
||||
template withFile(f, fn, mode: expr, actions: stmt): stmt {.immediate.} =
|
||||
var f: TFile
|
||||
var f: File
|
||||
if open(f, fn, mode):
|
||||
try:
|
||||
actions
|
||||
@@ -140,12 +140,12 @@ shadowed by the same argument name even when fully qualified:
|
||||
# module 'm'
|
||||
|
||||
type
|
||||
TLev = enum
|
||||
Lev = enum
|
||||
levA, levB
|
||||
|
||||
var abclev = levB
|
||||
|
||||
template tstLev(abclev: TLev) =
|
||||
template tstLev(abclev: Lev) =
|
||||
echo abclev, " ", m.abclev
|
||||
|
||||
tstLev(levA)
|
||||
@@ -157,12 +157,12 @@ But the global symbol can properly be captured by a ``bind`` statement:
|
||||
# module 'm'
|
||||
|
||||
type
|
||||
TLev = enum
|
||||
Lev = enum
|
||||
levA, levB
|
||||
|
||||
var abclev = levB
|
||||
|
||||
template tstLev(abclev: TLev) =
|
||||
template tstLev(abclev: Lev) =
|
||||
bind m.abclev
|
||||
echo abclev, " ", m.abclev
|
||||
|
||||
@@ -202,7 +202,7 @@ template parameter, it is an inject'ed symbol:
|
||||
.. code-block:: nim
|
||||
template withFile(f, fn, mode: expr, actions: stmt): stmt {.immediate.} =
|
||||
block:
|
||||
var f: TFile # since 'f' is a template param, it's injected implicitly
|
||||
var f: File # since 'f' is a template param, it's injected implicitly
|
||||
...
|
||||
|
||||
withFile(txt, "ttempl3.txt", fmWrite):
|
||||
|
||||
@@ -223,21 +223,21 @@ all the arguments, but also the matched operators in reverse polish notation:
|
||||
import macros
|
||||
|
||||
type
|
||||
TMatrix = object
|
||||
Matrix = object
|
||||
dummy: int
|
||||
|
||||
proc `*`(a, b: TMatrix): TMatrix = discard
|
||||
proc `+`(a, b: TMatrix): TMatrix = discard
|
||||
proc `-`(a, b: TMatrix): TMatrix = discard
|
||||
proc `$`(a: TMatrix): string = result = $a.dummy
|
||||
proc mat21(): TMatrix =
|
||||
proc `*`(a, b: Matrix): Matrix = discard
|
||||
proc `+`(a, b: Matrix): Matrix = discard
|
||||
proc `-`(a, b: Matrix): Matrix = discard
|
||||
proc `$`(a: Matrix): string = result = $a.dummy
|
||||
proc mat21(): Matrix =
|
||||
result.dummy = 21
|
||||
|
||||
macro optM{ (`+`|`-`|`*`) ** a }(a: TMatrix): expr =
|
||||
macro optM{ (`+`|`-`|`*`) ** a }(a: Matrix): expr =
|
||||
echo treeRepr(a)
|
||||
result = newCall(bindSym"mat21")
|
||||
|
||||
var x, y, z: TMatrix
|
||||
var x, y, z: Matrix
|
||||
|
||||
echo x + y * z - x
|
||||
|
||||
@@ -267,7 +267,7 @@ parameter is of the type ``varargs`` it is treated specially and it can match
|
||||
template optWrite{
|
||||
write(f, x)
|
||||
((write|writeln){w})(f, y)
|
||||
}(x, y: varargs[expr], f: TFile, w: expr) =
|
||||
}(x, y: varargs[expr], f: File, w: expr) =
|
||||
w(f, x, y)
|
||||
|
||||
|
||||
@@ -294,7 +294,7 @@ The following example shows how some form of hoisting can be implemented:
|
||||
.. code-block:: nim
|
||||
import pegs
|
||||
|
||||
template optPeg{peg(pattern)}(pattern: string{lit}): TPeg =
|
||||
template optPeg{peg(pattern)}(pattern: string{lit}): Peg =
|
||||
var gl {.global, gensym.} = peg(pattern)
|
||||
gl
|
||||
|
||||
@@ -341,21 +341,21 @@ The ``call`` constraint is particularly useful to implement a move
|
||||
optimization for types that have copying semantics:
|
||||
|
||||
.. code-block:: nim
|
||||
proc `[]=`*(t: var TTable, key: string, val: string) =
|
||||
proc `[]=`*(t: var Table, key: string, val: string) =
|
||||
## puts a (key, value)-pair into `t`. The semantics of string require
|
||||
## a copy here:
|
||||
let idx = findInsertionPosition(key)
|
||||
t[idx] = key
|
||||
t[idx] = val
|
||||
|
||||
proc `[]=`*(t: var TTable, key: string{call}, val: string{call}) =
|
||||
proc `[]=`*(t: var Table, key: string{call}, val: string{call}) =
|
||||
## puts a (key, value)-pair into `t`. Optimized version that knows that
|
||||
## the strings are unique and thus don't need to be copied:
|
||||
let idx = findInsertionPosition(key)
|
||||
shallowCopy t[idx], key
|
||||
shallowCopy t[idx], val
|
||||
|
||||
var t: TTable
|
||||
var t: Table
|
||||
# overloading resolution ensures that the optimized []= is called here:
|
||||
t[f()] = g()
|
||||
|
||||
|
||||
@@ -49,17 +49,17 @@ can then only be used in *destructible contexts* and as parameters:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TMyObj = object
|
||||
MyObj = object
|
||||
x, y: int
|
||||
p: pointer
|
||||
|
||||
proc destroy(o: var TMyObj) {.override.} =
|
||||
proc destroy(o: var MyObj) {.override.} =
|
||||
if o.p != nil: dealloc o.p
|
||||
|
||||
proc open: TMyObj =
|
||||
result = TMyObj(x: 1, y: 2, p: alloc(3))
|
||||
proc open: MyObj =
|
||||
result = MyObj(x: 1, y: 2, p: alloc(3))
|
||||
|
||||
proc work(o: TMyObj) =
|
||||
proc work(o: MyObj) =
|
||||
echo o.x
|
||||
# No destructor invoked here for 'o' as 'o' is a parameter.
|
||||
|
||||
|
||||
@@ -5,15 +5,15 @@ Example:
|
||||
|
||||
.. code-block:: nim
|
||||
type # example demonstrating mutually recursive types
|
||||
PNode = ref TNode # a traced pointer to a TNode
|
||||
TNode = object
|
||||
le, ri: PNode # left and right subtrees
|
||||
sym: ref TSym # leaves contain a reference to a TSym
|
||||
Node = ref NodeObj # a traced pointer to a NodeObj
|
||||
NodeObj = object
|
||||
le, ri: Node # left and right subtrees
|
||||
sym: ref Sym # leaves contain a reference to a Sym
|
||||
|
||||
TSym = object # a symbol
|
||||
name: string # the symbol's name
|
||||
line: int # the line the symbol was declared in
|
||||
code: PNode # the symbol's abstract syntax tree
|
||||
Sym = object # a symbol
|
||||
name: string # the symbol's name
|
||||
line: int # the line the symbol was declared in
|
||||
code: Node # the symbol's abstract syntax tree
|
||||
|
||||
A type section begins with the ``type`` keyword. It contains multiple
|
||||
type definitions. A type definition binds a type to a name. Type definitions
|
||||
|
||||
@@ -10,7 +10,7 @@ As their name suggests, static params must be known at compile-time:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
proc precompiledRegex(pattern: static[string]): TRegEx =
|
||||
proc precompiledRegex(pattern: static[string]): RegEx =
|
||||
var res {.global.} = re(pattern)
|
||||
return res
|
||||
|
||||
@@ -35,7 +35,7 @@ predicate:
|
||||
# The following proc will be compiled once for each unique static
|
||||
# value and also once for the case handling all run-time values:
|
||||
|
||||
proc re(pattern: semistatic[string]): TRegEx =
|
||||
proc re(pattern: semistatic[string]): RegEx =
|
||||
when isStatic(pattern):
|
||||
result = precompiledRegex(pattern)
|
||||
else:
|
||||
@@ -74,8 +74,8 @@ instantiation type using the param name:
|
||||
echo "allocating ", T.name
|
||||
new(result)
|
||||
|
||||
var n = TNode.new
|
||||
var tree = new(TBinaryTree[int])
|
||||
var n = Node.new
|
||||
var tree = new(BinaryTree[int])
|
||||
|
||||
When multiple typedesc params are present, they act like a distinct type class
|
||||
(i.e. they will bind freely to different types). To force a bind-once behavior
|
||||
|
||||
@@ -257,8 +257,8 @@ the resulting programs will still handle UTF-8 properly as UTF-8 was specially
|
||||
designed for this.
|
||||
Another reason is that Nim can support ``array[char, int]`` or
|
||||
``set[char]`` efficiently as many algorithms rely on this feature. The
|
||||
`TRune` type is used for Unicode characters, it can represent any Unicode
|
||||
character. ``TRune`` is declared in the `unicode module <unicode.html>`_.
|
||||
`Rune` type is used for Unicode characters, it can represent any Unicode
|
||||
character. ``Rune`` is declared in the `unicode module <unicode.html>`_.
|
||||
|
||||
|
||||
|
||||
@@ -591,38 +591,38 @@ An example:
|
||||
|
||||
# This is an example how an abstract syntax tree could be modelled in Nim
|
||||
type
|
||||
TNodeKind = enum # the different node types
|
||||
NodeKind = enum # the different node types
|
||||
nkInt, # a leaf with an integer value
|
||||
nkFloat, # a leaf with a float value
|
||||
nkString, # a leaf with a string value
|
||||
nkAdd, # an addition
|
||||
nkSub, # a subtraction
|
||||
nkIf # an if statement
|
||||
PNode = ref TNode
|
||||
TNode = object
|
||||
case kind: TNodeKind # the ``kind`` field is the discriminator
|
||||
Node = ref NodeObj
|
||||
NodeObj = object
|
||||
case kind: NodeKind # the ``kind`` field is the discriminator
|
||||
of nkInt: intVal: int
|
||||
of nkFloat: floatVal: float
|
||||
of nkString: strVal: string
|
||||
of nkAdd, nkSub:
|
||||
leftOp, rightOp: PNode
|
||||
leftOp, rightOp: Node
|
||||
of nkIf:
|
||||
condition, thenPart, elsePart: PNode
|
||||
condition, thenPart, elsePart: Node
|
||||
|
||||
# create a new case object:
|
||||
var n = PNode(kind: nkIf, condition: nil)
|
||||
var n = Node(kind: nkIf, condition: nil)
|
||||
# accessing n.thenPart is valid because the ``nkIf`` branch is active:
|
||||
n.thenPart = PNode(kind: nkFloat, floatVal: 2.0)
|
||||
n.thenPart = Node(kind: nkFloat, floatVal: 2.0)
|
||||
|
||||
# the following statement raises an `EInvalidField` exception, because
|
||||
# the following statement raises an `FieldError` exception, because
|
||||
# n.kind's value does not fit and the ``nkString`` branch is not active:
|
||||
n.strVal = ""
|
||||
|
||||
# invalid: would change the active object branch:
|
||||
n.kind = nkInt
|
||||
|
||||
var x = PNode(kind: nkAdd, leftOp: PNode(kind: nkInt, intVal: 4),
|
||||
rightOp: PNode(kind: nkInt, intVal: 2))
|
||||
var x = Node(kind: nkAdd, leftOp: Node(kind: nkInt, intVal: 4),
|
||||
rightOp: Node(kind: nkInt, intVal: 2))
|
||||
# valid: does not change the active object branch:
|
||||
x.kind = nkSub
|
||||
|
||||
@@ -672,13 +672,13 @@ dereferencing operations for reference types:
|
||||
.. code-block:: nim
|
||||
|
||||
type
|
||||
PNode = ref TNode
|
||||
TNode = object
|
||||
le, ri: PNode
|
||||
Node = ref NodeObj
|
||||
NodeObj = object
|
||||
le, ri: Node
|
||||
data: int
|
||||
|
||||
var
|
||||
n: PNode
|
||||
n: Node
|
||||
new(n)
|
||||
n.data = 9
|
||||
# no need to write n[].data; in fact n[].data is highly discouraged!
|
||||
@@ -717,10 +717,10 @@ memory manually:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TData = tuple[x, y: int, s: string]
|
||||
Data = tuple[x, y: int, s: string]
|
||||
|
||||
# allocate memory for TData on the heap:
|
||||
var d = cast[ptr TData](alloc0(sizeof(TData)))
|
||||
# allocate memory for Data on the heap:
|
||||
var d = cast[ptr Data](alloc0(sizeof(Data)))
|
||||
|
||||
# create a new string on the garbage collected heap:
|
||||
d.s = "abc"
|
||||
@@ -736,7 +736,7 @@ never be freed. The example also demonstrates two important features for low
|
||||
level programming: the ``sizeof`` proc returns the size of a type or value
|
||||
in bytes. The ``cast`` operator can circumvent the type system: the compiler
|
||||
is forced to treat the result of the ``alloc0`` call (which returns an untyped
|
||||
pointer) as if it would have the type ``ptr TData``. Casting should only be
|
||||
pointer) as if it would have the type ``ptr Data``. Casting should only be
|
||||
done if it is unavoidable: it breaks type safety and bugs can lead to
|
||||
mysterious crashes.
|
||||
|
||||
@@ -855,13 +855,13 @@ Examples:
|
||||
.. code-block:: nim
|
||||
|
||||
type
|
||||
TOnMouseMove = proc (x, y: int) {.closure.}
|
||||
OnMouseMove = proc (x, y: int) {.closure.}
|
||||
|
||||
proc onMouseMove(mouseX, mouseY: int) =
|
||||
# has default calling convention
|
||||
echo "x: ", mouseX, " y: ", mouseY
|
||||
|
||||
proc setOnMouseMove(mouseMoveEvent: TOnMouseMove) = discard
|
||||
proc setOnMouseMove(mouseMoveEvent: OnMouseMove) = discard
|
||||
|
||||
# ok, 'onMouseMove' has the default calling convention, which is compatible
|
||||
# to 'closure':
|
||||
@@ -962,33 +962,33 @@ types are a perfect tool to model different currencies:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TDollar = distinct int
|
||||
TEuro = distinct int
|
||||
Dollar = distinct int
|
||||
Euro = distinct int
|
||||
|
||||
var
|
||||
d: TDollar
|
||||
e: TEuro
|
||||
d: Dollar
|
||||
e: Euro
|
||||
|
||||
echo d + 12
|
||||
# Error: cannot add a number with no unit and a ``TDollar``
|
||||
# Error: cannot add a number with no unit and a ``Dollar``
|
||||
|
||||
Unfortunately, ``d + 12.TDollar`` is not allowed either,
|
||||
because ``+`` is defined for ``int`` (among others), not for ``TDollar``. So
|
||||
Unfortunately, ``d + 12.Dollar`` is not allowed either,
|
||||
because ``+`` is defined for ``int`` (among others), not for ``Dollar``. So
|
||||
a ``+`` for dollars needs to be defined:
|
||||
|
||||
.. code-block::
|
||||
proc `+` (x, y: TDollar): TDollar =
|
||||
result = TDollar(int(x) + int(y))
|
||||
proc `+` (x, y: Dollar): Dollar =
|
||||
result = Dollar(int(x) + int(y))
|
||||
|
||||
It does not make sense to multiply a dollar with a dollar, but with a
|
||||
number without unit; and the same holds for division:
|
||||
|
||||
.. code-block::
|
||||
proc `*` (x: TDollar, y: int): TDollar =
|
||||
result = TDollar(int(x) * y)
|
||||
proc `*` (x: Dollar, y: int): Dollar =
|
||||
result = Dollar(int(x) * y)
|
||||
|
||||
proc `*` (x: int, y: TDollar): TDollar =
|
||||
result = TDollar(x * int(y))
|
||||
proc `*` (x: int, y: Dollar): Dollar =
|
||||
result = Dollar(x * int(y))
|
||||
|
||||
proc `div` ...
|
||||
|
||||
@@ -999,15 +999,15 @@ The pragma `borrow`:idx: has been designed to solve this problem; in principle
|
||||
it generates the above trivial implementations:
|
||||
|
||||
.. code-block:: nim
|
||||
proc `*` (x: TDollar, y: int): TDollar {.borrow.}
|
||||
proc `*` (x: int, y: TDollar): TDollar {.borrow.}
|
||||
proc `div` (x: TDollar, y: int): TDollar {.borrow.}
|
||||
proc `*` (x: Dollar, y: int): Dollar {.borrow.}
|
||||
proc `*` (x: int, y: Dollar): Dollar {.borrow.}
|
||||
proc `div` (x: Dollar, y: int): Dollar {.borrow.}
|
||||
|
||||
The ``borrow`` pragma makes the compiler use the same implementation as
|
||||
the proc that deals with the distinct type's base type, so no code is
|
||||
generated.
|
||||
|
||||
But it seems all this boilerplate code needs to be repeated for the ``TEuro``
|
||||
But it seems all this boilerplate code needs to be repeated for the ``Euro``
|
||||
currency. This can be solved with templates_.
|
||||
|
||||
.. code-block:: nim
|
||||
@@ -1037,8 +1037,8 @@ currency. This can be solved with templates_.
|
||||
multiplicative(typ, base)
|
||||
comparable(typ)
|
||||
|
||||
defineCurrency(TDollar, int)
|
||||
defineCurrency(TEuro, int)
|
||||
defineCurrency(Dollar, int)
|
||||
defineCurrency(Euro, int)
|
||||
|
||||
|
||||
The borrow pragma can also be used to annotate the distinct type to allow
|
||||
@@ -1071,7 +1071,7 @@ values is vulnerable to the famous `SQL injection attack`:idx:\:
|
||||
.. code-block:: nim
|
||||
import strutils
|
||||
|
||||
proc query(db: TDbHandle, statement: string) = ...
|
||||
proc query(db: DbHandle, statement: string) = ...
|
||||
|
||||
var
|
||||
username: string
|
||||
@@ -1081,13 +1081,13 @@ values is vulnerable to the famous `SQL injection attack`:idx:\:
|
||||
|
||||
This can be avoided by distinguishing strings that contain SQL from strings
|
||||
that don't. Distinct types provide a means to introduce a new string type
|
||||
``TSQL`` that is incompatible with ``string``:
|
||||
``SQL`` that is incompatible with ``string``:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TSQL = distinct string
|
||||
SQL = distinct string
|
||||
|
||||
proc query(db: TDbHandle, statement: TSQL) = ...
|
||||
proc query(db: DbHandle, statement: SQL) = ...
|
||||
|
||||
var
|
||||
username: string
|
||||
@@ -1098,28 +1098,28 @@ that don't. Distinct types provide a means to introduce a new string type
|
||||
|
||||
It is an essential property of abstract types that they **do not** imply a
|
||||
subtype relation between the abtract type and its base type. Explict type
|
||||
conversions from ``string`` to ``TSQL`` are allowed:
|
||||
conversions from ``string`` to ``SQL`` are allowed:
|
||||
|
||||
.. code-block:: nim
|
||||
import strutils, sequtils
|
||||
|
||||
proc properQuote(s: string): TSQL =
|
||||
proc properQuote(s: string): SQL =
|
||||
# quotes a string properly for an SQL statement
|
||||
return TSQL(s)
|
||||
return SQL(s)
|
||||
|
||||
proc `%` (frmt: TSQL, values: openarray[string]): TSQL =
|
||||
proc `%` (frmt: SQL, values: openarray[string]): SQL =
|
||||
# quote each argument:
|
||||
let v = values.mapIt(TSQL, properQuote(it))
|
||||
let v = values.mapIt(SQL, properQuote(it))
|
||||
# we need a temporary type for the type conversion :-(
|
||||
type TStrSeq = seq[string]
|
||||
type StrSeq = seq[string]
|
||||
# call strutils.`%`:
|
||||
result = TSQL(string(frmt) % TStrSeq(v))
|
||||
result = SQL(string(frmt) % StrSeq(v))
|
||||
|
||||
db.query("SELECT FROM users WHERE name = '$1'".TSQL % [username])
|
||||
db.query("SELECT FROM users WHERE name = '$1'".SQL % [username])
|
||||
|
||||
Now we have compile-time checking against SQL injection attacks. Since
|
||||
``"".TSQL`` is transformed to ``TSQL("")`` no new syntax is needed for nice
|
||||
looking ``TSQL`` string literals. The hypothetical ``TSQL`` type actually
|
||||
``"".SQL`` is transformed to ``SQL("")`` no new syntax is needed for nice
|
||||
looking ``SQL`` string literals. The hypothetical ``SQL`` type actually
|
||||
exists in the library as the `TSqlQuery type <db_sqlite.html#TSqlQuery>`_ of
|
||||
modules like `db_sqlite <db_sqlite.html>`_.
|
||||
|
||||
|
||||
16
doc/nimc.txt
16
doc/nimc.txt
@@ -311,8 +311,8 @@ underlying C ``struct`` in a ``sizeof`` expression:
|
||||
|
||||
.. code-block:: Nim
|
||||
type
|
||||
TDIR* {.importc: "DIR", header: "<dirent.h>",
|
||||
final, pure, incompleteStruct.} = object
|
||||
DIR* {.importc: "DIR", header: "<dirent.h>",
|
||||
final, pure, incompleteStruct.} = object
|
||||
|
||||
|
||||
Compile pragma
|
||||
@@ -418,8 +418,8 @@ interfacing with libraries written in C++:
|
||||
irr = "<irrlicht/irrlicht.h>"
|
||||
|
||||
type
|
||||
TIrrlichtDevice {.final, header: irr, importc: "IrrlichtDevice".} = object
|
||||
PIrrlichtDevice = ptr TIrrlichtDevice
|
||||
IrrlichtDeviceObj {.final, header: irr, importc: "IrrlichtDevice".} = object
|
||||
IrrlichtDevice = ptr IrrlichtDeviceObj
|
||||
|
||||
proc createDevice(): PIrrlichtDevice {.
|
||||
header: irr, importc: "createDevice".}
|
||||
@@ -465,11 +465,11 @@ allows *sloppy* interfacing with libraries written in Objective C:
|
||||
""".}
|
||||
|
||||
type
|
||||
TId {.importc: "id", header: "<objc/Object.h>", final.} = distinct int
|
||||
Id {.importc: "id", header: "<objc/Object.h>", final.} = distinct int
|
||||
|
||||
proc newGreeter: TId {.importobjc: "Greeter new", nodecl.}
|
||||
proc greet(self: TId, x, y: int) {.importobjc: "greet", nodecl.}
|
||||
proc free(self: TId) {.importobjc: "free", nodecl.}
|
||||
proc newGreeter: Id {.importobjc: "Greeter new", nodecl.}
|
||||
proc greet(self: Id, x, y: int) {.importobjc: "greet", nodecl.}
|
||||
proc free(self: Id) {.importobjc: "free", nodecl.}
|
||||
|
||||
var g = newGreeter()
|
||||
g.greet(12, 34)
|
||||
|
||||
@@ -213,7 +213,7 @@ example ``*`` should not be greedy, so ``\[.*?\]`` should be used instead.
|
||||
PEG construction
|
||||
----------------
|
||||
There are two ways to construct a PEG in Nim code:
|
||||
(1) Parsing a string into an AST which consists of `TPeg` nodes with the
|
||||
(1) Parsing a string into an AST which consists of `Peg` nodes with the
|
||||
`peg` proc.
|
||||
(2) Constructing the AST directly with proc calls. This method does not
|
||||
support constructing rules, only simple expressions and is not as
|
||||
|
||||
@@ -8,9 +8,9 @@ can also be used to include elements (and ranges of elements):
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TCharSet = set[char]
|
||||
CharSet = set[char]
|
||||
var
|
||||
x: TCharSet
|
||||
x: CharSet
|
||||
x = {'a'..'z', '0'..'9'} # This constructs a set that contains the
|
||||
# letters from 'a' to 'z' and the digits
|
||||
# from '0' to '9'
|
||||
|
||||
10
doc/tut1.txt
10
doc/tut1.txt
@@ -1350,11 +1350,11 @@ integer.
|
||||
.. code-block:: nim
|
||||
|
||||
type
|
||||
TPerson = tuple[name: string, age: int] # type representing a person:
|
||||
# a person consists of a name
|
||||
# and an age
|
||||
Person = tuple[name: string, age: int] # type representing a person:
|
||||
# a person consists of a name
|
||||
# and an age
|
||||
var
|
||||
person: TPerson
|
||||
person: Person
|
||||
person = (name: "Peter", age: 30)
|
||||
# the same, but less readable:
|
||||
person = ("Peter", 30)
|
||||
@@ -1373,7 +1373,7 @@ integer.
|
||||
# The following line does not compile, they are different tuples!
|
||||
#person = building
|
||||
# --> Error: type mismatch: got (tuple[street: string, number: int])
|
||||
# but expected 'TPerson'
|
||||
# but expected 'Person'
|
||||
|
||||
# The following works because the field names and types are the same.
|
||||
var teacher: tuple[name: string, age: int] = ("Mark", 42)
|
||||
|
||||
96
doc/tut2.txt
96
doc/tut2.txt
@@ -56,19 +56,19 @@ Objects have access to their type at runtime. There is an
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TPerson = object of RootObj
|
||||
Person = object of RootObj
|
||||
name*: string # the * means that `name` is accessible from other modules
|
||||
age: int # no * means that the field is hidden from other modules
|
||||
|
||||
TStudent = object of TPerson # TStudent inherits from TPerson
|
||||
id: int # with an id field
|
||||
Student = object of Person # Student inherits from Person
|
||||
id: int # with an id field
|
||||
|
||||
var
|
||||
student: TStudent
|
||||
person: TPerson
|
||||
assert(student of TStudent) # is true
|
||||
student: Student
|
||||
person: Person
|
||||
assert(student of Student) # is true
|
||||
# object construction:
|
||||
student = TStudent(name: "Anton", age: 5, id: 2)
|
||||
student = Student(name: "Anton", age: 5, id: 2)
|
||||
|
||||
Object fields that should be visible from outside the defining module have to
|
||||
be marked by ``*``. In contrast to tuples, different object types are
|
||||
@@ -100,15 +100,15 @@ Example:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
PNode = ref TNode # a traced reference to a TNode
|
||||
TNode = object
|
||||
le, ri: PNode # left and right subtrees
|
||||
sym: ref TSym # leaves contain a reference to a TSym
|
||||
Node = ref NodeObj # a traced reference to a NodeObj
|
||||
NodeObj = object
|
||||
le, ri: Node # left and right subtrees
|
||||
sym: ref Sym # leaves contain a reference to a Sym
|
||||
|
||||
TSym = object # a symbol
|
||||
name: string # the symbol's name
|
||||
line: int # the line the symbol was declared in
|
||||
code: PNode # the symbol's abstract syntax tree
|
||||
Sym = object # a symbol
|
||||
name: string # the symbol's name
|
||||
line: int # the line the symbol was declared in
|
||||
code: PNode # the symbol's abstract syntax tree
|
||||
|
||||
|
||||
Type conversions
|
||||
@@ -126,11 +126,11 @@ The syntax for type conversions is ``destination_type(expression_to_convert)``
|
||||
(like an ordinary call):
|
||||
|
||||
.. code-block:: nim
|
||||
proc getID(x: TPerson): int =
|
||||
TStudent(x).id
|
||||
proc getID(x: Person): int =
|
||||
Student(x).id
|
||||
|
||||
The ``InvalidObjectConversionError`` exception is raised if ``x`` is not a
|
||||
``TStudent``.
|
||||
``Student``.
|
||||
|
||||
|
||||
Object variants
|
||||
@@ -144,16 +144,16 @@ An example:
|
||||
|
||||
# This is an example how an abstract syntax tree could be modeled in Nim
|
||||
type
|
||||
TNodeKind = enum # the different node types
|
||||
NodeKind = enum # the different node types
|
||||
nkInt, # a leaf with an integer value
|
||||
nkFloat, # a leaf with a float value
|
||||
nkString, # a leaf with a string value
|
||||
nkAdd, # an addition
|
||||
nkSub, # a subtraction
|
||||
nkIf # an if statement
|
||||
PNode = ref TNode
|
||||
TNode = object
|
||||
case kind: TNodeKind # the ``kind`` field is the discriminator
|
||||
Node = ref NodeObj
|
||||
NodeObj = object
|
||||
case kind: NodeKind # the ``kind`` field is the discriminator
|
||||
of nkInt: intVal: int
|
||||
of nkFloat: floatVal: float
|
||||
of nkString: strVal: string
|
||||
@@ -228,21 +228,21 @@ is needed:
|
||||
.. code-block:: nim
|
||||
|
||||
type
|
||||
TSocket* = object of RootObj
|
||||
Socket* = object of RootObj
|
||||
FHost: int # cannot be accessed from the outside of the module
|
||||
# the `F` prefix is a convention to avoid clashes since
|
||||
# the accessors are named `host`
|
||||
|
||||
proc `host=`*(s: var TSocket, value: int) {.inline.} =
|
||||
proc `host=`*(s: var Socket, value: int) {.inline.} =
|
||||
## setter of hostAddr
|
||||
s.FHost = value
|
||||
|
||||
proc host*(s: TSocket): int {.inline.} =
|
||||
proc host*(s: Socket): int {.inline.} =
|
||||
## getter of hostAddr
|
||||
s.FHost
|
||||
|
||||
var
|
||||
s: TSocket
|
||||
s: Socket
|
||||
s.host = 34 # same as `host=`(s, 34)
|
||||
|
||||
(The example also shows ``inline`` procedures.)
|
||||
@@ -253,10 +253,10 @@ The ``[]`` array access operator can be overloaded to provide
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TVector* = object
|
||||
Vector* = object
|
||||
x, y, z: float
|
||||
|
||||
proc `[]=`* (v: var TVector, i: int, value: float) =
|
||||
proc `[]=`* (v: var Vector, i: int, value: float) =
|
||||
# setter
|
||||
case i
|
||||
of 0: v.x = value
|
||||
@@ -264,7 +264,7 @@ The ``[]`` array access operator can be overloaded to provide
|
||||
of 2: v.z = value
|
||||
else: assert(false)
|
||||
|
||||
proc `[]`* (v: TVector, i: int): float =
|
||||
proc `[]`* (v: Vector, i: int): float =
|
||||
# getter
|
||||
case i
|
||||
of 0: result = v.x
|
||||
@@ -313,27 +313,27 @@ dispatching:
|
||||
.. code-block:: nim
|
||||
|
||||
type
|
||||
TThing = object of RootObj
|
||||
TUnit = object of TThing
|
||||
Thing = object of RootObj
|
||||
Unit = object of Thing
|
||||
x: int
|
||||
|
||||
method collide(a, b: TThing) {.inline.} =
|
||||
method collide(a, b: Thing) {.inline.} =
|
||||
quit "to override!"
|
||||
|
||||
method collide(a: TThing, b: TUnit) {.inline.} =
|
||||
method collide(a: Thing, b: Unit) {.inline.} =
|
||||
echo "1"
|
||||
|
||||
method collide(a: TUnit, b: TThing) {.inline.} =
|
||||
method collide(a: Unit, b: Thing) {.inline.} =
|
||||
echo "2"
|
||||
|
||||
var
|
||||
a, b: TUnit
|
||||
a, b: Unit
|
||||
collide(a, b) # output: 2
|
||||
|
||||
|
||||
As the example demonstrates, invocation of a multi-method cannot be ambiguous:
|
||||
Collide 2 is preferred over collide 1 because the resolution works from left to
|
||||
right. Thus ``TUnit, TThing`` is preferred over ``TThing, TUnit``.
|
||||
right. Thus ``Unit, Thing`` is preferred over ``Thing, Unit``.
|
||||
|
||||
**Perfomance note**: Nim does not produce a virtual method table, but
|
||||
generates dispatch trees. This avoids the expensive indirect branch for method
|
||||
@@ -479,18 +479,18 @@ containers:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TBinaryTree[T] = object # TBinaryTree is a generic type with
|
||||
# with generic param ``T``
|
||||
le, ri: ref TBinaryTree[T] # left and right subtrees; may be nil
|
||||
data: T # the data stored in a node
|
||||
PBinaryTree*[T] = ref TBinaryTree[T] # type that is exported
|
||||
BinaryTreeObj[T] = object # BinaryTree is a generic type with
|
||||
# with generic param ``T``
|
||||
le, ri: BinaryTree[T] # left and right subtrees; may be nil
|
||||
data: T # the data stored in a node
|
||||
BinaryTree*[T] = ref BinaryTreeObj[T] # type that is exported
|
||||
|
||||
proc newNode*[T](data: T): PBinaryTree[T] =
|
||||
proc newNode*[T](data: T): BinaryTree[T] =
|
||||
# constructor for a node
|
||||
new(result)
|
||||
result.data = data
|
||||
|
||||
proc add*[T](root: var PBinaryTree[T], n: PBinaryTree[T]) =
|
||||
proc add*[T](root: var BinaryTree[T], n: BinaryTree[T]) =
|
||||
# insert a node into the tree
|
||||
if root == nil:
|
||||
root = n
|
||||
@@ -511,15 +511,15 @@ containers:
|
||||
return
|
||||
it = it.ri
|
||||
|
||||
proc add*[T](root: var PBinaryTree[T], data: T) =
|
||||
proc add*[T](root: var BinaryTree[T], data: T) =
|
||||
# convenience proc:
|
||||
add(root, newNode(data))
|
||||
|
||||
iterator preorder*[T](root: PBinaryTree[T]): T =
|
||||
iterator preorder*[T](root: BinaryTree[T]): T =
|
||||
# Preorder traversal of a binary tree.
|
||||
# Since recursive iterators are not yet implemented,
|
||||
# this uses an explicit stack (which is more efficient anyway):
|
||||
var stack: seq[PBinaryTree[T]] = @[root]
|
||||
var stack: seq[BinaryTree[T]] = @[root]
|
||||
while stack.len > 0:
|
||||
var n = stack.pop()
|
||||
while n != nil:
|
||||
@@ -528,7 +528,7 @@ containers:
|
||||
n = n.le # and follow the left pointer
|
||||
|
||||
var
|
||||
root: PBinaryTree[string] # instantiate a PBinaryTree with ``string``
|
||||
root: BinaryTree[string] # instantiate a BinaryTree with ``string``
|
||||
add(root, newNode("hello")) # instantiates ``newNode`` and ``add``
|
||||
add(root, "world") # instantiates the second ``add`` proc
|
||||
for str in preorder(root):
|
||||
@@ -863,7 +863,7 @@ precisely made for compilation time (just like `gorge <system.html#gorge>`_
|
||||
which executes an external program and captures its output).
|
||||
|
||||
The interesting thing is that our macro does not return a runtime `Table
|
||||
<tables.html#TTable>`_ object. Instead, it builds up Nim source code into
|
||||
<tables.html#Table>`_ object. Instead, it builds up Nim source code into
|
||||
the ``source`` variable. For each line of the configuration file a ``const``
|
||||
variable will be generated (line 15). To avoid conflicts we prefix these
|
||||
variables with ``cfg``. In essence, what the compiler is doing is replacing
|
||||
|
||||
@@ -513,7 +513,7 @@ proc bounds*(c: Captures,
|
||||
|
||||
when not useUnicode:
|
||||
type
|
||||
TRune = char
|
||||
Rune = char
|
||||
template fastRuneAt(s, i, ch: expr) =
|
||||
ch = s[i]
|
||||
inc(i)
|
||||
|
||||
@@ -514,7 +514,7 @@ proc bounds*(c: Captures,
|
||||
|
||||
when not useUnicode:
|
||||
type
|
||||
TRune = char
|
||||
Rune = char
|
||||
template fastRuneAt(s, i, ch: expr) =
|
||||
ch = s[i]
|
||||
inc(i)
|
||||
|
||||
@@ -533,7 +533,7 @@ proc bounds*(c: TCaptures,
|
||||
|
||||
when not useUnicode:
|
||||
type
|
||||
TRune = char
|
||||
Rune = char
|
||||
template fastRuneAt(s, i, ch: expr) =
|
||||
ch = s[i]
|
||||
inc(i)
|
||||
@@ -563,7 +563,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
|
||||
result = -1
|
||||
of pkLetter:
|
||||
if s[start] != '\0':
|
||||
var a: TRune
|
||||
var a: Rune
|
||||
result = start
|
||||
fastRuneAt(s, result, a)
|
||||
if isAlpha(a): dec(result, start)
|
||||
@@ -572,7 +572,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
|
||||
result = -1
|
||||
of pkLower:
|
||||
if s[start] != '\0':
|
||||
var a: TRune
|
||||
var a: Rune
|
||||
result = start
|
||||
fastRuneAt(s, result, a)
|
||||
if isLower(a): dec(result, start)
|
||||
@@ -581,7 +581,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
|
||||
result = -1
|
||||
of pkUpper:
|
||||
if s[start] != '\0':
|
||||
var a: TRune
|
||||
var a: Rune
|
||||
result = start
|
||||
fastRuneAt(s, result, a)
|
||||
if isUpper(a): dec(result, start)
|
||||
@@ -590,7 +590,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
|
||||
result = -1
|
||||
of pkTitle:
|
||||
if s[start] != '\0':
|
||||
var a: TRune
|
||||
var a: Rune
|
||||
result = start
|
||||
fastRuneAt(s, result, a)
|
||||
if isTitle(a): dec(result, start)
|
||||
@@ -599,7 +599,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
|
||||
result = -1
|
||||
of pkWhitespace:
|
||||
if s[start] != '\0':
|
||||
var a: TRune
|
||||
var a: Rune
|
||||
result = start
|
||||
fastRuneAt(s, result, a)
|
||||
if isWhitespace(a): dec(result, start)
|
||||
@@ -623,7 +623,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
|
||||
of pkTerminalIgnoreCase:
|
||||
var
|
||||
i = 0
|
||||
a, b: TRune
|
||||
a, b: Rune
|
||||
result = start
|
||||
while i < len(p.term):
|
||||
fastRuneAt(p.term, i, a)
|
||||
@@ -635,15 +635,15 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
|
||||
of pkTerminalIgnoreStyle:
|
||||
var
|
||||
i = 0
|
||||
a, b: TRune
|
||||
a, b: Rune
|
||||
result = start
|
||||
while i < len(p.term):
|
||||
while true:
|
||||
fastRuneAt(p.term, i, a)
|
||||
if a != TRune('_'): break
|
||||
if a != Rune('_'): break
|
||||
while true:
|
||||
fastRuneAt(s, result, b)
|
||||
if b != TRune('_'): break
|
||||
if b != Rune('_'): break
|
||||
if toLower(a) != toLower(b):
|
||||
result = -1
|
||||
break
|
||||
@@ -865,7 +865,7 @@ template `=~`*(s: string, pattern: TPeg): expr =
|
||||
## else:
|
||||
## echo("syntax error")
|
||||
##
|
||||
when not definedInScope(matches):
|
||||
when not declaredInScope(matches):
|
||||
var matches {.inject.}: array[0..MaxSubpatterns-1, string]
|
||||
match(s, pattern, matches)
|
||||
|
||||
@@ -964,7 +964,7 @@ proc transformFile*(infile, outfile: string,
|
||||
## error occurs. This is supposed to be used for quick scripting.
|
||||
var x = readFile(infile)
|
||||
if not isNil(x):
|
||||
var f: TFile
|
||||
var f: File
|
||||
if open(f, outfile, fmWrite):
|
||||
write(f, x.parallelReplace(subs))
|
||||
close(f)
|
||||
@@ -1404,8 +1404,8 @@ proc arrowIsNextTok(c: TPegLexer): bool =
|
||||
# ----------------------------- parser ----------------------------------------
|
||||
|
||||
type
|
||||
EInvalidPeg* = object of EInvalidValue ## raised if an invalid
|
||||
## PEG has been detected
|
||||
EInvalidPeg* = object of ValueError ## raised if an invalid
|
||||
## PEG has been detected
|
||||
TPegParser = object of TPegLexer ## the PEG parser object
|
||||
tok: TToken
|
||||
nonterms: seq[PNonTerminal]
|
||||
|
||||
Reference in New Issue
Block a user